summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/analyzerbase/analyzerbase.pro15
-rw-r--r--src/plugins/analyzerbase/analyzerbase_dependencies.pri3
-rw-r--r--src/plugins/analyzerbase/analyzerconstants.h24
-rw-r--r--src/plugins/analyzerbase/analyzermanager.cpp347
-rw-r--r--src/plugins/analyzerbase/analyzermanager.h28
-rw-r--r--src/plugins/analyzerbase/analyzeroutputpane.cpp52
-rw-r--r--src/plugins/analyzerbase/analyzeroutputpane.h4
-rw-r--r--src/plugins/analyzerbase/analyzerplugin.cpp29
-rw-r--r--src/plugins/analyzerbase/analyzerplugin.h3
-rw-r--r--src/plugins/analyzerbase/analyzerrunconfigwidget.cpp9
-rw-r--r--src/plugins/analyzerbase/analyzerrunconfigwidget.h10
-rw-r--r--src/plugins/analyzerbase/analyzerruncontrol.cpp103
-rw-r--r--src/plugins/analyzerbase/analyzerruncontrol.h45
-rw-r--r--src/plugins/analyzerbase/analyzerruncontrolfactory.cpp123
-rw-r--r--src/plugins/analyzerbase/analyzerruncontrolfactory.h72
-rw-r--r--src/plugins/analyzerbase/analyzersettings.h32
-rw-r--r--src/plugins/analyzerbase/analyzerstartparameters.h76
-rw-r--r--src/plugins/analyzerbase/analyzerutils.cpp125
-rw-r--r--src/plugins/analyzerbase/analyzerutils.h55
-rw-r--r--src/plugins/analyzerbase/ianalyzerengine.cpp16
-rw-r--r--src/plugins/analyzerbase/ianalyzerengine.h28
-rw-r--r--src/plugins/analyzerbase/ianalyzeroutputpaneadapter.cpp188
-rw-r--r--src/plugins/analyzerbase/ianalyzeroutputpaneadapter.h107
-rw-r--r--src/plugins/analyzerbase/ianalyzertool.cpp158
-rw-r--r--src/plugins/analyzerbase/ianalyzertool.h96
-rw-r--r--src/plugins/analyzerbase/startremotedialog.cpp144
-rw-r--r--src/plugins/analyzerbase/startremotedialog.h68
-rw-r--r--src/plugins/analyzerbase/startremotedialog.ui178
-rw-r--r--src/plugins/bazaar/bazaarclient.cpp97
-rw-r--r--src/plugins/bazaar/bazaarclient.h55
-rw-r--r--src/plugins/bazaar/bazaareditor.cpp24
-rw-r--r--src/plugins/bazaar/constants.h2
-rw-r--r--src/plugins/bineditor/bineditorplugin.cpp6
-rw-r--r--src/plugins/bookmarks/bookmark.cpp9
-rw-r--r--src/plugins/bookmarks/bookmark.h5
-rw-r--r--src/plugins/bookmarks/bookmarkmanager.cpp27
-rw-r--r--src/plugins/bookmarks/bookmarkmanager.h9
-rw-r--r--src/plugins/callgrind/Callgrind.pluginspec.in22
-rw-r--r--src/plugins/callgrind/callgrind.pri5
-rw-r--r--src/plugins/callgrind/callgrind.pro43
-rw-r--r--src/plugins/callgrind/callgrind_dependencies.pri5
-rw-r--r--src/plugins/callgrind/callgrind_global.h45
-rw-r--r--src/plugins/callgrind/callgrindconfigwidget.cpp77
-rw-r--r--src/plugins/callgrind/callgrindconfigwidget.h66
-rw-r--r--src/plugins/callgrind/callgrindconfigwidget.ui110
-rw-r--r--src/plugins/callgrind/callgrindconstants.h41
-rw-r--r--src/plugins/callgrind/callgrindcostdelegate.cpp185
-rw-r--r--src/plugins/callgrind/callgrindcostdelegate.h78
-rw-r--r--src/plugins/callgrind/callgrindcostview.cpp147
-rw-r--r--src/plugins/callgrind/callgrindcostview.h72
-rw-r--r--src/plugins/callgrind/callgrindengine.cpp173
-rw-r--r--src/plugins/callgrind/callgrindengine.h92
-rw-r--r--src/plugins/callgrind/callgrindhelper.cpp71
-rw-r--r--src/plugins/callgrind/callgrindhelper.h65
-rw-r--r--src/plugins/callgrind/callgrindnamedelegate.cpp92
-rw-r--r--src/plugins/callgrind/callgrindnamedelegate.h53
-rw-r--r--src/plugins/callgrind/callgrindplugin.cpp73
-rw-r--r--src/plugins/callgrind/callgrindplugin.h57
-rw-r--r--src/plugins/callgrind/callgrindsettings.cpp229
-rw-r--r--src/plugins/callgrind/callgrindsettings.h139
-rw-r--r--src/plugins/callgrind/callgrindtextmark.cpp108
-rw-r--r--src/plugins/callgrind/callgrindtextmark.h76
-rw-r--r--src/plugins/callgrind/callgrindtool.cpp506
-rw-r--r--src/plugins/callgrind/callgrindtool.h155
-rw-r--r--src/plugins/callgrind/callgrindvisualisation.cpp502
-rw-r--r--src/plugins/callgrind/callgrindvisualisation.h94
-rw-r--r--src/plugins/callgrind/callgrindwidgethandler.cpp499
-rw-r--r--src/plugins/callgrind/callgrindwidgethandler.h162
-rw-r--r--src/plugins/callgrind/workarounds.cpp51
-rw-r--r--src/plugins/callgrind/workarounds.h45
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeeditor.cpp42
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeeditor.h10
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeproject.cpp39
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeproject.h7
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp19
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectmanager.h5
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketarget.cpp10
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketarget.h2
-rw-r--r--src/plugins/coreplugin/actionmanager/actionmanager.cpp12
-rw-r--r--src/plugins/coreplugin/actionmanager/commandsfile.cpp126
-rw-r--r--src/plugins/coreplugin/basefilewizard.cpp135
-rw-r--r--src/plugins/coreplugin/basefilewizard.h53
-rw-r--r--src/plugins/coreplugin/coreconstants.h17
-rw-r--r--src/plugins/coreplugin/coreplugin.pro3
-rw-r--r--src/plugins/coreplugin/designmode.cpp44
-rw-r--r--src/plugins/coreplugin/designmode.h11
-rw-r--r--src/plugins/coreplugin/dialogs/iwizard.cpp2
-rw-r--r--src/plugins/coreplugin/editmode.cpp49
-rw-r--r--src/plugins/coreplugin/editmode.h9
-rw-r--r--src/plugins/coreplugin/editormanager/iexternaleditor.cpp5
-rw-r--r--src/plugins/coreplugin/externaltool.cpp1
-rw-r--r--src/plugins/coreplugin/fancyactionbar.h2
-rw-r--r--src/plugins/coreplugin/filemanager.cpp10
-rw-r--r--src/plugins/coreplugin/icontext.h37
-rw-r--r--src/plugins/coreplugin/icore.cpp17
-rw-r--r--src/plugins/coreplugin/imode.h30
-rw-r--r--src/plugins/coreplugin/mimedatabase.cpp244
-rw-r--r--src/plugins/coreplugin/mimedatabase.h23
-rw-r--r--src/plugins/coreplugin/modemanager.h4
-rw-r--r--src/plugins/coreplugin/navigationsubwidget.h1
-rw-r--r--src/plugins/coreplugin/outputpanemanager.h1
-rw-r--r--src/plugins/coreplugin/statusbarwidget.cpp27
-rw-r--r--src/plugins/coreplugin/statusbarwidget.h7
-rw-r--r--src/plugins/coreplugin/uniqueidmanager.cpp2
-rw-r--r--src/plugins/coreplugin/uniqueidmanager.h2
-rw-r--r--src/plugins/coreplugin/vcsmanager.cpp188
-rw-r--r--src/plugins/coreplugin/vcsmanager.h4
-rw-r--r--src/plugins/cppeditor/cppeditor.cpp7
-rw-r--r--src/plugins/cppeditor/cppeditor.h4
-rw-r--r--src/plugins/cppeditor/cppeditorconstants.h8
-rw-r--r--src/plugins/cpptools/cpptoolsconstants.h1
-rw-r--r--src/plugins/cvs/cvsconstants.h2
-rw-r--r--src/plugins/cvs/cvsplugin.cpp125
-rw-r--r--src/plugins/cvs/cvsplugin.h3
-rw-r--r--src/plugins/debugger/breakhandler.cpp16
-rw-r--r--src/plugins/debugger/breakhandler.h3
-rw-r--r--src/plugins/debugger/breakpoint.cpp47
-rw-r--r--src/plugins/debugger/breakpoint.h30
-rw-r--r--src/plugins/debugger/breakpointmarker.cpp15
-rw-r--r--src/plugins/debugger/breakpointmarker.h4
-rw-r--r--src/plugins/debugger/breakwindow.cpp16
-rw-r--r--src/plugins/debugger/cdb/cdbengine.cpp119
-rw-r--r--src/plugins/debugger/cdb/cdbengine.h6
-rw-r--r--src/plugins/debugger/cdb/cdbparsehelpers.cpp159
-rw-r--r--src/plugins/debugger/cdb/cdbparsehelpers.h3
-rw-r--r--src/plugins/debugger/commonoptionspage.cpp3
-rw-r--r--src/plugins/debugger/commonoptionspage.ui22
-rw-r--r--src/plugins/debugger/debugger.pro6
-rw-r--r--src/plugins/debugger/debuggeractions.cpp7
-rw-r--r--src/plugins/debugger/debuggeractions.h1
-rw-r--r--src/plugins/debugger/debuggerconstants.h7
-rw-r--r--src/plugins/debugger/debuggerengine.cpp36
-rw-r--r--src/plugins/debugger/debuggerengine.h2
-rw-r--r--src/plugins/debugger/debuggerplugin.cpp56
-rw-r--r--src/plugins/debugger/debuggerrunner.cpp52
-rw-r--r--src/plugins/debugger/debuggerrunner.h1
-rw-r--r--src/plugins/debugger/debuggersourcepathmappingwidget.cpp100
-rw-r--r--src/plugins/debugger/debuggerstreamops.cpp8
-rw-r--r--src/plugins/debugger/debuggertooltipmanager.cpp65
-rw-r--r--src/plugins/debugger/debuggertooltipmanager.h1
-rw-r--r--src/plugins/debugger/disassembleragent.cpp59
-rw-r--r--src/plugins/debugger/disassembleragent.h3
-rw-r--r--src/plugins/debugger/disassemblerlines.cpp120
-rw-r--r--src/plugins/debugger/disassemblerlines.h33
-rw-r--r--src/plugins/debugger/gdb/abstractgdbadapter.cpp4
-rw-r--r--src/plugins/debugger/gdb/abstractgdbadapter.h3
-rw-r--r--src/plugins/debugger/gdb/abstractplaingdbadapter.cpp5
-rw-r--r--src/plugins/debugger/gdb/abstractplaingdbadapter.h2
-rw-r--r--src/plugins/debugger/gdb/attachgdbadapter.cpp4
-rw-r--r--src/plugins/debugger/gdb/attachgdbadapter.h2
-rw-r--r--src/plugins/debugger/gdb/classicgdbengine.cpp698
-rw-r--r--src/plugins/debugger/gdb/coregdbadapter.cpp4
-rw-r--r--src/plugins/debugger/gdb/coregdbadapter.h2
-rw-r--r--src/plugins/debugger/gdb/gdbengine.cpp291
-rw-r--r--src/plugins/debugger/gdb/gdbengine.h126
-rw-r--r--src/plugins/debugger/gdb/localplaingdbadapter.cpp4
-rw-r--r--src/plugins/debugger/gdb/localplaingdbadapter.h2
-rw-r--r--src/plugins/debugger/gdb/pythongdbengine.cpp67
-rw-r--r--src/plugins/debugger/gdb/remotegdbprocess.cpp16
-rw-r--r--src/plugins/debugger/gdb/remotegdbserveradapter.cpp15
-rw-r--r--src/plugins/debugger/gdb/remotegdbserveradapter.h6
-rw-r--r--src/plugins/debugger/gdb/remoteplaingdbadapter.cpp4
-rw-r--r--src/plugins/debugger/gdb/remoteplaingdbadapter.h2
-rw-r--r--src/plugins/debugger/gdb/termgdbadapter.cpp4
-rw-r--r--src/plugins/debugger/gdb/termgdbadapter.h2
-rw-r--r--src/plugins/debugger/memoryagent.cpp82
-rw-r--r--src/plugins/debugger/memoryagent.h14
-rw-r--r--src/plugins/debugger/memoryviewwidget.cpp666
-rw-r--r--src/plugins/debugger/memoryviewwidget.h187
-rw-r--r--src/plugins/debugger/qml/qmladapter.cpp26
-rw-r--r--src/plugins/debugger/qml/qmlengine.cpp6
-rw-r--r--src/plugins/debugger/registerhandler.cpp37
-rw-r--r--src/plugins/debugger/registerhandler.h5
-rw-r--r--src/plugins/debugger/registerwindow.cpp48
-rw-r--r--src/plugins/debugger/registerwindow.h3
-rw-r--r--src/plugins/debugger/shared/shared.pri2
-rw-r--r--src/plugins/debugger/sourceagent.cpp18
-rw-r--r--src/plugins/debugger/watchdata.cpp54
-rw-r--r--src/plugins/debugger/watchdata.h3
-rw-r--r--src/plugins/debugger/watchhandler.cpp14
-rw-r--r--src/plugins/debugger/watchutils.cpp687
-rw-r--r--src/plugins/debugger/watchutils.h166
-rw-r--r--src/plugins/debugger/watchwindow.cpp282
-rw-r--r--src/plugins/debugger/watchwindow.h2
-rw-r--r--src/plugins/designer/designerconstants.h4
-rw-r--r--src/plugins/designer/designercontext.cpp21
-rw-r--r--src/plugins/designer/designercontext.h6
-rw-r--r--src/plugins/designer/formwindoweditor.cpp29
-rw-r--r--src/plugins/designer/formwindoweditor.h8
-rw-r--r--src/plugins/fakevim/fakevimhandler.cpp111
-rw-r--r--src/plugins/fakevim/fakevimhandler.h1
-rw-r--r--src/plugins/fakevim/fakevimplugin.cpp288
-rw-r--r--src/plugins/find/searchresultwindow.cpp4
-rw-r--r--src/plugins/find/textfindconstants.h2
-rw-r--r--src/plugins/genericprojectmanager/genericproject.cpp43
-rw-r--r--src/plugins/genericprojectmanager/genericprojectconstants.h6
-rw-r--r--src/plugins/genericprojectmanager/genericprojectfileseditor.cpp15
-rw-r--r--src/plugins/genericprojectmanager/genericprojectfileseditor.h8
-rw-r--r--src/plugins/genericprojectmanager/genericprojectmanager.cpp29
-rw-r--r--src/plugins/genericprojectmanager/genericprojectmanager.h7
-rw-r--r--src/plugins/genericprojectmanager/genericprojectnodes.cpp36
-rw-r--r--src/plugins/genericprojectmanager/genericprojectnodes.h7
-rw-r--r--src/plugins/genericprojectmanager/generictarget.cpp18
-rw-r--r--src/plugins/genericprojectmanager/generictarget.h4
-rw-r--r--src/plugins/git/gitclient.cpp4
-rw-r--r--src/plugins/git/gitclient.h2
-rw-r--r--src/plugins/git/gitconstants.h1
-rw-r--r--src/plugins/glsleditor/glsleditor.cpp5
-rw-r--r--src/plugins/glsleditor/glsleditor.h2
-rw-r--r--src/plugins/glsleditor/glsleditorconstants.h3
-rw-r--r--src/plugins/glsleditor/glsleditoreditable.cpp4
-rw-r--r--src/plugins/glsleditor/glsleditoreditable.h6
-rw-r--r--src/plugins/helloworld/helloworldplugin.cpp24
-rw-r--r--src/plugins/help/helpmode.cpp29
-rw-r--r--src/plugins/help/helpmode.h14
-rw-r--r--src/plugins/help/helpplugin.cpp7
-rw-r--r--src/plugins/imageviewer/imageviewer.cpp19
-rw-r--r--src/plugins/imageviewer/imageviewer.h3
-rw-r--r--src/plugins/macros/macrosconstants.h1
-rw-r--r--src/plugins/memcheck/memcheckconfigwidget.cpp2
-rw-r--r--src/plugins/memcheck/memcheckconfigwidget.h8
-rw-r--r--src/plugins/memcheck/memcheckconfigwidget.ui8
-rw-r--r--src/plugins/memcheck/memcheckengine.cpp10
-rw-r--r--src/plugins/memcheck/memcheckengine.h18
-rw-r--r--src/plugins/memcheck/memcheckerrorview.cpp16
-rw-r--r--src/plugins/memcheck/memcheckerrorview.h18
-rw-r--r--src/plugins/memcheck/memcheckplugin.cpp4
-rw-r--r--src/plugins/memcheck/memcheckplugin.h4
-rw-r--r--src/plugins/memcheck/memchecksettings.cpp6
-rw-r--r--src/plugins/memcheck/memchecksettings.h4
-rw-r--r--src/plugins/memcheck/memchecktool.cpp55
-rw-r--r--src/plugins/memcheck/memchecktool.h28
-rw-r--r--src/plugins/memcheck/suppressiondialog.cpp6
-rw-r--r--src/plugins/memcheck/suppressiondialog.h18
-rw-r--r--src/plugins/memcheck/suppressiondialog.ui8
-rw-r--r--src/plugins/mercurial/constants.h24
-rw-r--r--src/plugins/mercurial/mercurialclient.cpp96
-rw-r--r--src/plugins/mercurial/mercurialclient.h54
-rw-r--r--src/plugins/mercurial/mercurialeditor.cpp20
-rw-r--r--src/plugins/perforce/perforceconstants.h2
-rw-r--r--src/plugins/perforce/perforceplugin.cpp98
-rw-r--r--src/plugins/perforce/perforceplugin.h3
-rw-r--r--src/plugins/plugins.pro15
-rw-r--r--src/plugins/projectexplorer/abi.cpp23
-rw-r--r--src/plugins/projectexplorer/abstractprocessstep.cpp8
-rw-r--r--src/plugins/projectexplorer/buildmanager.cpp50
-rw-r--r--src/plugins/projectexplorer/buildmanager.h4
-rw-r--r--src/plugins/projectexplorer/buildstep.h6
-rw-r--r--src/plugins/projectexplorer/doubletabwidget.cpp161
-rw-r--r--src/plugins/projectexplorer/doubletabwidget.h15
-rw-r--r--src/plugins/projectexplorer/environmentwidget.cpp14
-rw-r--r--src/plugins/projectexplorer/environmentwidget.h1
-rw-r--r--src/plugins/projectexplorer/gccparser.cpp15
-rw-r--r--src/plugins/projectexplorer/gcctoolchain.cpp27
-rw-r--r--src/plugins/projectexplorer/gcctoolchainfactories.h1
-rw-r--r--src/plugins/projectexplorer/iprojectmanager.h3
-rw-r--r--src/plugins/projectexplorer/localapplicationruncontrol.cpp9
-rw-r--r--src/plugins/projectexplorer/localapplicationruncontrol.h1
-rw-r--r--src/plugins/projectexplorer/miniprojecttargetselector.cpp50
-rw-r--r--src/plugins/projectexplorer/miniprojecttargetselector.h1
-rw-r--r--src/plugins/projectexplorer/outputwindow.cpp28
-rw-r--r--src/plugins/projectexplorer/outputwindow.h5
-rw-r--r--src/plugins/projectexplorer/persistentsettings.cpp439
-rw-r--r--src/plugins/projectexplorer/persistentsettings.h9
-rw-r--r--src/plugins/projectexplorer/project.cpp26
-rw-r--r--src/plugins/projectexplorer/project.h8
-rw-r--r--src/plugins/projectexplorer/projectexplorer.cpp58
-rw-r--r--src/plugins/projectexplorer/projectexplorer.h2
-rw-r--r--src/plugins/projectexplorer/projectexplorer.pro3
-rw-r--r--src/plugins/projectexplorer/projectexplorerconstants.h30
-rw-r--r--src/plugins/projectexplorer/projecttreewidget.cpp58
-rw-r--r--src/plugins/projectexplorer/projecttreewidget.h7
-rw-r--r--src/plugins/projectexplorer/projectwindow.cpp2
-rw-r--r--src/plugins/projectexplorer/runconfiguration.h5
-rw-r--r--src/plugins/projectexplorer/runsettingspropertiespage.cpp7
-rw-r--r--src/plugins/projectexplorer/session.cpp6
-rw-r--r--src/plugins/projectexplorer/session.h1
-rw-r--r--src/plugins/projectexplorer/target.cpp48
-rw-r--r--src/plugins/projectexplorer/target.h4
-rw-r--r--src/plugins/projectexplorer/taskwindow.cpp22
-rw-r--r--src/plugins/projectexplorer/toolchainconfigwidget.cpp6
-rw-r--r--src/plugins/projectexplorer/toolchainconfigwidget.h2
-rw-r--r--src/plugins/projectexplorer/toolchainmanager.cpp13
-rw-r--r--src/plugins/projectexplorer/toolchainmanager.h4
-rw-r--r--src/plugins/projectexplorer/toolchainoptionspage.cpp24
-rw-r--r--src/plugins/projectexplorer/userfileaccessor.cpp68
-rw-r--r--src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp1
-rw-r--r--src/plugins/qmldesigner/designmodecontext.cpp50
-rw-r--r--src/plugins/qmldesigner/designmodecontext.h32
-rw-r--r--src/plugins/qmldesigner/qmldesignerconstants.h8
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.h4
-rw-r--r--src/plugins/qmljseditor/qmljseditor.cpp5
-rw-r--r--src/plugins/qmljseditor/qmljseditorconstants.h1
-rw-r--r--src/plugins/qmljseditor/qmljseditoreditable.h5
-rw-r--r--src/plugins/qmljsinspector/qmljsinspectorconstants.h10
-rw-r--r--src/plugins/qmlprofiler/QmlProfiler.pluginspec.in20
-rw-r--r--src/plugins/qmlprofiler/canvas/canvas.pri11
-rw-r--r--src/plugins/qmlprofiler/canvas/qdeclarativecanvas.cpp257
-rw-r--r--src/plugins/qmlprofiler/canvas/qdeclarativecanvas_p.h124
-rw-r--r--src/plugins/qmlprofiler/canvas/qdeclarativecanvastimer.cpp98
-rw-r--r--src/plugins/qmlprofiler/canvas/qdeclarativecanvastimer_p.h80
-rw-r--r--src/plugins/qmlprofiler/canvas/qdeclarativecontext2d.cpp1139
-rw-r--r--src/plugins/qmlprofiler/canvas/qdeclarativecontext2d_p.h336
-rw-r--r--src/plugins/qmlprofiler/canvas/qdeclarativetiledcanvas.cpp164
-rw-r--r--src/plugins/qmlprofiler/canvas/qdeclarativetiledcanvas_p.h102
-rw-r--r--src/plugins/qmlprofiler/qml/Detail.qml67
-rw-r--r--src/plugins/qmlprofiler/qml/Label.qml56
-rw-r--r--src/plugins/qmlprofiler/qml/MainView.js149
-rw-r--r--src/plugins/qmlprofiler/qml/MainView.qml321
-rw-r--r--src/plugins/qmlprofiler/qml/RangeDetails.qml94
-rw-r--r--src/plugins/qmlprofiler/qml/RangeMover.qml95
-rw-r--r--src/plugins/qmlprofiler/qml/RecordButton.qml86
-rw-r--r--src/plugins/qmlprofiler/qml/ToolButton.qml60
-rw-r--r--src/plugins/qmlprofiler/qml/analyzer_category_small.pngbin0 -> 705 bytes
-rw-r--r--src/plugins/qmlprofiler/qml/lock.pngbin0 -> 265 bytes
-rw-r--r--src/plugins/qmlprofiler/qml/popup.pngbin0 -> 1538 bytes
-rw-r--r--src/plugins/qmlprofiler/qml/qml.qrc16
-rw-r--r--src/plugins/qmlprofiler/qml/range.pngbin0 -> 442 bytes
-rw-r--r--src/plugins/qmlprofiler/qmlprofiler.pro54
-rw-r--r--src/plugins/qmlprofiler/qmlprofiler_global.h46
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerattachdialog.cpp40
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerattachdialog.h34
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerattachdialog.ui109
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerconstants.h45
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerengine.cpp198
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerengine.h71
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerplugin.cpp129
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerplugin.h71
-rw-r--r--src/plugins/qmlprofiler/qmlprofilersummaryview.cpp277
-rw-r--r--src/plugins/qmlprofiler/qmlprofilersummaryview.h79
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertool.cpp416
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertool.h101
-rw-r--r--src/plugins/qmlprofiler/qmlprojectanalyzerruncontrolfactory.cpp123
-rw-r--r--src/plugins/qmlprofiler/qmlprojectanalyzerruncontrolfactory.h69
-rw-r--r--src/plugins/qmlprofiler/timelineview.cpp238
-rw-r--r--src/plugins/qmlprofiler/timelineview.h150
-rw-r--r--src/plugins/qmlprofiler/tracewindow.cpp345
-rw-r--r--src/plugins/qmlprofiler/tracewindow.h94
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.cpp4
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectconstants.h10
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectmanager.cpp11
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectmanager.h6
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectmanagerconstants.h1
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp11
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectruncontrol.h1
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojecttarget.cpp5
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojecttarget.h1
-rw-r--r--src/plugins/qt4projectmanager/profileeditor.cpp36
-rw-r--r--src/plugins/qt4projectmanager/profileeditor.h6
-rw-r--r--src/plugins/qt4projectmanager/qmakestep.cpp21
-rw-r--r--src/plugins/qt4projectmanager/qt-desktop/qt4desktoptarget.cpp8
-rw-r--r--src/plugins/qt4projectmanager/qt-desktop/qt4desktoptarget.h2
-rw-r--r--src/plugins/qt4projectmanager/qt-desktop/qt4desktoptargetfactory.cpp45
-rw-r--r--src/plugins/qt4projectmanager/qt-desktop/qt4desktoptargetfactory.h3
-rw-r--r--src/plugins/qt4projectmanager/qt-desktop/qt4simulatortarget.cpp8
-rw-r--r--src/plugins/qt4projectmanager/qt-desktop/qt4simulatortarget.h2
-rw-r--r--src/plugins/qt4projectmanager/qt-desktop/qt4simulatortargetfactory.cpp38
-rw-r--r--src/plugins/qt4projectmanager/qt-desktop/qt4simulatortargetfactory.h3
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/abstractmaemodeploystep.cpp458
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/abstractmaemodeploystep.h142
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoanalyzersupport.cpp76
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoanalyzersupport.h51
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.cpp51
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.h1
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoconstants.h2
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.cpp7
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeployable.h2
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeployables.cpp4
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeployables.h6
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeploybymountstep.cpp389
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeploybymountstep.h145
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeployconfigurationwidget.cpp174
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeployconfigurationwidget.h68
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeployconfigurationwidget.ui130
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeploymentmounter.cpp204
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeploymentmounter.h100
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.cpp1061
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.h73
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeploystepfactory.cpp125
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.cpp152
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.h13
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.ui149
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.cpp99
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.h40
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurationssettingswidget.cpp2
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigwizard.cpp169
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigwizardlogindatapage.ui156
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigwizardstartpage.ui40
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodirectdeviceuploadstep.cpp217
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemodirectdeviceuploadstep.h62
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoglobal.cpp83
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoglobal.h40
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoinstalltosysrootstep.cpp336
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoinstalltosysrootstep.h120
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp7
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemomanager.h2
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationfactory.cpp85
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.cpp863
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.h129
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.cpp41
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.h7
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.ui65
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopackageinstaller.cpp214
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopackageinstaller.h133
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopackageuploader.cpp159
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopackageuploader.h88
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopertargetdeviceconfigurationlistmodel.cpp21
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopertargetdeviceconfigurationlistmodel.h5
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemopublisherfremantlefree.cpp18
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoqemuruntimeparser.cpp3
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoremotecopyfacility.cpp156
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoremotecopyfacility.h88
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoremotemounter.cpp13
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp47
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h8
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.cpp9
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp14
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.h1
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemorunfactories.cpp10
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.cpp14
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.cpp4
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemouploadandinstalldeploystep.cpp278
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemouploadandinstalldeploystep.h132
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemousedportsgatherer.cpp2
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/qt-maemo.pri32
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/qt4maemodeployconfiguration.cpp193
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/qt4maemodeployconfiguration.h47
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/qt4maemotarget.cpp29
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/qt4maemotarget.h9
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/qt4maemotargetfactory.cpp62
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/qt4maemotargetfactory.h5
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/codaruncontrol.cpp38
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/codaruncontrol.h1
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.cpp14
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.h4
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/qt4symbiantargetfactory.cpp37
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/qt4symbiantargetfactory.h2
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.cpp8
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.h1
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp4
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp52
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60deploystep.h8
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp15
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp30
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h5
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp11
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h1
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60manager.cpp2
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60publisherovi.cpp40
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60publisherovi.h1
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60runcontrolbase.cpp4
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60runcontrolbase.h1
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/trkruncontrol.cpp21
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/trkruncontrol.h1
-rw-r--r--src/plugins/qt4projectmanager/qt4basetargetfactory.h10
-rw-r--r--src/plugins/qt4projectmanager/qt4buildconfiguration.cpp24
-rw-r--r--src/plugins/qt4projectmanager/qt4buildconfiguration.h1
-rw-r--r--src/plugins/qt4projectmanager/qt4project.cpp18
-rw-r--r--src/plugins/qt4projectmanager/qt4project.h3
-rw-r--r--src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp3
-rw-r--r--src/plugins/qt4projectmanager/qt4projectmanager.cpp58
-rw-r--r--src/plugins/qt4projectmanager/qt4projectmanager.h7
-rw-r--r--src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri1
-rw-r--r--src/plugins/qt4projectmanager/qt4projectmanagerconstants.h22
-rw-r--r--src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp58
-rw-r--r--src/plugins/qt4projectmanager/qt4projectmanagerplugin.h6
-rw-r--r--src/plugins/qt4projectmanager/qt4target.cpp332
-rw-r--r--src/plugins/qt4projectmanager/qt4target.h28
-rw-r--r--src/plugins/qt4projectmanager/qtoptionspage.cpp58
-rw-r--r--src/plugins/qt4projectmanager/qtoptionspage.h5
-rw-r--r--src/plugins/qt4projectmanager/qtversionmanager.cpp10
-rw-r--r--src/plugins/qt4projectmanager/qtversionmanager.ui7
-rw-r--r--src/plugins/qt4projectmanager/wizards/qtquickapp.h7
-rw-r--r--src/plugins/qt4projectmanager/wizards/targetsetuppage.ui6
-rw-r--r--src/plugins/resourceeditor/resourceeditorfactory.cpp4
-rw-r--r--src/plugins/resourceeditor/resourceeditorfactory.h2
-rw-r--r--src/plugins/resourceeditor/resourceeditorw.cpp11
-rw-r--r--src/plugins/resourceeditor/resourceeditorw.h5
-rw-r--r--src/plugins/subversion/subversionconstants.h3
-rw-r--r--src/plugins/subversion/subversionplugin.cpp139
-rw-r--r--src/plugins/subversion/subversionplugin.h2
-rw-r--r--src/plugins/texteditor/basetextdocument.cpp32
-rw-r--r--src/plugins/texteditor/basetextdocumentlayout.cpp1
-rw-r--r--src/plugins/texteditor/basetextdocumentlayout.h1
-rw-r--r--src/plugins/texteditor/basetexteditor.cpp88
-rw-r--r--src/plugins/texteditor/basetexteditor.h4
-rw-r--r--src/plugins/texteditor/basetextmark.cpp105
-rw-r--r--src/plugins/texteditor/basetextmark.h36
-rw-r--r--src/plugins/texteditor/itexteditor.cpp42
-rw-r--r--src/plugins/texteditor/itexteditor.h35
-rw-r--r--src/plugins/texteditor/plaintexteditor.cpp13
-rw-r--r--src/plugins/texteditor/plaintexteditor.h5
-rw-r--r--src/plugins/texteditor/snippets/snippeteditor.cpp15
-rw-r--r--src/plugins/texteditor/snippets/snippeteditor.h7
-rw-r--r--src/plugins/texteditor/texteditoractionhandler.cpp7
-rw-r--r--src/plugins/texteditor/texteditoractionhandler.h2
-rw-r--r--src/plugins/texteditor/texteditorconstants.h29
-rw-r--r--src/plugins/valgrindtoolbase/valgrindconfigwidget.cpp2
-rw-r--r--src/plugins/valgrindtoolbase/valgrindconfigwidget.h9
-rw-r--r--src/plugins/valgrindtoolbase/valgrindconfigwidget.ui6
-rw-r--r--src/plugins/valgrindtoolbase/valgrindengine.cpp47
-rw-r--r--src/plugins/valgrindtoolbase/valgrindengine.h18
-rw-r--r--src/plugins/valgrindtoolbase/valgrindsettings.cpp2
-rw-r--r--src/plugins/valgrindtoolbase/valgrindsettings.h4
-rw-r--r--src/plugins/valgrindtoolbase/valgrindtoolbaseplugin.cpp2
-rw-r--r--src/plugins/valgrindtoolbase/valgrindtoolbaseplugin.h2
-rw-r--r--src/plugins/vcsbase/baseannotationhighlighter.cpp13
-rw-r--r--src/plugins/vcsbase/baseannotationhighlighter.h6
-rw-r--r--src/plugins/vcsbase/basecheckoutwizard.cpp21
-rw-r--r--src/plugins/vcsbase/basecheckoutwizard.h14
-rw-r--r--src/plugins/vcsbase/basecheckoutwizardpage.cpp12
-rw-r--r--src/plugins/vcsbase/basecheckoutwizardpage.h5
-rw-r--r--src/plugins/vcsbase/basevcseditorfactory.cpp8
-rw-r--r--src/plugins/vcsbase/basevcseditorfactory.h2
-rw-r--r--src/plugins/vcsbase/checkoutjobs.cpp16
-rw-r--r--src/plugins/vcsbase/checkoutjobs.h2
-rw-r--r--src/plugins/vcsbase/checkoutprogresswizardpage.cpp9
-rw-r--r--src/plugins/vcsbase/checkoutprogresswizardpage.h3
-rw-r--r--src/plugins/vcsbase/checkoutwizarddialog.cpp7
-rw-r--r--src/plugins/vcsbase/checkoutwizarddialog.h4
-rw-r--r--src/plugins/vcsbase/cleandialog.cpp11
-rw-r--r--src/plugins/vcsbase/cleandialog.h5
-rw-r--r--src/plugins/vcsbase/commonsettingspage.cpp6
-rw-r--r--src/plugins/vcsbase/commonsettingspage.ui56
-rw-r--r--src/plugins/vcsbase/commonvcssettings.cpp9
-rw-r--r--src/plugins/vcsbase/commonvcssettings.h2
-rw-r--r--src/plugins/vcsbase/corelistener.cpp11
-rw-r--r--src/plugins/vcsbase/corelistener.h9
-rw-r--r--src/plugins/vcsbase/diffhighlighter.cpp28
-rw-r--r--src/plugins/vcsbase/diffhighlighter.h15
-rw-r--r--src/plugins/vcsbase/nicknamedialog.cpp12
-rw-r--r--src/plugins/vcsbase/nicknamedialog.h6
-rw-r--r--src/plugins/vcsbase/submiteditorfile.cpp6
-rw-r--r--src/plugins/vcsbase/submiteditorfile.h1
-rw-r--r--src/plugins/vcsbase/submitfilemodel.cpp7
-rw-r--r--src/plugins/vcsbase/submitfilemodel.h3
-rw-r--r--src/plugins/vcsbase/vcsbase.pro6
-rw-r--r--src/plugins/vcsbase/vcsbaseclient.cpp26
-rw-r--r--src/plugins/vcsbase/vcsbaseclient.h8
-rw-r--r--src/plugins/vcsbase/vcsbaseclientsettings.cpp8
-rw-r--r--src/plugins/vcsbase/vcsbaseeditor.cpp257
-rw-r--r--src/plugins/vcsbase/vcsbaseeditor.h52
-rw-r--r--src/plugins/vcsbase/vcsbaseeditorparameterwidget.cpp192
-rw-r--r--src/plugins/vcsbase/vcsbaseeditorparameterwidget.h80
-rw-r--r--src/plugins/vcsbase/vcsbaseoptionspage.cpp6
-rw-r--r--src/plugins/vcsbase/vcsbaseoptionspage.h3
-rw-r--r--src/plugins/vcsbase/vcsbaseoutputwindow.cpp15
-rw-r--r--src/plugins/vcsbase/vcsbaseoutputwindow.h9
-rw-r--r--src/plugins/vcsbase/vcsbaseplugin.cpp124
-rw-r--r--src/plugins/vcsbase/vcsbaseplugin.h33
-rw-r--r--src/plugins/vcsbase/vcsbasesubmiteditor.cpp51
-rw-r--r--src/plugins/vcsbase/vcsbasesubmiteditor.h25
-rw-r--r--src/plugins/vcsbase/vcsjobrunner.cpp21
-rw-r--r--src/plugins/vcsbase/vcsjobrunner.h2
-rw-r--r--src/plugins/welcome/welcome.pro7
-rw-r--r--src/plugins/welcome/welcomemode.cpp252
-rw-r--r--src/plugins/welcome/welcomemode.h85
-rw-r--r--src/plugins/welcome/welcomeplugin.cpp219
-rw-r--r--src/plugins/welcome/welcomeplugin.h6
559 files changed, 25651 insertions, 7027 deletions
diff --git a/src/plugins/analyzerbase/analyzerbase.pro b/src/plugins/analyzerbase/analyzerbase.pro
index d224a2518b..e34290af95 100644
--- a/src/plugins/analyzerbase/analyzerbase.pro
+++ b/src/plugins/analyzerbase/analyzerbase.pro
@@ -12,27 +12,38 @@ QT += network
SOURCES += \
ianalyzerengine.cpp \
+ ianalyzeroutputpaneadapter.cpp \
ianalyzertool.cpp \
analyzerplugin.cpp \
analyzerruncontrol.cpp \
+ analyzerruncontrolfactory.cpp \
analyzermanager.cpp \
analyzersettings.cpp \
analyzeroptionspage.cpp \
analyzerrunconfigwidget.cpp \
- analyzeroutputpane.cpp
+ analyzeroutputpane.cpp \
+ analyzerutils.cpp \
+ startremotedialog.cpp
HEADERS += \
ianalyzerengine.h \
+ ianalyzeroutputpaneadapter.h \
ianalyzertool.h \
analyzerbase_global.h \
analyzerconstants.h \
analyzerplugin.h \
analyzerruncontrol.h \
+ analyzerruncontrolfactory.h \
analyzermanager.h \
analyzersettings.h \
analyzeroptionspage.h \
analyzerrunconfigwidget.h \
- analyzeroutputpane.h
+ analyzeroutputpane.h \
+ analyzerutils.h \
+ startremotedialog.h
+
+FORMS += \
+ startremotedialog.ui
RESOURCES += \
analyzerbase.qrc
diff --git a/src/plugins/analyzerbase/analyzerbase_dependencies.pri b/src/plugins/analyzerbase/analyzerbase_dependencies.pri
index a3a44bbdaa..010452d61f 100644
--- a/src/plugins/analyzerbase/analyzerbase_dependencies.pri
+++ b/src/plugins/analyzerbase/analyzerbase_dependencies.pri
@@ -1,2 +1,3 @@
include(../../plugins/coreplugin/coreplugin.pri)
-include(../../plugins/projectexplorer/projectexplorer.pri) \ No newline at end of file
+include(../../libs/cplusplus/cplusplus.pri)
+include(../../plugins/projectexplorer/projectexplorer.pri)
diff --git a/src/plugins/analyzerbase/analyzerconstants.h b/src/plugins/analyzerbase/analyzerconstants.h
index 804333e0b9..01171b35bf 100644
--- a/src/plugins/analyzerbase/analyzerconstants.h
+++ b/src/plugins/analyzerbase/analyzerconstants.h
@@ -38,6 +38,13 @@
#include <QtCore/QtGlobal>
namespace Analyzer {
+
+enum AnalyzerStartMode
+{
+ StartLocal,
+ StartRemote
+};
+
namespace Constants {
// modes and their priorities
@@ -48,10 +55,16 @@ const int P_MODE_ANALYZE = 76;
const char * const C_ANALYZEMODE = "Analyzer.AnalyzeMode";
// menu
-const char * const M_TOOLS_ANALYZER = "Analyzer.Tools.Menu";
+const char * const M_DEBUG_ANALYZER = "Analyzer.Menu.StartAnalyzer";
+
+const char * const G_ANALYZER_STARTSTOP = "Menu.Group.Analyzer.StartStop";
+const char * const G_ANALYZER_TOOLS = "Menu.Group.Analyzer.Tools";
const char * const START = "Analyzer.Start";
+const char * const STARTREMOTE = "Analyzer.StartRemote";
const char * const STOP = "Analyzer.Stop";
+const char * const ANALYZER_TOOLS = "Menu.Action.Analyzer.Tools.";
+const char * const ANALYZER_TOOLS_SEPARATOR = "Menu.Action.Analyzer.Tools.Separator";
// options dialog
const char * const ANALYZER_SETTINGS_CATEGORY = "T.Analyzer";
@@ -60,8 +73,17 @@ const char * const ANALYZER_SETTINGS_TR_CATEGORY =
const char * const ANALYZER_SETTINGS_CATEGORY_ICON =
":/images/analyzer_category.png";
+// manager controls
+const char * const ANALYZER_CONTROL_START_ICON =
+ ":/images/analyzer_start_small.png";
+const char * const ANALYZER_CONTROL_STOP_ICON =
+ ":/debugger/images/debugger_stop_small.png";
+
const char * const ANALYZERTASK_ID = "Analyzer.TaskId";
+// private
+const char * const ANALYZER_DUMMYWIDGET_ID = "Analyzer.DummyWidget";
+
} // namespace Constants
} // namespace Analyzer
diff --git a/src/plugins/analyzerbase/analyzermanager.cpp b/src/plugins/analyzerbase/analyzermanager.cpp
index 018e1eb808..c20d31b349 100644
--- a/src/plugins/analyzerbase/analyzermanager.cpp
+++ b/src/plugins/analyzerbase/analyzermanager.cpp
@@ -33,13 +33,17 @@
**************************************************************************/
#include "analyzermanager.h"
-#include "analyzerconstants.h"
-#include "ianalyzertool.h"
+#include "analyzerconstants.h"
#include "analyzerplugin.h"
#include "analyzerruncontrol.h"
+#include "analyzerruncontrolfactory.h"
#include "analyzeroptionspage.h"
#include "analyzeroutputpane.h"
+#include "analyzerstartparameters.h"
+#include "analyzerutils.h"
+#include "ianalyzertool.h"
+#include "startremotedialog.h"
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/findplaceholder.h>
@@ -71,6 +75,7 @@
#include <utils/qtcassert.h>
#include <utils/checkablemessagebox.h>
#include <utils/statuslabel.h>
+#include <utils/ssh/sshconnection.h>
#include <cmakeprojectmanager/cmakeprojectconstants.h>
#include <qt4projectmanager/qt4projectmanagerconstants.h>
@@ -92,16 +97,12 @@
#include <QtGui/QCheckBox>
#include <QtGui/QDialogButtonBox>
#include <QtGui/QMainWindow>
+#include <QtGui/QPushButton>
using namespace Core;
using namespace Analyzer;
using namespace Analyzer::Internal;
-// A separate 'Analzye' mode is not used in Qt Creator 2.2.
-// Consider re-introducing it if a real use case for a separate main window with docks
-// appears.
-enum { useAnalyzeMode = 0 };
-
namespace Analyzer {
namespace Internal {
@@ -141,8 +142,17 @@ class AnalyzerMode : public Core::IMode
public:
AnalyzerMode(QObject *parent = 0)
: Core::IMode(parent)
- , m_widget(0)
- {}
+ {
+ setContext(Core::Context(
+ Core::Constants::C_EDITORMANAGER,
+ Constants::C_ANALYZEMODE,
+ Core::Constants::C_NAVIGATION_PANE));
+ setDisplayName(tr("Analyze"));
+ setIcon(QIcon(":/images/analyzer_mode.png"));
+ setPriority(Constants::P_MODE_ANALYZE);
+ setId(QLatin1String(Constants::MODE_ANALYZE));
+ setType(Core::Constants::MODE_EDIT_TYPE);
+ }
~AnalyzerMode()
{
@@ -153,23 +163,6 @@ public:
}
Core::EditorManager::instance()->setParent(0);
}
-
- QString displayName() const { return tr("Analyze"); }
- QIcon icon() const { return QIcon(":/images/analyzer_mode.png"); }
- int priority() const { return Constants::P_MODE_ANALYZE; }
- QWidget *widget() { return m_widget; }
- QString id() const { return QLatin1String(Constants::MODE_ANALYZE); }
- QString type() const { return Core::Constants::MODE_EDIT_TYPE; }
- Core::Context context() const
- {
- return Core::Context(Core::Constants::C_EDITORMANAGER, Constants::C_ANALYZEMODE,
- Core::Constants::C_NAVIGATION_PANE);
- }
- QString contextHelpId() const { return QString(); }
- void setWidget(QWidget *widget) { m_widget = widget; }
-
-private:
- QWidget *m_widget;
};
} // namespace Internal
@@ -193,6 +186,10 @@ public:
void setupActions();
QWidget *createModeContents();
QWidget *createModeMainWindow();
+ bool showPromptDialog(const QString &title,
+ const QString &text,
+ const QString &stopButtonText,
+ const QString &cancelButtonText) const;
void addDock(IAnalyzerTool *tool, Qt::DockWidgetArea area, QDockWidget *dockWidget);
void startTool();
@@ -203,17 +200,19 @@ public:
AnalyzerRunControlFactory *m_runControlFactory;
ProjectExplorer::RunControl *m_currentRunControl;
Utils::FancyMainWindow *m_mainWindow;
- QList<IAnalyzerTool*> m_tools;
+ QList<IAnalyzerTool *> m_tools;
QActionGroup *m_toolGroup;
QAction *m_startAction;
+ QAction *m_startRemoteAction;
QAction *m_stopAction;
- QMenu *m_menu;
+ ActionContainer *m_menu;
QComboBox *m_toolBox;
+ QStackedWidget *m_controlsWidget;
ActionContainer *m_viewsMenu;
Utils::StatusLabel *m_statusLabel;
- typedef QPair<Qt::DockWidgetArea, QDockWidget*> ToolWidgetPair;
+ typedef QPair<Qt::DockWidgetArea, QDockWidget *> ToolWidgetPair;
typedef QList<ToolWidgetPair> ToolWidgetPairList;
- QMap<IAnalyzerTool*, ToolWidgetPairList> m_toolWidgets;
+ QMap<IAnalyzerTool *, ToolWidgetPairList> m_toolWidgets;
DockWidgetEventFilter *m_resizeEventFilter;
QMap<IAnalyzerTool *, QSettings *> m_defaultSettings;
@@ -221,6 +220,7 @@ public:
typedef QWeakPointer<QDockWidget> DockPtr;
QList<DockPtr> m_dockWidgets;
+ bool m_restartOnStop;
bool m_initialized;
};
@@ -233,19 +233,21 @@ AnalyzerManager::AnalyzerManagerPrivate::AnalyzerManagerPrivate(AnalyzerManager
m_mainWindow(0),
m_toolGroup(0),
m_startAction(0),
+ m_startRemoteAction(0),
m_stopAction(0),
m_menu(0),
m_toolBox(new QComboBox),
+ m_controlsWidget(new QStackedWidget),
m_viewsMenu(0),
m_statusLabel(new Utils::StatusLabel),
m_resizeEventFilter(new DockWidgetEventFilter(qq)),
+ m_restartOnStop(false),
m_initialized(false)
{
m_toolBox->setObjectName(QLatin1String("AnalyzerManagerToolBox"));
m_runControlFactory = new AnalyzerRunControlFactory();
- AnalyzerPlugin::instance()->addAutoReleasedObject(m_runControlFactory);
- connect(m_runControlFactory, SIGNAL(runControlCreated(Analyzer::Internal::AnalyzerRunControl *)),
- q, SLOT(runControlCreated(Analyzer::Internal::AnalyzerRunControl *)));
+
+ q->registerRunControlFactory(m_runControlFactory);
connect(m_toolBox, SIGNAL(currentIndexChanged(int)),
q, SLOT(toolSelected(int)));
@@ -263,40 +265,69 @@ AnalyzerManager::AnalyzerManagerPrivate::~AnalyzerManagerPrivate()
}
}
+void AnalyzerManager::registerRunControlFactory(ProjectExplorer::IRunControlFactory *factory)
+{
+ AnalyzerPlugin::instance()->addAutoReleasedObject(factory);
+ connect(factory, SIGNAL(runControlCreated(Analyzer::AnalyzerRunControl *)),
+ this, SLOT(runControlCreated(Analyzer::AnalyzerRunControl *)));
+}
+
void AnalyzerManager::AnalyzerManagerPrivate::setupActions()
{
Core::ICore *core = Core::ICore::instance();
Core::ActionManager *am = core->actionManager();
Core::ActionContainer *mtools = am->actionContainer(ProjectExplorer::Constants::M_DEBUG);
- Core::ActionContainer *mAnalyzermenu = am->createMenu(Constants::M_TOOLS_ANALYZER);
+ m_menu = am->createMenu(Constants::M_DEBUG_ANALYZER);
+
+ const Core::Context globalcontext(Core::Constants::C_GLOBAL);
+ Core::Command *command = 0;
+
+ // add separator before Analyzer menu
+ QAction *act = new QAction(m_menu);
+ act->setSeparator(true);
+ command = am->registerAction(act, "Analyzer.Action.Sep", globalcontext);
+ mtools->addAction(command);
// Menus
- m_menu = mAnalyzermenu->menu();
- m_menu->setTitle(tr("Start &Analyzer"));
- m_menu->setEnabled(true);
- mtools->addMenu(mAnalyzermenu);
+ m_menu->menu()->setTitle(tr("Start &Analyzer"));
+ m_menu->menu()->setEnabled(true);
+
+ m_menu->appendGroup(Constants::G_ANALYZER_STARTSTOP);
+ m_menu->appendGroup(Constants::G_ANALYZER_TOOLS);
+
+ mtools->addMenu(m_menu);
m_toolGroup = new QActionGroup(m_menu);
connect(m_toolGroup, SIGNAL(triggered(QAction*)),
q, SLOT(toolSelected(QAction*)));
- const Core::Context globalcontext(Core::Constants::C_GLOBAL);
-
m_startAction = new QAction(tr("Start"), m_menu);
- m_startAction->setIcon(QIcon(QLatin1String(":/images/analyzer_start_small.png")));
- Core::Command *command = am->registerAction(m_startAction,
+ m_startAction->setIcon(QIcon(Constants::ANALYZER_CONTROL_START_ICON));
+ command = am->registerAction(m_startAction,
Constants::START, globalcontext);
- mAnalyzermenu->addAction(command);
+ m_menu->addAction(command, Constants::G_ANALYZER_STARTSTOP);
connect(m_startAction, SIGNAL(triggered()), q, SLOT(startTool()));
+ m_startRemoteAction = new QAction(tr("Start Remote"), m_menu);
+ ///FIXME: get an icon for this
+// m_startRemoteAction->setIcon(QIcon(QLatin1String(":/images/analyzer_start_remote_small.png")));
+ command = am->registerAction(m_startRemoteAction,
+ Constants::STARTREMOTE, globalcontext);
+ m_menu->addAction(command, Constants::G_ANALYZER_STARTSTOP);
+ connect(m_startRemoteAction, SIGNAL(triggered()), q, SLOT(startToolRemote()));
+
m_stopAction = new QAction(tr("Stop"), m_menu);
m_stopAction->setEnabled(false);
- m_stopAction->setIcon(QIcon(QLatin1String(":/debugger/images/debugger_stop_small.png")));
+ m_stopAction->setIcon(QIcon(Constants::ANALYZER_CONTROL_STOP_ICON));
command = am->registerAction(m_stopAction, Constants::STOP, globalcontext);
- mAnalyzermenu->addAction(command);
+ m_menu->addAction(command, Constants::G_ANALYZER_STARTSTOP);
connect(m_stopAction, SIGNAL(triggered()), q, SLOT(stopTool()));
- m_menu->addSeparator();
+
+ QAction *separatorAction = new QAction(m_menu);
+ separatorAction->setSeparator(true);
+ command = am->registerAction(separatorAction, Constants::ANALYZER_TOOLS_SEPARATOR, globalcontext);
+ m_menu->addAction(command, Constants::G_ANALYZER_TOOLS);
m_viewsMenu = am->actionContainer(Core::Id(Core::Constants::M_WINDOW_VIEWS));
}
@@ -306,17 +337,15 @@ void AnalyzerManager::AnalyzerManagerPrivate::delayedInit()
if (m_initialized)
return;
- if (useAnalyzeMode) {
- m_mode = new AnalyzerMode(q);
- m_mode->setWidget(createModeContents());
- AnalyzerPlugin::instance()->addAutoReleasedObject(m_mode);
- }
+ m_mode = new AnalyzerMode(q);
+ m_mode->setWidget(createModeContents());
+ AnalyzerPlugin::instance()->addAutoReleasedObject(m_mode);
+
m_initialized = true;
}
QWidget *AnalyzerManager::AnalyzerManagerPrivate::createModeContents()
{
- QTC_ASSERT(useAnalyzeMode, return 0; )
// right-side window with editor, output etc.
MiniSplitter *mainWindowSplitter = new MiniSplitter;
mainWindowSplitter->addWidget(createModeMainWindow());
@@ -341,18 +370,8 @@ static QToolButton *toolButton(QAction *action)
return button;
}
-void AnalyzerManager::addOutputPaneToolBarWidgets(QWidgetList *list) const
-{
- list->prepend(d->m_toolBox);
- list->prepend(toolButton(d->m_stopAction));
- list->prepend(toolButton(d->m_startAction));
- (*list) << new Utils::StyledSeparator << d->m_statusLabel;
-
-}
-
QWidget *AnalyzerManager::AnalyzerManagerPrivate::createModeMainWindow()
{
- QTC_ASSERT(useAnalyzeMode, return 0; )
m_mainWindow = new Utils::FancyMainWindow();
m_mainWindow->setObjectName(QLatin1String("AnalyzerManagerMainWindow"));
connect(m_mainWindow, SIGNAL(resetLayout()),
@@ -377,6 +396,34 @@ QWidget *AnalyzerManager::AnalyzerManagerPrivate::createModeMainWindow()
documentAndRightPane->setStretchFactor(0, 1);
documentAndRightPane->setStretchFactor(1, 0);
+ Utils::StyledBar *analyzeToolBar = new Utils::StyledBar;
+ analyzeToolBar->setProperty("topBorder", true);
+ QHBoxLayout *analyzeToolBarLayout = new QHBoxLayout(analyzeToolBar);
+ analyzeToolBarLayout->setMargin(0);
+ analyzeToolBarLayout->setSpacing(0);
+ QToolButton *startButton = toolButton(m_startAction);
+ QMenu *startMenu = new QMenu;
+ startMenu->addAction(m_startAction);
+ startMenu->addAction(m_startRemoteAction);
+ startButton->setMenu(startMenu);
+ analyzeToolBarLayout->addWidget(startButton);
+ analyzeToolBarLayout->addWidget(toolButton(m_stopAction));
+ analyzeToolBarLayout->addWidget(new Utils::StyledSeparator);
+ analyzeToolBarLayout->addWidget(m_toolBox);
+ analyzeToolBarLayout->addWidget(m_controlsWidget);
+ analyzeToolBarLayout->addWidget(m_statusLabel);
+ analyzeToolBarLayout->addStretch();
+
+ QDockWidget *dock = new QDockWidget(tr("Analyzer Toolbar"));
+ dock->setObjectName(QLatin1String("Analyzer Toolbar"));
+ dock->setWidget(analyzeToolBar);
+ dock->setFeatures(QDockWidget::NoDockWidgetFeatures);
+ dock->setProperty("managed_dockwidget", QLatin1String("true"));
+ dock->setAllowedAreas(Qt::BottomDockWidgetArea);
+ // hide title bar
+ dock->setTitleBarWidget(new QWidget(dock));
+ m_mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dock);
+ m_mainWindow->setToolBarDockWidget(dock);
QWidget *centralWidget = new QWidget;
m_mainWindow->setCentralWidget(centralWidget);
@@ -395,7 +442,7 @@ QWidget *AnalyzerManager::AnalyzerManagerPrivate::createModeMainWindow()
void AnalyzerManager::AnalyzerManagerPrivate::addDock(IAnalyzerTool *tool, Qt::DockWidgetArea area,
QDockWidget *dockWidget)
{
- QTC_ASSERT(useAnalyzeMode && tool == q->currentTool(), return)
+ QTC_ASSERT(tool == q->currentTool(), return)
dockWidget->setParent(m_mainWindow);
m_mainWindow->addDockWidget(area, dockWidget);
@@ -410,22 +457,13 @@ void AnalyzerManager::AnalyzerManagerPrivate::addDock(IAnalyzerTool *tool, Qt::D
cmd->setAttribute(Command::CA_Hide);
m_viewsMenu->addAction(cmd);
- /* TODO: save settings
- connect(dockWidget->toggleViewAction(), SIGNAL(triggered(bool)),
- SLOT(updateDockWidgetSettings()));
- connect(dockWidget, SIGNAL(topLevelChanged(bool)),
- SLOT(updateDockWidgetSettings()));
- connect(dockWidget, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)),
- SLOT(updateDockWidgetSettings()));
- */
-
// just add the dock below the toolbar by default
m_mainWindow->splitDockWidget(m_mainWindow->toolBarDockWidget(), dockWidget,
Qt::Vertical);
dockWidget->show();
}
-bool buildTypeAcceppted(IAnalyzerTool::ToolMode toolMode,
+bool buildTypeAccepted(IAnalyzerTool::ToolMode toolMode,
ProjectExplorer::BuildConfiguration::BuildType buildType)
{
if (toolMode == IAnalyzerTool::AnyMode)
@@ -442,13 +480,31 @@ bool buildTypeAcceppted(IAnalyzerTool::ToolMode toolMode,
return false;
}
+bool AnalyzerManager::AnalyzerManagerPrivate::showPromptDialog(const QString &title,
+ const QString &text,
+ const QString &stopButtonText,
+ const QString &cancelButtonText) const
+{
+ Utils::CheckableMessageBox messageBox(Core::ICore::instance()->mainWindow());
+ messageBox.setWindowTitle(title);
+ messageBox.setText(text);
+ messageBox.setStandardButtons(QDialogButtonBox::Yes|QDialogButtonBox::Cancel);
+ if (!stopButtonText.isEmpty())
+ messageBox.button(QDialogButtonBox::Yes)->setText(stopButtonText);
+ if (!cancelButtonText.isEmpty())
+ messageBox.button(QDialogButtonBox::Cancel)->setText(cancelButtonText);
+ messageBox.setDefaultButton(QDialogButtonBox::Yes);
+ messageBox.setCheckBoxVisible(false);
+ messageBox.exec();;
+ return messageBox.clickedStandardButton() == QDialogButtonBox::Yes;
+}
+
void AnalyzerManager::AnalyzerManagerPrivate::startTool()
{
- QTC_ASSERT(!m_currentRunControl && q->currentTool(), return);
- // make sure our mode is shown
- m_outputpane->popup();
- if (m_mode)
- ModeManager::instance()->activateMode(m_mode->id());
+ QTC_ASSERT(q->currentTool(), return);
+
+ // make sure mode is shown
+ q->showMode();
ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance();
@@ -467,14 +523,30 @@ void AnalyzerManager::AnalyzerManagerPrivate::startTool()
if (!runConfig || !runConfig->isEnabled())
return;
+ // check if there already is an analyzer run
+ if (m_currentRunControl) {
+ // ask if user wants to restart the analyzer
+ const QString msg = tr("<html><head/><body><center><i>%1</i> is still running. You have to quit the Analyzer before being able to run another instance.<center/>"
+ "<center>Force it to quit?</center></body></html>").arg(m_currentRunControl->displayName());
+ bool stopRequested = showPromptDialog(tr("Analyzer Still Running"), msg,
+ tr("Stop active run"), tr("Keep Running"));
+ if (!stopRequested)
+ return; // no restart, keep it running, do nothing
+
+ // user selected to stop the active run. stop it, activate restart on stop
+ m_restartOnStop = true;
+ q->stopTool();
+ return;
+ }
+
IAnalyzerTool::ToolMode toolMode = q->currentTool()->mode();
// check the project for whether the build config is in the correct mode
// if not, notify the user and urge him to use the correct mode
- if (!buildTypeAcceppted(toolMode, buildType))
+ if (!buildTypeAccepted(toolMode, buildType))
{
const QString &toolName = q->currentTool()->displayName();
- const QString &toolMode = q->currentTool()->modeString();
+ const QString &toolMode = IAnalyzerTool::modeString(q->currentTool()->mode());
const QString currentMode = buildType == ProjectExplorer::BuildConfiguration::Debug ? tr("Debug") : tr("Release");
QSettings *settings = Core::ICore::instance()->settings();
@@ -505,11 +577,9 @@ void AnalyzerManager::AnalyzerManagerPrivate::startTool()
pe->runProject(pro, Constants::MODE_ANALYZE);
- m_startAction->setEnabled(false);
- m_stopAction->setEnabled(true);
- m_toolBox->setEnabled(false);
- m_toolGroup->setEnabled(false);
+ q->updateRunActions();
}
+
// AnalyzerManager ////////////////////////////////////////////////////
AnalyzerManager *AnalyzerManager::m_instance = 0;
@@ -520,9 +590,8 @@ AnalyzerManager::AnalyzerManager(AnalyzerOutputPane *op, QObject *parent) :
m_instance = this;
d->m_outputpane = op;
- if (useAnalyzeMode)
- connect(ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)),
- this, SLOT(modeChanged(Core::IMode*)));
+ connect(ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)),
+ this, SLOT(modeChanged(Core::IMode*)));
ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance();
connect(pe, SIGNAL(updateRunActions()),
this, SLOT(updateRunActions()));
@@ -540,8 +609,7 @@ bool AnalyzerManager::isInitialized() const
void AnalyzerManager::shutdown()
{
- if (useAnalyzeMode)
- saveToolSettings(currentTool());
+ saveToolSettings(currentTool());
}
AnalyzerManager * AnalyzerManager::instance()
@@ -551,7 +619,8 @@ AnalyzerManager * AnalyzerManager::instance()
void AnalyzerManager::modeChanged(IMode *mode)
{
- QTC_ASSERT(d->m_mainWindow, return; )
+ if (!d->m_mainWindow)
+ return;
const bool makeVisible = mode->id() == Constants::MODE_ANALYZE;
if (!makeVisible)
return;
@@ -573,7 +642,7 @@ void AnalyzerManager::toolSelected(int idx)
selectingTool = true;
IAnalyzerTool *oldTool = currentTool();
- if (useAnalyzeMode && oldTool != 0) {
+ if (oldTool != 0) {
saveToolSettings(oldTool);
ActionManager *am = ICore::instance()->actionManager();
@@ -593,18 +662,20 @@ void AnalyzerManager::toolSelected(int idx)
d->m_toolGroup->actions().at(idx)->setChecked(true);
d->m_toolBox->setCurrentIndex(idx);
+ d->m_controlsWidget->setCurrentIndex(idx);
IAnalyzerTool *newTool = currentTool();
-
- if (useAnalyzeMode) {
- foreach (const AnalyzerManagerPrivate::ToolWidgetPair &widget, d->m_toolWidgets.value(newTool)) {
- d->addDock(newTool, widget.first, widget.second);
- }
- loadToolSettings(newTool);
+ foreach (const AnalyzerManagerPrivate::ToolWidgetPair &widget, d->m_toolWidgets.value(newTool)) {
+ d->addDock(newTool, widget.first, widget.second);
}
+ loadToolSettings(newTool);
d->m_outputpane->setTool(newTool);
+ updateRunActions();
+
selectingTool = false;
+
+ emit currentToolChanged(newTool);
}
void AnalyzerManager::toolSelected(QAction *action)
@@ -621,27 +692,36 @@ void AnalyzerManager::addTool(IAnalyzerTool *tool)
action->setData(d->m_tools.count());
action->setCheckable(true);
- d->m_menu->addAction(action);
+ ActionManager *am = Core::ICore::instance()->actionManager();
+
+ QString actionId = QString(Constants::ANALYZER_TOOLS) + QString::number(d->m_toolGroup->actions().count());
+ Core::Command *command = am->registerAction(action, actionId, Core::Context(Core::Constants::C_GLOBAL));
+ d->m_menu->addAction(command, Constants::G_ANALYZER_TOOLS);
+
d->m_toolGroup->setVisible(d->m_toolGroup->actions().count() > 1);
d->m_tools.append(tool);
d->m_toolBox->addItem(tool->displayName());
+
+ // populate controls widget
+ QWidget *controlWidget = tool->createControlWidget(); // might be 0
+ d->m_controlsWidget->addWidget(controlWidget ? controlWidget : AnalyzerUtils::createDummyWidget());
+
d->m_toolBox->setEnabled(d->m_toolBox->count() > 1);
if (currentTool() != tool)
selectTool(tool); // the first tool gets selected automatically due to signal emission from toolbox
+
tool->initialize(plugin);
- if (useAnalyzeMode) {
- QSettings *defaultSettings = new QSettings(this);
- d->m_defaultSettings[tool] = defaultSettings;
- d->m_mainWindow->saveSettings(defaultSettings);
- loadToolSettings(tool);
- }
+ QSettings *defaultSettings = new QSettings(this);
+ d->m_defaultSettings[tool] = defaultSettings;
+ d->m_mainWindow->saveSettings(defaultSettings);
+ loadToolSettings(tool);
}
QDockWidget *AnalyzerManager::createDockWidget(IAnalyzerTool *tool, const QString &title,
QWidget *widget, Qt::DockWidgetArea area)
{
- QTC_ASSERT(useAnalyzeMode && !widget->objectName().isEmpty(), return 0;);
+ QTC_ASSERT(!widget->objectName().isEmpty(), return 0;);
QDockWidget *dockWidget = d->m_mainWindow->addDockForWidget(widget);
d->m_dockWidgets << AnalyzerManagerPrivate::DockPtr(dockWidget);
@@ -674,6 +754,25 @@ void AnalyzerManager::startTool()
d->startTool();
}
+void AnalyzerManager::startToolRemote()
+{
+ StartRemoteDialog dlg;
+ if (dlg.exec() != QDialog::Accepted)
+ return;
+
+ AnalyzerStartParameters params;
+ params.connParams = dlg.sshParams();
+ params.debuggee = dlg.executable();
+ params.debuggeeArgs = dlg.arguments();
+ params.displayName = dlg.executable();
+ params.startMode = StartRemote;
+ params.workingDirectory = dlg.workingDirectory();
+
+ AnalyzerRunControl *rc = createAnalyzer(params);
+ QTC_ASSERT(rc, return);
+ ProjectExplorer::ProjectExplorerPlugin::instance()->startRunControl(rc, Constants::MODE_ANALYZE);
+}
+
void AnalyzerManager::runControlCreated(AnalyzerRunControl *rc)
{
QTC_ASSERT(!d->m_currentRunControl, qt_noop());
@@ -686,20 +785,21 @@ void AnalyzerManager::stopTool()
if (!d->m_currentRunControl)
return;
- d->m_currentRunControl->stop();
- handleToolFinished();
+ // be sure to call handleToolFinished only once, and only when the engine is really finished
+ if (d->m_currentRunControl->stop() == ProjectExplorer::RunControl::StoppedSynchronously)
+ handleToolFinished();
+ // else: wait for the finished() signal to trigger handleToolFinished()
}
void AnalyzerManager::handleToolFinished()
{
- // this may run as a consequence of calling stopMemcheck() or valgrind may have terminated
- // for a different reason (application exited through user action, segfault, ...), so we
- // duplicate some code from stopMemcheck().
- d->m_startAction->setEnabled(true);
- d->m_stopAction->setEnabled(false);
- d->m_toolBox->setEnabled(true);
- d->m_toolGroup->setEnabled(true);
d->m_currentRunControl = 0;
+ updateRunActions();
+
+ if (d->m_restartOnStop) {
+ startTool();
+ d->m_restartOnStop = false;
+ }
}
Utils::FancyMainWindow *AnalyzerManager::mainWindow() const
@@ -743,6 +843,12 @@ void AnalyzerManager::updateRunActions()
bool startEnabled = !d->m_currentRunControl && pe->canRun(project, Constants::MODE_ANALYZE)
&& currentTool();
d->m_startAction->setEnabled(startEnabled);
+ d->m_startRemoteAction->setEnabled(!d->m_currentRunControl && currentTool()
+ && currentTool()->canRunRemotely());
+ d->m_toolBox->setEnabled(!d->m_currentRunControl);
+ d->m_toolGroup->setEnabled(!d->m_currentRunControl);
+
+ d->m_stopAction->setEnabled(d->m_currentRunControl);
}
void AnalyzerManager::showStatusMessage(const QString &message, int timeoutMS)
@@ -767,4 +873,17 @@ QString AnalyzerManager::msgToolFinished(const QString &name, int issuesFound)
tr("Tool '%1' finished, no issues were found.").arg(name);
}
+AnalyzerRunControl *AnalyzerManager::createAnalyzer(const AnalyzerStartParameters &sp,
+ ProjectExplorer::RunConfiguration *rc)
+{
+ return d->m_runControlFactory->create(sp, rc);
+}
+
+void AnalyzerManager::showMode()
+{
+ if (d->m_mode)
+ ModeManager::instance()->activateMode(d->m_mode->id());
+ d->m_outputpane->popup();
+}
+
#include "analyzermanager.moc"
diff --git a/src/plugins/analyzerbase/analyzermanager.h b/src/plugins/analyzerbase/analyzermanager.h
index c8e56b2e9b..3d2463fe5e 100644
--- a/src/plugins/analyzerbase/analyzermanager.h
+++ b/src/plugins/analyzerbase/analyzermanager.h
@@ -36,6 +36,7 @@
#define ANALYZERMANAGER_H
#include "analyzerbase_global.h"
+#include "projectexplorer/runconfiguration.h"
#include <QtCore/QObject>
@@ -52,10 +53,16 @@ namespace Utils {
class FancyMainWindow;
}
+namespace ProjectExplorer {
+class RunConfiguration;
+}
+
namespace Analyzer {
class IAnalyzerTool;
-namespace Internal {
class AnalyzerRunControl;
+class AnalyzerStartParameters;
+
+namespace Internal {
class AnalyzerOutputPane;
} // namespace Internal
@@ -68,6 +75,7 @@ public:
~AnalyzerManager();
static AnalyzerManager *instance();
+ void registerRunControlFactory(ProjectExplorer::IRunControlFactory *factory);
bool isInitialized() const;
void shutdown();
@@ -87,28 +95,36 @@ public:
void selectTool(IAnalyzerTool *tool);
- void addOutputPaneToolBarWidgets(QList<QWidget *> *) const;
-
static QString msgToolStarted(const QString &name);
static QString msgToolFinished(const QString &name, int issuesFound);
+ // Used by Maemo analyzer support.
+ AnalyzerRunControl *createAnalyzer(const AnalyzerStartParameters &sp,
+ ProjectExplorer::RunConfiguration *rc = 0);
+ void showMode();
+
public slots:
+ void startTool();
+ void startToolRemote();
+ void stopTool();
+
void showStatusMessage(const QString &message, int timeoutMS = 10000);
void showPermanentStatusMessage(const QString &message);
private slots:
- void startTool();
- void stopTool();
void handleToolFinished();
void toolSelected(int);
void toolSelected(QAction *);
void modeChanged(Core::IMode *mode);
- void runControlCreated(Analyzer::Internal::AnalyzerRunControl *);
+ void runControlCreated(Analyzer::AnalyzerRunControl *);
void resetLayout();
void saveToolSettings(Analyzer::IAnalyzerTool *tool);
void loadToolSettings(Analyzer::IAnalyzerTool *tool);
void updateRunActions();
+signals:
+ void currentToolChanged(Analyzer::IAnalyzerTool *tool);
+
private:
class AnalyzerManagerPrivate;
friend class AnalyzerManagerPrivate;
diff --git a/src/plugins/analyzerbase/analyzeroutputpane.cpp b/src/plugins/analyzerbase/analyzeroutputpane.cpp
index f1233360ed..bd9102dfb8 100644
--- a/src/plugins/analyzerbase/analyzeroutputpane.cpp
+++ b/src/plugins/analyzerbase/analyzeroutputpane.cpp
@@ -31,8 +31,12 @@
**************************************************************************/
#include "analyzeroutputpane.h"
+
+#include "analyzerconstants.h"
#include "analyzermanager.h"
+#include "analyzerutils.h"
#include "ianalyzertool.h"
+#include "ianalyzeroutputpaneadapter.h"
#include <utils/qtcassert.h>
#include <utils/styledbar.h>
@@ -45,20 +49,13 @@
#include <QtGui/QLabel>
#include <QtGui/QStackedWidget>
-static const char dummyWidgetPropertyC[] = "dummyWidget";
enum { debug = 0 };
-enum { dummyIndex = 0 };
namespace Analyzer {
namespace Internal {
-static inline QWidget *createDummyWidget()
-{
- QWidget *widget = new QWidget;
- widget->setProperty(dummyWidgetPropertyC, QVariant(true));
- return widget;
-}
+static const int dummyWidgetIndex = 0;
/*!
\class AnalyzerPane::Internal::AnalyzerOutputPane
@@ -96,7 +93,8 @@ AnalyzerOutputPane::AnalyzerOutputPane(QObject *parent) :
m_paneWidget(0),
m_paneStackedLayout(0),
m_toolbarStackedWidget(0),
- m_toolBarSeparator(0)
+ m_toolBarSeparator(0),
+ m_delayedCurrentIndex(-1)
{
setObjectName(QLatin1String("AnalyzerOutputPane"));
}
@@ -105,8 +103,8 @@ void AnalyzerOutputPane::clearTool()
{
// No tool. Show dummy label, which is the last widget.
if (m_paneWidget) {
- m_paneStackedLayout->setCurrentIndex(dummyIndex);
- m_toolbarStackedWidget->setCurrentIndex(dummyIndex);
+ m_paneStackedLayout->setCurrentIndex(dummyWidgetIndex);
+ m_toolbarStackedWidget->setCurrentIndex(dummyWidgetIndex);
emit navigateStateChanged();
}
hide();
@@ -114,27 +112,27 @@ void AnalyzerOutputPane::clearTool()
int AnalyzerOutputPane::currentIndex() const
{
- return m_paneStackedLayout ? m_paneStackedLayout->currentIndex() : -1;
+ return isInitialized() ? m_paneStackedLayout->currentIndex() : m_delayedCurrentIndex;
}
IAnalyzerOutputPaneAdapter *AnalyzerOutputPane::currentAdapter() const
{
const int index = currentIndex(); // Rule out leading dummy widget
- if (index != dummyIndex && index < m_adapters.size())
+ if (index != dummyWidgetIndex && index < m_adapters.size())
return m_adapters.at(index);
return 0;
}
void AnalyzerOutputPane::setCurrentIndex(int i)
{
- QTC_ASSERT(isInitialized(), return )
-
- if (i != currentIndex()) {
+ if (!isInitialized()) {
+ m_delayedCurrentIndex = i;
+ } else if (i != currentIndex()) {
// Show up pane widget and optional toolbar widget. Hide
// the toolbar if the toolbar widget is a dummy.
m_paneStackedLayout->setCurrentIndex(i);
m_toolbarStackedWidget->setCurrentIndex(i);
- const bool hasToolBarWidget = !m_toolbarStackedWidget->currentWidget()->property(dummyWidgetPropertyC).toBool();
+ const bool hasToolBarWidget = !m_toolbarStackedWidget->currentWidget()->property(Constants::ANALYZER_DUMMYWIDGET_ID).toBool();
m_toolbarStackedWidget->setVisible(hasToolBarWidget);
m_toolBarSeparator->setVisible(hasToolBarWidget);
navigateStateChanged();
@@ -159,7 +157,7 @@ void AnalyzerOutputPane::addToWidgets(IAnalyzerOutputPaneAdapter *adapter)
QTC_ASSERT(toolPaneWidget, return; )
m_paneStackedLayout->addWidget(toolPaneWidget);
QWidget *toolBarWidget = adapter->toolBarWidget(); // Might be 0
- m_toolbarStackedWidget->addWidget(toolBarWidget ? toolBarWidget : createDummyWidget());
+ m_toolbarStackedWidget->addWidget(toolBarWidget ? toolBarWidget : AnalyzerUtils::createDummyWidget());
}
void AnalyzerOutputPane::setTool(IAnalyzerTool *t)
@@ -173,13 +171,12 @@ void AnalyzerOutputPane::setTool(IAnalyzerTool *t)
if (adapter) {
int index = m_adapters.indexOf(adapter);
if (index == -1) {
- index = m_adapters.size();
add(adapter);
+ index = m_adapters.size();
}
- if (isInitialized()) {
+ setCurrentIndex(index);
+ if (isInitialized())
popup(false);
- setCurrentIndex(index);
- }
} else {
clearTool();
}
@@ -207,17 +204,19 @@ void AnalyzerOutputPane::createWidgets(QWidget *paneParent)
// Temporarily assign to (wrong) parent to suppress flicker in conjunction with QStackedWidget.
m_toolbarStackedWidget = new QStackedWidget(paneParent);
m_toolbarStackedWidget->setObjectName(objectName() + QLatin1String("ToolBarStackedWidget"));
- m_toolbarStackedWidget->addWidget(createDummyWidget()); // placeholder
+ m_toolbarStackedWidget->addWidget(AnalyzerUtils::createDummyWidget()); // placeholder
m_toolBarSeparator = new Utils::StyledSeparator(paneParent);
m_toolBarSeparator->setObjectName(objectName() + QLatin1String("ToolBarSeparator"));
// Add adapters added before.
const int adapterCount = m_adapters.size();
- const int firstAdapter = dummyIndex + 1;
+ const int firstAdapter = dummyWidgetIndex + 1;
for (int i = firstAdapter; i < adapterCount; i++)
addToWidgets(m_adapters.at(i));
- // Make last one current
- if (adapterCount > firstAdapter)
+
+ if (m_delayedCurrentIndex != -1) // setTool was called before initialization
+ setCurrentIndex(m_delayedCurrentIndex);
+ else if (adapterCount > firstAdapter) // default: Make last one current
setCurrentIndex(adapterCount - 1);
}
@@ -229,7 +228,6 @@ QWidgetList AnalyzerOutputPane::toolBarWidgets() const
QWidgetList list;
list << m_toolBarSeparator << m_toolbarStackedWidget;
- AnalyzerManager::instance()->addOutputPaneToolBarWidgets(&list);
return list;
}
diff --git a/src/plugins/analyzerbase/analyzeroutputpane.h b/src/plugins/analyzerbase/analyzeroutputpane.h
index d5f8e4d0f3..6c95ecec53 100644
--- a/src/plugins/analyzerbase/analyzeroutputpane.h
+++ b/src/plugins/analyzerbase/analyzeroutputpane.h
@@ -56,7 +56,7 @@ public:
void setTool(IAnalyzerTool *t);
// IOutputPane
virtual QWidget *outputWidget(QWidget *parent);
- virtual QList<QWidget*> toolBarWidgets() const;
+ virtual QList<QWidget *> toolBarWidgets() const;
virtual QString displayName() const;
virtual int priorityInStatusBar() const;
@@ -92,6 +92,8 @@ private:
QList<IAnalyzerOutputPaneAdapter *> m_adapters;
QStackedWidget *m_toolbarStackedWidget;
Utils::StyledSeparator *m_toolBarSeparator;
+ // tracks selected index during !isInitialized() state
+ int m_delayedCurrentIndex;
};
} // namespace Internal
diff --git a/src/plugins/analyzerbase/analyzerplugin.cpp b/src/plugins/analyzerbase/analyzerplugin.cpp
index 5df1be0612..fb399641c6 100644
--- a/src/plugins/analyzerbase/analyzerplugin.cpp
+++ b/src/plugins/analyzerbase/analyzerplugin.cpp
@@ -36,7 +36,9 @@
#include "analyzerconstants.h"
#include "analyzermanager.h"
#include "analyzeroutputpane.h"
+#include "ianalyzertool.h"
+#include <coreplugin/icore.h>
#include <coreplugin/imode.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
@@ -53,6 +55,7 @@
using namespace Analyzer;
using namespace Analyzer::Internal;
+static const QLatin1String lastActiveToolC("Analyzer.Plugin.LastActiveTool");
AnalyzerPlugin *AnalyzerPlugin::m_instance = 0;
@@ -116,9 +119,6 @@ bool AnalyzerPlugin::initialize(const QStringList &arguments, QString *errorStri
//: Category under which Analyzer tasks are listed in build issues view
hub->addCategory(QLatin1String(Constants::ANALYZERTASK_ID), tr("Analyzer"));
- ///TODO: select last used tool or default tool
-// d->m_manager->selectTool(memcheckTool);
-
return true;
}
@@ -127,14 +127,35 @@ void AnalyzerPlugin::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."
+
+ // notify tools about the extensions initialized state
+ foreach(IAnalyzerTool *tool, d->m_manager->tools()) {
+ tool->extensionsInitialized();
+ }
+
+ // load the last active tool
+ QSettings *settings = Core::ICore::instance()->settings();
+ const QString lastActiveTool = settings->value(lastActiveToolC, QString()).toString();
+ foreach(IAnalyzerTool *tool, d->m_manager->tools()) {
+ if (tool->id() == lastActiveTool) {
+ d->m_manager->selectTool(tool);
+ break;
+ }
+ }
}
ExtensionSystem::IPlugin::ShutdownFlag AnalyzerPlugin::aboutToShutdown()
{
- d->m_manager->shutdown();
// Save settings
// Disconnect from signals that are not needed during shutdown
// Hide UI (if you add UI that is not in the main window directly)
+
+ if (const IAnalyzerTool *tool = d->m_manager->currentTool()) {
+ QSettings *settings = Core::ICore::instance()->settings();
+ settings->setValue(QLatin1String(lastActiveToolC), tool->id());
+ }
+
+ d->m_manager->shutdown();
return SynchronousShutdown;
}
diff --git a/src/plugins/analyzerbase/analyzerplugin.h b/src/plugins/analyzerbase/analyzerplugin.h
index f8a7173d9d..d57d7a053b 100644
--- a/src/plugins/analyzerbase/analyzerplugin.h
+++ b/src/plugins/analyzerbase/analyzerplugin.h
@@ -49,10 +49,11 @@ public:
static AnalyzerPlugin *instance();
AnalyzerPlugin();
- ~AnalyzerPlugin();
+ virtual ~AnalyzerPlugin();
bool initialize(const QStringList &arguments, QString *errorString);
void extensionsInitialized();
+
ShutdownFlag aboutToShutdown();
private:
diff --git a/src/plugins/analyzerbase/analyzerrunconfigwidget.cpp b/src/plugins/analyzerbase/analyzerrunconfigwidget.cpp
index 9ab51f1454..45e43f1806 100644
--- a/src/plugins/analyzerbase/analyzerrunconfigwidget.cpp
+++ b/src/plugins/analyzerbase/analyzerrunconfigwidget.cpp
@@ -44,12 +44,11 @@
#include <QtGui/QVBoxLayout>
using namespace Analyzer;
-using namespace Analyzer::Internal;
AnalyzerRunConfigWidget::AnalyzerRunConfigWidget()
: m_detailsWidget(new Utils::DetailsWidget(this))
{
- QWidget* mainWidget = new QWidget(this);
+ QWidget *mainWidget = new QWidget(this);
new QVBoxLayout(mainWidget);
m_detailsWidget->setWidget(mainWidget);
@@ -78,11 +77,11 @@ void AnalyzerRunConfigWidget::setRunConfiguration(ProjectExplorer::RunConfigurat
m_detailsWidget->setSummaryText(tr("Available settings: %1").arg(tools.join(", ")));
// add group boxes for each sub config
- QLayout* layout = m_detailsWidget->widget()->layout();
+ QLayout *layout = m_detailsWidget->widget()->layout();
foreach(AbstractAnalyzerSubConfig *config, settings->subConfigs()) {
- QGroupBox* box = new QGroupBox(config->displayName());
+ QGroupBox *box = new QGroupBox(config->displayName());
Q_UNUSED(box)
- QWidget* widget = config->createConfigWidget(this);
+ QWidget *widget = config->createConfigWidget(this);
layout->addWidget(widget);
}
}
diff --git a/src/plugins/analyzerbase/analyzerrunconfigwidget.h b/src/plugins/analyzerbase/analyzerrunconfigwidget.h
index 7337fe1487..0c799507ba 100644
--- a/src/plugins/analyzerbase/analyzerrunconfigwidget.h
+++ b/src/plugins/analyzerbase/analyzerrunconfigwidget.h
@@ -37,13 +37,10 @@
#define ANALYZER_INTERNAL_ANALYZERRUNCONFIGWIDGET_H
#include <projectexplorer/runconfiguration.h>
+#include <analyzerbase/analyzerbase_global.h>
QT_BEGIN_NAMESPACE
class QStandardItemModel;
-
-namespace Ui {
-class AnalyzerConfigWidget;
-}
QT_END_NAMESPACE
namespace Utils {
@@ -54,9 +51,7 @@ namespace Analyzer {
class AnalyzerSettings;
-namespace Internal {
-
-class AnalyzerRunConfigWidget : public ProjectExplorer::RunConfigWidget
+class ANALYZER_EXPORT AnalyzerRunConfigWidget : public ProjectExplorer::RunConfigWidget
{
Q_OBJECT
@@ -72,6 +67,5 @@ private:
};
}
-}
#endif // ANALYZER_INTERNAL_ANALYZERRUNCONFIGWIDGET_H
diff --git a/src/plugins/analyzerbase/analyzerruncontrol.cpp b/src/plugins/analyzerbase/analyzerruncontrol.cpp
index 9dc7e3f924..c4c413fb14 100644
--- a/src/plugins/analyzerbase/analyzerruncontrol.cpp
+++ b/src/plugins/analyzerbase/analyzerruncontrol.cpp
@@ -36,10 +36,8 @@
#include "analyzerconstants.h"
#include "ianalyzerengine.h"
#include "ianalyzertool.h"
-#include "analyzerplugin.h"
#include "analyzermanager.h"
-#include "analyzerrunconfigwidget.h"
-#include "analyzersettings.h"
+#include "analyzerstartparameters.h"
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/applicationrunconfiguration.h>
@@ -49,87 +47,54 @@
#include <coreplugin/ioutputpane.h>
#include <QtCore/QDebug>
-#include <QtGui/QHBoxLayout>
-#include <QtGui/QLabel>
-#include <QtGui/QMessageBox>
using namespace Analyzer;
using namespace Analyzer::Internal;
-// AnalyzerRunControlFactory ////////////////////////////////////////////////////
-AnalyzerRunControlFactory::AnalyzerRunControlFactory(QObject *parent)
- : IRunControlFactory(parent)
-{
-}
+// AnalyzerRunControl::Private ///////////////////////////////////////////
-bool AnalyzerRunControlFactory::canRun(RunConfiguration *runConfiguration, const QString &mode) const
-{
- if (!qobject_cast<ProjectExplorer::LocalApplicationRunConfiguration *>(runConfiguration))
- return false;
- return mode == Constants::MODE_ANALYZE;
-}
+class AnalyzerRunControl::Private {
+public:
+ Private();
-ProjectExplorer::RunControl *AnalyzerRunControlFactory::create(RunConfiguration *runConfiguration,
- const QString &mode)
-{
- if (!qobject_cast<ProjectExplorer::LocalApplicationRunConfiguration *>(runConfiguration) ||
- mode != Constants::MODE_ANALYZE) {
- return 0;
- }
- AnalyzerRunControl *rc = new AnalyzerRunControl(runConfiguration);
- emit runControlCreated(rc);
- return rc;
-}
+ bool m_isRunning;
+ IAnalyzerEngine *m_engine;
+};
-QString AnalyzerRunControlFactory::displayName() const
+AnalyzerRunControl::Private::Private()
+: m_isRunning(false)
+, m_engine(0)
{
- return tr("Analyzer");
-}
-ProjectExplorer::IRunConfigurationAspect *AnalyzerRunControlFactory::createRunConfigurationAspect()
-{
- return new AnalyzerProjectSettings;
}
-ProjectExplorer::RunConfigWidget *AnalyzerRunControlFactory::createConfigurationWidget(RunConfiguration
- *runConfiguration)
-{
- ProjectExplorer::LocalApplicationRunConfiguration *localRc =
- qobject_cast<ProjectExplorer::LocalApplicationRunConfiguration *>(runConfiguration);
- if (!localRc)
- return 0;
- AnalyzerProjectSettings *settings = runConfiguration->extraAspect<AnalyzerProjectSettings>();
- if (!settings)
- return 0;
-
- AnalyzerRunConfigWidget *ret = new AnalyzerRunConfigWidget;
- ret->setRunConfiguration(runConfiguration);
- return ret;
-}
// AnalyzerRunControl ////////////////////////////////////////////////////
-AnalyzerRunControl::AnalyzerRunControl(RunConfiguration *runConfiguration)
+AnalyzerRunControl::AnalyzerRunControl(const AnalyzerStartParameters &sp,
+ RunConfiguration *runConfiguration)
: RunControl(runConfiguration, Constants::MODE_ANALYZE),
- m_isRunning(false),
- m_engine(0)
+ d(new Private)
{
IAnalyzerTool *tool = AnalyzerManager::instance()->currentTool();
- m_engine = tool->createEngine(runConfiguration);
+ d->m_engine = tool->createEngine(sp, runConfiguration);
- connect(m_engine, SIGNAL(standardErrorReceived(QString)),
+ connect(d->m_engine, SIGNAL(standardErrorReceived(QString)),
SLOT(receiveStandardError(QString)));
- connect(m_engine, SIGNAL(standardOutputReceived(QString)),
+ connect(d->m_engine, SIGNAL(standardOutputReceived(QString)),
SLOT(receiveStandardOutput(QString)));
- connect(m_engine, SIGNAL(taskToBeAdded(ProjectExplorer::Task::TaskType,QString,QString,int)),
+ connect(d->m_engine, SIGNAL(taskToBeAdded(ProjectExplorer::Task::TaskType,QString,QString,int)),
SLOT(addTask(ProjectExplorer::Task::TaskType,QString,QString,int)));
- connect(m_engine, SIGNAL(finished()),
+ connect(d->m_engine, SIGNAL(finished()),
SLOT(engineFinished()));
}
AnalyzerRunControl::~AnalyzerRunControl()
{
- if (m_isRunning)
+ if (d->m_isRunning)
stop();
+
+ delete d->m_engine;
+ d->m_engine = 0;
}
void AnalyzerRunControl::start()
@@ -139,32 +104,40 @@ void AnalyzerRunControl::start()
ProjectExplorer::TaskHub *hub = pm->getObject<ProjectExplorer::TaskHub>();
hub->clearTasks(Constants::ANALYZERTASK_ID);
- m_isRunning = true;
+ d->m_isRunning = true;
emit started();
- m_engine->start();
+ d->m_engine->start();
}
ProjectExplorer::RunControl::StopResult AnalyzerRunControl::stop()
{
- m_engine->stop();
- m_isRunning = false;
+ if (!d->m_isRunning)
+ return StoppedSynchronously;
+
+ d->m_engine->stop();
+ d->m_isRunning = false;
return AsynchronousStop;
}
void AnalyzerRunControl::engineFinished()
{
- m_isRunning = false;
+ d->m_isRunning = false;
emit finished();
}
bool AnalyzerRunControl::isRunning() const
{
- return m_isRunning;
+ return d->m_isRunning;
}
QString AnalyzerRunControl::displayName() const
{
- return AnalyzerManager::instance()->currentTool()->displayName();
+ return d->m_engine->startParameters().displayName;
+}
+
+QIcon AnalyzerRunControl::icon() const
+{
+ return QIcon(QLatin1String(":/images/analyzer_start_small.png"));
}
void AnalyzerRunControl::receiveStandardOutput(const QString &text)
diff --git a/src/plugins/analyzerbase/analyzerruncontrol.h b/src/plugins/analyzerbase/analyzerruncontrol.h
index 4c670fe42c..6c846b1a5b 100644
--- a/src/plugins/analyzerbase/analyzerruncontrol.h
+++ b/src/plugins/analyzerbase/analyzerruncontrol.h
@@ -35,54 +35,26 @@
#ifndef ANALYZERRUNCONTROL_H
#define ANALYZERRUNCONTROL_H
-#include "analyzerconstants.h"
+#include "analyzerbase_global.h"
-#include <valgrind/xmlprotocol/parser.h>
+#include <utils/ssh/sshconnection.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/task.h>
-#include <QtCore/QScopedPointer>
-
namespace Analyzer {
class IAnalyzerEngine;
+class AnalyzerStartParameters;
-namespace Internal {
-
-class AnalyzerRunControl;
-
-class AnalyzerRunControlFactory: public ProjectExplorer::IRunControlFactory
-{
- Q_OBJECT
-
-public:
- AnalyzerRunControlFactory(QObject *parent = 0);
-
- typedef ProjectExplorer::RunConfiguration RunConfiguration;
- typedef ProjectExplorer::RunControl RunControl;
-
- // virtuals from IRunControlFactory
- bool canRun(RunConfiguration *runConfiguration, const QString &mode) const;
- RunControl *create(RunConfiguration *runConfiguration, const QString &mode);
- QString displayName() const;
-
- ProjectExplorer::IRunConfigurationAspect *createRunConfigurationAspect();
- ProjectExplorer::RunConfigWidget *createConfigurationWidget(RunConfiguration *runConfiguration);
-
-signals:
- void runControlCreated(Analyzer::Internal::AnalyzerRunControl *);
-};
-
-
-class AnalyzerRunControl: public ProjectExplorer::RunControl
+class ANALYZER_EXPORT AnalyzerRunControl: public ProjectExplorer::RunControl
{
Q_OBJECT
public:
typedef ProjectExplorer::RunConfiguration RunConfiguration;
// the constructor is likely to gain more arguments later
- explicit AnalyzerRunControl(RunConfiguration *runConfiguration);
+ explicit AnalyzerRunControl(const AnalyzerStartParameters &sp, RunConfiguration *runConfiguration);
~AnalyzerRunControl();
// pure virtuals from ProjectExplorer::RunControl
@@ -90,6 +62,7 @@ public:
StopResult stop();
bool isRunning() const;
QString displayName() const;
+ QIcon icon() const;
private slots:
void receiveStandardOutput(const QString &);
@@ -101,12 +74,10 @@ private slots:
void engineFinished();
private:
- bool m_isRunning;
- IAnalyzerEngine *m_engine;
+ class Private;
+ QScopedPointer<Private> d;
};
-
-} // namespace Internal
} // namespace Analyzer
#endif // ANALYZERRUNCONTROL_H
diff --git a/src/plugins/analyzerbase/analyzerruncontrolfactory.cpp b/src/plugins/analyzerbase/analyzerruncontrolfactory.cpp
new file mode 100644
index 0000000000..e919c82f62
--- /dev/null
+++ b/src/plugins/analyzerbase/analyzerruncontrolfactory.cpp
@@ -0,0 +1,123 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "analyzerruncontrolfactory.h"
+#include "analyzerruncontrol.h"
+#include "analyzerconstants.h"
+#include "analyzerrunconfigwidget.h"
+#include "analyzersettings.h"
+#include "analyzerstartparameters.h"
+
+#include <utils/qtcassert.h>
+
+#include <projectexplorer/applicationrunconfiguration.h>
+
+#include <QtCore/QDebug>
+
+using namespace Analyzer;
+using namespace Analyzer::Internal;
+
+AnalyzerStartParameters localStartParameters(ProjectExplorer::RunConfiguration *runConfiguration)
+{
+ AnalyzerStartParameters sp;
+ QTC_ASSERT(runConfiguration, return sp);
+ ProjectExplorer::LocalApplicationRunConfiguration *rc =
+ qobject_cast<ProjectExplorer::LocalApplicationRunConfiguration *>(runConfiguration);
+ QTC_ASSERT(rc, return sp);
+
+ sp.startMode = StartLocal;
+ sp.environment = rc->environment();
+ sp.workingDirectory = rc->workingDirectory();
+ sp.debuggee = rc->executable();
+ sp.debuggeeArgs = rc->commandLineArguments();
+ sp.displayName = rc->displayName();
+ return sp;
+}
+
+// AnalyzerRunControlFactory ////////////////////////////////////////////////////
+AnalyzerRunControlFactory::AnalyzerRunControlFactory(QObject *parent)
+ : IRunControlFactory(parent)
+{
+}
+
+bool AnalyzerRunControlFactory::canRun(RunConfiguration *runConfiguration, const QString &mode) const
+{
+ if (!qobject_cast<ProjectExplorer::LocalApplicationRunConfiguration *>(runConfiguration))
+ return false;
+ return mode == Constants::MODE_ANALYZE;
+}
+
+ProjectExplorer::RunControl *AnalyzerRunControlFactory::create(RunConfiguration *runConfiguration,
+ const QString &mode)
+{
+ if (!qobject_cast<ProjectExplorer::LocalApplicationRunConfiguration *>(runConfiguration) ||
+ mode != Constants::MODE_ANALYZE) {
+ return 0;
+ }
+ const AnalyzerStartParameters sp = localStartParameters(runConfiguration);
+ return create(sp, runConfiguration);
+}
+
+AnalyzerRunControl *AnalyzerRunControlFactory::create(const AnalyzerStartParameters &sp,
+ RunConfiguration *runConfiguration)
+{
+ AnalyzerRunControl *rc = new AnalyzerRunControl(sp, runConfiguration);
+ emit runControlCreated(rc);
+ return rc;
+}
+
+QString AnalyzerRunControlFactory::displayName() const
+{
+ return tr("Analyzer");
+}
+
+ProjectExplorer::IRunConfigurationAspect *AnalyzerRunControlFactory::createRunConfigurationAspect()
+{
+ return new AnalyzerProjectSettings;
+}
+
+ProjectExplorer::RunConfigWidget *AnalyzerRunControlFactory::createConfigurationWidget(RunConfiguration
+ *runConfiguration)
+{
+ ProjectExplorer::LocalApplicationRunConfiguration *localRc =
+ qobject_cast<ProjectExplorer::LocalApplicationRunConfiguration *>(runConfiguration);
+ if (!localRc)
+ return 0;
+ AnalyzerProjectSettings *settings = runConfiguration->extraAspect<AnalyzerProjectSettings>();
+ if (!settings)
+ return 0;
+
+ AnalyzerRunConfigWidget *ret = new AnalyzerRunConfigWidget;
+ ret->setRunConfiguration(runConfiguration);
+ return ret;
+}
diff --git a/src/plugins/analyzerbase/analyzerruncontrolfactory.h b/src/plugins/analyzerbase/analyzerruncontrolfactory.h
new file mode 100644
index 0000000000..02da795d30
--- /dev/null
+++ b/src/plugins/analyzerbase/analyzerruncontrolfactory.h
@@ -0,0 +1,72 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 ANALYZERRUNCONTROLFACTORY_H
+#define ANALYZERRUNCONTROLFACTORY_H
+
+#include <projectexplorer/runconfiguration.h>
+
+namespace Analyzer {
+
+class AnalyzerRunControl;
+class AnalyzerStartParameters;
+
+namespace Internal {
+
+class AnalyzerRunControlFactory: public ProjectExplorer::IRunControlFactory
+{
+ Q_OBJECT
+
+public:
+ AnalyzerRunControlFactory(QObject *parent = 0);
+
+ typedef ProjectExplorer::RunConfiguration RunConfiguration;
+ typedef ProjectExplorer::RunControl RunControl;
+
+ // virtuals from IRunControlFactory
+ bool canRun(RunConfiguration *runConfiguration, const QString &mode) const;
+ RunControl *create(RunConfiguration *runConfiguration, const QString &mode);
+ AnalyzerRunControl *create(const AnalyzerStartParameters &sp, RunConfiguration *rc = 0);
+ QString displayName() const;
+
+ ProjectExplorer::IRunConfigurationAspect *createRunConfigurationAspect();
+ ProjectExplorer::RunConfigWidget *createConfigurationWidget(RunConfiguration *runConfiguration);
+
+signals:
+ void runControlCreated(Analyzer::AnalyzerRunControl *);
+};
+
+} // namespace Internal
+} // namespace Analyzer
+
+#endif // ANALYZERRUNCONTROLFACTORY_H
diff --git a/src/plugins/analyzerbase/analyzersettings.h b/src/plugins/analyzerbase/analyzersettings.h
index dee13d6df8..a3d2eb194e 100644
--- a/src/plugins/analyzerbase/analyzersettings.h
+++ b/src/plugins/analyzerbase/analyzersettings.h
@@ -58,6 +58,9 @@ template <typename T> static void setIfPresent(const QVariantMap &map, const QSt
/**
* Subclass this to add configuration to your analyzer tool.
+ *
+ * If global and project-specific settings differ for your tool,
+ * create one subclass for each.
*/
class ANALYZER_EXPORT AbstractAnalyzerSubConfig : public QObject
{
@@ -66,12 +69,18 @@ public:
AbstractAnalyzerSubConfig(QObject *parent);
virtual ~AbstractAnalyzerSubConfig();
+ /// return a list of default values
virtual QVariantMap defaults() const = 0;
+ /// convert current configuration into map for storage
virtual QVariantMap toMap() const = 0;
+ /// read configuration from @p map
virtual bool fromMap(const QVariantMap &map) = 0;
+ /// unique ID for this configuration
virtual QString id() const = 0;
+ /// user readable display name for this configuration
virtual QString displayName() const = 0;
+ /// create a configuration widget for this configuration
virtual QWidget *createConfigWidget(QWidget *parent) = 0;
};
@@ -83,17 +92,21 @@ class ANALYZER_EXPORT AbstractAnalyzerSubConfigFactory
{
public:
AbstractAnalyzerSubConfigFactory(){}
- ~AbstractAnalyzerSubConfigFactory(){}
+ virtual ~AbstractAnalyzerSubConfigFactory(){}
virtual AbstractAnalyzerSubConfig *createGlobalSubConfig(QObject *parent) = 0;
virtual AbstractAnalyzerSubConfig *createProjectSubConfig(QObject *parent) = 0;
};
/**
- * Makes it easy to register configuration for a tool:
+ * Makes it easy to register custom configuration for a tool:
*
* @code
- * manager->registerSubConfigFactory(new AnalyzerSubConfigFactory<MemcheckGlobalSettings, MemcheckProjectSettings>);
+ * bool MemcheckPlugin::initialize(const QStringList &arguments, QString *errorString)
+ * {
+ * typedef AnalyzerSubConfigFactory<YourGlobalSettings, YourProjectSettings> YourConfigFactory;
+ * AnalyzerGlobalSettings::instance()->registerSubConfigFactory(new YourConfigFactory);
+ * }
* @endcode
*/
template<class GlobalConfigT, class ProjectConfigT>
@@ -125,7 +138,7 @@ public:
virtual ~AnalyzerSettings();
template<class T>
- T* subConfig() const
+ T *subConfig() const
{
return findChild<T *>();
}
@@ -154,6 +167,11 @@ protected:
// differently.
/**
* Global settings
+ *
+ * To access your custom configuration use:
+ * @code
+ * AnalyzerGlobalSettings::instance()->subConfig<YourGlobalConfig>()->...
+ * @endcode
*/
class ANALYZER_EXPORT AnalyzerGlobalSettings : public AnalyzerSettings
{
@@ -176,6 +194,12 @@ private:
/**
* Settings associated with a single project/run configuration
+ *
+ * To access your custom configuration use:
+ * @code
+ * ProjectExplorer::RunConfiguration *rc = ...;
+ * rc->extraAspect<AnalyzerProjectSettings>()->subConfig<YourProjectConfig>()->...
+ * @endcode
*/
class ANALYZER_EXPORT AnalyzerProjectSettings : public AnalyzerSettings, public ProjectExplorer::IRunConfigurationAspect
{
diff --git a/src/plugins/analyzerbase/analyzerstartparameters.h b/src/plugins/analyzerbase/analyzerstartparameters.h
new file mode 100644
index 0000000000..59bab57427
--- /dev/null
+++ b/src/plugins/analyzerbase/analyzerstartparameters.h
@@ -0,0 +1,76 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 ANALYZERSTARTPARAMETERS_H
+#define ANALYZERSTARTPARAMETERS_H
+
+#include "analyzerbase_global.h"
+#include "analyzerconstants.h"
+
+#include <QtCore/QMetaType>
+
+#include <utils/ssh/sshconnection.h>
+#include <utils/environment.h>
+
+namespace Analyzer {
+
+// Note: This is part of the "soft interface" of the analyzer plugin.
+// Do not add anything that needs implementation in a .cpp file.
+
+class ANALYZER_EXPORT AnalyzerStartParameters
+{
+public:
+ AnalyzerStartParameters()
+ : startMode(StartLocal)
+ , connParams(Utils::SshConnectionParameters::NoProxy)
+ { }
+
+ AnalyzerStartMode startMode;
+ Utils::SshConnectionParameters connParams;
+
+ QString debuggee;
+ QString debuggeeArgs;
+ QString analyzerCmdPrefix;
+ QString remoteMountPoint;
+ QString localMountDir;
+ QString remoteSourcesDir;
+ QString displayName;
+ Utils::Environment environment;
+ QString workingDirectory;
+};
+
+} // namespace Analyzer
+
+Q_DECLARE_METATYPE(Analyzer::AnalyzerStartParameters)
+
+#endif // ANALYZERSTARTPARAMETERS_H
diff --git a/src/plugins/analyzerbase/analyzerutils.cpp b/src/plugins/analyzerbase/analyzerutils.cpp
new file mode 100644
index 0000000000..3cf8c8b1d7
--- /dev/null
+++ b/src/plugins/analyzerbase/analyzerutils.cpp
@@ -0,0 +1,125 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "analyzerutils.h"
+
+#include "analyzerconstants.h"
+
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/icore.h>
+#include <texteditor/basetexteditor.h>
+#include <texteditor/itexteditor.h>
+#include <utils/qtcassert.h>
+
+#include <cplusplus/ExpressionUnderCursor.h>
+#include <cplusplus/ModelManagerInterface.h>
+#include <cplusplus/LookupItem.h>
+#include <cplusplus/TypeOfExpression.h>
+
+// shared/cplusplus includes
+#include <Scope.h>
+#include <Symbol.h>
+
+#include <QtGui/QTextDocumentFragment>
+#include <QtGui/QTextCursor>
+#include <QtGui/QWidget>
+
+using namespace Analyzer;
+using namespace Core;
+
+void moveCursorToEndOfName(QTextCursor *tc) {
+ QTextDocument *doc = tc->document();
+ if (!doc)
+ return;
+
+ QChar ch = doc->characterAt(tc->position());
+ while (ch.isLetterOrNumber() || ch == QLatin1Char('_')) {
+ tc->movePosition(QTextCursor::NextCharacter);
+ ch = doc->characterAt(tc->position());
+ }
+}
+
+// TODO: Can this be improved? This code is ripped from CppEditor, especially CppElementEvaluater
+// We cannot depend on this since CppEditor plugin code is internal and requires building the implementation files ourselves
+CPlusPlus::Symbol *AnalyzerUtils::findSymbolUnderCursor()
+{
+ EditorManager *editorManager = EditorManager::instance();
+ if (!editorManager)
+ return 0;
+ IEditor *editor = editorManager->currentEditor();
+ if (!editor)
+ return 0;
+ TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor *>(editor);
+ if (!textEditor)
+ return 0;
+ TextEditor::BaseTextEditorWidget *editorWidget = qobject_cast<TextEditor::BaseTextEditorWidget *>(editor->widget());
+ if (!editorWidget)
+ return 0;
+
+ QPlainTextEdit *ptEdit = qobject_cast<QPlainTextEdit *>(editor->widget());
+ if (!ptEdit)
+ return 0;
+
+ QTextCursor tc;
+ tc = ptEdit->textCursor();
+ int line = 0;
+ int column = 0;
+ const int pos = tc.position();
+ editorWidget->convertPosition(pos, &line, &column);
+
+ const CPlusPlus::Snapshot &snapshot = CPlusPlus::CppModelManagerInterface::instance()->snapshot();
+ CPlusPlus::Document::Ptr doc = snapshot.document(editor->file()->fileName());
+ QTC_ASSERT(doc, return 0)
+
+ // fetch the expression's code
+ CPlusPlus::ExpressionUnderCursor expressionUnderCursor;
+ moveCursorToEndOfName(&tc);
+ const QString &expression = expressionUnderCursor(tc);
+ CPlusPlus::Scope *scope = doc->scopeAt(line, column);
+
+ CPlusPlus::TypeOfExpression typeOfExpression;
+ typeOfExpression.init(doc, snapshot);
+ const QList<CPlusPlus::LookupItem> &lookupItems = typeOfExpression(expression, scope);
+ if (lookupItems.isEmpty())
+ return 0;
+
+ const CPlusPlus::LookupItem &lookupItem = lookupItems.first(); // ### TODO: select best candidate.
+ return lookupItem.declaration();
+}
+
+QWidget *AnalyzerUtils::createDummyWidget()
+{
+ QWidget *widget = new QWidget;
+ widget->setProperty(Constants::ANALYZER_DUMMYWIDGET_ID, QVariant(true));
+ return widget;
+}
diff --git a/src/plugins/analyzerbase/analyzerutils.h b/src/plugins/analyzerbase/analyzerutils.h
new file mode 100644
index 0000000000..38b5bb3c68
--- /dev/null
+++ b/src/plugins/analyzerbase/analyzerutils.h
@@ -0,0 +1,55 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 ANALYZERUTILS_H
+#define ANALYZERUTILS_H
+
+#include "analyzerbase_global.h"
+
+QT_BEGIN_NAMESPACE
+class QWidget;
+QT_END_NAMESPACE
+
+namespace CPlusPlus
+{
+class Symbol;
+}
+
+namespace AnalyzerUtils
+{
+ ANALYZER_EXPORT CPlusPlus::Symbol *findSymbolUnderCursor();
+
+ ANALYZER_EXPORT QWidget *createDummyWidget();
+}
+
+#endif // ANALYZERUTILS_H
diff --git a/src/plugins/analyzerbase/ianalyzerengine.cpp b/src/plugins/analyzerbase/ianalyzerengine.cpp
index 7f3e7522c9..cba8886012 100644
--- a/src/plugins/analyzerbase/ianalyzerengine.cpp
+++ b/src/plugins/analyzerbase/ianalyzerengine.cpp
@@ -36,9 +36,14 @@
using namespace Analyzer;
-IAnalyzerEngine::IAnalyzerEngine(ProjectExplorer::RunConfiguration *runConfig)
- : QObject(),
- m_runConfig(runConfig)
+IAnalyzerEngine::IAnalyzerEngine(const AnalyzerStartParameters &sp,
+ ProjectExplorer::RunConfiguration *runConfiguration)
+ : m_runConfig(runConfiguration)
+ , m_sp(sp)
+{
+}
+
+IAnalyzerEngine::~IAnalyzerEngine()
{
}
@@ -46,3 +51,8 @@ ProjectExplorer::RunConfiguration *IAnalyzerEngine::runConfiguration() const
{
return m_runConfig;
}
+
+AnalyzerStartParameters IAnalyzerEngine::startParameters() const
+{
+ return m_sp;
+}
diff --git a/src/plugins/analyzerbase/ianalyzerengine.h b/src/plugins/analyzerbase/ianalyzerengine.h
index 6b64724907..5302a12331 100644
--- a/src/plugins/analyzerbase/ianalyzerengine.h
+++ b/src/plugins/analyzerbase/ianalyzerengine.h
@@ -36,8 +36,10 @@
#define IANALYZERENGINE_H
#include "analyzerbase_global.h"
+#include "analyzerstartparameters.h"
#include <projectexplorer/task.h>
+#include <utils/ssh/sshconnection.h>
#include <QtCore/QObject>
#include <QtCore/QString>
@@ -48,28 +50,48 @@ class RunConfiguration;
namespace Analyzer {
+/**
+ * An IAnalyzerEngine instance handles the launch of an analyzation tool.
+ *
+ * It gets created for each launch and deleted when the launch is stopped or ended.
+ */
class ANALYZER_EXPORT IAnalyzerEngine : public QObject
{
Q_OBJECT
+
public:
- explicit IAnalyzerEngine(ProjectExplorer::RunConfiguration *runConfiguration);
+ explicit IAnalyzerEngine(const AnalyzerStartParameters &sp,
+ ProjectExplorer::RunConfiguration *runConfiguration = 0);
+ virtual ~IAnalyzerEngine();
+ /// start analyzation process
virtual void start() = 0;
- /// trigger async stop
+ /// trigger async stop of the analyzation process
virtual void stop() = 0;
+ /// the active run configuration for this engine, might be zero
ProjectExplorer::RunConfiguration *runConfiguration() const;
+ /// the start parameters for this engine
+ AnalyzerStartParameters startParameters() const;
+
signals:
+ /// should be emitted when the debuggee outputted something
void standardOutputReceived(const QString &);
+ /// should be emitted when the debuggee outputted an error
void standardErrorReceived(const QString &);
+ /// can be emitted when you want to show a task, e.g. to display an error
void taskToBeAdded(ProjectExplorer::Task::TaskType type, const QString &description,
const QString &file, int line);
+
+ /// must be emitted when the engine finished
void finished();
- void starting(const IAnalyzerEngine *);
+ /// must be emitted when the engine is starting
+ void starting(const Analyzer::IAnalyzerEngine *);
private:
ProjectExplorer::RunConfiguration *m_runConfig;
+ AnalyzerStartParameters m_sp;
};
} // namespace Analyzer
diff --git a/src/plugins/analyzerbase/ianalyzeroutputpaneadapter.cpp b/src/plugins/analyzerbase/ianalyzeroutputpaneadapter.cpp
new file mode 100644
index 0000000000..bf3119a04a
--- /dev/null
+++ b/src/plugins/analyzerbase/ianalyzeroutputpaneadapter.cpp
@@ -0,0 +1,188 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "ianalyzeroutputpaneadapter.h"
+
+#include "analyzeroutputpane.h"
+#include "ianalyzertool.h"
+
+#include <utils/qtcassert.h>
+
+#include <QtGui/QAbstractItemView>
+#include <QtGui/QItemSelectionModel>
+#include <QtCore/QAbstractItemModel>
+#include <QtCore/QModelIndex>
+
+using namespace Analyzer;
+
+IAnalyzerTool::IAnalyzerTool(QObject *parent) :
+ QObject(parent)
+{
+}
+
+/*!
+ \class Analyzer::IAnalyzerOutputPaneAdapter
+
+ \brief Adapter for handling multiple tools in the common 'Analysis' output pane.
+
+ Provides the tool-specific output pane widget and optionally, a widget to be
+ inserted into into the toolbar. Ownership of them is taken by the output pane.
+ Forwards navigation calls issued by the output pane.
+*/
+
+IAnalyzerOutputPaneAdapter::IAnalyzerOutputPaneAdapter(QObject *parent) :
+ QObject(parent)
+{
+}
+
+IAnalyzerOutputPaneAdapter::~IAnalyzerOutputPaneAdapter()
+{
+}
+
+/*!
+ \class Analyzer::ListItemViewOutputPaneAdapter
+
+ \brief Utility class implementing wrap-around navigation for flat lists.
+
+ Provides an optional mechanism to pop up automatically in case errors show up.
+*/
+
+ListItemViewOutputPaneAdapter::ListItemViewOutputPaneAdapter(QObject *parent) :
+ IAnalyzerOutputPaneAdapter(parent), m_listView(0), m_showOnRowsInserted(true)
+{
+}
+
+void ListItemViewOutputPaneAdapter::connectNavigationSignals(QAbstractItemModel *model)
+{
+ connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
+ this, SIGNAL(navigationStatusChanged()));
+ connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
+ this, SLOT(slotRowsInserted()));
+ connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
+ this, SIGNAL(navigationStatusChanged()));
+ connect(model, SIGNAL(modelReset()),
+ this, SIGNAL(navigationStatusChanged()));
+}
+
+void ListItemViewOutputPaneAdapter::slotRowsInserted()
+{
+ if (m_showOnRowsInserted && !m_listView->isVisible())
+ emit popup(true);
+}
+
+QWidget *ListItemViewOutputPaneAdapter::paneWidget()
+{
+ if (!m_listView) {
+ m_listView = createItemView();
+ if (QAbstractItemModel *model = m_listView->model())
+ connectNavigationSignals(model);
+ }
+ return m_listView;
+}
+
+void ListItemViewOutputPaneAdapter::setFocus()
+{
+ if (m_listView)
+ m_listView->setFocus();
+}
+
+bool ListItemViewOutputPaneAdapter::hasFocus() const
+{
+ return m_listView ? m_listView->hasFocus() : false;
+}
+
+bool ListItemViewOutputPaneAdapter::canFocus() const
+{
+ return true;
+}
+
+bool ListItemViewOutputPaneAdapter::canNavigate() const
+{
+ return true;
+}
+
+bool ListItemViewOutputPaneAdapter::canNext() const
+{
+ return rowCount() > 0;
+}
+
+bool ListItemViewOutputPaneAdapter::canPrevious() const
+{
+ return rowCount() > 0;
+}
+
+void ListItemViewOutputPaneAdapter::goToNext()
+{
+ setCurrentRow((currentRow() + 1) % rowCount());
+}
+
+void ListItemViewOutputPaneAdapter::goToPrev()
+{
+ const int prevRow = currentRow() - 1;
+ setCurrentRow(prevRow >= 0 ? prevRow : rowCount() - 1);
+}
+
+bool ListItemViewOutputPaneAdapter::showOnRowsInserted() const
+{
+ return m_showOnRowsInserted;
+}
+
+void ListItemViewOutputPaneAdapter::setShowOnRowsInserted(bool v)
+{
+ m_showOnRowsInserted = v;
+}
+
+int ListItemViewOutputPaneAdapter::currentRow() const
+{
+ if (m_listView) {
+ const QModelIndex index = m_listView->selectionModel()->currentIndex();
+ if (index.isValid())
+ return index.row();
+ }
+ return -1;
+}
+
+void ListItemViewOutputPaneAdapter::setCurrentRow(int r)
+{
+ QTC_ASSERT(m_listView, return)
+
+ const QModelIndex index = m_listView->model()->index(r, 0);
+ m_listView->selectionModel()->setCurrentIndex(index,
+ QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
+ m_listView->scrollTo(index);
+}
+
+int ListItemViewOutputPaneAdapter::rowCount() const
+{
+ return m_listView ? m_listView->model()->rowCount() : 0;
+}
diff --git a/src/plugins/analyzerbase/ianalyzeroutputpaneadapter.h b/src/plugins/analyzerbase/ianalyzeroutputpaneadapter.h
new file mode 100644
index 0000000000..8ed6d76baf
--- /dev/null
+++ b/src/plugins/analyzerbase/ianalyzeroutputpaneadapter.h
@@ -0,0 +1,107 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 IANALYZEROUTPUTPANEADAPTER_H
+#define IANALYZEROUTPUTPANEADAPTER_H
+
+#include "analyzerbase_global.h"
+
+#include <QtCore/QObject>
+
+QT_FORWARD_DECLARE_CLASS(QAbstractItemView)
+QT_FORWARD_DECLARE_CLASS(QAbstractItemModel)
+QT_FORWARD_DECLARE_CLASS(QWidget)
+
+namespace Analyzer {
+
+class ANALYZER_EXPORT IAnalyzerOutputPaneAdapter : public QObject
+{
+ Q_OBJECT
+public:
+ explicit IAnalyzerOutputPaneAdapter(QObject *parent = 0);
+ virtual ~IAnalyzerOutputPaneAdapter();
+
+ virtual QWidget *toolBarWidget() = 0;
+ virtual QWidget *paneWidget() = 0;
+ virtual void clearContents() = 0;
+ virtual void setFocus() = 0;
+ virtual bool hasFocus() const = 0;
+ virtual bool canFocus() const = 0;
+ virtual bool canNavigate() const = 0;
+ virtual bool canNext() const = 0;
+ virtual bool canPrevious() const = 0;
+ virtual void goToNext() = 0;
+ virtual void goToPrev() = 0;
+
+signals:
+ void popup(bool withFocus);
+ void navigationStatusChanged();
+};
+
+class ANALYZER_EXPORT ListItemViewOutputPaneAdapter : public IAnalyzerOutputPaneAdapter
+{
+ Q_OBJECT
+public:
+ explicit ListItemViewOutputPaneAdapter(QObject *parent = 0);
+
+ virtual QWidget *paneWidget();
+ virtual void setFocus();
+ virtual bool hasFocus() const;
+ virtual bool canFocus() const;
+ virtual bool canNavigate() const;
+ virtual bool canNext() const;
+ virtual bool canPrevious() const;
+ virtual void goToNext();
+ virtual void goToPrev();
+
+ bool showOnRowsInserted() const;
+ void setShowOnRowsInserted(bool v);
+
+protected:
+ int currentRow() const;
+ void setCurrentRow(int);
+ int rowCount() const;
+ void connectNavigationSignals(QAbstractItemModel *);
+ virtual QAbstractItemView *createItemView() = 0;
+
+private slots:
+ void slotRowsInserted();
+
+private:
+ QAbstractItemView *m_listView;
+ bool m_showOnRowsInserted;
+};
+
+}
+
+#endif // IANALYZEROUTPUTPANEADAPTER_H
diff --git a/src/plugins/analyzerbase/ianalyzertool.cpp b/src/plugins/analyzerbase/ianalyzertool.cpp
index 5db373c743..2ea3e72f69 100644
--- a/src/plugins/analyzerbase/ianalyzertool.cpp
+++ b/src/plugins/analyzerbase/ianalyzertool.cpp
@@ -33,161 +33,12 @@
**************************************************************************/
#include "ianalyzertool.h"
-#include "analyzeroutputpane.h"
-
-#include <utils/qtcassert.h>
-
-#include <QtGui/QAbstractItemView>
-#include <QtGui/QItemSelectionModel>
-#include <QtCore/QAbstractItemModel>
-#include <QtCore/QModelIndex>
namespace Analyzer {
-IAnalyzerTool::IAnalyzerTool(QObject *parent) :
- QObject(parent)
-{
-}
-
-/*!
- \class Analyzer::IAnalyzerOutputPaneAdapter
-
- \brief Adapter for handling multiple tools in the common 'Analysis' output pane.
-
- Provides the tool-specific output pane widget and optionally, a widget to be
- inserted into into the toolbar. Ownership of them is taken by the output pane.
- Forwards navigation calls issued by the output pane.
-*/
-
-IAnalyzerOutputPaneAdapter::IAnalyzerOutputPaneAdapter(QObject *parent) :
- QObject(parent)
-{
-}
-
-IAnalyzerOutputPaneAdapter::~IAnalyzerOutputPaneAdapter()
-{
-}
-
-/*!
- \class Analyzer::ListItemViewOutputPaneAdapter
-
- \brief Utility class implementing wrap-around navigation for flat lists.
-
- Provides an optional mechanism to pop up automatically in case errors show up.
-*/
-
-ListItemViewOutputPaneAdapter::ListItemViewOutputPaneAdapter(QObject *parent) :
- IAnalyzerOutputPaneAdapter(parent), m_listView(0), m_showOnRowsInserted(true)
-{
-}
-
-void ListItemViewOutputPaneAdapter::connectNavigationSignals(QAbstractItemModel *model)
-{
- connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
- this, SIGNAL(navigationStatusChanged()));
- connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
- this, SLOT(slotRowsInserted()));
- connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SIGNAL(navigationStatusChanged()));
- connect(model, SIGNAL(modelReset()),
- this, SIGNAL(navigationStatusChanged()));
-}
-
-void ListItemViewOutputPaneAdapter::slotRowsInserted()
-{
- if (m_showOnRowsInserted && !m_listView->isVisible())
- emit popup(true);
-}
-
-QWidget *ListItemViewOutputPaneAdapter::paneWidget()
-{
- if (!m_listView) {
- m_listView = createItemView();
- if (QAbstractItemModel *model = m_listView->model())
- connectNavigationSignals(model);
- }
- return m_listView;
-}
-
-void ListItemViewOutputPaneAdapter::setFocus()
-{
- if (m_listView)
- m_listView->setFocus();
-}
-
-bool ListItemViewOutputPaneAdapter::hasFocus() const
-{
- return m_listView ? m_listView->hasFocus() : false;
-}
-
-bool ListItemViewOutputPaneAdapter::canFocus() const
-{
- return true;
-}
-
-bool ListItemViewOutputPaneAdapter::canNavigate() const
-{
- return true;
-}
-
-bool ListItemViewOutputPaneAdapter::canNext() const
+QString IAnalyzerTool::modeString(ToolMode mode)
{
- return rowCount() > 0;
-}
-
-bool ListItemViewOutputPaneAdapter::canPrevious() const
-{
- return rowCount() > 0;
-}
-
-void ListItemViewOutputPaneAdapter::goToNext()
-{
- setCurrentRow((currentRow() + 1) % rowCount());
-}
-
-void ListItemViewOutputPaneAdapter::goToPrev()
-{
- const int prevRow = currentRow() - 1;
- setCurrentRow(prevRow >= 0 ? prevRow : rowCount() - 1);
-}
-
-bool ListItemViewOutputPaneAdapter::showOnRowsInserted() const
-{
- return m_showOnRowsInserted;
-}
-
-void ListItemViewOutputPaneAdapter::setShowOnRowsInserted(bool v)
-{
- m_showOnRowsInserted = v;
-}
-
-int ListItemViewOutputPaneAdapter::currentRow() const
-{
- if (m_listView) {
- const QModelIndex index = m_listView->selectionModel()->currentIndex();
- if (index.isValid())
- return index.row();
- }
- return -1;
-}
-
-void ListItemViewOutputPaneAdapter::setCurrentRow(int r)
-{
- QTC_ASSERT(m_listView, return; )
- const QModelIndex index = m_listView->model()->index(r, 0);
- m_listView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect|QItemSelectionModel::Current);
- m_listView->scrollTo(index);
-}
-
-int ListItemViewOutputPaneAdapter::rowCount() const
-{
- return m_listView ? m_listView->model()->rowCount() : 0;
-}
-
-// -------------IAnalyzerTool
-QString IAnalyzerTool::modeString()
-{
- switch (mode()) {
+ switch (mode) {
case IAnalyzerTool::DebugMode:
return tr("Debug");
case IAnalyzerTool::ReleaseMode:
@@ -203,4 +54,9 @@ IAnalyzerOutputPaneAdapter *IAnalyzerTool::outputPaneAdapter()
return 0;
}
+QWidget *IAnalyzerTool::createControlWidget()
+{
+ return 0;
+}
+
} // namespace Analyzer
diff --git a/src/plugins/analyzerbase/ianalyzertool.h b/src/plugins/analyzerbase/ianalyzertool.h
index 66dcf54a8b..8524c535f2 100644
--- a/src/plugins/analyzerbase/ianalyzertool.h
+++ b/src/plugins/analyzerbase/ianalyzertool.h
@@ -39,9 +39,6 @@
#include <QtCore/QObject>
-QT_FORWARD_DECLARE_CLASS(QAbstractItemView)
-QT_FORWARD_DECLARE_CLASS(QAbstractItemModel)
-
namespace ProjectExplorer {
class RunConfiguration;
}
@@ -51,79 +48,36 @@ class IPlugin;
}
namespace Analyzer {
-class IAnalyzerEngine;
-
-class ANALYZER_EXPORT IAnalyzerOutputPaneAdapter : public QObject
-{
- Q_OBJECT
-public:
- explicit IAnalyzerOutputPaneAdapter(QObject *parent = 0);
- virtual ~IAnalyzerOutputPaneAdapter();
-
- virtual QWidget *toolBarWidget() = 0;
- virtual QWidget *paneWidget() = 0;
- virtual void clearContents() = 0;
- virtual void setFocus() = 0;
- virtual bool hasFocus() const = 0;
- virtual bool canFocus() const = 0;
- virtual bool canNavigate() const = 0;
- virtual bool canNext() const = 0;
- virtual bool canPrevious() const = 0;
- virtual void goToNext() = 0;
- virtual void goToPrev() = 0;
-
-signals:
- void popup(bool withFocus);
- void navigationStatusChanged();
-};
-class ANALYZER_EXPORT ListItemViewOutputPaneAdapter : public IAnalyzerOutputPaneAdapter
-{
- Q_OBJECT
-public:
- explicit ListItemViewOutputPaneAdapter(QObject *parent = 0);
-
- virtual QWidget *paneWidget();
- virtual void setFocus();
- virtual bool hasFocus() const;
- virtual bool canFocus() const;
- virtual bool canNavigate() const;
- virtual bool canNext() const;
- virtual bool canPrevious() const;
- virtual void goToNext();
- virtual void goToPrev();
-
- bool showOnRowsInserted() const;
- void setShowOnRowsInserted(bool v);
-
-protected:
- int currentRow() const;
- void setCurrentRow(int);
- int rowCount() const;
- void connectNavigationSignals(QAbstractItemModel *);
- virtual QAbstractItemView *createItemView() = 0;
-
-private slots:
- void slotRowsInserted();
-
-private:
- QAbstractItemView *m_listView;
- bool m_showOnRowsInserted;
-};
+class AnalyzerStartParameters;
+class IAnalyzerOutputPaneAdapter;
+class IAnalyzerEngine;
+/**
+ * This class represents an analyzation tool, e.g. "Valgrind Memcheck".
+ * @code
+ * bool YourPlugin::initialize(const QStringList &arguments, QString *errorString)
+ * {
+ * AnalyzerManager::instance()->addTool(new MemcheckTool(this));
+ * return true;
+ * }
+ * @endcode
+ */
class ANALYZER_EXPORT IAnalyzerTool : public QObject
{
Q_OBJECT
public:
explicit IAnalyzerTool(QObject *parent = 0);
+ /// @return unique ID for this tool
virtual QString id() const = 0;
+ /// @return user readable display name for this tool
virtual QString displayName() const = 0;
/**
* The mode in which this tool should be run preferrably
*
- * e.g. memcheck requires debug symbols, hence DebugMode is prefferred.
+ * memcheck, for example, requires debug symbols, hence DebugMode is preferred.
* otoh callgrind should look at optimized code, hence ReleaseMode.
*/
enum ToolMode {
@@ -133,13 +87,27 @@ public:
};
virtual ToolMode mode() const = 0;
- QString modeString();
+ static QString modeString(ToolMode mode);
+ /**
+ * The implementation should setup widgets for the output pane here and optionally add
+ * dock widgets in the analyzation mode if wanted.
+ */
virtual void initialize(ExtensionSystem::IPlugin *plugin) = 0;
+ /// gets called after all analyzation tools where initialized.
+ virtual void extensionsInitialized() = 0;
virtual IAnalyzerOutputPaneAdapter *outputPaneAdapter();
+ /// subclass to return a control widget which will be shown
+ /// in the output pane when this tool is selected
+ virtual QWidget *createControlWidget();
+
+ /// @return a new engine for the given start parameters. Called each time the tool is launched.
+ virtual IAnalyzerEngine *createEngine(const AnalyzerStartParameters &sp,
+ ProjectExplorer::RunConfiguration *runConfiguration = 0) = 0;
- virtual IAnalyzerEngine *createEngine(ProjectExplorer::RunConfiguration *runConfiguration) = 0;
+ /// @return true when this tool can be run remotely, e.g. on a meego or maemo device
+ virtual bool canRunRemotely() const = 0;
};
} // namespace Analyzer
diff --git a/src/plugins/analyzerbase/startremotedialog.cpp b/src/plugins/analyzerbase/startremotedialog.cpp
new file mode 100644
index 0000000000..3c51231fbc
--- /dev/null
+++ b/src/plugins/analyzerbase/startremotedialog.cpp
@@ -0,0 +1,144 @@
+/**************************************************************************
+ * *
+ ** This file is part of Qt Creator Instrumentation Tools
+ **
+ ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ **
+ ** Contact: Nokia Corporation (qt-info@nokia.com)
+ **
+ ** Commercial Usage
+ **
+ ** Licensees holding valid Qt Commercial licenses may use this file in
+ ** accordance with the Qt Commercial License Agreement provided with the
+ ** Software or, alternatively, in accordance with the terms contained in
+ ** a written agreement between you and Nokia.
+ **
+ ** GNU Lesser General Public License Usage
+ **
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 2.1 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** If you are unsure which license is appropriate for your use, please
+ ** contact the sales department at http://qt.nokia.com/contact.
+ **
+ **************************************************************************/
+
+#include "startremotedialog.h"
+
+#include "ui_startremotedialog.h"
+
+#include <QtGui/QPushButton>
+
+#include <coreplugin/icore.h>
+
+namespace Analyzer {
+
+StartRemoteDialog::StartRemoteDialog(QWidget *parent, Qt::WindowFlags f)
+: QDialog(parent, f)
+, m_ui(new Ui::StartRemoteDialog)
+{
+ m_ui->setupUi(this);
+
+ m_ui->keyFile->setExpectedKind(Utils::PathChooser::File);
+
+ QSettings *settings = Core::ICore::instance()->settings();
+ settings->beginGroup("AnalyzerStartRemoteDialog");
+ m_ui->host->setText(settings->value("host").toString());
+ m_ui->port->setValue(settings->value("port", 22).toInt());
+ m_ui->user->setText(settings->value("user", qgetenv("USER")).toString());
+ m_ui->keyFile->setPath(settings->value("keyFile").toString());
+ m_ui->executable->setText(settings->value("executable").toString());
+ m_ui->workingDirectory->setText(settings->value("workingDirectory").toString());
+ m_ui->arguments->setText(settings->value("arguments").toString());
+ settings->endGroup();
+
+ connect(m_ui->host, SIGNAL(textChanged(QString)),
+ this, SLOT(validate()));
+ connect(m_ui->port, SIGNAL(valueChanged(int)),
+ this, SLOT(validate()));
+ connect(m_ui->password, SIGNAL(textChanged(QString)),
+ this, SLOT(validate()));
+ connect(m_ui->keyFile, SIGNAL(changed(QString)),
+ this, SLOT(validate()));
+
+ connect(m_ui->executable, SIGNAL(textChanged(QString)),
+ this, SLOT(validate()));
+ connect(m_ui->workingDirectory, SIGNAL(textChanged(QString)),
+ this, SLOT(validate()));
+ connect(m_ui->arguments, SIGNAL(textChanged(QString)),
+ this, SLOT(validate()));
+
+ connect(m_ui->buttonBox, SIGNAL(accepted()),
+ this, SLOT(accept()));
+ connect(m_ui->buttonBox, SIGNAL(rejected()),
+ this, SLOT(reject()));
+
+ validate();
+}
+
+StartRemoteDialog::~StartRemoteDialog()
+{
+ delete m_ui;
+}
+
+void StartRemoteDialog::accept()
+{
+ QSettings *settings = Core::ICore::instance()->settings();
+ settings->beginGroup("AnalyzerStartRemoteDialog");
+ settings->setValue("host", m_ui->host->text());
+ settings->setValue("port", m_ui->port->value());
+ settings->setValue("user", m_ui->user->text());
+ settings->setValue("keyFile", m_ui->keyFile->path());
+ settings->setValue("executable", m_ui->executable->text());
+ settings->setValue("workingDirectory", m_ui->workingDirectory->text());
+ settings->setValue("arguments", m_ui->arguments->text());
+ settings->endGroup();
+
+ QDialog::accept();
+}
+
+void StartRemoteDialog::validate()
+{
+ bool valid = !m_ui->host->text().isEmpty() && !m_ui->user->text().isEmpty()
+ && !m_ui->executable->text().isEmpty();
+ valid = valid && (!m_ui->password->text().isEmpty() || m_ui->keyFile->isValid());
+ m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(valid);
+}
+
+Utils::SshConnectionParameters StartRemoteDialog::sshParams() const
+{
+ Utils::SshConnectionParameters params(Utils::SshConnectionParameters::NoProxy);
+ params.host = m_ui->host->text();
+ params.userName = m_ui->user->text();
+ if (m_ui->keyFile->isValid()) {
+ params.authenticationType = Utils::SshConnectionParameters::AuthenticationByKey;
+ params.privateKeyFile = m_ui->keyFile->path();
+ } else {
+ params.authenticationType = Utils::SshConnectionParameters::AuthenticationByPassword;
+ params.password = m_ui->password->text();
+ }
+ params.port = m_ui->port->value();
+ params.timeout = 1;
+ return params;
+}
+
+QString StartRemoteDialog::executable() const
+{
+ return m_ui->executable->text();
+}
+
+QString StartRemoteDialog::arguments() const
+{
+ return m_ui->arguments->text();
+}
+
+QString StartRemoteDialog::workingDirectory() const
+{
+ return m_ui->workingDirectory->text();
+}
+
+}
diff --git a/src/plugins/analyzerbase/startremotedialog.h b/src/plugins/analyzerbase/startremotedialog.h
new file mode 100644
index 0000000000..ad92857f92
--- /dev/null
+++ b/src/plugins/analyzerbase/startremotedialog.h
@@ -0,0 +1,68 @@
+/**************************************************************************
+ * *
+ ** This file is part of Qt Creator Instrumentation Tools
+ **
+ ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ **
+ ** Contact: Nokia Corporation (qt-info@nokia.com)
+ **
+ ** Commercial Usage
+ **
+ ** Licensees holding valid Qt Commercial licenses may use this file in
+ ** accordance with the Qt Commercial License Agreement provided with the
+ ** Software or, alternatively, in accordance with the terms contained in
+ ** a written agreement between you and Nokia.
+ **
+ ** GNU Lesser General Public License Usage
+ **
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 2.1 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** If you are unsure which license is appropriate for your use, please
+ ** contact the sales department at http://qt.nokia.com/contact.
+ **
+ **************************************************************************/
+
+#ifndef STARTREMOTEDIALOG_H
+#define STARTREMOTEDIALOG_H
+
+#include <QtGui/QDialog>
+
+#include <utils/ssh/sshconnection.h>
+
+QT_BEGIN_NAMESPACE
+QT_END_NAMESPACE
+
+namespace Analyzer {
+
+namespace Ui {
+class StartRemoteDialog;
+}
+
+class StartRemoteDialog : public QDialog {
+ Q_OBJECT
+
+public:
+ explicit StartRemoteDialog(QWidget *parent = 0, Qt::WindowFlags f = 0);
+ virtual ~StartRemoteDialog();
+
+ Utils::SshConnectionParameters sshParams() const;
+ QString executable() const;
+ QString arguments() const;
+ QString workingDirectory() const;
+
+private slots:
+ void validate();
+ virtual void accept();
+
+private:
+ Ui::StartRemoteDialog *m_ui;
+};
+
+}
+
+#endif // STARTREMOTEDIALOG_H
diff --git a/src/plugins/analyzerbase/startremotedialog.ui b/src/plugins/analyzerbase/startremotedialog.ui
new file mode 100644
index 0000000000..dad3f4adf6
--- /dev/null
+++ b/src/plugins/analyzerbase/startremotedialog.ui
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Analyzer::StartRemoteDialog</class>
+ <widget class="QDialog" name="Analyzer::StartRemoteDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>446</width>
+ <height>296</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Start Debugger</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Remote</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout_2">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::ExpandingFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Host:</string>
+ </property>
+ <property name="buddy">
+ <cstring>host</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="host"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>User:</string>
+ </property>
+ <property name="buddy">
+ <cstring>user</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="user"/>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="toolTip">
+ <string>You need to pass either a password or a SSH Key.</string>
+ </property>
+ <property name="text">
+ <string>Password:</string>
+ </property>
+ <property name="buddy">
+ <cstring>password</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLineEdit" name="password">
+ <property name="echoMode">
+ <enum>QLineEdit::Password</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Port</string>
+ </property>
+ <property name="buddy">
+ <cstring>port</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QSpinBox" name="port">
+ <property name="maximum">
+ <number>65535</number>
+ </property>
+ <property name="singleStep">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>22</number>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_8">
+ <property name="toolTip">
+ <string>You need to pass either a password or a SSH Key.</string>
+ </property>
+ <property name="text">
+ <string>Private Key:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="Utils::PathChooser" name="keyFile" native="true"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Target</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Executable:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="executable"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>Arguments:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="arguments"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>Working Directory:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="workingDirectory"/>
+ </item>
+ </layout>
+ </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>Utils::PathChooser</class>
+ <extends>QWidget</extends>
+ <header location="global">utils/pathchooser.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>host</tabstop>
+ <tabstop>user</tabstop>
+ <tabstop>password</tabstop>
+ <tabstop>buttonBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/bazaar/bazaarclient.cpp b/src/plugins/bazaar/bazaarclient.cpp
index 328ad292da..f1a8c54e13 100644
--- a/src/plugins/bazaar/bazaarclient.cpp
+++ b/src/plugins/bazaar/bazaarclient.cpp
@@ -35,6 +35,10 @@
#include <vcsbase/vcsbaseclientsettings.h>
#include <vcsbase/vcsbaseplugin.h>
+#include <vcsbase/vcsbaseeditor.h>
+#include <vcsbase/vcsbaseeditorparameterwidget.h>
+
+#include <utils/qtcassert.h>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
@@ -313,9 +317,23 @@ QStringList BazaarClient::annotateArguments(const QString &file,
return args << file;
}
-QStringList BazaarClient::diffArguments(const QStringList &files) const
+QStringList BazaarClient::diffArguments(const QStringList &files,
+ const ExtraCommandOptions &extraOptions) const
{
QStringList args;
+ foreach (const QVariant &extraOption, extraOptions) {
+ switch (extraOption.type()) {
+ case QVariant::String:
+ args.append(extraOption.toString());
+ break;
+ case QVariant::StringList:
+ args.append(extraOption.toStringList());
+ break;
+ default:
+ QTC_ASSERT(false, continue; )
+ break;
+ }
+ }
if (!files.isEmpty())
args.append(files);
return args;
@@ -323,7 +341,7 @@ QStringList BazaarClient::diffArguments(const QStringList &files) const
QStringList BazaarClient::logArguments(const QStringList &files) const
{
- return diffArguments(files);
+ return diffArguments(files, ExtraCommandOptions());
}
QStringList BazaarClient::statusArguments(const QString &file) const
@@ -338,7 +356,7 @@ QStringList BazaarClient::statusArguments(const QString &file) const
QStringList BazaarClient::viewArguments(const QString &revision) const
{
QStringList args(QLatin1String("log"));
- args << QLatin1String("-p") << QLatin1String("--gnu-changelog")
+ args << QLatin1String("-p") << QLatin1String("-v")
<< QLatin1String("-r") << revision;
return args;
}
@@ -409,5 +427,78 @@ QStringList BazaarClient::commonPullOrPushArguments(const ExtraCommandOptions &e
return args;
}
+// Collect all parameters required for a diff to be able to associate them
+// with a diff editor and re-run the diff with parameters.
+struct BazaarDiffParameters
+{
+ QString workingDir;
+ QStringList files;
+ VCSBase::VCSBaseClient::ExtraCommandOptions extraOptions;
+};
+
+// Parameter widget controlling whitespace diff mode, associated with a parameter
+class BazaarDiffParameterWidget : public VCSBase::VCSBaseEditorParameterWidget
+{
+ Q_OBJECT
+public:
+ explicit BazaarDiffParameterWidget(const BazaarDiffParameters &p, QWidget *parent = 0);
+
+signals:
+ void reRunDiff(const Bazaar::Internal::BazaarDiffParameters &);
+
+private slots:
+ void triggerReRun();
+
+private:
+ const BazaarDiffParameters m_parameters;
+};
+
+BazaarDiffParameterWidget::BazaarDiffParameterWidget(const BazaarDiffParameters &p, QWidget *parent) :
+ VCSBase::VCSBaseEditorParameterWidget(parent), m_parameters(p)
+{
+ addIgnoreWhiteSpaceButton(QLatin1String("-w"));
+ addIgnoreBlankLinesButton(QLatin1String("-B"));
+ connect(this, SIGNAL(argumentsChanged()), this, SLOT(triggerReRun()));
+}
+
+void BazaarDiffParameterWidget::triggerReRun()
+{
+ BazaarDiffParameters effectiveParameters = m_parameters;
+ // Bazaar wants "--diff-options=-w -B.."
+ const QStringList formatArguments = arguments();
+ if (!formatArguments.isEmpty()) {
+ const QString a = QLatin1String("--diff-options=")
+ + formatArguments.join(QString(QLatin1Char(' ')));
+ effectiveParameters.extraOptions.insert(42, QVariant(a));
+ }
+ emit reRunDiff(effectiveParameters);
+}
+
+void BazaarClient::bazaarDiff(const Bazaar::Internal::BazaarDiffParameters &p)
+{
+ diff(p.workingDir, p.files, p.extraOptions);
+}
+
+void BazaarClient::initializeDiffEditor(const QString &workingDir, const QStringList &files,
+ const VCSBase::VCSBaseClient::ExtraCommandOptions &extra,
+ VCSBase::VCSBaseEditorWidget *diffEditorWidget)
+{
+ // Wire up the parameter widget to trigger a re-run on
+ // parameter change and 'revert' from inside the diff editor.
+ BazaarDiffParameters parameters;
+ parameters.workingDir = workingDir;
+ parameters.files = files;
+ parameters.extraOptions = extra;
+ diffEditorWidget->setRevertDiffChunkEnabled(true);
+ BazaarDiffParameterWidget *pw = new BazaarDiffParameterWidget(parameters);
+ connect(pw, SIGNAL(reRunDiff(Bazaar::Internal::BazaarDiffParameters)),
+ this, SLOT(bazaarDiff(Bazaar::Internal::BazaarDiffParameters)));
+ connect(diffEditorWidget, SIGNAL(diffChunkReverted(VCSBase::DiffChunk)),
+ pw, SLOT(triggerReRun()));
+ diffEditorWidget->setConfigurationWidget(pw);
+}
+
} //namespace Internal
} // namespace Bazaar
+
+#include "bazaarclient.moc"
diff --git a/src/plugins/bazaar/bazaarclient.h b/src/plugins/bazaar/bazaarclient.h
index 9d5d0a3773..9076642de3 100644
--- a/src/plugins/bazaar/bazaarclient.h
+++ b/src/plugins/bazaar/bazaarclient.h
@@ -38,9 +38,11 @@
namespace Bazaar {
namespace Internal {
+struct BazaarDiffParameters;
class BazaarClient : public VCSBase::VCSBaseClient
{
+ Q_OBJECT
public:
enum ExtraOptionId
{
@@ -72,33 +74,40 @@ public:
bool synchronousSetUserId();
BranchInfo synchronousBranchQuery(const QString &repositoryRoot) const;
- virtual QString findTopLevelForFile(const QFileInfo &file) const;
+ QString findTopLevelForFile(const QFileInfo &file) const;
+
+private slots:
+ void bazaarDiff(const Bazaar::Internal::BazaarDiffParameters &p);
protected:
- virtual QString vcsEditorKind(VCSCommand cmd) const;
+ QString vcsEditorKind(VCSCommand cmd) const;
- virtual QStringList cloneArguments(const QString &srcLocation,
- const QString &dstLocation,
- const ExtraCommandOptions &extraOptions) const;
- virtual QStringList pullArguments(const QString &srcLocation,
- const ExtraCommandOptions &extraOptions) const;
- virtual QStringList pushArguments(const QString &dstLocation,
- const ExtraCommandOptions &extraOptions) const;
- virtual QStringList commitArguments(const QStringList &files,
- const QString &commitMessageFile,
- const ExtraCommandOptions &extraOptions) const;
- virtual QStringList importArguments(const QStringList &files) const;
- virtual QStringList updateArguments(const QString &revision) const;
- virtual QStringList revertArguments(const QString &file, const QString &revision) const;
- virtual QStringList revertAllArguments(const QString &revision) const;
- virtual QStringList annotateArguments(const QString &file,
- const QString &revision, int lineNumber) const;
- virtual QStringList diffArguments(const QStringList &files) const;
- virtual QStringList logArguments(const QStringList &files) const;
- virtual QStringList statusArguments(const QString &file) const;
- virtual QStringList viewArguments(const QString &revision) const;
+ QStringList cloneArguments(const QString &srcLocation,
+ const QString &dstLocation,
+ const ExtraCommandOptions &extraOptions) const;
+ QStringList pullArguments(const QString &srcLocation,
+ const ExtraCommandOptions &extraOptions) const;
+ QStringList pushArguments(const QString &dstLocation,
+ const ExtraCommandOptions &extraOptions) const;
+ QStringList commitArguments(const QStringList &files,
+ const QString &commitMessageFile,
+ const ExtraCommandOptions &extraOptions) const;
+ QStringList importArguments(const QStringList &files) const;
+ QStringList updateArguments(const QString &revision) const;
+ QStringList revertArguments(const QString &file, const QString &revision) const;
+ QStringList revertAllArguments(const QString &revision) const;
+ QStringList annotateArguments(const QString &file,
+ const QString &revision, int lineNumber) const;
+ QStringList diffArguments(const QStringList &files,
+ const ExtraCommandOptions &extraOptions) const;
+ void initializeDiffEditor(const QString &workingDir, const QStringList &files,
+ const VCSBase::VCSBaseClient::ExtraCommandOptions &extra,
+ VCSBase::VCSBaseEditorWidget *diffEditorWidget);
+ QStringList logArguments(const QStringList &files) const;
+ QStringList statusArguments(const QString &file) const;
+ QStringList viewArguments(const QString &revision) const;
- virtual QPair<QString, QString> parseStatusLine(const QString &line) const;
+ QPair<QString, QString> parseStatusLine(const QString &line) const;
private:
QStringList commonPullOrPushArguments(const ExtraCommandOptions &extraOptions) const;
friend class CloneWizard;
diff --git a/src/plugins/bazaar/bazaareditor.cpp b/src/plugins/bazaar/bazaareditor.cpp
index 0a85272fa3..d90ad5f149 100644
--- a/src/plugins/bazaar/bazaareditor.cpp
+++ b/src/plugins/bazaar/bazaareditor.cpp
@@ -106,16 +106,22 @@ VCSBase::BaseAnnotationHighlighter *BazaarEditor::createAnnotationHighlighter(co
return new BazaarAnnotationHighlighter(changes);
}
-QString BazaarEditor::fileNameFromDiffSpecification(const QTextBlock &diffFileSpec) const
+QString BazaarEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
{
- const QString filechangeId(QLatin1String("+++ b/"));
- QTextBlock::iterator iterator;
- for (iterator = diffFileSpec.begin(); !(iterator.atEnd()); iterator++) {
- QTextFragment fragment = iterator.fragment();
- if(fragment.isValid()) {
- if (fragment.text().startsWith(filechangeId)) {
- const QString filename = fragment.text().remove(0, filechangeId.size());
- return findDiffFile(filename, BazaarPlugin::instance()->versionControl());
+ // Check for:
+ // === modified file 'mainwindow.cpp'
+ // --- mainwindow.cpp<tab>2011-03-28 08:12:28 +0000
+ // +++ mainwindow.cpp<tab>2011-03-28 08:53:55 +0000
+ const QString newFileIndicator = QLatin1String("+++ ");
+ const QChar tab = QLatin1Char('\t');
+ for (QTextBlock block = inBlock; block.isValid(); block = block.previous()) {
+ const QString line = block.text();
+ if (line.startsWith(newFileIndicator)) {
+ const int tabIndex = line.indexOf(tab);
+ if (tabIndex != -1) {
+ const QString diffFileName = line.mid(newFileIndicator.size(),
+ tabIndex - newFileIndicator.size());
+ return findDiffFile(diffFileName);
}
}
}
diff --git a/src/plugins/bazaar/constants.h b/src/plugins/bazaar/constants.h
index 6bf16678c8..e944d33592 100644
--- a/src/plugins/bazaar/constants.h
+++ b/src/plugins/bazaar/constants.h
@@ -43,7 +43,6 @@ const char * const BAZAARDEFAULT = "bzr";
//changeset identifiers
const char * const CHANGESET_ID = "([0-9]+)"; // match and capture
const char * const CHANGESET_ID_EXACT = "[0-9]+"; // match
-const char * const DIFF_ID = "^[-+]{3,3} [ab]{1,1}.*"; // match e.g. +++ b/filename
//BaseEditorParameters
const char * const COMMANDLOG_ID = "Bazaar Command Log Editor";
@@ -95,7 +94,6 @@ const char * const LOGMULTI = "Bazaar.Action.Logmulti";
const char * const PULL = "Bazaar.Action.Pull";
const char * const PUSH = "Bazaar.Action.Push";
const char * const UPDATE = "Bazaar.Action.Update";
-const char * const CLONE = "Bazaar.Action.Clone";
const char * const COMMIT = "Bazaar.Action.Commit";
const char * const CREATE_REPOSITORY = "Bazaar.Action.CreateRepository";
diff --git a/src/plugins/bineditor/bineditorplugin.cpp b/src/plugins/bineditor/bineditorplugin.cpp
index 34932eb3d6..f76e8589f8 100644
--- a/src/plugins/bineditor/bineditorplugin.cpp
+++ b/src/plugins/bineditor/bineditorplugin.cpp
@@ -317,6 +317,7 @@ class BinEditorInterface : public Core::IEditor
public:
BinEditorInterface(BinEditor *editor)
{
+ setWidget(editor);
m_editor = editor;
m_file = new BinEditorFile(m_editor);
m_context.add(Core::Constants::K_DEFAULT_BINARY_EDITOR_ID);
@@ -350,10 +351,6 @@ public:
delete m_editor;
}
- QWidget *widget() { return m_editor; }
-
- Core::Context context() const { return m_context; }
-
bool createNew(const QString & /* contents */ = QString()) {
m_editor->clear();
m_file->setFilename(QString());
@@ -391,7 +388,6 @@ private:
BinEditor *m_editor;
QString m_displayName;
BinEditorFile *m_file;
- Core::Context m_context;
QToolBar *m_toolBar;
QLineEdit *m_addressEdit;
};
diff --git a/src/plugins/bookmarks/bookmark.cpp b/src/plugins/bookmarks/bookmark.cpp
index 1abc556468..3e0fbe5797 100644
--- a/src/plugins/bookmarks/bookmark.cpp
+++ b/src/plugins/bookmarks/bookmark.cpp
@@ -39,7 +39,6 @@
using namespace Bookmarks::Internal;
Bookmark::Bookmark(const QString& fileName, int lineNumber, BookmarkManager *manager) :
- BaseTextMark(fileName, lineNumber),
m_manager(manager),
m_fileInfo(fileName),
m_fileName(fileName),
@@ -47,11 +46,9 @@ Bookmark::Bookmark(const QString& fileName, int lineNumber, BookmarkManager *man
m_path(m_fileInfo.path()),
m_lineNumber(lineNumber)
{
-}
-
-QIcon Bookmark::icon() const
-{
- return m_manager->bookmarkIcon();
+ setLocation(fileName, lineNumber),
+ setPriority(TextEditor::ITextMark::LowPriority);
+ setIcon(m_manager->bookmarkIcon());
}
void Bookmark::removedFromEditor()
diff --git a/src/plugins/bookmarks/bookmark.h b/src/plugins/bookmarks/bookmark.h
index dcfa1a4a8c..1e0ade8874 100644
--- a/src/plugins/bookmarks/bookmark.h
+++ b/src/plugins/bookmarks/bookmark.h
@@ -53,19 +53,16 @@ class Bookmark : public TextEditor::BaseTextMark
public:
Bookmark(const QString &fileName, int lineNumber, BookmarkManager *manager);
- QIcon icon() const;
-
void updateLineNumber(int lineNumber);
void updateBlock(const QTextBlock &block);
void removedFromEditor();
- TextEditor::ITextMark::Priority priority() const { return TextEditor::ITextMark::LowPriority; }
QString filePath() const;
QString fileName() const;
QString path() const;
QString lineText() const;
- inline int lineNumber() const { return m_lineNumber; }
+ int lineNumber() const { return m_lineNumber; }
private:
BookmarkManager *m_manager;
diff --git a/src/plugins/bookmarks/bookmarkmanager.cpp b/src/plugins/bookmarks/bookmarkmanager.cpp
index 01bd35ecff..b07df80de2 100644
--- a/src/plugins/bookmarks/bookmarkmanager.cpp
+++ b/src/plugins/bookmarks/bookmarkmanager.cpp
@@ -299,21 +299,11 @@ void BookmarkView::gotoBookmark(const QModelIndex &index)
// BookmarkContext
////
-BookmarkContext::BookmarkContext(BookmarkView *widget)
- : Core::IContext(widget),
- m_bookmarkView(widget),
- m_context(Constants::BOOKMARKS_CONTEXT)
+BookmarkContext::BookmarkContext(QWidget *widget)
+ : Core::IContext(widget)
{
-}
-
-Context BookmarkContext::context() const
-{
- return m_context;
-}
-
-QWidget *BookmarkContext::widget()
-{
- return m_bookmarkView;
+ setWidget(widget);
+ setContext(Core::Context(Constants::BOOKMARKS_CONTEXT));
}
////
@@ -485,7 +475,7 @@ void BookmarkManager::removeBookmark(Bookmark *bookmark)
saveBookmarks();
}
-Bookmark *BookmarkManager::bookmarkForIndex(QModelIndex index)
+Bookmark *BookmarkManager::bookmarkForIndex(const QModelIndex &index)
{
if (!index.isValid() || index.row() >= m_bookmarksList.size())
return 0;
@@ -493,7 +483,7 @@ Bookmark *BookmarkManager::bookmarkForIndex(QModelIndex index)
}
-bool BookmarkManager::gotoBookmark(Bookmark* bookmark)
+bool BookmarkManager::gotoBookmark(Bookmark *bookmark)
{
using namespace TextEditor;
if (ITextEditor *editor = BaseTextEditorWidget::openEditorAt(bookmark->filePath(), bookmark->lineNumber()))
@@ -523,7 +513,7 @@ void BookmarkManager::documentPrevNext(bool next)
int lastLine = -1;
int prevLine = -1;
int nextLine = -1;
- const QList<Bookmark*> marks = m_bookmarksMap.value(fi.path())->values(fi.fileName());
+ const QList<Bookmark *> marks = m_bookmarksMap.value(fi.path())->values(fi.fileName());
for (int i = 0; i < marks.count(); ++i) {
int markLine = marks.at(i)->lineNumber();
if (firstLine == -1 || firstLine > markLine)
@@ -676,7 +666,7 @@ void BookmarkManager::moveDown()
}
/* Returns the bookmark at the given file and line number, or 0 if no such bookmark exists. */
-Bookmark* BookmarkManager::findBookmark(const QString &path, const QString &fileName, int lineNumber)
+Bookmark *BookmarkManager::findBookmark(const QString &path, const QString &fileName, int lineNumber)
{
if (m_bookmarksMap.contains(path)) {
foreach (Bookmark *bookmark, m_bookmarksMap.value(path)->values(fileName)) {
@@ -773,7 +763,6 @@ void BookmarkManager::loadBookmarks()
BookmarkViewFactory::BookmarkViewFactory(BookmarkManager *bm)
: m_manager(bm)
{
-
}
QString BookmarkViewFactory::displayName() const
diff --git a/src/plugins/bookmarks/bookmarkmanager.h b/src/plugins/bookmarks/bookmarkmanager.h
index c95af18285..96a49a57b0 100644
--- a/src/plugins/bookmarks/bookmarkmanager.h
+++ b/src/plugins/bookmarks/bookmarkmanager.h
@@ -75,7 +75,7 @@ public:
void updateBookmark(Bookmark *bookmark);
void removeBookmark(Bookmark *bookmark); // Does not remove the mark
void removeAllBookmarks();
- Bookmark *bookmarkForIndex(QModelIndex index);
+ Bookmark *bookmarkForIndex(const QModelIndex &index);
enum State { NoBookMarks, HasBookMarks, HasBookmarksInDocument };
State state() const;
@@ -163,12 +163,7 @@ private:
class BookmarkContext : public Core::IContext
{
public:
- BookmarkContext(BookmarkView *widget);
- virtual Core::Context context() const;
- virtual QWidget *widget();
-private:
- BookmarkView *m_bookmarkView;
- const Core::Context m_context;
+ BookmarkContext(QWidget *widget);
};
class BookmarkViewFactory : public Core::INavigationWidgetFactory
diff --git a/src/plugins/callgrind/Callgrind.pluginspec.in b/src/plugins/callgrind/Callgrind.pluginspec.in
new file mode 100644
index 0000000000..e2ca63846b
--- /dev/null
+++ b/src/plugins/callgrind/Callgrind.pluginspec.in
@@ -0,0 +1,22 @@
+<plugin name=\"Callgrind\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2011 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>Code Analyzer</category>
+ <description>Valgrind Callgrind Tool Plugin</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"AnalyzerBase\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ValgrindToolBase\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/callgrind/callgrind.pri b/src/plugins/callgrind/callgrind.pri
new file mode 100644
index 0000000000..3453c69508
--- /dev/null
+++ b/src/plugins/callgrind/callgrind.pri
@@ -0,0 +1,5 @@
+include(callgrind_dependencies.pri)
+
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+LIBS *= -l$$qtLibraryName(Callgrind)
diff --git a/src/plugins/callgrind/callgrind.pro b/src/plugins/callgrind/callgrind.pro
new file mode 100644
index 0000000000..c3fd62e347
--- /dev/null
+++ b/src/plugins/callgrind/callgrind.pro
@@ -0,0 +1,43 @@
+TEMPLATE = lib
+TARGET = Callgrind
+
+DEFINES += CALLGRIND_LIBRARY
+
+include(../../qtcreatorplugin.pri)
+include(callgrind_dependencies.pri)
+
+# Callgrind files
+
+HEADERS += \
+ callgrindplugin.h \
+ callgrind_global.h \
+ callgrindconfigwidget.h \
+ callgrindcostdelegate.h \
+ callgrindcostview.h \
+ callgrindhelper.h \
+ callgrindnamedelegate.h \
+ callgrindsettings.h \
+ callgrindtool.h \
+ callgrindvisualisation.h \
+ callgrindwidgethandler.h \
+ callgrindengine.h \
+ workarounds.h \
+ callgrindtextmark.h
+
+SOURCES += \
+ callgrindplugin.cpp \
+ callgrindconfigwidget.cpp \
+ callgrindcostdelegate.cpp \
+ callgrindcostview.cpp \
+ callgrindhelper.cpp \
+ callgrindnamedelegate.cpp \
+ callgrindsettings.cpp \
+ callgrindtool.cpp \
+ callgrindvisualisation.cpp \
+ callgrindwidgethandler.cpp \
+ callgrindengine.cpp \
+ workarounds.cpp \
+ callgrindtextmark.cpp
+
+FORMS += \
+ callgrindconfigwidget.ui
diff --git a/src/plugins/callgrind/callgrind_dependencies.pri b/src/plugins/callgrind/callgrind_dependencies.pri
new file mode 100644
index 0000000000..532881cea9
--- /dev/null
+++ b/src/plugins/callgrind/callgrind_dependencies.pri
@@ -0,0 +1,5 @@
+include(../../plugins/coreplugin/coreplugin.pri)
+include(../../plugins/texteditor/texteditor.pri)
+include(../../plugins/analyzerbase/analyzerbase.pri)
+include(../../plugins/valgrindtoolbase/valgrindtoolbase.pri)
+include(../../libs/cplusplus/cplusplus.pri)
diff --git a/src/plugins/callgrind/callgrind_global.h b/src/plugins/callgrind/callgrind_global.h
new file mode 100644
index 0000000000..a74f297eb9
--- /dev/null
+++ b/src/plugins/callgrind/callgrind_global.h
@@ -0,0 +1,45 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 CALLGRIND_GLOBAL_H
+#define CALLGRIND_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(CALLGRIND_LIBRARY)
+# define CALLGRINDSHARED_EXPORT Q_DECL_EXPORT
+#else
+# define CALLGRINDSHARED_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // CALLGRIND_GLOBAL_H
diff --git a/src/plugins/callgrind/callgrindconfigwidget.cpp b/src/plugins/callgrind/callgrindconfigwidget.cpp
new file mode 100644
index 0000000000..77cf248270
--- /dev/null
+++ b/src/plugins/callgrind/callgrindconfigwidget.cpp
@@ -0,0 +1,77 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "callgrindconfigwidget.h"
+
+#include "ui_callgrindconfigwidget.h"
+
+#include "callgrindsettings.h"
+
+using namespace Callgrind::Internal;
+
+CallgrindConfigWidget::CallgrindConfigWidget(AbstractCallgrindSettings *settings, QWidget *parent)
+ : QWidget(parent)
+ , m_ui(new Ui::CallgrindConfigWidget)
+ , m_settings(settings)
+{
+ m_ui->setupUi(this);
+
+ m_ui->enableCacheSim->setChecked(m_settings->enableCacheSim());
+ connect(m_ui->enableCacheSim, SIGNAL(toggled(bool)),
+ m_settings, SLOT(setEnableCacheSim(bool)));
+ connect(m_settings, SIGNAL(enableCacheSimChanged(bool)),
+ m_ui->enableCacheSim, SLOT(setChecked(bool)));
+
+ m_ui->enableBranchSim->setChecked(m_settings->enableBranchSim());
+ connect(m_ui->enableBranchSim, SIGNAL(toggled(bool)),
+ m_settings, SLOT(setEnableBranchSim(bool)));
+ connect(m_settings, SIGNAL(enableBranchSimChanged(bool)),
+ m_ui->enableBranchSim, SLOT(setChecked(bool)));
+
+ m_ui->collectSystime->setChecked(m_settings->collectSystime());
+ connect(m_ui->collectSystime, SIGNAL(toggled(bool)),
+ m_settings, SLOT(setCollectSystime(bool)));
+ connect(m_settings, SIGNAL(collectSystimeChanged(bool)),
+ m_ui->collectSystime, SLOT(setChecked(bool)));
+
+ m_ui->collectBusEvents->setChecked(m_settings->collectBusEvents());
+ connect(m_ui->collectBusEvents, SIGNAL(toggled(bool)),
+ m_settings, SLOT(setCollectBusEvents(bool)));
+ connect(m_settings, SIGNAL(collectBusEventsChanged(bool)),
+ m_ui->collectBusEvents, SLOT(setChecked(bool)));
+}
+
+CallgrindConfigWidget::~CallgrindConfigWidget()
+{
+ delete m_ui;
+}
diff --git a/src/plugins/callgrind/callgrindconfigwidget.h b/src/plugins/callgrind/callgrindconfigwidget.h
new file mode 100644
index 0000000000..9949c30716
--- /dev/null
+++ b/src/plugins/callgrind/callgrindconfigwidget.h
@@ -0,0 +1,66 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 ANALYZER_INTERNAL_CALLGRINDCONFIGWIDGET_H
+#define ANALYZER_INTERNAL_CALLGRINDCONFIGWIDGET_H
+
+#include <QtGui/QWidget>
+
+namespace Callgrind {
+namespace Internal {
+
+namespace Ui {
+class CallgrindConfigWidget;
+}
+
+class AbstractCallgrindSettings;
+
+class CallgrindConfigWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ CallgrindConfigWidget(AbstractCallgrindSettings *settings, QWidget *parent);
+ virtual ~CallgrindConfigWidget();
+
+private:
+ Ui::CallgrindConfigWidget *m_ui;
+
+ AbstractCallgrindSettings *m_settings;
+};
+
+}
+}
+
+#endif // ANALYZER_INTERNAL_CALLGRINDCONFIGWIDGET_H
diff --git a/src/plugins/callgrind/callgrindconfigwidget.ui b/src/plugins/callgrind/callgrindconfigwidget.ui
new file mode 100644
index 0000000000..8147c03ff7
--- /dev/null
+++ b/src/plugins/callgrind/callgrindconfigwidget.ui
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Callgrind::Internal::CallgrindConfigWidget</class>
+ <widget class="QWidget" name="Callgrind::Internal::CallgrindConfigWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>416</width>
+ <height>565</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="memcheckOptions">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Profiling Options</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="4" column="0" 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>
+ <item row="0" column="0" colspan="2">
+ <widget class="QCheckBox" name="enableCacheSim">
+ <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:9pt; 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;
+&lt;p&gt;Specify if you want to do full cache simulation.&lt;/p&gt;
+&lt;p&gt;By default, only instruction read accesses will be counted (&quot;Ir&quot;).&lt;/p&gt;
+
+&lt;p&gt;
+With cache simulation, further event counters are enabled:
+&lt;ul&gt;&lt;li&gt;Cache misses on instruction reads (&quot;I1mr&quot;/&quot;I2mr&quot;)&lt;/li&gt;
+&lt;li&gt;Data read accesses (&quot;Dr&quot;) and related cache misses (&quot;D1mr&quot;/&quot;D2mr&quot;)&lt;/li&gt;
+&lt;li&gt;Data write accesses (&quot;Dw&quot;) and related cache misses (&quot;D1mw&quot;/&quot;D2mw&quot;)&lt;/li&gt;&lt;/ul&gt;
+&lt;/p&gt;
+
+For more information, see ???.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string>Enable cache simulation</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QCheckBox" name="enableBranchSim">
+ <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:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p&gt;Specify if you want to do branch prediction simulation.&lt;/p&gt;
+&lt;p&gt;Further event counters are enabled: &lt;/p&gt;
+&lt;ul&gt;&lt;li&gt;Number of executed conditional branches and related predictor misses (
+&quot;Bc&quot;/&quot;Bcm&quot;)&lt;/li&gt;
+&lt;li&gt;Executed indirect jumps and related misses of the jump address predictor (
+&quot;Bi&quot;/&quot;Bim&quot;)&lt;/li&gt;&lt;/ul&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string>Enable branch prediction simulation</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="collectSystime">
+ <property name="toolTip">
+ <string>This specifies whether information for system call times should be collected.</string>
+ </property>
+ <property name="text">
+ <string>Collect system call time</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QCheckBox" name="collectBusEvents">
+ <property name="toolTip">
+ <string>This specifies whether the number of global bus events executed should be collected. The event type &quot;Ge&quot; is used for these events.</string>
+ </property>
+ <property name="text">
+ <string>Collect global bus events</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/callgrind/callgrindconstants.h b/src/plugins/callgrind/callgrindconstants.h
new file mode 100644
index 0000000000..698fb141ca
--- /dev/null
+++ b/src/plugins/callgrind/callgrindconstants.h
@@ -0,0 +1,41 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator Analyzer Tools
+**
+** 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 CALLGRINDCONSTANTS_H
+#define CALLGRINDCONSTANTS_H
+
+namespace Callgrind {
+namespace Constants {
+
+const char * const A_SHOWCOSTSOFFUNCTION = "Analyzer.Callgrind.ShowCostsOfFunction";
+
+}
+}
+
+#endif // CALLGRINDCONSTANTS_H
diff --git a/src/plugins/callgrind/callgrindcostdelegate.cpp b/src/plugins/callgrind/callgrindcostdelegate.cpp
new file mode 100644
index 0000000000..bd1a53700f
--- /dev/null
+++ b/src/plugins/callgrind/callgrindcostdelegate.cpp
@@ -0,0 +1,185 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "callgrindcostdelegate.h"
+
+#include "callgrindcostview.h"
+#include "callgrindhelper.h"
+
+#include <valgrind/callgrind/callgrindabstractmodel.h>
+#include <valgrind/callgrind/callgrindparsedata.h>
+
+#include <utils/qtcassert.h>
+
+#include <QPainter>
+#include <QDebug>
+#include <QApplication>
+
+using namespace Valgrind::Callgrind;
+
+namespace Callgrind {
+namespace Internal {
+
+class CostDelegate::Private
+{
+public:
+ Private();
+
+ QAbstractItemModel *m_model;
+ CostDelegate::CostFormat m_format;
+
+ static int toNativeRole(CostFormat format);
+ float relativeCost(const QModelIndex &index) const;
+ QString displayText(const QModelIndex &index, const QLocale &locale) const;
+};
+
+CostDelegate::Private::Private()
+: m_model(0)
+, m_format(CostDelegate::FormatAbsolute)
+{
+}
+
+int CostDelegate::Private::toNativeRole(CostDelegate::CostFormat format)
+{
+ switch(format)
+ {
+ case FormatAbsolute:
+ case FormatRelative:
+ return Valgrind::Callgrind::RelativeTotalCostRole;
+ case FormatRelativeToParent:
+ return Valgrind::Callgrind::RelativeParentCostRole;
+ default:
+ return -1;
+ }
+}
+
+float CostDelegate::Private::relativeCost(const QModelIndex &index) const
+{
+ bool ok = false;
+ float cost = index.data(toNativeRole(m_format)).toFloat(&ok);
+ QTC_ASSERT(ok, return 0);
+ return cost;
+}
+
+QString CostDelegate::Private::displayText(const QModelIndex &index, const QLocale &locale) const
+{
+ switch (m_format) {
+ case FormatAbsolute:
+ return locale.toString(index.data().toULongLong());
+ case FormatRelative:
+ case FormatRelativeToParent:
+ if (!m_model)
+ break;
+ float cost = relativeCost(index) * 100.0f;
+ return CallgrindHelper::toPercent(cost, locale);
+ }
+
+ return QString();
+}
+//END CostDelegate::Private
+
+//BEGIN CostDelegate
+CostDelegate::CostDelegate(QObject *parent)
+ : QStyledItemDelegate(parent)
+ , d(new Private)
+{
+
+}
+
+CostDelegate::~CostDelegate()
+{
+ delete d;
+}
+
+void CostDelegate::setModel(QAbstractItemModel *model)
+{
+ d->m_model = model;
+}
+
+void CostDelegate::setFormat(CostFormat format)
+{
+ d->m_format = format;
+}
+
+CostDelegate::CostFormat CostDelegate::format() const
+{
+ return d->m_format;
+}
+
+void CostDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ // init
+ QStyleOptionViewItemV4 opt(option);
+ initStyleOption(&opt, index);
+
+ QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
+
+ // draw controls, but no text
+ opt.text.clear();
+ style->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
+
+ painter->save();
+
+ // draw bar
+ float ratio = qBound(0.0f, d->relativeCost(index), 1.0f);
+ QRect barRect = opt.rect;
+ barRect.setWidth(opt.rect.width() * ratio);
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(CallgrindHelper::colorForCostRatio(ratio));
+ painter->drawRect(barRect);
+
+ // draw text
+ const QString text = d->displayText(index, opt.locale);
+ const QBrush &textBrush = (option.state & QStyle::State_Selected ? opt.palette.highlightedText() : opt.palette.text());
+ painter->setBrush(Qt::NoBrush);
+ painter->setPen(textBrush.color());
+ painter->drawText(opt.rect, Qt::AlignRight, text);
+
+ painter->restore();
+}
+
+QSize CostDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ QStyleOptionViewItemV4 opt(option);
+ initStyleOption(&opt, index);
+
+ const QString text = d->displayText(index, opt.locale);
+ const QSize size = QSize(option.fontMetrics.width(text),
+ option.fontMetrics.height());
+ return size;
+}
+
+} // Internal
+} // Callgrind
diff --git a/src/plugins/callgrind/callgrindcostdelegate.h b/src/plugins/callgrind/callgrindcostdelegate.h
new file mode 100644
index 0000000000..091cfb01e6
--- /dev/null
+++ b/src/plugins/callgrind/callgrindcostdelegate.h
@@ -0,0 +1,78 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 CALLGRINDCOSTDELEGATE_H
+#define CALLGRINDCOSTDELEGATE_H
+
+#include <QtGui/QStyledItemDelegate>
+
+namespace Callgrind {
+namespace Internal {
+
+class CostDelegate : public QStyledItemDelegate
+{
+ Q_OBJECT
+
+public:
+ explicit CostDelegate(QObject *parent = 0);
+ virtual ~CostDelegate();
+
+ virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+ virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
+
+ void setModel(QAbstractItemModel *model);
+
+ enum CostFormat {
+ /// show absolute numbers
+ FormatAbsolute,
+ /// show percentages relative to the total inclusive cost
+ FormatRelative,
+ /// show percentages relative to the parent cost
+ FormatRelativeToParent
+ };
+
+ void setFormat(CostFormat format);
+ CostFormat format() const;
+
+private:
+ class Private;
+ Private *d;
+};
+
+} // Internal
+} // Callgrind
+
+Q_DECLARE_METATYPE(Callgrind::Internal::CostDelegate::CostFormat)
+
+#endif // CALLGRINDCOSTDELEGATE_H
diff --git a/src/plugins/callgrind/callgrindcostview.cpp b/src/plugins/callgrind/callgrindcostview.cpp
new file mode 100644
index 0000000000..d756346c53
--- /dev/null
+++ b/src/plugins/callgrind/callgrindcostview.cpp
@@ -0,0 +1,147 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "callgrindcostview.h"
+
+#include "callgrindnamedelegate.h"
+
+#include <valgrind/callgrind/callgrindabstractmodel.h>
+#include <valgrind/callgrind/callgrinddatamodel.h>
+#include <valgrind/callgrind/callgrindfunction.h>
+#include <valgrind/callgrind/callgrindcallmodel.h>
+
+#include <QtGui/QAbstractProxyModel>
+#include <QtGui/QHeaderView>
+#include <QtCore/QDebug>
+
+using namespace Valgrind::Callgrind;
+
+namespace Callgrind {
+namespace Internal {
+
+//BEGIN CostView::Private
+
+class CostView::Private {
+public:
+ explicit Private(CostView *qq);
+ ~Private();
+
+ CostDelegate *m_costDelegate;
+ NameDelegate *m_nameDelegate;
+};
+
+CostView::Private::Private(CostView *qq)
+ : m_costDelegate(new CostDelegate(qq))
+ , m_nameDelegate(new NameDelegate(qq))
+{
+}
+
+CostView::Private::~Private()
+{
+}
+
+//END CostView::Private
+
+//BEGIN CostView
+
+CostView::CostView(QWidget *parent)
+ : QTreeView(parent)
+ , d(new Private(this))
+{
+ setSelectionMode(QAbstractItemView::ExtendedSelection);
+ setSelectionBehavior(QAbstractItemView::SelectRows);
+ setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
+ setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
+ setAutoScroll(false);
+ setSortingEnabled(true);
+ setRootIsDecorated(false);
+}
+
+CostView::~CostView()
+{
+ delete d;
+}
+
+void CostView::setModel(QAbstractItemModel *model)
+{
+ QTreeView::setModel(model);
+
+ forever {
+ QAbstractProxyModel *proxy = qobject_cast<QAbstractProxyModel *>(model);
+ if (proxy)
+ model = proxy->sourceModel();
+ else
+ break;
+ }
+
+ QHeaderView *headerView = header();
+ setItemDelegate(new QStyledItemDelegate(this));
+ headerView->setResizeMode(QHeaderView::Interactive);
+ headerView->setStretchLastSection(false);
+
+ if (qobject_cast<CallModel *>(model)) {
+ setItemDelegateForColumn(CallModel::CostColumn, d->m_costDelegate);
+ headerView->setResizeMode(CallModel::CostColumn, QHeaderView::ResizeToContents);
+ headerView->setResizeMode(CallModel::CallsColumn, QHeaderView::ResizeToContents);
+ headerView->setResizeMode(CallModel::CalleeColumn, QHeaderView::Stretch);
+ setItemDelegateForColumn(CallModel::CalleeColumn, d->m_nameDelegate);
+ headerView->setResizeMode(CallModel::CallerColumn, QHeaderView::Stretch);
+ setItemDelegateForColumn(CallModel::CallerColumn, d->m_nameDelegate);
+ } else if (qobject_cast<DataModel *>(model)) {
+ setItemDelegateForColumn(DataModel::SelfCostColumn, d->m_costDelegate);
+ headerView->setResizeMode(DataModel::SelfCostColumn, QHeaderView::ResizeToContents);
+ setItemDelegateForColumn(DataModel::InclusiveCostColumn, d->m_costDelegate);
+ headerView->setResizeMode(DataModel::InclusiveCostColumn, QHeaderView::ResizeToContents);
+ setItemDelegateForColumn(DataModel::NameColumn, d->m_nameDelegate);
+ headerView->setResizeMode(DataModel::NameColumn, QHeaderView::Stretch);
+ headerView->setResizeMode(DataModel::LocationColumn, QHeaderView::Stretch);
+ }
+
+ d->m_costDelegate->setModel(model);
+}
+
+void CostView::setCostFormat(CostDelegate::CostFormat format)
+{
+ d->m_costDelegate->setFormat(format);
+ viewport()->update();
+}
+
+CostDelegate::CostFormat CostView::costFormat() const
+{
+ return d->m_costDelegate->format();
+}
+
+//END CostView
+
+} // Internal
+} // Callgrind
diff --git a/src/plugins/callgrind/callgrindcostview.h b/src/plugins/callgrind/callgrindcostview.h
new file mode 100644
index 0000000000..d30c8d9a30
--- /dev/null
+++ b/src/plugins/callgrind/callgrindcostview.h
@@ -0,0 +1,72 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 CALLGRINDCOSTVIEW_H
+#define CALLGRINDCOSTVIEW_H
+
+#include <QtGui/QTreeView>
+
+#include "callgrindcostdelegate.h"
+
+namespace Callgrind {
+namespace Internal {
+
+class CostView : public QTreeView
+{
+ Q_OBJECT
+
+public:
+ explicit CostView(QWidget *parent = 0);
+ virtual ~CostView();
+
+ /**
+ * Overload automatically updates the cost delegate
+ * and sets it for the cost columns of DataModel and CallModel.
+ */
+ virtual void setModel(QAbstractItemModel *model);
+
+ /**
+ * How to format cost data columns in the view.
+ */
+ void setCostFormat(CostDelegate::CostFormat format);
+ CostDelegate::CostFormat costFormat() const;
+
+private:
+ class Private;
+ Private *d;
+};
+
+} // Internal
+} // Callgrind
+
+#endif // CALLGRINDCOSTVIEW_H \ No newline at end of file
diff --git a/src/plugins/callgrind/callgrindengine.cpp b/src/plugins/callgrind/callgrindengine.cpp
new file mode 100644
index 0000000000..70c399283b
--- /dev/null
+++ b/src/plugins/callgrind/callgrindengine.cpp
@@ -0,0 +1,173 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "callgrindengine.h"
+
+#include "callgrindsettings.h"
+
+#include <valgrind/callgrind/callgrindcontroller.h>
+#include <valgrind/callgrind/callgrindparser.h>
+
+#include <analyzerbase/analyzermanager.h>
+
+#include <utils/qtcassert.h>
+
+using namespace Analyzer;
+using namespace Callgrind;
+using namespace Callgrind::Internal;
+
+CallgrindEngine::CallgrindEngine(const AnalyzerStartParameters &sp,
+ ProjectExplorer::RunConfiguration *runConfiguration)
+ : ValgrindEngine(sp, runConfiguration)
+ , m_markAsPaused(false)
+{
+ connect(&m_runner, SIGNAL(finished()), this, SLOT(slotFinished()));
+ connect(&m_runner, SIGNAL(started()), this, SLOT(slotStarted()));
+
+ connect(m_runner.parser(), SIGNAL(parserDataReady()), this, SLOT(slotFinished()));
+
+ connect(&m_runner, SIGNAL(statusMessage(QString)),
+ Analyzer::AnalyzerManager::instance(), SLOT(showStatusMessage(QString)));
+
+ m_progress->setProgressRange(0, 2);
+}
+
+CallgrindEngine::~CallgrindEngine()
+{
+}
+
+QStringList CallgrindEngine::toolArguments() const
+{
+ QStringList arguments;
+
+ AbstractCallgrindSettings *callgrindSettings = m_settings->subConfig<AbstractCallgrindSettings>();
+ QTC_ASSERT(callgrindSettings, return arguments);
+
+ if (callgrindSettings->enableCacheSim())
+ arguments << "--cache-sim=yes";
+
+ if (callgrindSettings->enableBranchSim())
+ arguments << "--branch-sim=yes";
+
+ if (callgrindSettings->collectBusEvents())
+ arguments << "--collect-bus=yes";
+
+ if (callgrindSettings->collectSystime())
+ arguments << "--collect-systime=yes";
+
+ if (m_markAsPaused)
+ arguments << "--instr-atstart=no";
+
+ // add extra arguments
+ arguments << extraArguments();
+
+ return arguments;
+}
+
+QString CallgrindEngine::progressTitle() const
+{
+ return tr("Profiling");
+}
+
+Valgrind::ValgrindRunner * CallgrindEngine::runner()
+{
+ return &m_runner;
+}
+
+void CallgrindEngine::start()
+{
+ emit standardOutputReceived(tr("Profiling %1").arg(executable()));
+ ValgrindEngine::start();
+}
+
+void CallgrindEngine::dump()
+{
+ m_runner.controller()->run(Valgrind::Callgrind::CallgrindController::Dump);
+}
+
+void CallgrindEngine::setExtraArguments(const QStringList &extraArguments)
+{
+ m_extraArguments = extraArguments;
+}
+
+void CallgrindEngine::setPaused(bool paused)
+{
+ if (m_markAsPaused == paused)
+ return;
+
+ m_markAsPaused = paused;
+
+ // call controller
+ if (paused)
+ pause();
+ else
+ unpause();
+}
+
+void CallgrindEngine::setToggleCollectFunction(const QString &toggleCollectFunction)
+{
+ if (toggleCollectFunction.isEmpty())
+ return;
+
+ m_extraArguments << QString("--toggle-collect=%1").arg(toggleCollectFunction);
+}
+
+void CallgrindEngine::reset()
+{
+ m_runner.controller()->run(Valgrind::Callgrind::CallgrindController::ResetEventCounters);
+}
+
+void CallgrindEngine::pause()
+{
+ m_runner.controller()->run(Valgrind::Callgrind::CallgrindController::Pause);
+}
+
+void CallgrindEngine::unpause()
+{
+ m_runner.controller()->run(Valgrind::Callgrind::CallgrindController::UnPause);
+}
+
+Valgrind::Callgrind::ParseData *CallgrindEngine::takeParserData()
+{
+ return m_runner.parser()->takeData();
+}
+
+void CallgrindEngine::slotFinished()
+{
+ emit parserDataReady(this);
+}
+
+void CallgrindEngine::slotStarted()
+{
+ m_progress->setProgressValue(1);;
+}
diff --git a/src/plugins/callgrind/callgrindengine.h b/src/plugins/callgrind/callgrindengine.h
new file mode 100644
index 0000000000..756459c650
--- /dev/null
+++ b/src/plugins/callgrind/callgrindengine.h
@@ -0,0 +1,92 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 CALLGRINDENGINE_H
+#define CALLGRINDENGINE_H
+
+#include <valgrindtoolbase/valgrindengine.h>
+
+#include <valgrind/callgrind/callgrindrunner.h>
+#include <valgrind/callgrind/callgrindparsedata.h>
+
+namespace Callgrind {
+namespace Internal {
+
+class CallgrindEngine : public Valgrind::Internal::ValgrindEngine
+{
+ Q_OBJECT
+public:
+ explicit CallgrindEngine(const Analyzer::AnalyzerStartParameters &sp,
+ ProjectExplorer::RunConfiguration *runConfiguration);
+ virtual ~CallgrindEngine();
+
+ void start();
+
+ Valgrind::Callgrind::ParseData *takeParserData();
+
+public slots:
+ // controller actions
+ void dump();
+ void reset();
+ void pause();
+ void unpause();
+
+ void setPaused(bool paused);
+ void setToggleCollectFunction(const QString &toggleCollectFunction);
+
+protected:
+ void setExtraArguments(const QStringList &extraArguments);
+ inline QStringList extraArguments() const { return m_extraArguments; }
+
+ virtual QStringList toolArguments() const;
+ virtual QString progressTitle() const;
+ virtual Valgrind::ValgrindRunner *runner();
+
+signals:
+ void parserDataReady(CallgrindEngine *engine);
+
+private:
+ Valgrind::Callgrind::CallgrindRunner m_runner;
+ bool m_markAsPaused;
+
+ QStringList m_extraArguments;
+
+private slots:
+ void slotFinished();
+ void slotStarted();
+};
+
+} // namespace Internal
+} // namespace Callgrind
+
+#endif // CALLGRINDENGINE_H
diff --git a/src/plugins/callgrind/callgrindhelper.cpp b/src/plugins/callgrind/callgrindhelper.cpp
new file mode 100644
index 0000000000..9a7f604acb
--- /dev/null
+++ b/src/plugins/callgrind/callgrindhelper.cpp
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator Analyzer Tools
+**
+** 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 "callgrindhelper.h"
+
+#include <cstdlib>
+
+#include <QtGui/QColor>
+#include <QtCore/QMap>
+#include <QtCore/QString>
+
+using namespace Callgrind::Internal;
+
+QColor CallgrindHelper::colorForString(const QString &text)
+{
+ static QMap<QString, QColor> colorCache;
+
+ if (colorCache.contains(text))
+ return colorCache.value(text);
+
+ // Minimum lightness of 100 to be readable with black text.
+ const QColor color = QColor::fromHsl(((qreal)qrand() / RAND_MAX * 359),
+ ((qreal)qrand() / RAND_MAX * 255),
+ ((qreal)qrand() / RAND_MAX * 127) + 128);
+ colorCache[text] = color;
+ return color;
+}
+
+QColor CallgrindHelper::colorForCostRatio(qreal ratio)
+{
+ ratio = qBound(0.0, ratio, 1.0);
+ return QColor::fromHsv(120 - ratio * 120, 255, 255, (-((ratio-1) * (ratio-1))) * 120 + 120);
+}
+
+QString CallgrindHelper::toPercent(float costs, const QLocale &locale)
+{
+ if (costs > 99.9f)
+ return locale.toString(100) + locale.percent();
+ else if (costs > 9.99f)
+ return locale.toString(costs, 'f', 1) + locale.percent();
+ else if (costs > 0.009f)
+ return locale.toString(costs, 'f', 2) + locale.percent();
+ else
+ return QString("<") + locale.toString(0.01f) + locale.percent();
+}
diff --git a/src/plugins/callgrind/callgrindhelper.h b/src/plugins/callgrind/callgrindhelper.h
new file mode 100644
index 0000000000..061857d925
--- /dev/null
+++ b/src/plugins/callgrind/callgrindhelper.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator Analyzer Tools
+**
+** 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 CALLGRINDHELPER_H
+#define CALLGRINDHELPER_H
+
+#include <QtCore/QLocale>
+
+QT_BEGIN_NAMESPACE
+class QColor;
+class QString;
+QT_END_NAMESPACE
+
+namespace Callgrind {
+namespace Internal {
+
+namespace CallgrindHelper
+{
+ /**
+ * Returns color for a specific string, the string<->color mapping is cached
+ */
+ QColor colorForString(const QString &text);
+
+ /**
+ * Returns color for a specific cost ratio
+ * \param ratio The cost ratio, ratio should be of [0,1]
+ */
+ QColor colorForCostRatio(qreal ratio);
+
+ /**
+ * Returns a proper percent representation of a float limited to 5 chars
+ */
+ QString toPercent(float costs, const QLocale &locale = QLocale());
+}
+
+}
+}
+
+#endif // CALLGRINDHELPER_H
diff --git a/src/plugins/callgrind/callgrindnamedelegate.cpp b/src/plugins/callgrind/callgrindnamedelegate.cpp
new file mode 100644
index 0000000000..45cb6b52f7
--- /dev/null
+++ b/src/plugins/callgrind/callgrindnamedelegate.cpp
@@ -0,0 +1,92 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator Analyzer Tools
+**
+** 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 "callgrindnamedelegate.h"
+
+#include "callgrindhelper.h"
+
+#include <QApplication>
+#include <QPainter>
+
+namespace Callgrind {
+namespace Internal {
+
+NameDelegate::NameDelegate(QObject *parent)
+ : QStyledItemDelegate(parent)
+{
+
+}
+
+NameDelegate::~NameDelegate()
+{
+}
+
+void NameDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ // init
+ QStyleOptionViewItemV4 opt(option);
+ initStyleOption(&opt, index);
+
+ const int margin = 2;
+ const int size = 10;
+
+ const QString text = index.data().toString();
+ QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
+
+ // draw controls, but no text
+ opt.text.clear();
+ style->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
+
+ // draw bar in the first few pixels
+ painter->save();
+ const QRectF barRect = opt.rect.adjusted(
+ margin, margin, -opt.rect.width() + size - margin, -margin);
+ painter->setPen(Qt::black);
+ painter->setBrush(CallgrindHelper::colorForString(text));
+ painter->drawRect(barRect);
+
+ // move cell rect to right
+ opt.rect.adjust(size+margin, 0, 0, 0);
+
+ // draw text
+ const QString elidedText = painter->fontMetrics().elidedText(text, Qt::ElideRight,
+ opt.rect.width());
+
+ const QBrush &textBrush = (option.state & QStyle::State_Selected)
+ ? opt.palette.highlightedText()
+ : opt.palette.text();
+ painter->setBrush(Qt::NoBrush);
+ painter->setPen(textBrush.color());
+ painter->drawText(opt.rect, elidedText);
+ painter->restore();
+}
+
+} // Internal
+} // Callgrind
diff --git a/src/plugins/callgrind/callgrindnamedelegate.h b/src/plugins/callgrind/callgrindnamedelegate.h
new file mode 100644
index 0000000000..1e18c54f0b
--- /dev/null
+++ b/src/plugins/callgrind/callgrindnamedelegate.h
@@ -0,0 +1,53 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator Analyzer Tools
+**
+** 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 CALLGRINDNAMEDELEGATE_H
+#define CALLGRINDNAMEDELEGATE_H
+
+#include <QtGui/QStyledItemDelegate>
+
+namespace Callgrind {
+namespace Internal {
+
+class NameDelegate : public QStyledItemDelegate
+{
+ Q_OBJECT
+
+public:
+ explicit NameDelegate(QObject *parent = 0);
+ virtual ~NameDelegate();
+
+ virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+};
+
+} // Internal
+} // Callgrind
+
+#endif // CALLGRINDNAMEDELEGATE_H
diff --git a/src/plugins/callgrind/callgrindplugin.cpp b/src/plugins/callgrind/callgrindplugin.cpp
new file mode 100644
index 0000000000..e2d58edc4b
--- /dev/null
+++ b/src/plugins/callgrind/callgrindplugin.cpp
@@ -0,0 +1,73 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "callgrindplugin.h"
+
+#include "callgrindtool.h"
+#include "callgrindsettings.h"
+
+#include <analyzerbase/analyzermanager.h>
+
+#include <QStringList>
+#include <QtPlugin>
+
+using namespace Analyzer;
+using namespace Callgrind;
+using namespace Callgrind::Internal;
+
+CallgrindPlugin::CallgrindPlugin()
+{
+
+}
+
+CallgrindPlugin::~CallgrindPlugin()
+{
+
+}
+
+bool CallgrindPlugin::initialize(const QStringList &/*arguments*/, QString */*errorString*/)
+{
+ typedef AnalyzerSubConfigFactory<CallgrindGlobalSettings, CallgrindProjectSettings> CallgrindConfigFactory;
+ AnalyzerGlobalSettings::instance()->registerSubConfigFactory(new CallgrindConfigFactory);
+ AnalyzerManager::instance()->addTool(new CallgrindTool(this));
+
+ return true;
+}
+
+
+void CallgrindPlugin::extensionsInitialized()
+{
+
+}
+
+Q_EXPORT_PLUGIN(CallgrindPlugin) \ No newline at end of file
diff --git a/src/plugins/callgrind/callgrindplugin.h b/src/plugins/callgrind/callgrindplugin.h
new file mode 100644
index 0000000000..2045021c7b
--- /dev/null
+++ b/src/plugins/callgrind/callgrindplugin.h
@@ -0,0 +1,57 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 CALLGRINDPLUGIN_H
+#define CALLGRINDPLUGIN_H
+
+#include <extensionsystem/iplugin.h>
+
+namespace Callgrind {
+namespace Internal {
+
+class CallgrindPlugin : public ExtensionSystem::IPlugin
+{
+ Q_OBJECT
+
+public:
+ CallgrindPlugin();
+ ~CallgrindPlugin();
+
+ virtual bool initialize(const QStringList &arguments, QString *errorString);
+ virtual void extensionsInitialized();
+};
+
+} // namespace Internal
+} // namespace Callgrind
+
+#endif // CALLGRINDPLUGIN_H
diff --git a/src/plugins/callgrind/callgrindsettings.cpp b/src/plugins/callgrind/callgrindsettings.cpp
new file mode 100644
index 0000000000..e6d4ef6618
--- /dev/null
+++ b/src/plugins/callgrind/callgrindsettings.cpp
@@ -0,0 +1,229 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "callgrindsettings.h"
+
+#include "callgrindconfigwidget.h"
+
+#include <QDebug>
+
+using namespace Analyzer;
+using namespace Callgrind::Internal;
+using namespace Callgrind;
+
+static const QLatin1String callgrindEnableCacheSimC("Analyzer.Valgrind.Callgrind.EnableCacheSim");
+static const QLatin1String callgrindEnableBranchSimC("Analyzer.Valgrind.Callgrind.EnableBranchSim");
+static const QLatin1String callgrindCollectSystimeC("Analyzer.Valgrind.Callgrind.CollectSystime");
+static const QLatin1String callgrindCollectBusEventsC("Analyzer.Valgrind.Callgrind.CollectBusEvents");
+
+static const QLatin1String callgrindCycleDetectionC("Analyzer.Valgrind.Callgrind.CycleDetection");
+static const QLatin1String callgrindCostFormatC("Analyzer.Valgrind.Callgrind.CostFormat");
+static const QLatin1String callgrindMinimumCostRatioC("Analyzer.Valgrind.Callgrind.MinimumCostRatio");
+
+AbstractCallgrindSettings::AbstractCallgrindSettings(QObject *parent)
+ : AbstractAnalyzerSubConfig(parent)
+{
+
+}
+
+AbstractCallgrindSettings::~AbstractCallgrindSettings()
+{
+
+}
+
+void AbstractCallgrindSettings::setEnableCacheSim(bool enable)
+{
+ if (m_enableCacheSim == enable)
+ return;
+
+ m_enableCacheSim = enable;
+ emit enableCacheSimChanged(enable);
+}
+
+void AbstractCallgrindSettings::setEnableBranchSim(bool enable)
+{
+ if (m_enableBranchSim == enable)
+ return;
+
+ m_enableBranchSim = enable;
+ emit enableBranchSimChanged(enable);
+}
+
+void AbstractCallgrindSettings::setCollectSystime(bool collect)
+{
+ if (m_collectSystime == collect)
+ return;
+
+ m_collectSystime = collect;
+ emit collectSystimeChanged(collect);
+}
+
+void AbstractCallgrindSettings::setCollectBusEvents(bool collect)
+{
+ if (m_collectBusEvents == collect)
+ return;
+
+ m_collectBusEvents = collect;
+ emit collectBusEventsChanged(collect);
+}
+
+QVariantMap AbstractCallgrindSettings::defaults() const
+{
+ QVariantMap map;
+ map.insert(callgrindEnableCacheSimC, false);
+ map.insert(callgrindEnableBranchSimC, false);
+ map.insert(callgrindCollectSystimeC, false);
+ map.insert(callgrindCollectBusEventsC, false);
+ return map;
+}
+
+bool AbstractCallgrindSettings::fromMap(const QVariantMap &map)
+{
+ setIfPresent(map, callgrindEnableCacheSimC, &m_enableCacheSim);
+ setIfPresent(map, callgrindEnableBranchSimC, &m_enableBranchSim);
+ setIfPresent(map, callgrindCollectSystimeC, &m_collectSystime);
+ setIfPresent(map, callgrindCollectBusEventsC, &m_collectBusEvents);
+ return true;
+}
+
+QVariantMap AbstractCallgrindSettings::toMap() const
+{
+ QVariantMap map;
+ map.insert(callgrindEnableCacheSimC, m_enableCacheSim);
+ map.insert(callgrindEnableBranchSimC, m_enableBranchSim);
+ map.insert(callgrindCollectSystimeC, m_collectSystime);
+ map.insert(callgrindCollectBusEventsC, m_collectBusEvents);
+
+ return map;
+}
+
+QString AbstractCallgrindSettings::id() const
+{
+ return "Analyzer.Valgrind.Settings.Callgrind";
+}
+
+QString AbstractCallgrindSettings::displayName() const
+{
+ return tr("Profiling");
+}
+
+QWidget *AbstractCallgrindSettings::createConfigWidget(QWidget *parent)
+{
+ return new CallgrindConfigWidget(this, parent);
+}
+
+
+CallgrindGlobalSettings::CallgrindGlobalSettings(QObject *parent)
+ : AbstractCallgrindSettings(parent)
+{
+
+}
+
+CallgrindGlobalSettings::~CallgrindGlobalSettings()
+{
+
+}
+
+QVariantMap CallgrindGlobalSettings::defaults() const
+{
+ QVariantMap map = AbstractCallgrindSettings::defaults();
+ map.insert(callgrindCostFormatC, CostDelegate::FormatRelative);
+ map.insert(callgrindCycleDetectionC, true);
+ map.insert(callgrindMinimumCostRatioC, 0.0001);
+ return map;
+}
+
+bool CallgrindGlobalSettings::fromMap(const QVariantMap &map)
+{
+ AbstractCallgrindSettings::fromMap(map);
+ // special code as the default one does not cope with the enum properly
+ if (map.contains(callgrindCostFormatC)) {
+ m_costFormat = static_cast<CostDelegate::CostFormat>(map.value(callgrindCostFormatC).toInt());
+ }
+ setIfPresent(map, callgrindCycleDetectionC, &m_detectCycles);
+ setIfPresent(map, callgrindMinimumCostRatioC, &m_minimumInclusiveCostRatio);
+ return true;
+}
+
+QVariantMap CallgrindGlobalSettings::toMap() const
+{
+ QVariantMap map = AbstractCallgrindSettings::toMap();
+ map.insert(callgrindCostFormatC, m_costFormat);
+ map.insert(callgrindCycleDetectionC, m_detectCycles);
+ map.insert(callgrindMinimumCostRatioC, m_minimumInclusiveCostRatio);
+ return map;
+}
+
+CostDelegate::CostFormat CallgrindGlobalSettings::costFormat() const
+{
+ return m_costFormat;
+}
+
+void CallgrindGlobalSettings::setCostFormat(CostDelegate::CostFormat format)
+{
+ m_costFormat = format;
+ AnalyzerGlobalSettings::instance()->writeSettings();
+}
+
+bool CallgrindGlobalSettings::detectCycles() const
+{
+ return m_detectCycles;
+}
+
+void CallgrindGlobalSettings::setDetectCycles(bool detect)
+{
+ m_detectCycles = detect;
+ AnalyzerGlobalSettings::instance()->writeSettings();
+}
+
+double CallgrindGlobalSettings::minimumInclusiveCostRatio() const
+{
+ return m_minimumInclusiveCostRatio;
+}
+
+void CallgrindGlobalSettings::setMinimumInclusiveCostRatio(double minimumInclusiveCost)
+{
+ m_minimumInclusiveCostRatio = minimumInclusiveCost;
+ AnalyzerGlobalSettings::instance()->writeSettings();
+}
+
+CallgrindProjectSettings::CallgrindProjectSettings(QObject *parent)
+ : AbstractCallgrindSettings(parent)
+{
+
+}
+
+CallgrindProjectSettings::~CallgrindProjectSettings()
+{
+
+}
diff --git a/src/plugins/callgrind/callgrindsettings.h b/src/plugins/callgrind/callgrindsettings.h
new file mode 100644
index 0000000000..873fa7ddc6
--- /dev/null
+++ b/src/plugins/callgrind/callgrindsettings.h
@@ -0,0 +1,139 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 ANALYZER_INTERNAL_CALLGRINDSETTINGS_H
+#define ANALYZER_INTERNAL_CALLGRINDSETTINGS_H
+
+#include <analyzerbase/analyzersettings.h>
+
+#include <QString>
+#include "callgrindcostdelegate.h"
+
+namespace Callgrind {
+namespace Internal {
+
+/**
+ * Generic callgrind settings
+ */
+class AbstractCallgrindSettings : public Analyzer::AbstractAnalyzerSubConfig
+{
+ Q_OBJECT
+
+public:
+ AbstractCallgrindSettings(QObject *parent = 0);
+ virtual ~AbstractCallgrindSettings();
+
+ inline bool enableCacheSim() const { return m_enableCacheSim; }
+ inline bool enableBranchSim() const { return m_enableBranchSim; }
+ inline bool collectSystime() const { return m_collectSystime; }
+ inline bool collectBusEvents() const { return m_collectBusEvents; }
+
+ // abstract virtual methods from base class
+ virtual bool fromMap(const QVariantMap &map);
+
+ virtual QVariantMap defaults() const;
+
+ virtual QString id() const;
+ virtual QString displayName() const;
+ virtual QWidget *createConfigWidget(QWidget *parent);
+
+public Q_SLOTS:
+ void setEnableCacheSim(bool enable);
+ void setEnableBranchSim(bool enable);
+ void setCollectSystime(bool collect);
+ void setCollectBusEvents(bool collect);
+
+Q_SIGNALS:
+ void enableCacheSimChanged(bool);
+ void enableBranchSimChanged(bool);
+ void collectSystimeChanged(bool);
+ void collectBusEventsChanged(bool);
+
+protected:
+ virtual QVariantMap toMap() const;
+
+private:
+ bool m_enableCacheSim;
+ bool m_collectSystime;
+ bool m_collectBusEvents;
+ bool m_enableBranchSim;
+};
+
+/**
+ * Global callgrind settings
+ */
+class CallgrindGlobalSettings : public AbstractCallgrindSettings
+{
+ Q_OBJECT
+
+public:
+ CallgrindGlobalSettings(QObject *parent = 0);
+ virtual ~CallgrindGlobalSettings();
+
+ virtual bool fromMap(const QVariantMap &map);
+ virtual QVariantMap defaults() const;
+
+ CostDelegate::CostFormat costFormat() const;
+ bool detectCycles() const;
+ double minimumInclusiveCostRatio() const;
+
+public slots:
+ void setCostFormat(Callgrind::Internal::CostDelegate::CostFormat format);
+ void setDetectCycles(bool detect);
+ void setMinimumInclusiveCostRatio(double minimumInclusiveCost);
+
+protected:
+ virtual QVariantMap toMap() const;
+
+private:
+ CostDelegate::CostFormat m_costFormat;
+ bool m_detectCycles;
+ double m_minimumInclusiveCostRatio;
+};
+
+/**
+ * Per-project callgrind settings, saves a diff to the global suppression files list
+ */
+class CallgrindProjectSettings : public AbstractCallgrindSettings
+{
+ Q_OBJECT
+
+public:
+ CallgrindProjectSettings(QObject *parent = 0);
+ virtual ~CallgrindProjectSettings();
+};
+
+}
+}
+
+#endif // ANALYZER_INTERNAL_CALLGRINDSETTINGS_H
diff --git a/src/plugins/callgrind/callgrindtextmark.cpp b/src/plugins/callgrind/callgrindtextmark.cpp
new file mode 100644
index 0000000000..f78612e5f9
--- /dev/null
+++ b/src/plugins/callgrind/callgrindtextmark.cpp
@@ -0,0 +1,108 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator Analyzer Tools
+**
+** 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 "callgrindtextmark.h"
+
+#include "callgrindhelper.h"
+
+#include <valgrind/callgrind/callgrinddatamodel.h>
+#include <valgrind/callgrind/callgrindfunction.h>
+
+#include <QDebug>
+#include <QPainter>
+
+#include <utils/qtcassert.h>
+
+using namespace Callgrind::Internal;
+using namespace Valgrind::Callgrind;
+
+CallgrindTextMark::CallgrindTextMark(const QPersistentModelIndex &index,
+ const QString &fileName, int lineNumber)
+ : m_modelIndex(index)
+{
+ setLocation(fileName, lineNumber);
+ setPriority(TextEditor::ITextMark::HighPriority);
+}
+
+CallgrindTextMark::~CallgrindTextMark()
+{
+}
+
+void CallgrindTextMark::paint(QPainter *painter, const QRect &paintRect) const
+{
+ if (!m_modelIndex.isValid())
+ return;
+
+ bool ok;
+ qreal costs = m_modelIndex.data(RelativeTotalCostRole).toReal(&ok);
+ QTC_ASSERT(ok, return)
+ QTC_ASSERT(costs >= 0.0 && costs <= 100.0, return)
+
+ painter->save();
+
+ // set up
+ painter->setPen(Qt::black);
+
+ // draw bar
+ QRect fillRect = paintRect;
+ fillRect.setWidth(paintRect.width() * costs);
+ painter->fillRect(paintRect, Qt::white);
+ painter->fillRect(fillRect, CallgrindHelper::colorForCostRatio(costs));
+ painter->drawRect(paintRect);
+
+ // draw text
+ const QTextOption flags = Qt::AlignHCenter | Qt::AlignVCenter;
+ const QString text = CallgrindHelper::toPercent(costs * 100.0f);
+
+ // decrease font size if paint rect is too small (very unlikely, but may happen)
+ QFont font = painter->font();
+ QFontMetrics fm = font;
+ while (fm.boundingRect(text).width() > paintRect.width()) {
+ font.setPointSize(font.pointSize() - 1);
+ fm = font;
+ }
+ painter->setFont(font);
+
+ painter->drawText(paintRect, text, flags);
+
+ painter->restore();
+}
+
+const Function* CallgrindTextMark::function() const
+{
+ if (!m_modelIndex.isValid())
+ return 0;
+
+ return m_modelIndex.data(DataModel::FunctionRole).value<const Function *>();
+}
+
+double CallgrindTextMark::widthFactor() const
+{
+ return 4.0;
+}
diff --git a/src/plugins/callgrind/callgrindtextmark.h b/src/plugins/callgrind/callgrindtextmark.h
new file mode 100644
index 0000000000..d03ceee67b
--- /dev/null
+++ b/src/plugins/callgrind/callgrindtextmark.h
@@ -0,0 +1,76 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator Analyzer Tools
+**
+** 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 CALLGRINDTEXTMARK_H
+#define CALLGRINDTEXTMARK_H
+
+#include <texteditor/basetextmark.h>
+
+#include <QtCore/QPersistentModelIndex>
+
+QT_BEGIN_NAMESPACE
+QT_END_NAMESPACE
+
+namespace Valgrind {
+namespace Callgrind {
+class Function;
+}
+}
+
+namespace Callgrind {
+namespace Internal {
+
+class CallgrindTextMark : public TextEditor::BaseTextMark
+{
+ Q_OBJECT
+
+public:
+ /**
+ * This creates a callgrind text mark for a specific Function
+ *
+ * \param index DataModel model index
+ * \note The index parameter must refer to one of the DataModel cost columns
+ */
+ explicit CallgrindTextMark(const QPersistentModelIndex &index,
+ const QString &fileName, int lineNumber);
+ virtual ~CallgrindTextMark();
+
+ const Valgrind::Callgrind::Function *function() const;
+
+ virtual double widthFactor() const;
+ virtual void paint(QPainter *painter, const QRect &paintRect) const;
+
+private:
+ QPersistentModelIndex m_modelIndex;
+};
+
+} // namespace Internal
+} // namespace Callgrind
+
+#endif // CALLGRINDTEXTMARK_H
diff --git a/src/plugins/callgrind/callgrindtool.cpp b/src/plugins/callgrind/callgrindtool.cpp
new file mode 100644
index 0000000000..32c1ffe3a6
--- /dev/null
+++ b/src/plugins/callgrind/callgrindtool.cpp
@@ -0,0 +1,506 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "callgrindtool.h"
+
+#include "callgrindconstants.h"
+#include "callgrindcostview.h"
+#include "callgrindengine.h"
+#include "callgrindwidgethandler.h"
+#include "callgrindtextmark.h"
+#include "callgrindvisualisation.h"
+#include "callgrindsettings.h"
+
+#include <analyzerbase/analyzermanager.h>
+#include <analyzerbase/analyzersettings.h>
+#include <analyzerbase/analyzerutils.h>
+#include <analyzerbase/ianalyzeroutputpaneadapter.h>
+
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/icontext.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/actionmanager/command.h>
+#include <cplusplus/LookupContext.h>
+#include <cplusplus/Overview.h>
+#include <cppeditor/cppeditorconstants.h>
+#include <extensionsystem/iplugin.h>
+#include <texteditor/basetexteditor.h>
+#include <utils/qtcassert.h>
+#include <utils/fancymainwindow.h>
+#include <utils/styledbar.h>
+
+#include <valgrind/callgrind/callgrinddatamodel.h>
+#include <valgrind/callgrind/callgrindparsedata.h>
+#include <valgrind/callgrind/callgrindcostitem.h>
+#include <valgrind/callgrind/callgrindproxymodel.h>
+#include <valgrind/callgrind/callgrindfunction.h>
+#include <valgrind/callgrind/callgrindstackbrowser.h>
+
+#include <QtGui/QDockWidget>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QCheckBox>
+#include <QtGui/QGraphicsItem>
+#include <QtGui/QMenu>
+#include <QtGui/QToolButton>
+#include <QtGui/QAction>
+#include <QtGui/QLineEdit>
+#include <QtGui/QToolBar>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+
+// shared/cplusplus includes
+#include <Symbols.h>
+
+using namespace Callgrind;
+
+using namespace Analyzer;
+using namespace Core;
+using namespace Valgrind::Callgrind;
+
+namespace Callgrind {
+namespace Internal {
+
+// Adapter for output pane.
+class CallgrindOutputPaneAdapter : public Analyzer::ListItemViewOutputPaneAdapter
+{
+public:
+ explicit CallgrindOutputPaneAdapter(CallgrindTool *mct) :
+ ListItemViewOutputPaneAdapter(mct), m_tool(mct) {}
+
+ virtual QWidget *toolBarWidget() { return m_tool->createPaneToolBarWidget(); }
+ virtual void clearContents() { m_tool->clearErrorView(); }
+
+protected:
+ virtual QAbstractItemView *createItemView()
+ {
+ return m_tool->callgrindWidgetHandler()->flatView();
+ }
+
+private:
+ CallgrindTool *m_tool;
+};
+
+static QToolButton *createToolButton(QAction *action)
+{
+ QToolButton *button = new QToolButton;
+ button->setDefaultAction(action);
+ button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ return button;
+}
+
+CallgrindTool::CallgrindTool(QObject *parent)
+: Analyzer::IAnalyzerTool(parent)
+, m_callgrindWidgetHandler(0)
+, m_dumpAction(0)
+, m_resetAction(0)
+, m_pauseAction(0)
+, m_showCostsOfFunctionAction(0)
+, m_outputPaneAdapter(0)
+{
+ Core::ICore *core = Core::ICore::instance();
+
+ // EditorManager
+ QObject *editorManager = core->editorManager();
+ connect(editorManager, SIGNAL(editorOpened(Core::IEditor*)),
+ SLOT(editorOpened(Core::IEditor*)));
+}
+
+CallgrindTool::~CallgrindTool()
+{
+ qDeleteAll(m_textMarks);
+}
+
+QString CallgrindTool::id() const
+{
+ return "Callgrind";
+}
+
+QString CallgrindTool::displayName() const
+{
+ return tr("Profile");
+}
+
+IAnalyzerTool::ToolMode CallgrindTool::mode() const
+{
+ return ReleaseMode;
+}
+
+void CallgrindTool::initialize(ExtensionSystem::IPlugin */*plugin*/)
+{
+ AnalyzerManager *am = AnalyzerManager::instance();
+
+ CallgrindWidgetHandler *handler = new CallgrindWidgetHandler(am->mainWindow());
+ m_callgrindWidgetHandler = handler;
+
+ QDockWidget *visDock = am->createDockWidget(this, tr("Visualisation"),
+ handler->visualisation(), Qt::LeftDockWidgetArea);
+
+ QDockWidget *calleesDock = am->createDockWidget(this, tr("Callees"),
+ handler->calleesView(), Qt::BottomDockWidgetArea);
+ QDockWidget *callersDock = am->createDockWidget(this, tr("Callers"),
+ handler->callersView(), Qt::BottomDockWidgetArea);
+
+ am->mainWindow()->tabifyDockWidget(callersDock, calleesDock);
+ am->mainWindow()->tabifyDockWidget(calleesDock, visDock);
+
+ connect(m_callgrindWidgetHandler, SIGNAL(functionSelected(const Valgrind::Callgrind::Function*)),
+ this, SLOT(slotFunctionSelected(const Valgrind::Callgrind::Function*)));
+}
+
+void CallgrindTool::extensionsInitialized()
+{
+ Core::ICore *core = Core::ICore::instance();
+ Core::ActionManager *actionManager = core->actionManager();
+
+ Core::Context analyzerContext = Core::Context(Analyzer::Constants::C_ANALYZEMODE);
+
+ // check if there is a CppEditor context menu, if true, add our own context menu actions
+ if (Core::ActionContainer *editorContextMenu =
+ actionManager->actionContainer(CppEditor::Constants::M_CONTEXT)) {
+ QAction *action = 0;
+ Core::Command *cmd = 0;
+
+ action = new QAction(this);
+ action->setSeparator(true);
+ cmd = actionManager->registerAction(action, "Analyzer.Callgrind.ContextMenu.Sep",
+ analyzerContext);
+ editorContextMenu->addAction(cmd);
+
+ action = new QAction(tr("Profile costs of this function and its callees"), this);
+ action->setIcon(QIcon(Analyzer::Constants::ANALYZER_CONTROL_START_ICON));
+ connect(action, SIGNAL(triggered()), SLOT(handleShowCostsOfFunction()));
+ cmd = actionManager->registerAction(action, Callgrind::Constants::A_SHOWCOSTSOFFUNCTION,
+ analyzerContext);
+ editorContextMenu->addAction(cmd);
+ cmd->setAttribute(Core::Command::CA_Hide);
+ cmd->setAttribute(Core::Command::CA_NonConfigurable);
+ m_showCostsOfFunctionAction = action;
+ }
+}
+
+IAnalyzerEngine *CallgrindTool::createEngine(const AnalyzerStartParameters &sp,
+ ProjectExplorer::RunConfiguration *runConfiguration)
+{
+ CallgrindEngine *engine = new CallgrindEngine(sp, runConfiguration);
+
+ connect(engine, SIGNAL(parserDataReady(CallgrindEngine *)), SLOT(takeParserData(CallgrindEngine *)));
+
+ connect(engine, SIGNAL(starting(const Analyzer::IAnalyzerEngine*)),
+ this, SLOT(engineStarting(const Analyzer::IAnalyzerEngine*)));
+ connect(engine, SIGNAL(finished()),
+ this, SLOT(engineFinished()));
+
+ connect(this, SIGNAL(dumpRequested()), engine, SLOT(dump()));
+ connect(this, SIGNAL(resetRequested()), engine, SLOT(reset()));
+ connect(this, SIGNAL(pauseToggled(bool)), engine, SLOT(setPaused(bool)));
+
+ // initialize engine
+ engine->setPaused(m_pauseAction->isChecked());
+
+ // we may want to toggle collect for one function only in this run
+ engine->setToggleCollectFunction(m_toggleCollectFunction);
+ m_toggleCollectFunction.clear();
+
+ AnalyzerManager::instance()->showStatusMessage(AnalyzerManager::msgToolStarted(displayName()));
+
+ return engine;
+}
+
+QWidget *CallgrindTool::createControlWidget()
+{
+ QWidget *widget = new QWidget;
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->setMargin(0);
+ layout->setSpacing(0);
+ widget->setLayout(layout);
+
+ // dump action
+ m_dumpAction = new QAction(this);
+ m_dumpAction->setDisabled(true);
+ m_dumpAction->setIcon(QIcon(QLatin1String(Core::Constants::ICON_REDO)));
+ m_dumpAction->setText(tr("Dump"));
+ m_dumpAction->setToolTip(tr("Request the dumping of profile information. This will update the callgrind visualization."));
+ connect(m_dumpAction, SIGNAL(triggered()), this, SLOT(slotRequestDump()));
+ layout->addWidget(createToolButton(m_dumpAction));
+
+ // reset action
+ m_resetAction = new QAction(this);
+ m_resetAction->setDisabled(true);
+ m_resetAction->setIcon(QIcon(QLatin1String(Core::Constants::ICON_CLEAR)));
+ m_resetAction->setText(tr("Reset"));
+ m_resetAction->setToolTip(tr("Zero all event counters."));
+ connect(m_resetAction, SIGNAL(triggered()), this, SIGNAL(resetRequested()));
+ layout->addWidget(createToolButton(m_resetAction));
+
+ // pause action
+ m_pauseAction = new QAction(this);
+ m_pauseAction->setCheckable(true);
+ m_pauseAction->setIcon(QIcon(QLatin1String(":/qml/images/pause-small.png")));
+ m_pauseAction->setText(tr("Ignore"));
+ m_pauseAction->setToolTip(tr("If enabled, no events are counted which will speed up program execution during profiling."));
+ connect(m_pauseAction, SIGNAL(toggled(bool)), this, SIGNAL(pauseToggled(bool)));
+ layout->addWidget(createToolButton(m_pauseAction));
+
+ layout->addWidget(new Utils::StyledSeparator);
+ layout->addStretch();
+
+ return widget;
+}
+
+CallgrindWidgetHandler *CallgrindTool::callgrindWidgetHandler() const
+{
+ return m_callgrindWidgetHandler;
+}
+
+QWidget *CallgrindTool::createPaneToolBarWidget()
+{
+ QWidget *toolbarWidget = new QWidget;
+ toolbarWidget->setObjectName("CallgrindToolBarWidget");
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->setMargin(0);
+ layout->setSpacing(0);
+ toolbarWidget->setLayout(layout);
+
+ m_callgrindWidgetHandler->populateActions(layout);
+
+ CallgrindGlobalSettings *settings = AnalyzerGlobalSettings::instance()->subConfig<CallgrindGlobalSettings>();
+ m_callgrindWidgetHandler->setCostFormat(settings->costFormat());
+ m_callgrindWidgetHandler->enableCycleDetection(settings->detectCycles());
+ connect(m_callgrindWidgetHandler, SIGNAL(costFormatChanged(Callgrind::Internal::CostDelegate::CostFormat)),
+ settings, SLOT(setCostFormat(Callgrind::Internal::CostDelegate::CostFormat)));
+ connect(m_callgrindWidgetHandler, SIGNAL(cycleDetectionEnabled(bool)),
+ settings, SLOT(setDetectCycles(bool)));
+
+ // performance: add a minimum cost index so that we are not flooded by the results
+ m_callgrindWidgetHandler->proxyModel()->setMinimumInclusiveCostRatio(settings->minimumInclusiveCostRatio());
+
+ return toolbarWidget;
+}
+
+void CallgrindTool::clearErrorView()
+{
+ clearTextMarks();
+
+ m_callgrindWidgetHandler->slotClear();
+}
+
+void CallgrindTool::clearTextMarks()
+{
+ qDeleteAll(m_textMarks);
+ m_textMarks.clear();
+}
+
+void CallgrindTool::engineStarting(const Analyzer::IAnalyzerEngine *)
+{
+ // enable/disable actions
+ m_resetAction->setEnabled(true);
+ m_dumpAction->setEnabled(true);
+
+ clearErrorView();
+}
+
+void CallgrindTool::engineFinished()
+{
+ // enable/disable actions
+ m_resetAction->setEnabled(false);
+ m_dumpAction->setEnabled(false);
+
+ const ParseData *data = m_callgrindWidgetHandler->dataModel()->parseData();
+ if (data)
+ showParserResults(data);
+ else
+ AnalyzerManager::instance()->showStatusMessage(tr("Profiling aborted."));
+}
+
+void CallgrindTool::showParserResults(const ParseData *data)
+{
+ QString msg;
+ if (data) {
+ // be careful, the list of events might be empty
+ if (data->events().isEmpty()) {
+ msg = tr("Parsing finished, no data.");
+ }
+ else {
+ const QString costStr = QString("%1 %2").arg(QString::number(data->totalCost(0)), data->events().first());
+ msg = tr("Parsing finished, total cost of %1 reported.").arg(costStr);
+ }
+ } else {
+ msg = tr("Parsing failed.");
+ }
+ AnalyzerManager::instance()->showStatusMessage(msg);
+}
+
+void CallgrindTool::editorOpened(Core::IEditor *editor)
+{
+ TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor *>(editor);
+ if (!textEditor)
+ return;
+
+ connect(textEditor,
+ SIGNAL(markContextMenuRequested(TextEditor::ITextEditor*,int,QMenu*)),
+ SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*)));
+}
+
+void CallgrindTool::requestContextMenu(TextEditor::ITextEditor *editor, int line, QMenu *menu)
+{
+ // find callgrind text mark that corresponds to this editor's file and line number
+ const Function *func = 0;
+ foreach(CallgrindTextMark *textMark, m_textMarks) {
+ if (textMark->fileName() == editor->file()->fileName() && textMark->lineNumber() == line) {
+ func = textMark->function();
+ break;
+ }
+ }
+ if (!func)
+ return; // no callgrind text mark under cursor, return
+
+ // add our action to the context menu
+ QAction *action = new QAction(tr("Select this function in the analyzer output"), menu);
+ connect(action, SIGNAL(triggered()), this, SLOT(handleShowCostsAction()));
+ action->setData(QVariant::fromValue<const Function *>(func));
+ menu->addAction(action);
+}
+
+void CallgrindTool::handleShowCostsAction()
+{
+ const QAction *action = qobject_cast<QAction *>(sender());
+ QTC_ASSERT(action, return)
+
+ const Function *func = action->data().value<const Function *>();
+ QTC_ASSERT(func, return)
+
+ m_callgrindWidgetHandler->selectFunction(func);
+}
+
+void CallgrindTool::handleShowCostsOfFunction()
+{
+ CPlusPlus::Symbol *symbol = AnalyzerUtils::findSymbolUnderCursor();
+ if (!symbol)
+ return;
+
+ if (!symbol->isFunction())
+ return;
+
+ CPlusPlus::Overview view;
+ const QString qualifiedFunctionName = view.prettyName(CPlusPlus::LookupContext::fullyQualifiedName(symbol));
+
+ m_toggleCollectFunction = QString("%1()").arg(qualifiedFunctionName);
+
+ AnalyzerManager::instance()->selectTool(this);
+ AnalyzerManager::instance()->startTool();
+}
+
+
+void CallgrindTool::slotRequestDump()
+{
+ m_callgrindWidgetHandler->visualisation()->setText(tr("Populating..."));
+ emit dumpRequested();
+}
+
+void CallgrindTool::slotFunctionSelected(const Function *func)
+{
+ if (func && QFile::exists(func->file())) {
+ ///TODO: custom position support?
+ int line = func->lineNumber();
+ TextEditor::BaseTextEditorWidget::openEditorAt(func->file(), qMax(line, 0));
+ }
+}
+
+void CallgrindTool::takeParserData(CallgrindEngine *engine)
+{
+ ParseData *data = engine->takeParserData();
+ showParserResults(data);
+
+ if (!data)
+ return;
+
+ // clear first
+ clearErrorView();
+
+ m_callgrindWidgetHandler->setParseData(data);
+ createTextMarks();
+}
+
+void CallgrindTool::createTextMarks()
+{
+ DataModel *model = m_callgrindWidgetHandler->dataModel();
+ QTC_ASSERT(model, return)
+
+ QList<QString> locations;
+ for (int row = 0; row < model->rowCount(); ++row)
+ {
+ const QModelIndex index = model->index(row, DataModel::InclusiveCostColumn);
+
+ QString fileName = index.data(DataModel::FileNameRole).toString();
+ if (fileName.isEmpty() || fileName == "???")
+ continue;
+
+ bool ok = false;
+ const int lineNumber = index.data(DataModel::LineNumberRole).toInt(&ok);
+ QTC_ASSERT(ok, continue);
+
+ // sanitize filename, text marks need a canonical (i.e. no ".."s) path
+ // BaseTextMark::editorOpened(Core::IEditor *editor) compares file names on string basis
+ QFileInfo info(fileName);
+ fileName = info.canonicalFilePath();
+ if (fileName.isEmpty())
+ continue; // isEmpty == true => file does not exist, continue then
+
+ // create only one text mark per location
+ const QString location = QString("%1:%2").arg(fileName, QString::number(lineNumber));
+ if (locations.contains(location))
+ continue;
+ locations << location;
+
+ CallgrindTextMark *mark = new CallgrindTextMark(index, fileName, lineNumber);
+ m_textMarks << mark;
+ }
+}
+
+IAnalyzerOutputPaneAdapter *CallgrindTool::outputPaneAdapter()
+{
+ if (!m_outputPaneAdapter)
+ m_outputPaneAdapter = new CallgrindOutputPaneAdapter(this);
+ return m_outputPaneAdapter;
+}
+
+bool CallgrindTool::canRunRemotely() const
+{
+ return true;
+}
+
+
+}
+}
diff --git a/src/plugins/callgrind/callgrindtool.h b/src/plugins/callgrind/callgrindtool.h
new file mode 100644
index 0000000000..2b1322f55e
--- /dev/null
+++ b/src/plugins/callgrind/callgrindtool.h
@@ -0,0 +1,155 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 CALLGRINDTOOL_H
+#define CALLGRINDTOOL_H
+
+#include <analyzerbase/ianalyzertool.h>
+
+#include <QVector>
+
+QT_BEGIN_NAMESPACE
+class QCheckBox;
+class QAction;
+class QComboBox;
+class QSortFilterProxyModel;
+class QMenu;
+class QModelIndex;
+QT_END_NAMESPACE
+
+namespace Valgrind {
+namespace Callgrind {
+class CostView;
+class DataModel;
+class DataProxyModel;
+class Function;
+class ParseData;
+class StackBrowser;
+class Visualisation;
+}
+}
+
+namespace TextEditor
+{
+class ITextEditor;
+}
+namespace Core
+{
+class IEditor;
+}
+
+namespace Callgrind {
+namespace Internal {
+
+class CallgrindEngine;
+class CallgrindWidgetHandler;
+class CallgrindOutputPaneAdapter;
+class CallgrindTextMark;
+
+class CallgrindTool : public Analyzer::IAnalyzerTool
+{
+ Q_OBJECT
+
+public:
+ explicit CallgrindTool(QObject *parent = 0);
+ virtual ~CallgrindTool();
+
+ virtual QString id() const;
+ virtual QString displayName() const;
+ virtual ToolMode mode() const;
+
+ virtual void initialize(ExtensionSystem::IPlugin *plugin);
+ virtual void extensionsInitialized();
+
+ virtual Analyzer::IAnalyzerOutputPaneAdapter *outputPaneAdapter();
+ virtual Analyzer::IAnalyzerEngine *createEngine(const Analyzer::AnalyzerStartParameters &sp,
+ ProjectExplorer::RunConfiguration *runConfiguration = 0);
+ virtual QWidget *createControlWidget();
+
+ // For the output pane adapter.
+ CallgrindWidgetHandler *callgrindWidgetHandler() const;
+ QWidget *createPaneToolBarWidget();
+ void clearErrorView();
+
+ virtual bool canRunRemotely() const;
+
+signals:
+ void dumpRequested();
+ void resetRequested();
+ void pauseToggled(bool checked);
+
+ void profilingStartRequested(const QString &toggleCollectFunction);
+
+private slots:
+ void showParserResults(const Valgrind::Callgrind::ParseData *data);
+
+ void slotRequestDump();
+ void slotFunctionSelected(const Valgrind::Callgrind::Function *);
+
+ void editorOpened(Core::IEditor *);
+ void requestContextMenu(TextEditor::ITextEditor *editor, int line, QMenu *menu);
+
+ void handleShowCostsAction();
+ void handleShowCostsOfFunction();
+
+ void takeParserData(CallgrindEngine *engine);
+
+ void engineStarting(const Analyzer::IAnalyzerEngine *);
+ void engineFinished();
+
+private:
+ /// This function will add custom text marks to the editor
+ /// \note Call this after the data model has been populated
+ void createTextMarks();
+
+ /// This function will clear all text marks from the editor
+ void clearTextMarks();
+
+ CallgrindWidgetHandler *m_callgrindWidgetHandler;
+ QVector<CallgrindTextMark *> m_textMarks;
+
+ QAction *m_dumpAction;
+ QAction *m_resetAction;
+ QAction *m_pauseAction;
+
+ QAction *m_showCostsOfFunctionAction;
+
+ CallgrindOutputPaneAdapter *m_outputPaneAdapter;
+
+ QString m_toggleCollectFunction;
+};
+
+} // namespace Internal
+} // namespace Callgrind
+
+#endif // CALLGRINDTOOL_H
diff --git a/src/plugins/callgrind/callgrindvisualisation.cpp b/src/plugins/callgrind/callgrindvisualisation.cpp
new file mode 100644
index 0000000000..7cd6dcb96d
--- /dev/null
+++ b/src/plugins/callgrind/callgrindvisualisation.cpp
@@ -0,0 +1,502 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "callgrindvisualisation.h"
+
+#include "callgrindhelper.h"
+
+#include <valgrind/callgrind/callgrindabstractmodel.h>
+#include <valgrind/callgrind/callgrinddatamodel.h>
+#include <valgrind/callgrind/callgrindfunction.h>
+#include <valgrind/callgrind/callgrindproxymodel.h>
+#include <utils/qtcassert.h>
+
+#include <QAbstractItemModel>
+#include <QDebug>
+#include <QGraphicsRectItem>
+#include <QGraphicsScene>
+#include <QGraphicsSimpleTextItem>
+#include <QMouseEvent>
+#include <QStaticText>
+#include <QStyleOptionGraphicsItem>
+#include <QPair>
+#include <QPersistentModelIndex>
+#include <QLinkedList>
+
+#define VISUALISATION_DEBUG 0
+// Margin from hardcoded value in:
+// QGraphicsView::fitInView(const QRectF &rect,
+// Qt::AspectRatioMode aspectRatioMode)
+// Bug report here: http://bugreports.qt.nokia.com/browse/QTBUG-11945
+#define FIT_IN_VIEW_MARGIN 2;
+
+using namespace Valgrind::Callgrind;
+
+namespace Callgrind {
+namespace Internal {
+
+class FunctionGraphicsTextItem : public QAbstractGraphicsShapeItem
+{
+public:
+ FunctionGraphicsTextItem(const QString &text, QGraphicsItem *parent);
+
+ virtual void paint(QPainter *painter,
+ const QStyleOptionGraphicsItem *option, QWidget *widget);
+ virtual QRectF boundingRect() const;
+
+ void setRotateText(bool rotate);
+
+private:
+ QString m_text;
+ QStaticText m_staticText;
+ bool m_rotateText;
+ QColor m_textColor;
+ qreal m_previousViewportDimension;
+};
+
+class FunctionGraphicsItem : public QGraphicsRectItem
+{
+public:
+ enum DataKey {
+ FunctionCallKey
+ };
+
+ FunctionGraphicsItem(const QString &text, qreal x, qreal y,
+ qreal width, qreal height, QGraphicsItem *parent = 0);
+
+ virtual void paint(QPainter *painter,
+ const QStyleOptionGraphicsItem *option, QWidget *widget);
+ FunctionGraphicsTextItem *textItem() const;
+
+private:
+ FunctionGraphicsTextItem *m_text;
+};
+
+FunctionGraphicsTextItem::FunctionGraphicsTextItem(const QString &text,
+ QGraphicsItem *parent)
+ : QAbstractGraphicsShapeItem(parent)
+ , m_text(text)
+ , m_rotateText(true)
+ , m_previousViewportDimension(0)
+{
+ setFlag(QGraphicsItem::ItemIgnoresTransformations);
+ setAcceptedMouseButtons(0); // do not steal focus from parent item
+ setToolTip(text);
+}
+
+void FunctionGraphicsTextItem::setRotateText(bool rotate)
+{
+ m_rotateText = rotate;
+}
+
+void FunctionGraphicsTextItem::paint(QPainter *painter,
+ const QStyleOptionGraphicsItem *,
+ QWidget *widget)
+{
+ const qreal textHeight = painter->fontMetrics().height();
+ // Magic number based on what looked best.
+ const int margin = 2 + FIT_IN_VIEW_MARGIN;
+ const QRectF viewportRect =
+ widget->rect().adjusted(margin, margin, -margin, -margin);
+
+ const qreal maxWidth = viewportRect.width()
+ * parentItem()->boundingRect().width()
+ / scene()->sceneRect().width();
+ const qreal maxHeight = viewportRect.height()
+ * parentItem()->boundingRect().height()
+ / scene()->sceneRect().height();
+
+ qreal textMaxHeight;
+ qreal textMaxWidth;
+ qreal viewportDim;
+ if (m_rotateText) {
+ viewportDim = viewportRect.height();
+ textMaxHeight = maxWidth;
+ textMaxWidth = maxHeight;
+ } else {
+ viewportDim = viewportRect.width();
+ textMaxHeight = maxHeight;
+ textMaxWidth = maxWidth;
+ }
+
+ if (textHeight > textMaxHeight)
+ return;
+
+ if (viewportDim != m_previousViewportDimension) {
+ const QString &elidedText =
+ painter->fontMetrics().elidedText(m_text, Qt::ElideRight,
+ textMaxWidth);
+ m_staticText.setText(elidedText);
+ m_staticText.prepare();
+
+ m_previousViewportDimension = viewportDim;
+ }
+
+#if VISUALISATION_DEBUG
+ painter->setPen(Qt::red);
+ painter->drawRect(boundingRect());
+#endif
+
+ painter->save();
+ int textLeft = 0;
+ int textTop = 0;
+ if (m_rotateText) {
+ painter->rotate(90);
+ textLeft = 2;
+ textTop = -textHeight/2;
+ }
+ else {
+ const int textWidth = painter->fontMetrics().width(m_staticText.text());
+ textLeft = -textWidth/2;
+ textTop = (maxHeight - textHeight)/2;
+ }
+ painter->drawStaticText(textLeft, textTop, m_staticText);
+
+ painter->restore();
+}
+
+QRectF FunctionGraphicsTextItem::boundingRect() const
+{
+ return mapRectFromParent(parentItem()->boundingRect());
+}
+
+FunctionGraphicsItem::FunctionGraphicsItem(const QString &text,
+ qreal x, qreal y, qreal width,
+ qreal height, QGraphicsItem *parent)
+ : QGraphicsRectItem(x, y, width, height, parent)
+ , m_text(0)
+{
+ setFlag(QGraphicsItem::ItemIsSelectable);
+ setFlag(QGraphicsItem::ItemClipsToShape);
+ setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ setToolTip(text);
+
+ m_text = new FunctionGraphicsTextItem(text, this);
+ m_text->setPos(rect().center().x(), y);
+}
+
+FunctionGraphicsTextItem *FunctionGraphicsItem::textItem() const
+{
+ return m_text;
+}
+
+void FunctionGraphicsItem::paint(QPainter *painter,
+ const QStyleOptionGraphicsItem *option,
+ QWidget *)
+{
+ painter->save();
+
+ QRectF rect = this->rect();
+ const QColor &color = brush().color();
+ if (option->state & QStyle::State_Selected) {
+ QLinearGradient gradient(0, 0, rect.width(), rect.height());
+ gradient.setColorAt(0, color.lighter(250));
+ gradient.setColorAt(1, color.darker());
+ painter->setBrush(gradient);
+ }
+ else {
+ painter->setBrush(color);
+ }
+
+#if VISUALISATION_DEBUG
+ painter->setPen(Qt::blue);
+ painter->drawRect(boundingRect());
+#endif
+
+ QPen pen = painter->pen();
+ pen.setColor(color.darker());
+ pen.setWidthF(0.5);
+ painter->setPen(pen);
+ qreal halfPenWidth = pen.widthF()/2.0;
+ rect.adjust(halfPenWidth, halfPenWidth, -halfPenWidth, -halfPenWidth);
+ painter->drawRect(rect);
+
+ painter->restore();
+}
+
+class Visualisation::Private
+{
+public:
+ Private(Visualisation *qq);
+ ~Private();
+
+ void handleMousePressEvent(QMouseEvent *event, bool doubleClicked);
+ qreal sceneHeight() const;
+ qreal sceneWidth() const;
+
+ Visualisation *q;
+ DataProxyModel *m_model;
+ QGraphicsScene m_scene;
+ int m_modelColumn;
+};
+
+Visualisation::Private::Private(Visualisation *qq)
+ : q(qq)
+ , m_model(new DataProxyModel(qq))
+ , m_modelColumn(-1)
+{
+ // setup scene
+ m_scene.setObjectName("Visualisation Scene");
+ ///NOTE: with size 100x100 the Qt-internal mouse selection fails...
+ m_scene.setSceneRect(0, 0, 1024, 1024);
+
+ // setup model
+ m_model->setMinimumInclusiveCostRatio(0.1);
+ connect(m_model,
+ SIGNAL(filterFunctionChanged(const Function*,const Function*)),
+ qq, SLOT(populateScene()));
+}
+
+Visualisation::Private::~Private()
+{
+
+}
+
+void Visualisation::Private::handleMousePressEvent(QMouseEvent *event,
+ bool doubleClicked)
+{
+ // find the first item that accepts mouse presses under the cursor position
+ QGraphicsItem *itemAtPos = 0;
+ foreach(QGraphicsItem *item, q->items(event->pos())) {
+ if (!(item->acceptedMouseButtons() & event->button()))
+ continue;
+
+ itemAtPos = item;
+ break;
+ }
+
+ // if there is an item, select it
+ if (itemAtPos) {
+ const Function *func = q->functionForItem(itemAtPos);
+
+ if (doubleClicked) {
+ q->functionActivated(func);
+ }
+ else {
+ q->scene()->clearSelection();
+ itemAtPos->setSelected(true);
+ q->functionSelected(func);
+ }
+ }
+
+}
+
+qreal Visualisation::Private::sceneHeight() const
+{
+ return m_scene.height() - FIT_IN_VIEW_MARGIN;
+}
+
+qreal Visualisation::Private::sceneWidth() const
+{
+ // Magic number to improve margins appearance
+ return m_scene.width() + 1;
+}
+
+Visualisation::Visualisation(QWidget *parent)
+ : QGraphicsView(parent)
+ , d(new Private(this))
+{
+ setObjectName("Visualisation View");
+ setScene(&d->m_scene);
+ setRenderHint(QPainter::Antialiasing);
+}
+
+Visualisation::~Visualisation()
+{
+ delete d;
+}
+
+const Function *Visualisation::functionForItem(QGraphicsItem *item) const
+{
+ return item->data(FunctionGraphicsItem::FunctionCallKey).value<const Function *>();
+}
+
+QGraphicsItem *Visualisation::itemForFunction(const Function *function) const
+{
+ foreach(QGraphicsItem *item, items()) {
+ if (functionForItem(item) == function)
+ return item;
+ }
+ return 0;
+}
+
+void Visualisation::setFunction(const Function *function)
+{
+ d->m_model->setFilterFunction(function);
+}
+
+const Function *Visualisation::function() const
+{
+ return d->m_model->filterFunction();
+}
+
+void Visualisation::setModel(DataModel *model)
+{
+ QTC_ASSERT(!d->m_model->sourceModel() && model, return); // only set once!
+ d->m_model->setSourceModel(model);
+
+ connect(model,
+ SIGNAL(columnsInserted(const QModelIndex&, int, int)),
+ SLOT(populateScene()));
+ connect(model,
+ SIGNAL(columnsMoved(const QModelIndex&, int, int, const QModelIndex&, int)),
+ SLOT(populateScene()));
+ connect(model,
+ SIGNAL(columnsRemoved(const QModelIndex&, int, int)),
+ SLOT(populateScene()));
+ connect(model,
+ SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
+ SLOT(populateScene()));
+ connect(model,
+ SIGNAL(headerDataChanged(Qt::Orientation, int, int)),
+ SLOT(populateScene()));
+ connect(model, SIGNAL(layoutChanged()), SLOT(populateScene()));
+ connect(model, SIGNAL(modelReset()), SLOT(populateScene()));
+ connect(model,
+ SIGNAL(rowsInserted(const QModelIndex&, int, int)),
+ SLOT(populateScene()));
+ connect(model,
+ SIGNAL(rowsMoved(const QModelIndex&, int, int, const QModelIndex&, int)),
+ SLOT(populateScene()));
+ connect(model,
+ SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
+ SLOT(populateScene()));
+
+ populateScene();
+}
+
+void Visualisation::setText(const QString &message)
+{
+ d->m_scene.clear();
+
+ QGraphicsSimpleTextItem *textItem = d->m_scene.addSimpleText(message);
+ textItem->setBrush(palette().foreground());
+ textItem->setPos((d->sceneWidth() - textItem->boundingRect().width()) / 2,
+ (d->sceneHeight() - textItem->boundingRect().height()) / 2);
+ textItem->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+}
+
+void Visualisation::populateScene()
+{
+ // reset scene first
+ d->m_scene.clear();
+
+ const qreal sceneWidth = d->sceneWidth();
+ const qreal sceneHeight = d->sceneHeight();
+
+ // cache costs of each element, calculate total costs
+ qreal total = 0;
+
+ typedef QPair<QModelIndex, qreal> Pair;
+ QLinkedList<Pair> costs;
+ for (int row=0; row < d->m_model->rowCount(); ++row)
+ {
+ const QModelIndex index = d->m_model->index(row, DataModel::InclusiveCostColumn);
+
+ bool ok = false;
+ const qreal cost = index.data().toReal(&ok);
+ QTC_ASSERT(ok, continue);
+ costs << QPair<QModelIndex, qreal>(d->m_model->index(row, 0), cost);
+ total += cost;
+ }
+
+ if (!costs.isEmpty() || d->m_model->filterFunction()) {
+ // item showing the current filter function
+
+ QString text;
+ if (d->m_model->filterFunction())
+ text = d->m_model->filterFunction()->name();
+ else {
+ const float ratioPercent = d->m_model->minimumInclusiveCostRatio() * 100;
+ QString ratioPercentString = QString::number(ratioPercent);
+ ratioPercentString.append(QLocale::system().percent());
+ const int hiddenFunctions = d->m_model->sourceModel()->rowCount() - d->m_model->rowCount();
+ text = tr("All functions with an inclusive cost ratio higher than %1 (%2 are hidden)")
+ .arg(ratioPercentString)
+ .arg(hiddenFunctions);
+ }
+
+ const qreal height = sceneHeight* (costs.isEmpty() ? 1.0 : 0.1);
+ FunctionGraphicsItem *item = new FunctionGraphicsItem(text, 0, 0, sceneWidth, height);
+ const QColor background = CallgrindHelper::colorForString(text);
+ item->setBrush(background);
+ item->setData(FunctionGraphicsItem::FunctionCallKey, QVariant::fromValue(d->m_model->filterFunction()));
+ item->textItem()->setRotateText(false);
+ // NOTE: workaround wrong tooltip being show, no idea why...
+ item->setZValue(-1);
+ d->m_scene.addItem(item);
+ }
+
+ // add the canvas elements to the scene
+ qreal used = 0;
+ foreach(const Pair &cost, costs)
+ {
+ const QModelIndex &index = cost.first;
+ const QString text = index.data().toString();
+
+ const qreal width = (sceneWidth * cost.second) / total;
+ const qreal height = sceneHeight * 0.9;
+
+ FunctionGraphicsItem *item = new FunctionGraphicsItem(text, used, sceneHeight - height, width, height);
+ const QColor background = CallgrindHelper::colorForString(text);
+ item->setBrush(background);
+ item->setData(FunctionGraphicsItem::FunctionCallKey, index.data(DataModel::FunctionRole));
+ d->m_scene.addItem(item);
+ used += width;
+ }
+}
+
+void Visualisation::mousePressEvent(QMouseEvent *event)
+{
+ d->handleMousePressEvent(event, false);
+
+ QGraphicsView::mousePressEvent(event);
+}
+
+void Visualisation::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ d->handleMousePressEvent(event, true);
+
+ QGraphicsView::mouseDoubleClickEvent(event);
+}
+
+void Visualisation::resizeEvent(QResizeEvent *event)
+{
+ fitInView(sceneRect());
+
+ QGraphicsView::resizeEvent(event);
+}
+
+
+} // Internal
+} // Callgrind
diff --git a/src/plugins/callgrind/callgrindvisualisation.h b/src/plugins/callgrind/callgrindvisualisation.h
new file mode 100644
index 0000000000..d5dd397910
--- /dev/null
+++ b/src/plugins/callgrind/callgrindvisualisation.h
@@ -0,0 +1,94 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 CALLGRINDVISUALISATION_H
+#define CALLGRINDVISUALISATION_H
+
+#include <QGraphicsView>
+
+QT_BEGIN_NAMESPACE
+class QAbstractItemModel;
+class QModelIndex;
+QT_END_NAMESPACE
+
+namespace Valgrind {
+namespace Callgrind {
+class Function;
+class DataModel;
+}
+}
+
+namespace Callgrind {
+namespace Internal {
+
+class Visualisation : public QGraphicsView
+{
+ Q_OBJECT
+
+public:
+ explicit Visualisation(QWidget *parent = 0);
+ virtual ~Visualisation();
+
+ void setModel(Valgrind::Callgrind::DataModel *model);
+
+ const Valgrind::Callgrind::Function *functionForItem(QGraphicsItem *item) const;
+ QGraphicsItem *itemForFunction(const Valgrind::Callgrind::Function *function) const;
+
+ void setFunction(const Valgrind::Callgrind::Function *function);
+ const Valgrind::Callgrind::Function *function() const;
+
+public slots:
+ void setText(const QString &message);
+
+signals:
+ void functionActivated(const Valgrind::Callgrind::Function *);
+ void functionSelected(const Valgrind::Callgrind::Function *);
+
+protected slots:
+ void populateScene();
+
+ virtual void mousePressEvent(QMouseEvent *event);
+ virtual void mouseDoubleClickEvent(QMouseEvent *event);
+
+protected:
+ virtual void resizeEvent(QResizeEvent *event);
+
+private:
+ class Private;
+ Private *d;
+};
+
+} // Internal
+} // Callgrind
+
+#endif // VALGRIND_CALLGRIND_CALLGRINDVISUALISATION_H
diff --git a/src/plugins/callgrind/callgrindwidgethandler.cpp b/src/plugins/callgrind/callgrindwidgethandler.cpp
new file mode 100644
index 0000000000..af85791a38
--- /dev/null
+++ b/src/plugins/callgrind/callgrindwidgethandler.cpp
@@ -0,0 +1,499 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "callgrindwidgethandler.h"
+
+#include "callgrindcostview.h"
+#include "callgrindengine.h"
+#include "callgrindvisualisation.h"
+
+#ifndef DISABLE_CALLGRIND_WORKAROUNDS
+#include "workarounds.h"
+#endif
+
+#include <analyzerbase/analyzerconstants.h>
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/actionmanager/command.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/projectexplorer.h>
+
+#include <valgrind/callgrind/callgrinddatamodel.h>
+#include <valgrind/callgrind/callgrindparsedata.h>
+#include <valgrind/callgrind/callgrindfunction.h>
+#include <valgrind/callgrind/callgrindcostitem.h>
+#include <valgrind/callgrind/callgrindstackbrowser.h>
+#include <valgrind/callgrind/callgrindcallmodel.h>
+#include <valgrind/callgrind/callgrindproxymodel.h>
+#include <valgrind/callgrind/callgrindfunctioncall.h>
+
+#include <utils/fancymainwindow.h>
+#include <utils/styledbar.h>
+#include <utils/qtcassert.h>
+
+#include <QtCore/QTimer>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QCheckBox>
+#include <QtGui/QLineEdit>
+#include <QtGui/QGraphicsItem>
+#include <QtGui/QToolButton>
+#include <QtGui/QAction>
+#include <QtGui/QLineEdit>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QMenu>
+#include <QtGui/QActionGroup>
+#include <QSortFilterProxyModel>
+#include <QComboBox>
+
+using namespace Valgrind::Callgrind;
+
+namespace Callgrind {
+namespace Internal {
+
+CallgrindWidgetHandler::CallgrindWidgetHandler(QWidget *parent)
+: QObject(parent)
+, m_dataModel(new DataModel(this))
+, m_dataProxy(new DataProxyModel(this))
+, m_stackBrowser(new StackBrowser(this))
+, m_callersModel(new CallModel(this))
+, m_calleesModel(new CallModel(this))
+, m_flatView(0)
+, m_callersView(0)
+, m_calleesView(0)
+, m_visualisation(0)
+, m_goToOverview(0)
+, m_goBack(0)
+, m_searchFilter(0)
+, m_filterProjectCosts(0)
+, m_costAbsolute(0)
+, m_costRelative(0)
+, m_costRelativeToParent(0)
+, m_eventCombo(0)
+, m_updateTimer(new QTimer(this))
+{
+ connect(m_stackBrowser, SIGNAL(currentChanged()), this, SLOT(stackBrowserChanged()));
+
+ m_updateTimer->setInterval(200);
+ m_updateTimer->setSingleShot(true);
+ connect(m_updateTimer, SIGNAL(timeout()), SLOT(updateFilterString()));
+
+ m_dataProxy->setSourceModel(m_dataModel);
+ m_dataProxy->setDynamicSortFilter(true);
+ m_dataProxy->setSortCaseSensitivity(Qt::CaseInsensitive);
+ m_dataProxy->setFilterKeyColumn(DataModel::NameColumn);
+ m_dataProxy->setFilterCaseSensitivity(Qt::CaseInsensitive);
+
+ m_flatView = new CostView(parent);
+ m_flatView->sortByColumn(DataModel::SelfCostColumn);
+ m_flatView->setFrameStyle(QFrame::NoFrame);
+ m_flatView->setAttribute(Qt::WA_MacShowFocusRect, false);
+ m_flatView->setModel(m_dataProxy);
+ m_flatView->setObjectName("Valgrind.CallgrindWidgetHandler.FlatView");
+ connect(m_flatView, SIGNAL(activated(QModelIndex)),
+ this, SLOT(dataFunctionSelected(QModelIndex)));
+
+ m_visualisation = new Visualisation(parent);
+ m_visualisation->setObjectName("Valgrind.CallgrindWidgetHandler.Visualisation");
+ m_visualisation->setModel(m_dataModel);
+ connect(m_visualisation, SIGNAL(functionActivated(const Valgrind::Callgrind::Function*)),
+ this, SLOT(visualisationFunctionSelected(const Valgrind::Callgrind::Function*)));
+
+ {
+ m_calleesView = new CostView(parent);
+ m_calleesView->sortByColumn(CallModel::CostColumn);
+ m_calleesView->setObjectName("Valgrind.CallgrindWidgetHandler.CalleesView");
+ // enable sorting
+ QSortFilterProxyModel *calleeProxy = new QSortFilterProxyModel(m_calleesModel);
+ calleeProxy->setSourceModel(m_calleesModel);
+ m_calleesView->setModel(calleeProxy);
+ m_calleesView->hideColumn(CallModel::CallerColumn);
+ connect(m_calleesView, SIGNAL(activated(QModelIndex)),
+ this, SLOT(calleeFunctionSelected(QModelIndex)));
+ }
+ {
+ m_callersView = new CostView(parent);
+ m_callersView->sortByColumn(CallModel::CostColumn);
+ m_callersView->setObjectName("Valgrind.CallgrindWidgetHandler.CallersView");
+ // enable sorting
+ QSortFilterProxyModel *callerProxy = new QSortFilterProxyModel(m_callersModel);
+ callerProxy->setSourceModel(m_callersModel);
+ m_callersView->setModel(callerProxy);
+ m_callersView->hideColumn(CallModel::CalleeColumn);
+ connect(m_callersView, SIGNAL(activated(QModelIndex)),
+ this, SLOT(callerFunctionSelected(QModelIndex)));
+ }
+}
+
+void CallgrindWidgetHandler::populateActions(QLayout *layout)
+{
+ // navigation
+ {
+ QToolButton *button;
+ QAction *action;
+
+ // go back
+ action = new QAction(this);
+ action->setDisabled(true);
+ action->setIcon(QIcon::fromTheme("go-previous"));
+ action->setText(tr("Back"));
+ action->setToolTip(tr("Go back one step in history. This will select the previously selected item."));
+ m_goBack = action;
+ connect(action, SIGNAL(triggered(bool)), m_stackBrowser, SLOT(goBack()));
+ button = new QToolButton;
+ button->setDefaultAction(action);
+ layout->addWidget(button);
+
+ // overview
+ action = new QAction(this);
+ action->setDisabled(true);
+ action->setIcon(QIcon::fromTheme("go-up"));
+ action->setText(tr("All Functions"));
+ action->setToolTip(tr("Show the overview of all function calls."));
+ m_goToOverview = action;
+ connect(action, SIGNAL(triggered(bool)), this, SLOT(slotGoToOverview()));
+ button = new QToolButton;
+ button->setDefaultAction(action);
+ layout->addWidget(button);
+ }
+
+ layout->addWidget(new Utils::StyledSeparator);
+
+ // event selection
+ {
+ m_eventCombo = new QComboBox;
+ m_eventCombo->setToolTip(tr("Selects which events from the profiling data are shown and visualized."));
+ connect(m_eventCombo, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(setCostEvent(int)));
+ updateEventCombo();
+ layout->addWidget(m_eventCombo);
+ }
+
+ // cost formatting
+ {
+ QMenu *menu = new QMenu(layout->parentWidget());
+ QActionGroup *group = new QActionGroup(this);
+
+ // show costs as absolute numbers
+ m_costAbsolute = new QAction(tr("Absolute Costs"), this);
+ ///FIXME: icon
+ m_costAbsolute->setToolTip(tr("Show costs as absolute numbers."));
+ m_costAbsolute->setCheckable(true);
+ m_costAbsolute->setChecked(true);
+ connect(m_costAbsolute, SIGNAL(toggled(bool)),
+ this, SLOT(updateCostFormat()));
+ group->addAction(m_costAbsolute);
+ menu->addAction(m_costAbsolute);
+
+ // show costs in percentages
+ m_costRelative = new QAction(tr("Relative Costs"), this);
+ ///FIXME: icon (percentage sign?)
+ m_costRelative->setToolTip(tr("Show costs relative to total inclusive cost."));
+ m_costRelative->setCheckable(true);
+ connect(m_costRelative, SIGNAL(toggled(bool)),
+ this, SLOT(updateCostFormat()));
+ group->addAction(m_costRelative);
+ menu->addAction(m_costRelative);
+
+ // show costs relative to parent
+ m_costRelativeToParent = new QAction(tr("Relative Costs To Parent"), this);
+ ///FIXME: icon
+ m_costRelativeToParent->setToolTip(tr("Show costs relative to parent functions inclusive cost."));
+ m_costRelativeToParent->setCheckable(true);
+ connect(m_costRelativeToParent, SIGNAL(toggled(bool)),
+ this, SLOT(updateCostFormat()));
+ group->addAction(m_costRelativeToParent);
+ menu->addAction(m_costRelativeToParent);
+
+ QToolButton *button = new QToolButton;
+ button->setMenu(menu);
+ button->setPopupMode(QToolButton::InstantPopup);
+ button->setText(tr("Cost Format"));
+ layout->addWidget(button);
+ }
+
+ {
+ // cycle detection
+ m_cycleDetection = new QAction(tr("Cycle Detection"), this);
+ ///FIXME: icon
+ m_cycleDetection->setToolTip(tr("Enable cycle detection to properly handle recursive or circular function calls."));
+ connect(m_cycleDetection, SIGNAL(toggled(bool)),
+ m_dataModel, SLOT(enableCycleDetection(bool)));
+ connect(m_cycleDetection, SIGNAL(toggled(bool)),
+ this, SIGNAL(cycleDetectionEnabled(bool)));
+ m_cycleDetection->setCheckable(true);
+ QToolButton *button = new QToolButton;
+ button->setDefaultAction(m_cycleDetection);
+ layout->addWidget(button);
+ }
+
+ // filtering
+ {
+ QToolButton *button;
+ m_filterProjectCosts = new QAction(tr("Show Project Costs Only"), this);
+ m_filterProjectCosts->setIcon(QIcon(Core::Constants::ICON_FILTER));
+ m_filterProjectCosts->setToolTip(tr("Show only profiling info that originated from this project source."));
+ m_filterProjectCosts->setCheckable(true);
+ connect(m_filterProjectCosts, SIGNAL(toggled(bool)),
+ this, SLOT( handleFilterProjectCosts()));
+ button = new QToolButton;
+ button->setDefaultAction(m_filterProjectCosts);
+ layout->addWidget(button);
+
+ // filter
+ ///FIXME: find workaround for http://bugreports.qt.nokia.com/browse/QTCREATORBUG-3247
+ QLineEdit *filter = new QLineEdit;
+ filter->setPlaceholderText(tr("Filter..."));
+ connect(filter, SIGNAL(textChanged(QString)),
+ m_updateTimer, SLOT(start()));
+ layout->addWidget(filter);
+ m_searchFilter = filter;
+ }
+
+ layout->addWidget(new Utils::StyledSeparator);
+}
+
+CallgrindWidgetHandler::~CallgrindWidgetHandler()
+{
+ slotClear();
+}
+
+void CallgrindWidgetHandler::slotGoToOverview()
+{
+ selectFunction(0);
+}
+
+void CallgrindWidgetHandler::slotClear()
+{
+ setParseData(0);
+
+ // clear filters
+ m_filterProjectCosts->setChecked(false);
+ m_dataProxy->setFilterBaseDir(QString());
+ m_searchFilter->setText(QString());
+ m_dataProxy->setFilterFixedString(QString());
+}
+
+void CallgrindWidgetHandler::slotRequestDump()
+{
+ m_visualisation->setText(tr("Populating..."));
+ emit dumpRequested();
+}
+
+void CallgrindWidgetHandler::selectFunction(const Function *func)
+{
+ if (!func) {
+ m_goToOverview->setDisabled(true);
+
+ m_flatView->clearSelection();
+ m_visualisation->setFunction(0);
+ m_callersModel->clear();
+ m_calleesModel->clear();
+
+ emit functionSelected(0);
+ return;
+ }
+
+ m_goToOverview->setEnabled(true);
+
+ const QModelIndex index = m_dataModel->indexForObject(func);
+ const QModelIndex proxyIndex = m_dataProxy->mapFromSource(index);
+ m_flatView->selectionModel()->clearSelection();
+ m_flatView->selectionModel()->setCurrentIndex(proxyIndex,
+ QItemSelectionModel::ClearAndSelect |
+ QItemSelectionModel::Rows);
+ m_flatView->scrollTo(proxyIndex);
+
+ m_callersModel->setCalls(func->incomingCalls(), func);
+ m_calleesModel->setCalls(func->outgoingCalls(), func);
+ m_visualisation->setFunction(func);
+
+ const Function *item = m_stackBrowser->current();
+ if (!item || item != func)
+ m_stackBrowser->select(func);
+
+ emit functionSelected(func);
+}
+
+void CallgrindWidgetHandler::stackBrowserChanged()
+{
+ const Function *item = m_stackBrowser->current();
+ m_goBack->setEnabled(item != 0);
+ selectFunction(item);
+}
+
+void CallgrindWidgetHandler::updateFilterString()
+{
+ m_dataProxy->setFilterFixedString(m_searchFilter->text());
+}
+
+void CallgrindWidgetHandler::setCostFormat(CostDelegate::CostFormat format)
+{
+ switch(format) {
+ case CostDelegate::FormatAbsolute:
+ m_costAbsolute->setChecked(true);
+ break;
+ case CostDelegate::FormatRelative:
+ m_costRelative->setChecked(true);
+ break;
+ case CostDelegate::FormatRelativeToParent:
+ m_costRelativeToParent->setChecked(true);
+ break;
+ }
+}
+
+void CallgrindWidgetHandler::setCostEvent(int index)
+{
+ // prevent assert in model, don't try to set event to -1
+ // happens when we clear the eventcombo
+ if (index == -1)
+ index = 0;
+
+ m_dataModel->setCostEvent(index);
+ m_calleesModel->setCostEvent(index);
+ m_callersModel->setCostEvent(index);
+}
+
+void CallgrindWidgetHandler::enableCycleDetection(bool enabled)
+{
+ m_cycleDetection->setChecked(enabled);
+}
+
+void CallgrindWidgetHandler::updateCostFormat()
+{
+ CostDelegate::CostFormat format = CostDelegate::FormatAbsolute;
+
+ if (m_costRelativeToParent->isChecked())
+ format = CostDelegate::FormatRelativeToParent;
+ else if (m_costRelative->isChecked())
+ format = CostDelegate::FormatRelative;
+ // else = Absolute
+
+ m_flatView->setCostFormat(format);
+ m_calleesView->setCostFormat(format);
+ m_callersView->setCostFormat(format);
+
+ emit costFormatChanged(format);
+}
+
+void CallgrindWidgetHandler::handleFilterProjectCosts()
+{
+ ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance();
+ ProjectExplorer::Project *pro = pe->currentProject();
+ QTC_ASSERT(pro, return)
+
+ if (m_filterProjectCosts->isChecked()) {
+ const QString projectDir = pro->projectDirectory();
+ m_dataProxy->setFilterBaseDir(projectDir);
+ }
+ else {
+ m_dataProxy->setFilterBaseDir(QString());
+ }
+}
+
+void CallgrindWidgetHandler::dataFunctionSelected(const QModelIndex &index)
+{
+ const Function *func = index.data(DataModel::FunctionRole).value<const Function *>();
+ QTC_ASSERT(func, return);
+
+ selectFunction(func);
+}
+
+void CallgrindWidgetHandler::calleeFunctionSelected(const QModelIndex &index)
+{
+ const FunctionCall *call = index.data(CallModel::FunctionCallRole).value<const FunctionCall *>();
+ QTC_ASSERT(call, return);
+
+ selectFunction(call->callee());
+}
+
+void CallgrindWidgetHandler::callerFunctionSelected(const QModelIndex &index)
+{
+ const FunctionCall *call = index.data(CallModel::FunctionCallRole).value<const FunctionCall *>();
+ QTC_ASSERT(call, return);
+
+ selectFunction(call->caller());
+}
+
+void CallgrindWidgetHandler::visualisationFunctionSelected(const Function *function)
+{
+ if (function && function == m_visualisation->function())
+ // up-navigation when the initial function was activated
+ m_stackBrowser->goBack();
+ else
+ selectFunction(function);
+}
+
+void CallgrindWidgetHandler::setParseData(ParseData *data)
+{
+ // we have new parse data, invalidate filters in the proxy model
+ m_visualisation->setFunction(0);
+
+ // invalidate parse data in the data model
+ delete m_dataModel->parseData();
+
+ if (data && data->events().isEmpty()) {
+ // might happen if the user cancelled the profile run
+ // callgrind then sometimes produces empty callgrind.out.PID files
+ delete data;
+ data = 0;
+ }
+ m_dataModel->setParseData(data);
+ m_calleesModel->setParseData(data);
+ m_callersModel->setParseData(data);
+
+ updateEventCombo();
+
+ // clear history for new data
+ m_stackBrowser->clear();
+}
+
+void CallgrindWidgetHandler::updateEventCombo()
+{
+ QTC_ASSERT(m_eventCombo, return)
+
+ m_eventCombo->clear();
+
+ const ParseData *data = m_dataModel->parseData();
+ if (!data || data->events().isEmpty()) {
+ m_eventCombo->hide();
+ return;
+ }
+
+ m_eventCombo->show();
+ foreach(const QString &event, data->events())
+ m_eventCombo->addItem(ParseData::prettyStringForEvent(event));
+}
+
+}
+}
diff --git a/src/plugins/callgrind/callgrindwidgethandler.h b/src/plugins/callgrind/callgrindwidgethandler.h
new file mode 100644
index 0000000000..88a027849b
--- /dev/null
+++ b/src/plugins/callgrind/callgrindwidgethandler.h
@@ -0,0 +1,162 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 CALLGRINDWIDGETHANDLER_H
+#define CALLGRINDWIDGETHANDLER_H
+
+#include <QObject>
+
+#include "callgrindcostdelegate.h"
+
+QT_BEGIN_NAMESPACE
+class QToolButton;
+class QAction;
+class QLineEdit;
+class QModelIndex;
+class QSortFilterProxyModel;
+class QTimer;
+class QComboBox;
+QT_END_NAMESPACE
+
+namespace Valgrind {
+namespace Callgrind {
+class DataModel;
+class DataProxyModel;
+class Function;
+class ParseData;
+class StackBrowser;
+class CallModel;
+}
+}
+
+namespace Callgrind {
+namespace Internal {
+
+class CallgrindEngine;
+class Visualisation;
+class CostView;
+
+/**
+ * Encapsulates all widgets required for a fully operational callgrind UI.
+ * Prevents code duplication between QtC code and unit tests.
+ */
+class CallgrindWidgetHandler : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit CallgrindWidgetHandler(QWidget *parent);
+ virtual ~CallgrindWidgetHandler();
+
+ void populateActions(QLayout *layout);
+
+ void setParseData(Valgrind::Callgrind::ParseData *data);
+
+ Valgrind::Callgrind::DataModel *dataModel() const { return m_dataModel; }
+ Valgrind::Callgrind::DataProxyModel *proxyModel() const { return m_dataProxy; }
+ CostView *flatView() const { return m_flatView; }
+ Visualisation *visualisation() const { return m_visualisation; }
+
+ Valgrind::Callgrind::CallModel *callersModel() const { return m_callersModel; }
+ CostView *callersView() const { return m_callersView; }
+ Valgrind::Callgrind::CallModel *calleesModel() const { return m_calleesModel; }
+ CostView *calleesView() const { return m_calleesView; }
+
+signals:
+ void dumpRequested();
+ void resetRequested();
+ void pauseToggled(bool checked);
+
+ void functionSelected(const Valgrind::Callgrind::Function *);
+
+ void costFormatChanged(Callgrind::Internal::CostDelegate::CostFormat format);
+ void cycleDetectionEnabled(bool enabled);
+
+public slots:
+ void slotClear();
+ void slotRequestDump();
+
+ void selectFunction(const Valgrind::Callgrind::Function *);
+ void setCostFormat(Callgrind::Internal::CostDelegate::CostFormat format);
+ void enableCycleDetection(bool enabled);
+ void setCostEvent(int index);
+
+private slots:
+ void updateFilterString();
+ void updateCostFormat();
+
+ void handleFilterProjectCosts();
+
+ void slotGoToOverview();
+ void stackBrowserChanged();
+
+ void dataFunctionSelected(const QModelIndex &index);
+ void calleeFunctionSelected(const QModelIndex &index);
+ void callerFunctionSelected(const QModelIndex &index);
+ void visualisationFunctionSelected(const Valgrind::Callgrind::Function *function);
+
+private:
+ void updateEventCombo();
+
+ Valgrind::Callgrind::DataModel *m_dataModel;
+ Valgrind::Callgrind::DataProxyModel *m_dataProxy;
+ Valgrind::Callgrind::StackBrowser *m_stackBrowser;
+
+ Valgrind::Callgrind::CallModel *m_callersModel;
+ Valgrind::Callgrind::CallModel *m_calleesModel;
+
+ CostView *m_flatView;
+ CostView *m_callersView;
+ CostView *m_calleesView;
+ Visualisation *m_visualisation;
+
+ // navigation
+ QAction *m_goToOverview;
+ QAction *m_goBack;
+ QLineEdit *m_searchFilter;
+
+ // cost formatting
+ QAction *m_filterProjectCosts;
+ QAction *m_costAbsolute;
+ QAction *m_costRelative;
+ QAction *m_costRelativeToParent;
+ QAction *m_cycleDetection;
+ QComboBox *m_eventCombo;
+
+ QTimer *m_updateTimer;
+};
+
+} // namespace Internal
+} // namespace Callgrind
+
+#endif // CALLGRINDWIDGETHANDLER_H
diff --git a/src/plugins/callgrind/workarounds.cpp b/src/plugins/callgrind/workarounds.cpp
new file mode 100644
index 0000000000..c361f3497a
--- /dev/null
+++ b/src/plugins/callgrind/workarounds.cpp
@@ -0,0 +1,51 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "workarounds.h"
+
+#include <QtGui/QPalette>
+
+#include <utils/stylehelper.h>
+
+QPalette panelPalette(const QPalette &oldPalette, bool lightColored)
+{
+ QColor color = Utils::StyleHelper::panelTextColor(lightColored);
+ QPalette pal = oldPalette;
+ pal.setBrush(QPalette::All, QPalette::WindowText, color);
+ pal.setBrush(QPalette::All, QPalette::ButtonText, color);
+ pal.setBrush(QPalette::All, QPalette::Foreground, color);
+ color.setAlpha(100);
+ pal.setBrush(QPalette::Disabled, QPalette::WindowText, color);
+ pal.setBrush(QPalette::Disabled, QPalette::ButtonText, color);
+ pal.setBrush(QPalette::Disabled, QPalette::Foreground, color);
+ return pal;
+}
diff --git a/src/plugins/callgrind/workarounds.h b/src/plugins/callgrind/workarounds.h
new file mode 100644
index 0000000000..7a4be0eb89
--- /dev/null
+++ b/src/plugins/callgrind/workarounds.h
@@ -0,0 +1,45 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 WORKAROUNDS_H
+#define WORKAROUNDS_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+class QPalette;
+QT_END_NAMESPACE
+
+///FIXME: remove this once http://bugreports.qt.nokia.com/browse/QTCREATORBUG-3247 gets fixed
+QPalette panelPalette(const QPalette &oldPalette, bool lightColored = false);
+
+#endif // WORKAROUNDS_H
diff --git a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp
index 67beed6723..360f213676 100644
--- a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp
@@ -35,7 +35,10 @@
#include "cmakehighlighter.h"
#include "cmakeeditorfactory.h"
#include "cmakeprojectconstants.h"
+#include "cmakeproject.h"
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/session.h>
#include <texteditor/fontsettings.h>
#include <texteditor/texteditoractionhandler.h>
#include <texteditor/texteditorconstants.h>
@@ -51,14 +54,11 @@ using namespace CMakeProjectManager::Internal;
//
CMakeEditor::CMakeEditor(CMakeEditorWidget *editor)
- : BaseTextEditor(editor),
- m_context(CMakeProjectManager::Constants::C_CMAKEEDITOR,
- TextEditor::Constants::C_TEXTEDITOR)
-{ }
-
-Core::Context CMakeEditor::context() const
+ : BaseTextEditor(editor)
{
- return m_context;
+ setContext(Core::Context(CMakeProjectManager::Constants::C_CMAKEEDITOR,
+ TextEditor::Constants::C_TEXTEDITOR));
+ connect(this, SIGNAL(changed()), this, SLOT(markAsChanged()));
}
Core::IEditor *CMakeEditor::duplicate(QWidget *parent)
@@ -75,6 +75,30 @@ QString CMakeEditor::id() const
return QLatin1String(CMakeProjectManager::Constants::CMAKE_EDITOR_ID);
}
+void CMakeEditor::markAsChanged()
+{
+ Core::EditorManager::instance()->
+ showEditorInfoBar(QLatin1String("CMakeEditor.RunCMake"),
+ tr("Changes to cmake files are shown in the project tree after building."),
+ tr("Build now"),
+ this, SLOT(build()));
+}
+
+void CMakeEditor::build()
+{
+ QList<ProjectExplorer::Project *> projects =
+ ProjectExplorer::ProjectExplorerPlugin::instance()->session()->projects();
+ foreach (ProjectExplorer::Project *p, projects) {
+ CMakeProject *cmakeProject = qobject_cast<CMakeProject *>(p);
+ if (cmakeProject) {
+ if (cmakeProject->isProjectFile(file()->fileName())) {
+ ProjectExplorer::ProjectExplorerPlugin::instance()->buildProject(cmakeProject);
+ break;
+ }
+ }
+ }
+}
+
//
// CMakeEditor
//
@@ -91,10 +115,6 @@ CMakeEditorWidget::CMakeEditorWidget(QWidget *parent, CMakeEditorFactory *factor
baseTextDocument()->setSyntaxHighlighter(new CMakeHighlighter);
}
-CMakeEditorWidget::~CMakeEditorWidget()
-{
-}
-
TextEditor::BaseTextEditor *CMakeEditorWidget::createEditor()
{
return new CMakeEditor(this);
diff --git a/src/plugins/cmakeprojectmanager/cmakeeditor.h b/src/plugins/cmakeprojectmanager/cmakeeditor.h
index cf4562214c..0c12a0a836 100644
--- a/src/plugins/cmakeprojectmanager/cmakeeditor.h
+++ b/src/plugins/cmakeprojectmanager/cmakeeditor.h
@@ -52,16 +52,19 @@ class CMakeManager;
class CMakeEditor : public TextEditor::BaseTextEditor
{
+ Q_OBJECT
+
public:
CMakeEditor(CMakeEditorWidget *);
- Core::Context context() const;
bool duplicateSupported() const { return true; }
Core::IEditor *duplicate(QWidget *parent);
QString id() const;
bool isTemporary() const { return false; }
-private:
- const Core::Context m_context;
+
+private slots:
+ void markAsChanged();
+ void build();
};
class CMakeEditorWidget : public TextEditor::BaseTextEditorWidget
@@ -70,7 +73,6 @@ class CMakeEditorWidget : public TextEditor::BaseTextEditorWidget
public:
CMakeEditorWidget(QWidget *parent, CMakeEditorFactory *factory, TextEditor::TextEditorActionHandler *ah);
- ~CMakeEditorWidget();
bool save(const QString &fileName = QString());
diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
index 6aec0f17b1..28886c5586 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
@@ -96,9 +96,11 @@ CMakeProject::CMakeProject(CMakeManager *manager, const QString &fileName)
: m_manager(manager),
m_fileName(fileName),
m_rootNode(new CMakeProjectNode(m_fileName)),
- m_insideFileChanged(false),
m_lastEditor(0)
{
+ setProjectContext(Core::Context(CMakeProjectManager::Constants::PROJECTCONTEXT));
+ setProjectLanguage(Core::Context(ProjectExplorer::Constants::LANG_CXX));
+
m_file = new CMakeFile(this, fileName);
connect(this, SIGNAL(addedTarget(ProjectExplorer::Target*)),
@@ -125,15 +127,8 @@ CMakeProject::~CMakeProject()
void CMakeProject::fileChanged(const QString &fileName)
{
Q_UNUSED(fileName)
- if (!activeTarget() ||
- !activeTarget()->activeBuildConfiguration())
- return;
- if (m_insideFileChanged)
- return;
- m_insideFileChanged = true;
- changeActiveBuildConfiguration(activeTarget()->activeBuildConfiguration());
- m_insideFileChanged = false;
+ parseCMakeLists();
}
void CMakeProject::changeActiveBuildConfiguration(ProjectExplorer::BuildConfiguration *bc)
@@ -200,6 +195,8 @@ bool CMakeProject::parseCMakeLists()
!activeTarget()->activeBuildConfiguration())
return false;
+ Core::EditorManager::instance()->hideEditorInfoBar("CMakeEditor.RunCMake");
+
// Find cbp file
CMakeBuildConfiguration *activeBC = activeTarget()->activeBuildConfiguration();
QString cbpFile = CMakeManager::findCbpFile(activeBC->buildDirectory());
@@ -211,12 +208,17 @@ bool CMakeProject::parseCMakeLists()
//qDebug()<<"Parsing file "<<cbpFile;
if (!cbpparser.parseCbpFile(cbpFile)) {
// TODO report error
- qDebug()<<"Parsing failed";
- // activeBC->updateToolChain(QString::null);
emit buildTargetsChanged();
return false;
}
+ foreach (const QString &file, m_watcher->files())
+ if (file != cbpFile)
+ m_watcher->removePath(file);
+
+ // how can we ensure that it is completly written?
+ m_watcher->addPath(cbpFile);
+
// ToolChain
// activeBC->updateToolChain(cbpparser.compilerName());
m_projectName = cbpparser.projectName();
@@ -237,12 +239,6 @@ bool CMakeProject::parseCMakeLists()
projectFiles.insert(cmakeListTxt);
}
- QSet<QString> added = projectFiles;
- added.subtract(m_watchedFiles);
- foreach(const QString &add, added)
- m_watcher->addFile(add);
- foreach(const QString &remove, m_watchedFiles.subtract(projectFiles))
- m_watcher->removeFile(remove);
m_watchedFiles = projectFiles;
m_files.clear();
@@ -278,7 +274,6 @@ bool CMakeProject::parseCMakeLists()
}
cmakeCache.close();
- //qDebug()<<"Updating CodeModel";
createUiCodeModelSupport();
if (!activeBC->toolChain())
@@ -316,12 +311,16 @@ bool CMakeProject::parseCMakeLists()
m_codeModelFuture = modelmanager->updateSourceFiles(pinfo.sourceFiles);
}
}
-
emit buildTargetsChanged();
emit fileListChanged();
return true;
}
+bool CMakeProject::isProjectFile(const QString &fileName)
+{
+ return m_watchedFiles.contains(fileName);
+}
+
QList<CMakeBuildTarget> CMakeProject::buildTargets() const
{
return m_buildTargets;
@@ -561,7 +560,7 @@ bool CMakeProject::fromMap(const QVariantMap &map)
}
}
- m_watcher = new ProjectExplorer::FileWatcher(this);
+ m_watcher = new QFileSystemWatcher(this);
connect(m_watcher, SIGNAL(fileChanged(QString)), this, SLOT(fileChanged(QString)));
if (!parseCMakeLists()) // Gets the directory from the active buildconfiguration
diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h
index 54ae009630..563ae9f424 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.h
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.h
@@ -45,9 +45,11 @@
#include <projectexplorer/filewatcher.h>
#include <projectexplorer/buildconfiguration.h>
#include <coreplugin/ifile.h>
+#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <QtCore/QXmlStreamReader>
+#include <QtCore/QFileSystemWatcher>
#include <QtGui/QPushButton>
#include <QtGui/QLineEdit>
@@ -104,6 +106,8 @@ public:
QString uicCommand() const;
+ bool isProjectFile(const QString &fileName);
+
signals:
/// emitted after parsing
void buildTargetsChanged();
@@ -141,8 +145,7 @@ private:
CMakeProjectNode *m_rootNode;
QStringList m_files;
QList<CMakeBuildTarget> m_buildTargets;
- ProjectExplorer::FileWatcher *m_watcher;
- bool m_insideFileChanged;
+ QFileSystemWatcher *m_watcher;
QSet<QString> m_watchedFiles;
QFuture<void> m_codeModelFuture;
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp
index 566c487647..ad46cd07e3 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp
@@ -62,9 +62,6 @@ using namespace CMakeProjectManager::Internal;
CMakeManager::CMakeManager(CMakeSettingsPage *cmakeSettingsPage)
: m_settingsPage(cmakeSettingsPage)
{
- m_projectContext = Core::Context(CMakeProjectManager::Constants::PROJECTCONTEXT);
- m_projectLanguage = Core::Context(ProjectExplorer::Constants::LANG_CXX);
-
ProjectExplorer::ProjectExplorerPlugin *projectExplorer = ProjectExplorer::ProjectExplorerPlugin::instance();
connect(projectExplorer, SIGNAL(aboutToShowContextMenu(ProjectExplorer::Project*, ProjectExplorer::Node*)),
this, SLOT(updateContextMenu(ProjectExplorer::Project*, ProjectExplorer::Node*)));
@@ -78,14 +75,16 @@ CMakeManager::CMakeManager(CMakeSettingsPage *cmakeSettingsPage)
Core::ActionContainer *msubproject =
am->actionContainer(ProjectExplorer::Constants::M_SUBPROJECTCONTEXT);
+ const Core::Context projectContext(CMakeProjectManager::Constants::PROJECTCONTEXT);
+
m_runCMakeAction = new QAction(QIcon(), tr("Run CMake"), this);
- Core::Command *command = am->registerAction(m_runCMakeAction, Constants::RUNCMAKE, m_projectContext);
+ Core::Command *command = am->registerAction(m_runCMakeAction, Constants::RUNCMAKE, projectContext);
command->setAttribute(Core::Command::CA_Hide);
mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_PROJECT);
connect(m_runCMakeAction, SIGNAL(triggered()), this, SLOT(runCMake()));
m_runCMakeActionContextMenu = new QAction(QIcon(), tr("Run CMake"), this);
- command = am->registerAction(m_runCMakeActionContextMenu, Constants::RUNCMAKECONTEXTMENU, m_projectContext);
+ command = am->registerAction(m_runCMakeActionContextMenu, Constants::RUNCMAKECONTEXTMENU, projectContext);
command->setAttribute(Core::Command::CA_Hide);
mproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
@@ -132,16 +131,6 @@ void CMakeManager::runCMake(ProjectExplorer::Project *project)
}
}
-Core::Context CMakeManager::projectContext() const
-{
- return m_projectContext;
-}
-
-Core::Context CMakeManager::projectLanguage() const
-{
- return m_projectLanguage;
-}
-
ProjectExplorer::Project *CMakeManager::openProject(const QString &fileName)
{
// TODO check whether this project is already opened
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h
index 1383a9d255..4253944840 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h
@@ -65,9 +65,6 @@ class CMakeManager : public ProjectExplorer::IProjectManager
public:
CMakeManager(CMakeSettingsPage *cmakeSettingsPage);
- virtual Core::Context projectContext() const;
- virtual Core::Context projectLanguage() const;
-
virtual ProjectExplorer::Project *openProject(const QString &fileName);
virtual QString mimeType() const;
@@ -94,8 +91,6 @@ private:
void runCMake(ProjectExplorer::Project *project);
static QString qtVersionForQMake(const QString &qmakePath);
static QPair<QString, QString> findQtDir(const Utils::Environment &env);
- Core::Context m_projectContext;
- Core::Context m_projectLanguage;
CMakeSettingsPage *m_settingsPage;
QAction *m_runCMakeAction;
QAction *m_runCMakeActionContextMenu;
diff --git a/src/plugins/cmakeprojectmanager/cmaketarget.cpp b/src/plugins/cmakeprojectmanager/cmaketarget.cpp
index 026f545aa9..ec0bb308b2 100644
--- a/src/plugins/cmakeprojectmanager/cmaketarget.cpp
+++ b/src/plugins/cmakeprojectmanager/cmaketarget.cpp
@@ -64,8 +64,7 @@ QString displayNameForId(const QString &id) {
CMakeTarget::CMakeTarget(CMakeProject *parent) :
ProjectExplorer::Target(parent, QLatin1String(DEFAULT_CMAKE_TARGET_ID)),
- m_buildConfigurationFactory(new CMakeBuildConfigurationFactory(this)),
- m_deployConfigurationFactory(new ProjectExplorer::DeployConfigurationFactory(this))
+ m_buildConfigurationFactory(new CMakeBuildConfigurationFactory(this))
{
setDefaultDisplayName(displayNameForId(id()));
setIcon(qApp->style()->standardIcon(QStyle::SP_ComputerIcon));
@@ -101,11 +100,6 @@ CMakeBuildConfigurationFactory *CMakeTarget::buildConfigurationFactory() const
return m_buildConfigurationFactory;
}
-ProjectExplorer::DeployConfigurationFactory *CMakeTarget::deployConfigurationFactory() const
-{
- return m_deployConfigurationFactory;
-}
-
QString CMakeTarget::defaultBuildDirectory() const
{
return cmakeProject()->defaultBuildDirectory();
@@ -227,7 +221,7 @@ CMakeTarget *CMakeTargetFactory::create(ProjectExplorer::Project *parent, const
t->addBuildConfiguration(bc);
- t->addDeployConfiguration(t->deployConfigurationFactory()->create(t, ProjectExplorer::Constants::DEFAULT_DEPLOYCONFIGURATION_ID));
+ t->addDeployConfiguration(t->createDeployConfiguration(ProjectExplorer::Constants::DEFAULT_DEPLOYCONFIGURATION_ID));
t->updateRunConfigurations();
diff --git a/src/plugins/cmakeprojectmanager/cmaketarget.h b/src/plugins/cmakeprojectmanager/cmaketarget.h
index 5d97419b44..794878b385 100644
--- a/src/plugins/cmakeprojectmanager/cmaketarget.h
+++ b/src/plugins/cmakeprojectmanager/cmaketarget.h
@@ -63,7 +63,6 @@ public:
CMakeBuildConfiguration *activeBuildConfiguration() const;
CMakeBuildConfigurationFactory *buildConfigurationFactory() const;
- ProjectExplorer::DeployConfigurationFactory *deployConfigurationFactory() const;
QString defaultBuildDirectory() const;
@@ -75,7 +74,6 @@ private slots:
private:
CMakeBuildConfigurationFactory *m_buildConfigurationFactory;
- ProjectExplorer::DeployConfigurationFactory *m_deployConfigurationFactory;
};
class CMakeTargetFactory : public ProjectExplorer::ITargetFactory
diff --git a/src/plugins/coreplugin/actionmanager/actionmanager.cpp b/src/plugins/coreplugin/actionmanager/actionmanager.cpp
index ee8f7b8ffe..5f802dc268 100644
--- a/src/plugins/coreplugin/actionmanager/actionmanager.cpp
+++ b/src/plugins/coreplugin/actionmanager/actionmanager.cpp
@@ -145,7 +145,7 @@ namespace {
*/
/*!
- \fn ActionContainer *ActionManager::createMenu(const QString &id)
+ \fn ActionContainer *ActionManager::createMenu(const Id &id)
\brief Creates a new menu with the given string \a id.
Returns a new ActionContainer that you can use to get the QMenu instance
@@ -156,7 +156,7 @@ namespace {
*/
/*!
- \fn ActionContainer *ActionManager::createMenuBar(const QString &id)
+ \fn ActionContainer *ActionManager::createMenuBar(const Id &id)
\brief Creates a new menu bar with the given string \a id.
Returns a new ActionContainer that you can use to get the QMenuBar instance
@@ -165,7 +165,7 @@ namespace {
*/
/*!
- \fn Command *ActionManager::registerAction(QAction *action, const QString &id, const Context &context, bool scriptable)
+ \fn Command *ActionManager::registerAction(QAction *action, const Id &id, const Context &context, bool scriptable)
\brief Makes an \a action known to the system under the specified string \a id.
Returns a command object that represents the action in the application and is
@@ -191,7 +191,7 @@ namespace {
*/
/*!
- \fn Command *ActionManager::command(const QString &id) const
+ \fn Command *ActionManager::command(const Id &id) const
\brief Returns the Command object that is known to the system
under the given string \a id.
@@ -199,7 +199,7 @@ namespace {
*/
/*!
- \fn ActionContainer *ActionManager::actionContainer(const QString &id) const
+ \fn ActionContainer *ActionManager::actionContainer(const Id &id) const
\brief Returns the IActionContainter object that is know to the system
under the given string \a id.
@@ -208,7 +208,7 @@ namespace {
*/
/*!
- \fn Command *ActionManager::unregisterAction(QAction *action, const QString &id)
+ \fn Command *ActionManager::unregisterAction(QAction *action, const Id &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
diff --git a/src/plugins/coreplugin/actionmanager/commandsfile.cpp b/src/plugins/coreplugin/actionmanager/commandsfile.cpp
index ff6334b11d..9f15973f78 100644
--- a/src/plugins/coreplugin/actionmanager/commandsfile.cpp
+++ b/src/plugins/coreplugin/actionmanager/commandsfile.cpp
@@ -35,12 +35,39 @@
#include "command_p.h"
#include <coreplugin/uniqueidmanager.h>
+#include <coreplugin/coreconstants.h>
+
+#include <utils/qtcassert.h>
#include <QtCore/QFile>
-#include <QtXml/QDomDocument>
+#include <QtCore/QXmlStreamAttributes>
+#include <QtCore/QXmlStreamWriter>
+#include <QtCore/QXmlStreamReader>
+#include <QtCore/QDebug>
+#include <QtCore/QDateTime>
+
+namespace Core {
+namespace Internal {
-using namespace Core;
-using namespace Core::Internal;
+struct Context // XML parsing context with strings.
+{
+ Context();
+
+ const QString mappingElement;
+ const QString shortCutElement;
+ const QString idAttribute;
+ const QString keyElement;
+ const QString valueAttribute;
+};
+
+Context::Context() :
+ mappingElement(QLatin1String("mapping")),
+ shortCutElement(QLatin1String("shortcut")),
+ idAttribute(QLatin1String("id")),
+ keyElement(QLatin1String("key")),
+ valueAttribute(QLatin1String("value"))
+{
+}
/*!
\class CommandsFile
@@ -65,29 +92,36 @@ QMap<QString, QKeySequence> CommandsFile::importCommands() const
QMap<QString, QKeySequence> result;
QFile file(m_filename);
- if (!file.open(QIODevice::ReadOnly))
- return result;
-
- QDomDocument doc("KeyboardMappingScheme");
- if (!doc.setContent(&file))
- return result;
-
- QDomElement root = doc.documentElement();
- if (root.nodeName() != QLatin1String("mapping"))
+ if (!file.open(QIODevice::ReadOnly|QIODevice::Text))
return result;
- QDomElement ks = root.firstChildElement();
- for (; !ks.isNull(); ks = ks.nextSiblingElement()) {
- if (ks.nodeName() == QLatin1String("shortcut")) {
- QString id = ks.attribute(QLatin1String("id"));
- QKeySequence shortcutkey;
- QDomElement keyelem = ks.firstChildElement("key");
- if (!keyelem.isNull())
- shortcutkey = QKeySequence(keyelem.attribute("value"));
- result.insert(id, shortcutkey);
- }
- }
-
+ Context ctx;
+ QXmlStreamReader r(&file);
+
+ QString currentId;
+
+ while (!r.atEnd()) {
+ switch (r.readNext()) {
+ case QXmlStreamReader::StartElement: {
+ const QStringRef name = r.name();
+ if (name == ctx.shortCutElement) {
+ currentId = r.attributes().value(ctx.idAttribute).toString();
+ } else if (name == ctx.keyElement) {
+ QTC_ASSERT(!currentId.isEmpty(), return result; )
+ const QXmlStreamAttributes attributes = r.attributes();
+ if (attributes.hasAttribute(ctx.valueAttribute)) {
+ const QString keyString = attributes.value(ctx.valueAttribute).toString();
+ result.insert(currentId, QKeySequence(keyString));
+ } else {
+ result.insert(currentId, QKeySequence());
+ }
+ currentId.clear();
+ } // if key element
+ } // case QXmlStreamReader::StartElement
+ default:
+ break;
+ } // switch
+ } // while !atEnd
file.close();
return result;
}
@@ -95,29 +129,43 @@ QMap<QString, QKeySequence> CommandsFile::importCommands() const
/*!
...
*/
+
bool CommandsFile::exportCommands(const QList<ShortcutItem *> &items)
{
- UniqueIDManager *idmanager = UniqueIDManager::instance();
+ const UniqueIDManager *idmanager = UniqueIDManager::instance();
QFile file(m_filename);
- if (!file.open(QIODevice::WriteOnly))
+ if (!file.open(QIODevice::WriteOnly|QIODevice::Text))
return false;
- QDomDocument doc("KeyboardMappingScheme");
- QDomElement root = doc.createElement("mapping");
- doc.appendChild(root);
-
+ const Context ctx;
+ QXmlStreamWriter w(&file);
+ w.setAutoFormatting(true);
+ w.setAutoFormattingIndent(1); // Historical, used to be QDom.
+ w.writeStartDocument();
+ w.writeDTD(QLatin1String("<!DOCTYPE KeyboardMappingScheme>"));
+ w.writeComment(QString::fromAscii(" Written by Qt Creator %1, %2. ").
+ arg(QLatin1String(Core::Constants::IDE_VERSION_LONG),
+ QDateTime::currentDateTime().toString(Qt::ISODate)));
+ w.writeStartElement(ctx.mappingElement);
foreach (const ShortcutItem *item, items) {
- QDomElement ctag = doc.createElement("shortcut");
- ctag.setAttribute(QLatin1String("id"), idmanager->stringForUniqueIdentifier(item->m_cmd->id()));
- root.appendChild(ctag);
-
- QDomElement ktag = doc.createElement("key");
- ktag.setAttribute(QLatin1String("value"), item->m_key.toString());
- ctag.appendChild(ktag);
+ const QString id = idmanager->stringForUniqueIdentifier(item->m_cmd->id());
+ if (item->m_key.isEmpty()) {
+ w.writeEmptyElement(ctx.shortCutElement);
+ w.writeAttribute(ctx.idAttribute, id);
+ } else {
+ w.writeStartElement(ctx.shortCutElement);
+ w.writeAttribute(ctx.idAttribute, id);
+ w.writeEmptyElement(ctx.keyElement);
+ w.writeAttribute(ctx.valueAttribute, item->m_key.toString());
+ w.writeEndElement(); // Shortcut
+ }
}
-
- file.write(doc.toByteArray());
+ w.writeEndElement();
+ w.writeEndDocument();
file.close();
return true;
}
+
+} // namespace Internal
+} // namespace Core
diff --git a/src/plugins/coreplugin/basefilewizard.cpp b/src/plugins/coreplugin/basefilewizard.cpp
index e1bda7b3d8..ebd8f3db7f 100644
--- a/src/plugins/coreplugin/basefilewizard.cpp
+++ b/src/plugins/coreplugin/basefilewizard.cpp
@@ -60,6 +60,17 @@
enum { debugWizard = 0 };
+/*!
+ \class Core::GeneratedFile
+ \brief Represents a file generated by a wizard.
+
+ The Wizard class will check for each file whether it already exists and will
+ report any errors that may occur during creation of the files.
+
+ \sa Core::BaseFileWizardParameters, Core::BaseFileWizard, Core::StandardFileWizard
+ \sa Core::Internal::WizardEventLoop
+ */
+
namespace Core {
class GeneratedFilePrivate : public QSharedData
@@ -229,6 +240,15 @@ void BaseFileWizardParameterData::clear()
displayCategory.clear();
}
+/*!
+ \class Core::BaseFileWizardParameters
+ \brief Parameter class for passing parameters to instances of class Wizard
+ containing name, icon and such.
+
+ \sa Core::GeneratedFile, Core::BaseFileWizard, Core::StandardFileWizard
+ \sa Core::Internal::WizardEventLoop
+*/
+
BaseFileWizardParameters::BaseFileWizardParameters(IWizard::WizardKind kind) :
m_d(new BaseFileWizardParameterData(kind))
{
@@ -335,15 +355,24 @@ void BaseFileWizardParameters::setDisplayCategory(const QString &v)
m_d->displayCategory = v;
}
-/* WizardEventLoop: Special event loop that runs a QWizard and terminates if the page changes.
- * Synopsis:
- * \code
+/*!
+ \class Core::Internal::WizardEventLoop
+ \brief Special event loop that runs a QWizard and terminates if the page changes.
+
+ Use by Core::BaseFileWizard to intercept the change from the standard wizard pages
+ to the extension pages (as the latter require the list of Core::GeneratedFile generated).
+
+ Synopsis:
+ \code
Wizard wizard(parent);
WizardEventLoop::WizardResult wr;
do {
wr = WizardEventLoop::execWizardPage(wizard);
} while (wr == WizardEventLoop::PageChanged);
- * \endcode */
+ \endcode
+
+ \sa Core::GeneratedFile, Core::BaseFileWizardParameters, Core::BaseFileWizard, Core::StandardFileWizard
+*/
class WizardEventLoop : public QEventLoop
{
@@ -421,7 +450,24 @@ void WizardEventLoop::rejected()
quit();
}
-// ---------------- BaseFileWizardPrivate
+/*!
+ \class Core::BaseFileWizard
+ \brief A generic wizard for creating files.
+
+ The abstract methods:
+ \list
+ \o createWizardDialog(): Called to create the QWizard dialog to be shown
+ \o generateFiles(): Generate file content
+ \endlist
+
+ must be implemented.
+ The behaviour can be further customized by overwriting the virtual method \c postGenerateFiles(),
+ which is called after generating the files.
+
+ \sa Core::GeneratedFile, Core::BaseFileWizardParameters, Core::StandardFileWizard
+ \sa Core::Internal::WizardEventLoop
+*/
+
struct BaseFileWizardPrivate
{
explicit BaseFileWizardPrivate(const Core::BaseFileWizardParameters &parameters)
@@ -586,7 +632,27 @@ void BaseFileWizard::runWizard(const QString &path, QWidget *parent)
QMessageBox::critical(0, tr("File Generation Failure"), errorMessage);
}
-// Write
+/*!
+ \fn virtual QWizard *Core::BaseFileWizard::createWizardDialog(QWidget *parent,
+ const QString &defaultPath,
+ const WizardPageList &extensionPages) const = 0
+ \brief Implement to create the wizard dialog on the parent, adding the extension pages.
+*/
+
+/*!
+ \fn virtual Core::GeneratedFiles Core::BaseFileWizard::generateFiles(const QWizard *w,
+ QString *errorMessage) const = 0
+ \brief Overwrite to query the parameters from the dialog and generate the files.
+
+ Note: This does not generate physical files, but merely the list of Core::GeneratedFile.
+*/
+
+/*!
+ \brief Physically write files.
+
+ Re-implement (calling the base implementation) to create files with CustomGeneratorAttribute set.
+*/
+
bool BaseFileWizard::writeFiles(const GeneratedFiles &files, QString *errorMessage)
{
foreach (const GeneratedFile &generatedFile, files)
@@ -596,6 +662,9 @@ bool BaseFileWizard::writeFiles(const GeneratedFiles &files, QString *errorMessa
return true;
}
+/*!
+ \brief Sets some standard options on a QWizard
+*/
void BaseFileWizard::setupWizard(QWizard *w)
{
@@ -604,6 +673,11 @@ void BaseFileWizard::setupWizard(QWizard *w)
w->setOption(QWizard::NoBackButtonOnStartPage, true);
}
+/*!
+ \brief Read "shortTitle" dynamic property of the pageId and apply it as the title
+ of corresponding progress item
+*/
+
void BaseFileWizard::applyExtensionPageShortTitle(Utils::Wizard *wizard, int pageId)
{
if (pageId < 0)
@@ -619,11 +693,21 @@ void BaseFileWizard::applyExtensionPageShortTitle(Utils::Wizard *wizard, int pag
item->setTitle(shortTitle);
}
+/*!
+ \brief Overwrite to perform steps to be done after files are actually created.
+
+ The default implementation opens editors with the newly generated files.
+*/
+
bool BaseFileWizard::postGenerateFiles(const QWizard *, const GeneratedFiles &l, QString *errorMessage)
{
return BaseFileWizard::postGenerateOpenEditors(l, errorMessage);
}
+/*!
+ \brief Utility to open the editors for the files whose attribute is set accordingly.
+*/
+
bool BaseFileWizard::postGenerateOpenEditors(const GeneratedFiles &l, QString *errorMessage)
{
Core::EditorManager *em = Core::EditorManager::instance();
@@ -639,6 +723,11 @@ bool BaseFileWizard::postGenerateOpenEditors(const GeneratedFiles &l, QString *e
return true;
}
+/*!
+ \brief Utility that performs an overwrite check on a set of files. It checks if
+ the file exists, can be overwritten at all and prompts the user with a summary.
+*/
+
BaseFileWizard::OverwriteResult BaseFileWizard::promptOverwrite(const QStringList &files,
QString *errorMessage) const
{
@@ -706,6 +795,10 @@ BaseFileWizard::OverwriteResult BaseFileWizard::promptOverwrite(const QStringLis
return yes ? OverwriteOk : OverwriteCanceled;
}
+/*!
+ \brief Build a file name, adding the extension unless baseName already has one.
+*/
+
QString BaseFileWizard::buildFileName(const QString &path,
const QString &baseName,
const QString &extension)
@@ -726,6 +819,10 @@ QString BaseFileWizard::buildFileName(const QString &path,
return rc;
}
+/*!
+ \brief Utility that returns the preferred suffix for a mime type
+*/
+
QString BaseFileWizard::preferredSuffix(const QString &mimeType)
{
const QString rc = Core::ICore::instance()->mimeDatabase()->preferredSuffixByType(mimeType);
@@ -735,7 +832,23 @@ QString BaseFileWizard::preferredSuffix(const QString &mimeType)
return rc;
}
-// ------------- StandardFileWizard
+/*!
+ \class Core::StandardFileWizard
+ \brief Convenience class for creating one file.
+
+ It uses Utils::FileWizardDialog and introduces a new virtual to generate the
+ files from path and name.
+
+ \sa Core::GeneratedFile, Core::BaseFileWizardParameters, Core::BaseFileWizard
+ \sa Core::Internal::WizardEventLoop
+*/
+
+/*!
+ \fn Core::GeneratedFiles Core::StandardFileWizard::generateFilesFromPath(const QString &path,
+ const QString &name,
+ QString *errorMessage) const = 0
+ \brief Newly introduced virtual that creates the files under the path.
+*/
StandardFileWizard::StandardFileWizard(const BaseFileWizardParameters &parameters,
QObject *parent) :
@@ -743,6 +856,10 @@ StandardFileWizard::StandardFileWizard(const BaseFileWizardParameters &parameter
{
}
+/*!
+ \brief Implemented to create a Utils::FileWizardDialog.
+*/
+
QWizard *StandardFileWizard::createWizardDialog(QWidget *parent,
const QString &defaultPath,
const WizardPageList &extensionPages) const
@@ -756,6 +873,10 @@ QWizard *StandardFileWizard::createWizardDialog(QWidget *parent,
return standardWizardDialog;
}
+/*!
+ \brief Implemented to retrieve path and name and call generateFilesFromPath()
+*/
+
GeneratedFiles StandardFileWizard::generateFiles(const QWizard *w,
QString *errorMessage) const
{
diff --git a/src/plugins/coreplugin/basefilewizard.h b/src/plugins/coreplugin/basefilewizard.h
index 72d04354be..38c0786c1a 100644
--- a/src/plugins/coreplugin/basefilewizard.h
+++ b/src/plugins/coreplugin/basefilewizard.h
@@ -60,11 +60,6 @@ class BaseFileWizardParameterData;
struct BaseFileWizardPrivate;
class GeneratedFilePrivate;
-/*!
- * Represents a file generated by a wizard. The Wizard class will check for
- * each file whether it already exists and will report any errors that may
- * occur during creation of the files.
- */
class CORE_EXPORT GeneratedFile
{
public:
@@ -114,9 +109,6 @@ private:
typedef QList<GeneratedFile> GeneratedFiles;
-/* Parameter class for passing parameters to instances of class Wizard
- * containing name, icon and such. */
-
class CORE_EXPORT BaseFileWizardParameters
{
public:
@@ -154,18 +146,6 @@ private:
CORE_EXPORT QDebug operator<<(QDebug d, const BaseFileWizardParameters &);
-/* A generic wizard for creating files.
- *
- * The abstract methods:
- *
- * createWizardDialog() : Called to create the QWizard dialog to be shown
- * generateFiles() : Generate file content
- *
- * must be implemented. The behaviour can be further customized by overwriting
- * the virtual method:
- * postGenerateFiles() : Called after generating the files.
- */
-
class CORE_EXPORT BaseFileWizard : public IWizard
{
Q_DISABLE_COPY(BaseFileWizard)
@@ -186,13 +166,8 @@ public:
virtual void runWizard(const QString &path, QWidget *parent);
- // Build a file name, adding the extension unless baseName already has one
static QString buildFileName(const QString &path, const QString &baseName, const QString &extension);
-
- // Sets some standard options on a QWizard
static void setupWizard(QWizard *);
-
- // Read "shortTitle" dynamic property of the pageId and apply it as the title of corresponding progress item
static void applyExtensionPageShortTitle(Utils::Wizard *wizard, int pageId);
protected:
@@ -200,44 +175,27 @@ protected:
explicit BaseFileWizard(const BaseFileWizardParameters &parameters, QObject *parent = 0);
- // Overwrite to create the wizard dialog on the parent, adding
- // the extension pages.
virtual QWizard *createWizardDialog(QWidget *parent,
const QString &defaultPath,
const WizardPageList &extensionPages) const = 0;
-
- // Overwrite to query the parameters from the dialog and generate the files.
virtual GeneratedFiles generateFiles(const QWizard *w,
QString *errorMessage) const = 0;
- /* Physically write files. Re-implement (calling the base implementation)
- * to create files with CustomGeneratorAttribute set. */
virtual bool writeFiles(const GeneratedFiles &files, QString *errorMessage);
- /* Overwrite to perform steps to be done after files are actually created.
- * The default implementation opens editors with the newly generated files. */
virtual bool postGenerateFiles(const QWizard *w, const GeneratedFiles &l, QString *errorMessage);
- // Utility that returns the preferred suffix for a mime type
static QString preferredSuffix(const QString &mimeType);
- // Utility that performs an overwrite check on a set of files. It checks if
- // the file exists, can be overwritten at all and prompts the user.
enum OverwriteResult { OverwriteOk, OverwriteError, OverwriteCanceled };
OverwriteResult promptOverwrite(const QStringList &files,
QString *errorMessage) const;
-
- // Utility to open the editors for the files whose attribute is set accordingly.
static bool postGenerateOpenEditors(const GeneratedFiles &l, QString *errorMessage = 0);
private:
BaseFileWizardPrivate *m_d;
};
-// StandardFileWizard convenience class for creating one file. It uses
-// Utils::FileWizardDialog and introduces a new virtual to generate the
-// files from path and name.
-
class CORE_EXPORT StandardFileWizard : public BaseFileWizard
{
Q_DISABLE_COPY(StandardFileWizard)
@@ -245,18 +203,11 @@ class CORE_EXPORT StandardFileWizard : public BaseFileWizard
protected:
explicit StandardFileWizard(const BaseFileWizardParameters &parameters, QObject *parent = 0);
-
- // Implemented to create a Utils::FileWizardDialog
virtual QWizard *createWizardDialog(QWidget *parent,
const QString &defaultPath,
const WizardPageList &extensionPages) const;
- // Implemented to retrieve path and name and call generateFilesFromPath()
- virtual GeneratedFiles generateFiles(const QWizard *w,
- QString *errorMessage) const;
-
- // Newly introduced virtual that creates a file from a path
- virtual GeneratedFiles generateFilesFromPath(const QString &path,
- const QString &name,
+ virtual GeneratedFiles generateFiles(const QWizard *w, QString *errorMessage) const;
+ virtual GeneratedFiles generateFilesFromPath(const QString &path, const QString &name,
QString *errorMessage) const = 0;
};
diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h
index 8423c3bbde..b3728fd5ee 100644
--- a/src/plugins/coreplugin/coreconstants.h
+++ b/src/plugins/coreplugin/coreconstants.h
@@ -77,15 +77,12 @@ const char * const MODE_DESIGN_TYPE = "Type.Design";
const int P_MODE_WELCOME = 100;
const int P_MODE_EDIT = 90;
const int P_MODE_DESIGN = 89;
-const int P_MODE_OUTPUT = 10;
//menubar
const char * const MENU_BAR = "QtCreator.MenuBar";
//menus
const char * const M_FILE = "QtCreator.Menu.File";
-const char * const M_FILE_OPEN = "QtCreator.Menu.File.Open";
-const char * const M_FILE_NEW = "QtCreator.Menu.File.New";
const char * const M_FILE_RECENTFILES = "QtCreator.Menu.File.RecentFiles";
const char * const M_EDIT = "QtCreator.Menu.Edit";
const char * const M_EDIT_ADVANCED = "QtCreator.Menu.Edit.Advanced";
@@ -134,18 +131,20 @@ const char * const OPTIONS = "QtCreator.Options";
const char * const TOGGLE_SIDEBAR = "QtCreator.ToggleSidebar";
const char * const TOGGLE_FULLSCREEN = "QtCreator.ToggleFullScreen";
+#ifdef Q_WS_MAC
const char * const MINIMIZE_WINDOW = "QtCreator.MinimizeWindow";
const char * const ZOOM_WINDOW = "QtCreator.ZoomWindow";
+#endif
const char * const SPLIT = "QtCreator.Split";
const char * const SPLIT_SIDE_BY_SIDE = "QtCreator.SplitSideBySide";
const char * const REMOVE_CURRENT_SPLIT = "QtCreator.RemoveCurrentSplit";
const char * const REMOVE_ALL_SPLITS = "QtCreator.RemoveAllSplits";
const char * const GOTO_OTHER_SPLIT = "QtCreator.GotoOtherSplit";
-const char * const SAVEASDEFAULT = "QtCreator.SaveAsDefaultLayout";
-const char * const RESTOREDEFAULT = "QtCreator.RestoreDefaultLayout";
const char * const CLOSE = "QtCreator.Close";
+#ifdef Q_WS_WIN
const char * const CLOSE_ALTERNATIVE = "QtCreator.Close_Alternative"; // temporary, see QTCREATORBUG-72
+#endif
const char * const CLOSEALL = "QtCreator.CloseAll";
const char * const CLOSEOTHERS = "QtCreator.CloseOthers";
const char * const GOTONEXT = "QtCreator.GotoNext";
@@ -154,14 +153,9 @@ const char * const GOTONEXTINHISTORY = "QtCreator.GotoNextInHistory";
const char * const GOTOPREVINHISTORY = "QtCreator.GotoPreviousInHistory";
const char * const GO_BACK = "QtCreator.GoBack";
const char * const GO_FORWARD = "QtCreator.GoForward";
-const char * const GOTOPREVIOUSGROUP = "QtCreator.GotoPreviousTabGroup";
-const char * const GOTONEXTGROUP = "QtCreator.GotoNextTabGroup";
-const char * const WINDOWSLIST = "QtCreator.WindowsList";
const char * const ABOUT_QTCREATOR = "QtCreator.AboutQtCreator";
const char * const ABOUT_PLUGINS = "QtCreator.AboutPlugins";
-const char * const ABOUT_QT = "QtCreator.AboutQt";
const char * const S_RETURNTOEDITOR = "QtCreator.ReturnToEditor";
-const char * const OPEN_IN_EXTERNAL_EDITOR = "QtCreator.OpenInExternalEditor";
// default groups
const char * const G_DEFAULT_ONE = "QtCreator.Group.Default.One";
@@ -231,9 +225,6 @@ const char * const ICON_PREV = ":/core/images/prev.png";
const char * const ICON_DIR = ":/core/images/dir.png";
const char * const ICON_CLEAN_PANE = ":/core/images/clean_pane_small.png";
const char * const ICON_CLEAR = ":/core/images/clear.png";
-const char * const ICON_FIND = ":/core/images/find.png";
-const char * const ICON_FINDNEXT = ":/core/images/findnext.png";
-const char * const ICON_REPLACE = ":/core/images/replace.png";
const char * const ICON_RESET = ":/core/images/reset.png";
const char * const ICON_MAGNIFIER = ":/core/images/magnifier.png";
const char * const ICON_TOGGLE_SIDEBAR = ":/core/images/sidebaricon.png";
diff --git a/src/plugins/coreplugin/coreplugin.pro b/src/plugins/coreplugin/coreplugin.pro
index 63a4a52aba..a3b0f4928c 100644
--- a/src/plugins/coreplugin/coreplugin.pro
+++ b/src/plugins/coreplugin/coreplugin.pro
@@ -1,8 +1,7 @@
TEMPLATE = lib
TARGET = Core
DEFINES += CORE_LIBRARY
-QT += xml \
- network \
+QT += network \
script \
sql
CONFIG += help
diff --git a/src/plugins/coreplugin/designmode.cpp b/src/plugins/coreplugin/designmode.cpp
index c08c5ef4e7..fdc1046f50 100644
--- a/src/plugins/coreplugin/designmode.cpp
+++ b/src/plugins/coreplugin/designmode.cpp
@@ -119,6 +119,14 @@ DesignMode::DesignMode(EditorManager *editorManager) :
{
setObjectName(QLatin1String("DesignMode"));
setEnabled(false);
+ setContext(Context(Constants::C_DESIGN_MODE));
+ setWidget(d->m_stackWidget);
+ setDisplayName(tr("Design"));
+ setIcon(QIcon(QLatin1String(":/fancyactionbar/images/mode_Design.png")));
+ setPriority(Constants::P_MODE_DESIGN);
+ setId(Constants::MODE_DESIGN);
+ setType(Constants::MODE_DESIGN_TYPE);
+
ExtensionSystem::PluginManager::instance()->addObject(d->m_coreListener);
connect(editorManager, SIGNAL(currentEditorChanged(Core::IEditor*)),
@@ -137,42 +145,6 @@ DesignMode::~DesignMode()
delete d;
}
-Context DesignMode::context() const
-{
- static Context contexts(Constants::C_DESIGN_MODE);
- return contexts;
-}
-
-QWidget *DesignMode::widget()
-{
- return d->m_stackWidget;
-}
-
-QString DesignMode::displayName() const
-{
- return tr("Design");
-}
-
-QIcon DesignMode::icon() const
-{
- return QIcon(QLatin1String(":/fancyactionbar/images/mode_Design.png"));
-}
-
-int DesignMode::priority() const
-{
- return Constants::P_MODE_DESIGN;
-}
-
-QString DesignMode::id() const
-{
- return QLatin1String(Constants::MODE_DESIGN);
-}
-
-QString DesignMode::type() const
-{
- return QLatin1String(Constants::MODE_DESIGN_TYPE);
-}
-
QStringList DesignMode::registeredMimeTypes() const
{
QStringList rc;
diff --git a/src/plugins/coreplugin/designmode.h b/src/plugins/coreplugin/designmode.h
index 4bb313f678..dab3877350 100644
--- a/src/plugins/coreplugin/designmode.h
+++ b/src/plugins/coreplugin/designmode.h
@@ -67,17 +67,6 @@ public:
QStringList registeredMimeTypes() const;
- // IContext
- Context context() const;
- QWidget *widget();
-
- // IMode
- QString displayName() const;
- QIcon icon() const;
- int priority() const;
- QString id() const;
- QString type() const;
-
signals:
void actionsUpdated(Core::IEditor *editor);
diff --git a/src/plugins/coreplugin/dialogs/iwizard.cpp b/src/plugins/coreplugin/dialogs/iwizard.cpp
index 1e7ea29a02..cbbae0da9f 100644
--- a/src/plugins/coreplugin/dialogs/iwizard.cpp
+++ b/src/plugins/coreplugin/dialogs/iwizard.cpp
@@ -105,7 +105,7 @@
*/
/*!
- \fn QString IWizard::name() const
+ \fn QString IWizard::displayName() const
Returns the translated name of the wizard, how it should appear in the
dialog.
*/
diff --git a/src/plugins/coreplugin/editmode.cpp b/src/plugins/coreplugin/editmode.cpp
index 015972103a..d9e49d1e0a 100644
--- a/src/plugins/coreplugin/editmode.cpp
+++ b/src/plugins/coreplugin/editmode.cpp
@@ -57,6 +57,12 @@ EditMode::EditMode(EditorManager *editorManager) :
m_rightSplitWidgetLayout(new QVBoxLayout)
{
setObjectName(QLatin1String("EditMode"));
+ setDisplayName(tr("Edit"));
+ setIcon(QIcon(QLatin1String(":/fancyactionbar/images/mode_Edit.png")));
+ setPriority(Constants::P_MODE_EDIT);
+ setId(QLatin1String(Constants::MODE_EDIT));
+ setType(QLatin1String(Constants::MODE_EDIT_TYPE));
+
m_rightSplitWidgetLayout->setSpacing(0);
m_rightSplitWidgetLayout->setMargin(0);
QWidget *rightSplitWidget = new QWidget;
@@ -87,6 +93,11 @@ EditMode::EditMode(EditorManager *editorManager) :
connect(modeManager, SIGNAL(currentModeChanged(Core::IMode*)),
this, SLOT(grabEditorManager(Core::IMode*)));
m_splitter->setFocusProxy(m_editorManager);
+
+ setWidget(m_splitter);
+ setContext(Context(Constants::C_EDIT_MODE,
+ Constants::C_EDITORMANAGER,
+ Constants::C_NAVIGATION_PANE));
}
EditMode::~EditMode()
@@ -96,44 +107,6 @@ EditMode::~EditMode()
delete m_splitter;
}
-QString EditMode::displayName() const
-{
- return tr("Edit");
-}
-
-QIcon EditMode::icon() const
-{
- return QIcon(QLatin1String(":/fancyactionbar/images/mode_Edit.png"));
-}
-
-int EditMode::priority() const
-{
- return Constants::P_MODE_EDIT;
-}
-
-QWidget* EditMode::widget()
-{
- return m_splitter;
-}
-
-QString EditMode::id() const
-{
- return QLatin1String(Constants::MODE_EDIT);
-}
-
-QString EditMode::type() const
-{
- return QLatin1String(Constants::MODE_EDIT_TYPE);
-}
-
-Context EditMode::context() const
-{
- static Context contexts(Constants::C_EDIT_MODE,
- Constants::C_EDITORMANAGER,
- Constants::C_NAVIGATION_PANE);
- return contexts;
-}
-
void EditMode::grabEditorManager(Core::IMode *mode)
{
if (mode != this)
diff --git a/src/plugins/coreplugin/editmode.h b/src/plugins/coreplugin/editmode.h
index 37f4dffb61..ad45d2ae9c 100644
--- a/src/plugins/coreplugin/editmode.h
+++ b/src/plugins/coreplugin/editmode.h
@@ -55,15 +55,6 @@ public:
EditMode(EditorManager *editorManager);
~EditMode();
- // IMode
- QString displayName() const;
- QIcon icon() const;
- int priority() const;
- QWidget* widget();
- QString id() const;
- QString type() const;
- Context context() const;
-
private slots:
void grabEditorManager(Core::IMode *mode);
diff --git a/src/plugins/coreplugin/editormanager/iexternaleditor.cpp b/src/plugins/coreplugin/editormanager/iexternaleditor.cpp
index b3755b5e18..536a40fa38 100644
--- a/src/plugins/coreplugin/editormanager/iexternaleditor.cpp
+++ b/src/plugins/coreplugin/editormanager/iexternaleditor.cpp
@@ -56,11 +56,6 @@
*/
/*!
- \fn QString IExternalEditor::kind() const
- Returns the editor kind (identifying string).
-*/
-
-/*!
\fn bool IExternalEditor::startEditor(const QString &fileName, QString *errorMessage) = 0;
diff --git a/src/plugins/coreplugin/externaltool.cpp b/src/plugins/coreplugin/externaltool.cpp
index 888d7f8a5e..9acbb591e3 100644
--- a/src/plugins/coreplugin/externaltool.cpp
+++ b/src/plugins/coreplugin/externaltool.cpp
@@ -657,6 +657,7 @@ void ExternalToolRunner::error(QProcess::ProcessError error)
FileManager::instance()->unexpectFileChange(m_expectedFileName);
}
// TODO inform about errors
+ Q_UNUSED(error);
deleteLater();
}
diff --git a/src/plugins/coreplugin/fancyactionbar.h b/src/plugins/coreplugin/fancyactionbar.h
index fbd2dc542b..9720239e77 100644
--- a/src/plugins/coreplugin/fancyactionbar.h
+++ b/src/plugins/coreplugin/fancyactionbar.h
@@ -36,12 +36,10 @@
#include <QtGui/QToolButton>
QT_BEGIN_NAMESPACE
-class QMenu;
class QVBoxLayout;
QT_END_NAMESPACE
namespace Core {
- class IMode;
namespace Internal {
class FancyToolButton : public QToolButton
diff --git a/src/plugins/coreplugin/filemanager.cpp b/src/plugins/coreplugin/filemanager.cpp
index 3831d1a079..2b579acd5a 100644
--- a/src/plugins/coreplugin/filemanager.cpp
+++ b/src/plugins/coreplugin/filemanager.cpp
@@ -305,7 +305,7 @@ void FileManager::dump()
}
/*!
- \fn void FileManager::renamedFile(const QString &from, QString &to)
+ \fn void FileManager::renamedFile(const QString &from, const 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
@@ -702,7 +702,7 @@ QString FileManager::getSaveFileNameWithExtension(const QString &title, const QS
}
/*!
- \fn QString FileManager::getSaveAsFileName(IFile *file)
+ \fn QString FileManager::getSaveAsFileName(IFile *file, const QString &filter, QString *selectedFilter)
Asks the user for a new file name (Save File As) for /arg file.
*/
@@ -738,7 +738,9 @@ QString FileManager::getSaveAsFileName(IFile *file, const QString &filter, QStri
}
/*!
- \fn QString FileManager::getOpenFileNames(const QString &filters, const QString &pathIn, QString *selectedFilter) const
+ \fn QStringList FileManager::getOpenFileNames(const QString &filters,
+ const QString pathIn,
+ QString *selectedFilter)
Asks the user for a set of file names to be opened. The \a filters
and \a selectedFilter parameters is interpreted like in
@@ -1037,7 +1039,7 @@ void FileManager::syncWithEditor(Core::IContext *context)
}
/*!
- \fn void FileManager::addToRecentFiles(const QString &fileName, , const QString &editorId)
+ \fn void FileManager::addToRecentFiles(const QString &fileName, const QString &editorId)
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.
diff --git a/src/plugins/coreplugin/icontext.h b/src/plugins/coreplugin/icontext.h
index 4fc4c5c940..66e2c94a28 100644
--- a/src/plugins/coreplugin/icontext.h
+++ b/src/plugins/coreplugin/icontext.h
@@ -37,10 +37,8 @@
#include <QtCore/QList>
#include <QtCore/QObject>
-
-QT_BEGIN_NAMESPACE
-class QWidget;
-QT_END_NAMESPACE
+#include <QtCore/QPointer>
+#include <QtGui/QWidget>
namespace Core {
@@ -79,31 +77,20 @@ class CORE_EXPORT IContext : public QObject
{
Q_OBJECT
public:
- IContext(QObject *parent = 0) : QObject(parent) {}
- virtual ~IContext() {}
+ IContext(QObject *parent = 0) : QObject(parent), m_widget(0) {}
- virtual Context context() const = 0;
- virtual QWidget *widget() = 0;
- virtual QString contextHelpId() const { return QString(); }
-};
+ virtual Context context() const { return m_context; }
+ virtual QWidget *widget() const { return m_widget; }
+ virtual QString contextHelpId() const { return m_contextHelpId; }
-class BaseContext : public Core::IContext
-{
-public:
- BaseContext(QWidget *widget, const Context &context, QObject *parent = 0)
- : Core::IContext(parent),
- m_widget(widget),
- m_context(context)
- {
- }
+ virtual void setContext(const Context &context) { m_context = context; }
+ virtual void setWidget(QWidget *widget) { m_widget = widget; }
+ virtual void setContextHelpId(const QString &id) { m_contextHelpId = id; }
- Context context() const { return m_context; }
-
- QWidget *widget() { return m_widget; }
-
-private:
- QWidget *m_widget;
+protected:
Context m_context;
+ QPointer<QWidget> m_widget;
+ QString m_contextHelpId;
};
} // namespace Core
diff --git a/src/plugins/coreplugin/icore.cpp b/src/plugins/coreplugin/icore.cpp
index 77abfcc25b..99c02e7197 100644
--- a/src/plugins/coreplugin/icore.cpp
+++ b/src/plugins/coreplugin/icore.cpp
@@ -72,7 +72,8 @@
/*!
\fn bool ICore::showOptionsDialog(const QString &group = QString(),
- const QString &page = QString())
+ const QString &page = QString(),
+ QWidget *parent = 0)
\brief Opens the application options/preferences dialog with preselected
\a page in a specified \a group.
@@ -124,14 +125,6 @@
*/
/*!
- \fn ExtensionSystem::PluginManager *ICore::pluginManager() const
- \brief Returns the application's plugin manager.
-
- The plugin manager handles the plugin life cycles and manages
- the common object pool.
-*/
-
-/*!
\fn EditorManager *ICore::editorManager() const
\brief Returns the application's editor manager.
@@ -191,7 +184,7 @@
*/
/*!
- \fn QSettings *ICore::settings(QSettings::UserScope scope) const
+ \fn QSettings *ICore::settings(QSettings::Scope scope = QSettings::UserScope) const
\brief Returns the application's main settings object.
You can use it to retrieve or set application wide settings
@@ -262,7 +255,7 @@
*/
/*!
- \fn void ICore::updateAdditionalContexts(const Core::Context &remove, const Core::Context &add)
+ \fn void ICore::updateAdditionalContexts(const Context &remove, const Context &add)
\brief Change the currently active additional contexts.
Removes the list of additional contexts specified by \a remove and adds the
@@ -302,7 +295,7 @@
*/
/*!
- \fn void ICore::openFiles(const QStringList &fileNames)
+ \fn void ICore::openFiles(const QStringList &fileNames, OpenFilesFlags flags = None)
\brief Open all files from a list of \a fileNames like it would be
done if they were given to Qt Creator on the command line, or
they were opened via \gui{File|Open}.
diff --git a/src/plugins/coreplugin/imode.h b/src/plugins/coreplugin/imode.h
index 5b1b9bdf88..508776e28b 100644
--- a/src/plugins/coreplugin/imode.h
+++ b/src/plugins/coreplugin/imode.h
@@ -35,11 +35,7 @@
#include "icontext.h"
-#include <coreplugin/core_global.h>
-
-QT_BEGIN_NAMESPACE
-class QIcon;
-QT_END_NAMESPACE
+#include <QtGui/QIcon>
namespace Core {
@@ -47,23 +43,33 @@ class CORE_EXPORT IMode : public IContext
{
Q_OBJECT
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
+
public:
IMode(QObject *parent = 0);
- virtual ~IMode() {}
- virtual QString displayName() const = 0;
- virtual QIcon icon() const = 0;
- virtual int priority() const = 0;
- virtual QString id() const = 0;
- virtual QString type() const = 0;
+ QString displayName() const { return m_displayName; }
+ QIcon icon() const { return m_icon; }
+ int priority() const { return m_priority; }
+ QString id() const { return m_id; }
+ QString type() const { return m_type; }
+ bool isEnabled() const;
void setEnabled(bool enabled);
- bool isEnabled() const;
+ void setDisplayName(const QString &displayName) { m_displayName = displayName; }
+ void setIcon(const QIcon &icon) { m_icon = icon; }
+ void setPriority(int priority) { m_priority = priority; }
+ void setId(const QString &id) { m_id = id; }
+ void setType(const QString &type) { m_type = type; }
signals:
void enabledStateChanged(bool enabled);
private:
+ QString m_displayName;
+ QIcon m_icon;
+ int m_priority;
+ QString m_id;
+ QString m_type;
bool m_isEnabled;
};
diff --git a/src/plugins/coreplugin/mimedatabase.cpp b/src/plugins/coreplugin/mimedatabase.cpp
index e317a0b3fd..0210432a6a 100644
--- a/src/plugins/coreplugin/mimedatabase.cpp
+++ b/src/plugins/coreplugin/mimedatabase.cpp
@@ -95,17 +95,14 @@ enum {
TextMatchPriority
};
-/* Parse sth like (<mime-info> being optional):
- *\code
-?xml version="1.0" encoding="UTF-8"?>
-<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
- <!-- Mime types must match the desktop file associations -->
- <mime-type type="application/vnd.nokia.qt.qmakeprofile">
- <comment xml:lang="en">Qt qmake Profile</comment>
- <glob pattern="*.pro" weight="50"/>
- </mime-type>
-</mime-info>
- *\endcode
+/*!
+ \class Core::IMagicMatcher
+
+ \brief Interface for a Mime type magic matcher (examinig file contents).
+
+ \sa Core::MimeType, Core::MimeDatabase, Core::MagicRuleMatcher, Core::MagicRule, Core::MagicStringRule, Core::MagicByteRule, Core::GlobPattern
+ \sa Core::Internal::FileMatchContext, Core::Internal::BinaryMatcher, Core::Internal::HeuristicTextMagicMatcher
+ \sa Core::Internal::BaseMimeTypeParser, Core::Internal::MimeTypeParser
*/
namespace Core {
@@ -114,10 +111,18 @@ typedef QSharedPointer<MagicRuleMatcher> MagicRuleMatcherPtr;
namespace Internal {
-// FileMatchContext: Passed on to the mimetypes from the database
-// when looking for a file match. It exists to enable reading the file
-// contents "on demand" (as opposed to each mime type trying to open
-// and read while checking).
+/*!
+ \class Core::Internal::FileMatchContext
+
+ \brief Context passed on to the mime types when looking for a file match.
+
+ It exists to enable reading the file contents "on demand"
+ (as opposed to each mime type trying to open and read while checking).
+
+ \sa Core::MimeType, Core::MimeDatabase, Core::IMagicMatcher, Core::MagicRuleMatcher, Core::MagicRule, Core::MagicStringRule, Core::MagicByteRule, Core::GlobPattern
+ \sa Core::Internal::BinaryMatcher, Core::Internal::HeuristicTextMagicMatcher
+ \sa Core::Internal::BaseMimeTypeParser, Core::Internal::MimeTypeParser
+*/
class FileMatchContext {
Q_DISABLE_COPY(FileMatchContext)
@@ -169,7 +174,15 @@ QByteArray FileMatchContext::data()
return m_data;
}
-// The binary fallback matcher for "application/octet-stream".
+/*!
+ \class Core::Internal::BinaryMatcher
+ \brief The binary fallback matcher for mime type "application/octet-stream".
+
+ \sa Core::MimeType, Core::MimeDatabase, Core::IMagicMatcher, Core::MagicRuleMatcher, Core::MagicRule, Core::MagicStringRule, Core::MagicByteRule, Core::GlobPattern
+ \sa Core::Internal::FileMatchContext, Core::Internal::HeuristicTextMagicMatcher
+ \sa Core::Internal::BaseMimeTypeParser, Core::Internal::MimeTypeParser
+*/
+
class BinaryMatcher : public IMagicMatcher {
Q_DISABLE_COPY(BinaryMatcher)
public:
@@ -178,8 +191,18 @@ public:
virtual int priority() const { return BinaryMatchPriority; }
};
-// A heuristic text file matcher: If the data do not contain any character
-// below tab (9), detect as text.
+/*!
+ \class Core::Internal::HeuristicTextMagicMatcher
+ \brief Heuristic text file matcher for mime types.
+
+ If the data do not contain any character below tab (9), detect as text.
+ Additionally, check on UTF16 byte order markers.
+
+ \sa Core::MimeType, Core::MimeDatabase, Core::IMagicMatcher, Core::MagicRuleMatcher, Core::MagicRule, Core::MagicStringRule, Core::MagicByteRule, Core::GlobPattern
+ \sa Core::Internal::FileMatchContext, Core::Internal::BinaryMatcher
+ \sa Core::Internal::BaseMimeTypeParser, Core::Internal::MimeTypeParser
+*/
+
class HeuristicTextMagicMatcher : public IMagicMatcher {
Q_DISABLE_COPY(HeuristicTextMagicMatcher)
public:
@@ -213,7 +236,20 @@ bool HeuristicTextMagicMatcher::matches(const QByteArray &data) const
} // namespace Internal
-// MagicRule
+/*!
+ \class Core::MagicRule
+ \brief Base class for standard Magic match rules based on contents
+ and offset specification.
+
+ Stores the offset and provides conversion helpers.
+ Base class for implementations for "string" and "byte".
+ (Others like little16, big16, etc. can be created whenever there is a need.)
+
+ \sa Core::MimeType, Core::MimeDatabase, Core::IMagicMatcher, Core::MagicRuleMatcher, Core::MagicStringRule, Core::MagicByteRule, Core::GlobPattern
+ \sa Core::Internal::FileMatchContext, Core::Internal::BinaryMatcher, Core::Internal::HeuristicTextMagicMatcher
+ \sa Core::Internal::BaseMimeTypeParser, Core::Internal::MimeTypeParser
+ */
+
const QChar MagicRule::kColon(QLatin1Char(':'));
MagicRule::MagicRule(int startPos, int endPos) : m_startPos(startPos), m_endPos(endPos)
@@ -246,6 +282,15 @@ QPair<int, int> MagicRule::fromOffset(const QString &offset)
return qMakePair(startEnd.at(0).toInt(), startEnd.at(1).toInt());
}
+/*!
+ \class Core::MagicStringRule
+ \brief Match on a string.
+
+ \sa Core::MimeType, Core::MimeDatabase, Core::IMagicMatcher, Core::MagicRuleMatcher, Core::MagicRule, Core::MagicByteRule, Core::GlobPattern
+ \sa Core::Internal::FileMatchContext, Core::Internal::BinaryMatcher, Core::Internal::HeuristicTextMagicMatcher
+ \sa Core::Internal::BaseMimeTypeParser, Core::Internal::MimeTypeParser
+ */
+
const QString MagicStringRule::kMatchType("string");
MagicStringRule::MagicStringRule(const QString &s, int startPos, int endPos) :
@@ -283,6 +328,20 @@ bool MagicStringRule::matches(const QByteArray &data) const
return rc;
}
+/*!
+ \class Core::MagicByteRule
+ \brief Match on a sequence of binary data.
+
+ Format:
+ \code
+ \0x7f\0x45\0x4c\0x46
+ \endcode
+
+ \sa Core::MimeType, Core::MimeDatabase, Core::IMagicMatcher, Core::MagicRuleMatcher, Core::MagicRule, Core::MagicStringRule, Core::MagicByteRule, Core::GlobPattern
+ \sa Core::Internal::FileMatchContext, Core::Internal::BinaryMatcher, Core::Internal::HeuristicTextMagicMatcher
+ \sa Core::Internal::BaseMimeTypeParser, Core::Internal::MimeTypeParser
+ */
+
const QString MagicByteRule::kMatchType(QLatin1String("byte"));
MagicByteRule::MagicByteRule(const QString &s, int startPos, int endPos) :
@@ -351,7 +410,18 @@ bool MagicByteRule::matches(const QByteArray &data) const
return false;
}
-// List matcher
+/*!
+ \class Core::MagicRuleMatcher
+
+ \brief A Magic matcher that checks a number of rules based on operator "or".
+
+ It is used for rules parsed from XML files.
+
+ \sa Core::MimeType, Core::MimeDatabase, Core::IMagicMatcher, Core::MagicRule, Core::MagicStringRule, Core::MagicByteRule, Core::GlobPattern
+ \sa Core::Internal::FileMatchContext, Core::Internal::BinaryMatcher, Core::Internal::HeuristicTextMagicMatcher
+ \sa Core::Internal::BaseMimeTypeParser, Core::Internal::MimeTypeParser
+*/
+
MagicRuleMatcher::MagicRuleMatcher() :
m_priority(65535)
{
@@ -405,7 +475,15 @@ IMagicMatcher::IMagicMatcherList MagicRuleMatcher::createMatchers(
return matchers;
}
-// GlobPattern
+/*!
+ \class Core::GlobPattern
+ \brief Glob pattern for file names for mime type matching.
+
+ \sa Core::MimeType, Core::MimeDatabase, Core::IMagicMatcher, Core::MagicRuleMatcher, Core::MagicRule, Core::MagicStringRule, Core::MagicByteRule
+ \sa Core::Internal::FileMatchContext, Core::Internal::BinaryMatcher, Core::Internal::HeuristicTextMagicMatcher
+ \sa Core::Internal::BaseMimeTypeParser, Core::Internal::MimeTypeParser
+*/
+
MimeGlobPattern::MimeGlobPattern(const QRegExp &regExp, unsigned weight) :
m_regExp(regExp), m_weight(weight)
{
@@ -425,7 +503,38 @@ unsigned MimeGlobPattern::weight() const
return m_weight;
}
-// ---------- MimeTypeData
+/*!
+ \class Core::MimeType
+
+ \brief Mime type data used in Qt Creator.
+
+ Contains most information from standard mime type XML database files.
+
+ Currently, magic of types "string", "bytes" is supported. In addition,
+ C++ classes, derived from Core::IMagicMatcher can be added to check
+ on contents.
+
+ In addition, the class provides a list of suffixes and a concept of the
+ 'preferred suffix' (derived from glob patterns). This is used for example
+ to be able to configure the suffix used for C++-files in Qt Creator.
+
+ Mime XML looks like:
+ \code
+ <?xml version="1.0" encoding="UTF-8"?>
+ <mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
+ <!-- Mime types must match the desktop file associations -->
+ <mime-type type="application/vnd.nokia.qt.qmakeprofile">
+ <comment xml:lang="en">Qt qmake Profile</comment>
+ <glob pattern="*.pro" weight="50"/>
+ </mime-type>
+ </mime-info>
+ \endcode
+
+ \sa Core::MimeDatabase, Core::IMagicMatcher, Core::MagicRuleMatcher, Core::MagicRule, Core::MagicStringRule, Core::MagicByteRule, Core::GlobPattern
+ \sa Core::Internal::FileMatchContext, Core::Internal::BinaryMatcher, Core::Internal::HeuristicTextMagicMatcher
+ \sa Core::Internal::BaseMimeTypeParser, Core::Internal::MimeTypeParser
+*/
+
class MimeTypeData : public QSharedData {
public:
typedef QHash<QString,QString> LocaleHash;
@@ -795,8 +904,17 @@ QDebug operator<<(QDebug d, const MimeType &mt)
namespace Internal {
-// MimeDatabase helpers: Generic parser for a sequence of <mime-type>.
-// Calls abstract handler function process for MimeType it finds.
+/*!
+ \class Core::Internal::BaseMimeTypeParser
+ \brief Generic parser for a sequence of <mime-type>.
+
+ Calls abstract handler function process for MimeType it finds.
+
+ \sa Core::MimeDatabase, Core::IMagicMatcher, Core::MagicRuleMatcher, Core::MagicRule, Core::MagicStringRule, Core::MagicByteRule, Core::GlobPattern
+ \sa Core::Internal::FileMatchContext, Core::Internal::BinaryMatcher, Core::Internal::HeuristicTextMagicMatcher
+ \sa Core::Internal::MimeTypeParser
+*/
+
class BaseMimeTypeParser {
Q_DISABLE_COPY(BaseMimeTypeParser)
public:
@@ -1058,28 +1176,50 @@ MimeMapEntry::MimeMapEntry(const MimeType &t, int aLevel) :
{
}
-/* MimeDatabasePrivate: Requirements for storage:
- * - Must be robust in case of incomplete hierachies, dangling entries
- * - Plugins will not load and register their mime types in order
- * of inheritance.
- * - Multiple inheritance (several subClassesOf) can occur
- * - Provide quick lookup by name
- * - Provide quick lookup by file type.
- * This basically rules out some pointer-based tree, so the structure chosen
- * is:
- * - An alias map QString->QString for mapping aliases to types
- * - A Map QString->MimeMapEntry for the types (MimeMapEntry being a pair of
- * MimeType and (hierarchy) level.
- * - A map QString->QString representing parent->child relations (enabling
- * recursing over children)
- * Using strings avoids dangling pointers.
- * The hierarchy level is used for mapping by file types. When findByFile()
- * is first called after addMimeType() it recurses over the hierarchy and sets
- * the hierarchy level of the entries accordingly (0 toplevel, 1 first
- * order...). It then does several passes over the type map, checking the
- * globs for maxLevel, maxLevel-1....until it finds a match (idea being to
- * to check the most specific types first). Starting a recursion from the
- * leaves is not suitable since it will hit parent nodes several times. */
+/*!
+ \class Core::MimeDatabase
+ \brief Mime data base to which the plugins can add the mime types they handle.
+
+ The class is protected by a QMutex and can therefore be accessed by threads.
+
+ A good testcase is to run it over \c '/usr/share/mime/<*>/<*>.xml' on Linux.
+
+ When adding a "text/plain" to it, the mimetype will receive a magic matcher
+ that checks for text files that do not match the globs by heuristics.
+
+ \section1 Design Considerations
+
+ Storage requirements:
+ \list
+ \o Must be robust in case of incomplete hierarchies, dangling entries
+ \o Plugins will not load and register their mime types in order of inheritance.
+ \o Multiple inheritance (several subClassesOf) can occur
+ \o Provide quick lookup by name
+ \o Provide quick lookup by file type.
+ \endlist
+
+ This basically rules out some pointer-based tree, so the structure chosen is:
+ \list
+ \o An alias map QString->QString for mapping aliases to types
+ \o A Map QString->MimeMapEntry for the types (MimeMapEntry being a pair of
+ MimeType and (hierarchy) level.
+ \o A map QString->QString representing parent->child relations (enabling
+ recursing over children)
+ \o Using strings avoids dangling pointers.
+ \endlist
+
+ The hierarchy level is used for mapping by file types. When findByFile()
+ is first called after addMimeType() it recurses over the hierarchy and sets
+ the hierarchy level of the entries accordingly (0 toplevel, 1 first
+ order...). It then does several passes over the type map, checking the
+ globs for maxLevel, maxLevel-1....until it finds a match (idea being to
+ to check the most specific types first). Starting a recursion from the
+ leaves is not suitable since it will hit parent nodes several times.
+
+ \sa Core::MimeType, Core::IMagicMatcher, Core::MagicRuleMatcher, Core::MagicRule, Core::MagicStringRule, Core::MagicByteRule, Core::GlobPattern
+ \sa Core::Internal::FileMatchContext, Core::Internal::BinaryMatcher, Core::Internal::HeuristicTextMagicMatcher
+ \sa Core::Internal::BaseMimeTypeParser, Core::Internal::MimeTypeParser
+*/
class MimeDatabasePrivate
{
@@ -1154,6 +1294,17 @@ MimeDatabasePrivate::MimeDatabasePrivate() :
kModifiedMimeTypesPath = ICore::instance()->userResourcePath() + QLatin1String("/mimetypes/");
}
+/*!
+ \class Core::Internal::MimeTypeParser
+ \brief Mime type parser
+
+ Populates Core::MimeDataBase
+
+ \sa Core::MimeDatabase, Core::IMagicMatcher, Core::MagicRuleMatcher, Core::MagicRule, Core::MagicStringRule, Core::MagicByteRule, Core::GlobPattern
+ \sa Core::Internal::FileMatchContext, Core::Internal::BinaryMatcher, Core::Internal::HeuristicTextMagicMatcher
+ \sa Core::Internal::MimeTypeParser
+*/
+
namespace Internal {
// Parser that builds MimeDB hierarchy by adding to MimeDatabasePrivate
class MimeTypeParser : public BaseMimeTypeParser {
@@ -1642,7 +1793,6 @@ void MimeDatabasePrivate::debug(QTextStream &str) const
str << "<MimeDatabase\n";
}
-// --------------- MimeDatabase
MimeDatabase::MimeDatabase() :
m_d(new MimeDatabasePrivate)
{
diff --git a/src/plugins/coreplugin/mimedatabase.h b/src/plugins/coreplugin/mimedatabase.h
index e695d9c83f..2900c2935e 100644
--- a/src/plugins/coreplugin/mimedatabase.h
+++ b/src/plugins/coreplugin/mimedatabase.h
@@ -44,9 +44,7 @@
QT_BEGIN_NAMESPACE
class QIODevice;
-class QRegExp;
class QDebug;
-class QFileInfo;
QT_END_NAMESPACE
namespace Core {
@@ -59,7 +57,6 @@ namespace Internal {
class FileMatchContext;
}
-/* Magic (file contents) matcher interface. */
class CORE_EXPORT IMagicMatcher
{
Q_DISABLE_COPY(IMagicMatcher)
@@ -76,9 +73,6 @@ public:
virtual ~IMagicMatcher() {}
};
-/* Utility class: A standard Magic match rule based on contents. Currently there are
- * implementations for "string" and "byte". (Others like little16, big16, etc. can be
- * created whenever there is a need.) */
class CORE_EXPORT MagicRule
{
Q_DISABLE_COPY(MagicRule)
@@ -138,8 +132,6 @@ private:
QList<int> m_bytes;
};
-/* Utility class: A Magic matcher that checks a number of rules based on
- * operator "or". It is used for rules parsed from XML files. */
class CORE_EXPORT MagicRuleMatcher : public IMagicMatcher
{
Q_DISABLE_COPY(MagicRuleMatcher)
@@ -183,15 +175,6 @@ private:
int m_weight;
};
-/* Mime type data used in Qt Creator. Contains most information from
- * standard mime type XML database files.
- * Omissions:
- * - Only magic of type "string" is supported. In addition, C++ classes
- * derived from IMagicMatcher can be added to check on contents
- * - acronyms, language-specific comments
- * Extensions:
- * - List of suffixes and preferred suffix (derived from glob patterns).
- */
class CORE_EXPORT MimeType
{
public:
@@ -267,12 +250,6 @@ private:
QSharedDataPointer<MimeTypeData> m_d;
};
-/* A Mime data base to which the plugins can add the mime types they handle.
- * When adding a "text/plain" to it, the mimetype will receive a magic matcher
- * that checks for text files that do not match the globs by heuristics.
- * The class is protected by a QMutex and can therefore be accessed by threads.
- * A good testcase is to run it over '/usr/share/mime/<*>/<*>.xml' on Linux. */
-
class CORE_EXPORT MimeDatabase
{
Q_DISABLE_COPY(MimeDatabase)
diff --git a/src/plugins/coreplugin/modemanager.h b/src/plugins/coreplugin/modemanager.h
index 59e42a4bc6..f91a0c9c27 100644
--- a/src/plugins/coreplugin/modemanager.h
+++ b/src/plugins/coreplugin/modemanager.h
@@ -62,8 +62,8 @@ public:
void init();
static ModeManager *instance();
- IMode* currentMode() const;
- IMode* mode(const QString &id) const;
+ IMode *currentMode() const;
+ IMode *mode(const QString &id) const;
void addAction(QAction *action, int priority);
void addProjectSelector(QAction *action);
diff --git a/src/plugins/coreplugin/navigationsubwidget.h b/src/plugins/coreplugin/navigationsubwidget.h
index ae9d1b680e..29dc219066 100644
--- a/src/plugins/coreplugin/navigationsubwidget.h
+++ b/src/plugins/coreplugin/navigationsubwidget.h
@@ -47,7 +47,6 @@ class StyledBar;
namespace Core {
class INavigationWidgetFactory;
-class IMode;
class Command;
class NavigationWidget;
diff --git a/src/plugins/coreplugin/outputpanemanager.h b/src/plugins/coreplugin/outputpanemanager.h
index 4a3994dd1d..f6545bf19f 100644
--- a/src/plugins/coreplugin/outputpanemanager.h
+++ b/src/plugins/coreplugin/outputpanemanager.h
@@ -46,7 +46,6 @@ QT_END_NAMESPACE
namespace Core {
-class IMode;
class IOutputPane;
namespace Internal {
diff --git a/src/plugins/coreplugin/statusbarwidget.cpp b/src/plugins/coreplugin/statusbarwidget.cpp
index e90d5b549b..9b96599af6 100644
--- a/src/plugins/coreplugin/statusbarwidget.cpp
+++ b/src/plugins/coreplugin/statusbarwidget.cpp
@@ -37,10 +37,7 @@
using namespace Core;
StatusBarWidget::StatusBarWidget(QObject *parent)
- : IContext(parent),
- m_widget(0),
- m_context(),
- m_defaultPosition(StatusBarWidget::First)
+ : IContext(parent), m_defaultPosition(StatusBarWidget::First)
{
}
@@ -49,33 +46,11 @@ StatusBarWidget::~StatusBarWidget()
delete m_widget;
}
-Context StatusBarWidget::context() const
-{
- return m_context;
-}
-
-QWidget *StatusBarWidget::widget()
-{
- return m_widget;
-}
-
StatusBarWidget::StatusBarPosition StatusBarWidget::position() const
{
return m_defaultPosition;
}
-QWidget *StatusBarWidget::setWidget(QWidget *widget)
-{
- QWidget *oldWidget = m_widget;
- m_widget = widget;
- return oldWidget;
-}
-
-void StatusBarWidget::setContext(const Context &context)
-{
- m_context = context;
-}
-
void StatusBarWidget::setPosition(StatusBarWidget::StatusBarPosition position)
{
m_defaultPosition = position;
diff --git a/src/plugins/coreplugin/statusbarwidget.h b/src/plugins/coreplugin/statusbarwidget.h
index be2dcfce4b..3f3116bc37 100644
--- a/src/plugins/coreplugin/statusbarwidget.h
+++ b/src/plugins/coreplugin/statusbarwidget.h
@@ -49,17 +49,10 @@ public:
StatusBarWidget(QObject *parent = 0);
~StatusBarWidget();
- Context context() const;
- QWidget *widget();
StatusBarWidget::StatusBarPosition position() const;
-
- QWidget *setWidget(QWidget *widget);
- void setContext(const Context &context);
void setPosition(StatusBarWidget::StatusBarPosition position);
private:
- QPointer<QWidget> m_widget;
- Context m_context;
StatusBarWidget::StatusBarPosition m_defaultPosition;
};
diff --git a/src/plugins/coreplugin/uniqueidmanager.cpp b/src/plugins/coreplugin/uniqueidmanager.cpp
index 118ed888e7..f8745f6e4b 100644
--- a/src/plugins/coreplugin/uniqueidmanager.cpp
+++ b/src/plugins/coreplugin/uniqueidmanager.cpp
@@ -62,7 +62,7 @@ int UniqueIDManager::uniqueIdentifier(const Id &id)
return uid;
}
-QString UniqueIDManager::stringForUniqueIdentifier(int uid)
+QString UniqueIDManager::stringForUniqueIdentifier(int uid) const
{
return m_uniqueIdentifiers.key(uid);
}
diff --git a/src/plugins/coreplugin/uniqueidmanager.h b/src/plugins/coreplugin/uniqueidmanager.h
index 94a2b60c93..fd00d44e3f 100644
--- a/src/plugins/coreplugin/uniqueidmanager.h
+++ b/src/plugins/coreplugin/uniqueidmanager.h
@@ -80,7 +80,7 @@ public:
bool hasUniqueIdentifier(const Id &id) const;
int uniqueIdentifier(const Id &id);
- QString stringForUniqueIdentifier(int uid);
+ QString stringForUniqueIdentifier(int uid) const;
private:
QHash<Id, int> m_uniqueIdentifiers;
diff --git a/src/plugins/coreplugin/vcsmanager.cpp b/src/plugins/coreplugin/vcsmanager.cpp
index cc16c15268..a2ea37a78d 100644
--- a/src/plugins/coreplugin/vcsmanager.cpp
+++ b/src/plugins/coreplugin/vcsmanager.cpp
@@ -43,29 +43,98 @@
#include <QtCore/QMap>
#include <QtCore/QCoreApplication>
-#include <QtCore/QDebug>
#include <QtCore/QFileInfo>
#include <QtGui/QMessageBox>
-enum { debug = 0 };
-
namespace Core {
typedef QList<IVersionControl *> VersionControlList;
-typedef QMap<QString, IVersionControl *> VersionControlCache;
static inline VersionControlList allVersionControls()
{
return ExtensionSystem::PluginManager::instance()->getObjects<IVersionControl>();
}
+static const QChar SLASH('/');
+
// ---- VCSManagerPrivate:
// Maintains a cache of top-level directory->version control.
class VcsManagerPrivate
{
public:
- VersionControlCache m_cachedMatches;
+ class VcsInfo {
+ public:
+ VcsInfo(IVersionControl *vc, const QString &tl) :
+ versionControl(vc), topLevel(tl)
+ { }
+
+ bool operator == (const VcsInfo &other) const
+ {
+ return versionControl == other.versionControl &&
+ topLevel == other.topLevel;
+ }
+
+ IVersionControl *versionControl;
+ QString topLevel;
+ };
+
+ ~VcsManagerPrivate()
+ {
+ qDeleteAll(m_vcsInfoList);
+ }
+
+ VcsInfo *findInCache(const QString &directory)
+ {
+ const QMap<QString, VcsInfo *>::const_iterator it = m_cachedMatches.constFind(directory);
+ if (it != m_cachedMatches.constEnd())
+ return it.value();
+ return 0;
+ }
+
+ VcsInfo *findUpInCache(const QString &directory)
+ {
+ VcsInfo *result = 0;
+
+ // Split the path, trying to find the matching repository. We start from the reverse
+ // in order to detected nested repositories correctly (say, a git checkout under SVN).
+ for (int pos = directory.size() - 1; pos >= 0; pos = directory.lastIndexOf(SLASH, pos) - 1) {
+ const QString directoryPart = directory.left(pos);
+ result = findInCache(directoryPart);
+ if (result != 0)
+ break;
+ }
+ return result;
+ }
+
+ void cache(IVersionControl *vc, const QString topLevel, const QString directory)
+ {
+ Q_ASSERT(directory.startsWith(topLevel));
+
+ VcsInfo *newInfo = new VcsInfo(vc, topLevel);
+ bool createdNewInfo(true);
+ // Do we have a matching VcsInfo already?
+ foreach(VcsInfo *i, m_vcsInfoList) {
+ if (*i == *newInfo) {
+ delete newInfo;
+ newInfo = i;
+ createdNewInfo = false;
+ break;
+ }
+ }
+ if (createdNewInfo)
+ m_vcsInfoList.append(newInfo);
+
+ QString tmpDir = directory;
+ while (tmpDir.count() >= topLevel.count() && tmpDir.count() > 0) {
+ m_cachedMatches.insert(tmpDir, newInfo);
+ int slashPos = tmpDir.lastIndexOf(SLASH);
+ tmpDir = slashPos >= 0 ? tmpDir.left(tmpDir.lastIndexOf(SLASH)) : QString();
+ }
+ }
+
+ QMap<QString, VcsInfo *> m_cachedMatches;
+ QList<VcsInfo *> m_vcsInfoList;
};
VcsManager::VcsManager(QObject *parent) :
@@ -74,6 +143,8 @@ VcsManager::VcsManager(QObject *parent) :
{
}
+// ---- VCSManager:
+
VcsManager::~VcsManager()
{
delete m_d;
@@ -99,91 +170,52 @@ static bool longerThanPath(QPair<QString, IVersionControl *> &pair1, QPair<QStri
IVersionControl* VcsManager::findVersionControlForDirectory(const QString &directory,
QString *topLevelDirectory)
{
- typedef VersionControlCache::const_iterator VersionControlCacheConstIterator;
-
- if (debug) {
- qDebug(">findVersionControlForDirectory %s topLevelPtr %d",
- qPrintable(directory), (topLevelDirectory != 0));
- if (debug > 1) {
- const VersionControlCacheConstIterator cend = m_d->m_cachedMatches.constEnd();
- for (VersionControlCacheConstIterator it = m_d->m_cachedMatches.constBegin(); it != cend; ++it)
- qDebug("Cache %s -> '%s'", qPrintable(it.key()), qPrintable(it.value()->displayName()));
- }
- }
- QTC_ASSERT(!directory.isEmpty(), return 0);
-
- const VersionControlCacheConstIterator cacheEnd = m_d->m_cachedMatches.constEnd();
-
- if (topLevelDirectory)
- topLevelDirectory->clear();
+ if (directory.isEmpty())
+ return 0;
- // First check if the directory has an entry, meaning it is a top level
- const VersionControlCacheConstIterator fullPathIt = m_d->m_cachedMatches.constFind(directory);
- if (fullPathIt != cacheEnd) {
+ VcsManagerPrivate::VcsInfo *cachedData = m_d->findInCache(directory);
+ if (cachedData) {
if (topLevelDirectory)
- *topLevelDirectory = directory;
- if (debug)
- qDebug("<findVersionControlForDirectory: full cache match for VCS '%s'", qPrintable(fullPathIt.value()->displayName()));
- return fullPathIt.value();
+ *topLevelDirectory = cachedData->topLevel;
+ return cachedData->versionControl;
}
- // Split the path, trying to find the matching repository. We start from the reverse
- // in order to detected nested repositories correctly (say, a git checkout under SVN).
- // Note that detection of a nested version control will still fail if the
- // above-located version control is detected and entered into the cache first.
- // The nested one can then no longer be found due to the splitting of the paths.
- int pos = directory.size() - 1;
- const QChar slash = QLatin1Char('/');
- while (true) {
- const int index = directory.lastIndexOf(slash, pos);
- if (index <= 0) // Stop at '/' or not found
- break;
- const QString directoryPart = directory.left(index);
- const VersionControlCacheConstIterator it = m_d->m_cachedMatches.constFind(directoryPart);
- if (it != cacheEnd) {
- if (topLevelDirectory)
- *topLevelDirectory = it.key();
- if (debug)
- qDebug("<findVersionControlForDirectory: cache match for VCS '%s', topLevel: %s",
- qPrintable(it.value()->displayName()), qPrintable(it.key()));
- return it.value();
- }
- pos = index - 1;
- }
-
- // Nothing: ask the IVersionControls directly, insert the toplevel into the cache.
+ // Nothing: ask the IVersionControls directly.
const VersionControlList versionControls = allVersionControls();
QList<QPair<QString, IVersionControl *> > allThatCanManage;
foreach (IVersionControl * versionControl, versionControls) {
QString topLevel;
- if (versionControl->managesDirectory(directory, &topLevel)) {
- if (debug)
- qDebug("<findVersionControlForDirectory: %s manages %s",
- qPrintable(versionControl->displayName()),
- qPrintable(topLevel));
+ if (versionControl->managesDirectory(directory, &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 (allThatCanManage.isEmpty()) {
+ m_d->cache(0, QString(), directory); // register that nothing was found!
+
+ // report result;
if (topLevelDirectory)
- *topLevelDirectory = toplevel;
- if (debug)
- qDebug("<findVersionControlForDirectory: invocation of '%s' matches: %s",
- qPrintable(versionControl->displayName()), qPrintable(toplevel));
- return versionControl;
+ topLevelDirectory->clear();
+ return 0;
}
- if (debug)
- qDebug("<findVersionControlForDirectory: No match for %s", qPrintable(directory));
- return 0;
+
+ // Register Vcs(s) with the cache
+ QString tmpDir = directory;
+ for (QList<QPair<QString, IVersionControl *> >::const_iterator i = allThatCanManage.constBegin();
+ i != allThatCanManage.constEnd(); ++i) {
+ m_d->cache(i->second, i->first, tmpDir);
+ tmpDir = i->first;
+ tmpDir = tmpDir.left(tmpDir.lastIndexOf(SLASH));
+ }
+
+ // return result
+ if (topLevelDirectory)
+ *topLevelDirectory = allThatCanManage.first().first;
+ return allThatCanManage.first().second;
}
bool VcsManager::promptToDelete(const QString &fileName)
@@ -201,7 +233,7 @@ IVersionControl *VcsManager::checkout(const QString &versionControlType,
if (versionControl->displayName() == versionControlType
&& versionControl->supportsOperation(Core::IVersionControl::CheckoutOperation)) {
if (versionControl->vcsCheckout(directory, url)) {
- m_d->m_cachedMatches.insert(directory, versionControl);
+ m_d->cache(versionControl, directory, directory);
return versionControl;
}
return 0;
@@ -243,14 +275,4 @@ bool VcsManager::promptToDelete(IVersionControl *vc, const QString &fileName)
return vc->vcsDelete(fileName);
}
-CORE_EXPORT QDebug operator<<(QDebug in, const VcsManager &v)
-{
- QDebug nospace = in.nospace();
- const VersionControlCache::const_iterator cend = v.m_d->m_cachedMatches.constEnd();
- for (VersionControlCache::const_iterator it = v.m_d->m_cachedMatches.constBegin(); it != cend; ++it)
- nospace << "Directory: " << it.key() << ' ' << it.value()->displayName() << '\n';
- nospace << '\n';
- return in;
-}
-
} // namespace Core
diff --git a/src/plugins/coreplugin/vcsmanager.h b/src/plugins/coreplugin/vcsmanager.h
index 2b96b08705..a086a05c2c 100644
--- a/src/plugins/coreplugin/vcsmanager.h
+++ b/src/plugins/coreplugin/vcsmanager.h
@@ -84,8 +84,6 @@ public:
bool promptToDelete(const QString &fileName);
bool promptToDelete(IVersionControl *versionControl, const QString &fileName);
- friend CORE_EXPORT QDebug operator<<(QDebug in, const VcsManager &);
-
signals:
void repositoryChanged(const QString &repository);
@@ -93,8 +91,6 @@ private:
VcsManagerPrivate *m_d;
};
-CORE_EXPORT QDebug operator<<(QDebug in, const VcsManager &);
-
} // namespace Core
#endif // VCSMANAGER_H
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index 349fd8e53b..30542972ba 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -478,7 +478,7 @@ void CPPEditorWidget::createToolBar(CPPEditor *editor)
outlineView->header()->hide();
outlineView->setItemsExpandable(false);
m_outlineCombo->setView(outlineView);
- m_outlineCombo->setMaxVisibleItems(20);
+ m_outlineCombo->setMaxVisibleItems(40);
m_outlineModel = new OverviewModel(this);
m_proxyModel = new OverviewProxyModel(m_outlineModel, this);
@@ -1774,11 +1774,6 @@ void CPPEditorWidget::keyPressEvent(QKeyEvent *e)
finishRename();
}
-Core::Context CPPEditor::context() const
-{
- return m_context;
-}
-
Core::IEditor *CPPEditor::duplicate(QWidget *parent)
{
CPPEditorWidget *newEditor = new CPPEditorWidget(parent);
diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h
index 7a5d143ca3..53f86f0f8d 100644
--- a/src/plugins/cppeditor/cppeditor.h
+++ b/src/plugins/cppeditor/cppeditor.h
@@ -146,7 +146,6 @@ class CPPEditor : public TextEditor::BaseTextEditor
Q_OBJECT
public:
CPPEditor(CPPEditorWidget *);
- Core::Context context() const;
bool duplicateSupported() const { return true; }
Core::IEditor *duplicate(QWidget *parent);
@@ -154,9 +153,6 @@ public:
bool isTemporary() const { return false; }
virtual bool open(const QString & fileName);
-
-private:
- Core::Context m_context;
};
class CPPEditorWidget : public TextEditor::BaseTextEditorWidget
diff --git a/src/plugins/cppeditor/cppeditorconstants.h b/src/plugins/cppeditor/cppeditorconstants.h
index a9c90dfd3d..6efb3f1dbd 100644
--- a/src/plugins/cppeditor/cppeditorconstants.h
+++ b/src/plugins/cppeditor/cppeditorconstants.h
@@ -36,7 +36,6 @@
namespace CppEditor {
namespace Constants {
-const char * const FORMATCODE = "CppEditor.FormatCode";
const char * const M_CONTEXT = "CppEditor.ContextMenu";
const char * const C_CPPEDITOR = "CppPlugin.C++Editor";
const char * const CPPEDITOR_ID = "CppPlugin.C++Editor";
@@ -49,7 +48,6 @@ const char * const SEPARATOR = "CppEditor.Separator";
const char * const SEPARATOR2 = "CppEditor.Separator2";
const char * const SEPARATOR3 = "CppEditor.Separator3";
const char * const SEPARATOR4 = "CppEditor.Separator4";
-const char * const FIND_REFERENCES = "CppEditor.FindReferences";
const char * const JUMP_TO_DEFINITION = "CppEditor.JumpToDefinition";
const char * const UPDATE_CODEMODEL = "CppEditor.UpdateCodeModel";
@@ -57,12 +55,6 @@ const int TYPE_HIERARCHY_PRIORITY = 700;
const char * const TYPE_HIERARCHY_ID = "CppEditor.TypeHierarchy";
const char * const OPEN_TYPE_HIERARCHY = "CppEditor.OpenTypeHierarchy";
-const char * const HEADER_FILE_TYPE = "CppHeaderFiles";
-const char * const SOURCE_FILE_TYPE = "CppSourceFiles";
-
-const char * const MOVE_TO_PREVIOUS_TOKEN = "CppEditor.MoveToPreviousToken";
-const char * const MOVE_TO_NEXT_TOKEN = "CppEditor.MoveToNextToken";
-
const char * const C_SOURCE_MIMETYPE = "text/x-csrc";
const char * const C_HEADER_MIMETYPE = "text/x-chdr";
const char * const CPP_SOURCE_MIMETYPE = "text/x-c++src";
diff --git a/src/plugins/cpptools/cpptoolsconstants.h b/src/plugins/cpptools/cpptoolsconstants.h
index f4ddc39d21..5732a491d4 100644
--- a/src/plugins/cpptools/cpptoolsconstants.h
+++ b/src/plugins/cpptools/cpptoolsconstants.h
@@ -39,7 +39,6 @@ namespace CppTools {
namespace Constants {
const char * const M_TOOLS_CPP = "CppTools.Tools.Menu";
-const char * const M_CPP_REFACTORING = "CppTools.Refactoring.Menu";
const char * const SWITCH_HEADER_SOURCE = "CppTools.SwitchHeaderSource";
const char * const TASK_INDEX = "CppTools.Task.Index";
const char * const TASK_SEARCH = "CppTools.Task.Search";
diff --git a/src/plugins/cvs/cvsconstants.h b/src/plugins/cvs/cvsconstants.h
index 93c8bdd41e..f7ef98d152 100644
--- a/src/plugins/cvs/cvsconstants.h
+++ b/src/plugins/cvs/cvsconstants.h
@@ -37,8 +37,6 @@ namespace CVS {
namespace Constants {
const char * const CVS_SUBMIT_MIMETYPE = "application/vnd.nokia.text.cvs.submit";
-const char * const CVSEDITOR = "CVS Editor";
-const char * const CVSEDITOR_KIND = "CVS Editor";
const char * const CVSCOMMITEDITOR = "CVS Commit Editor";
const char * const CVSCOMMITEDITOR_ID = "CVS Commit Editor";
const char * const CVSCOMMITEDITOR_DISPLAY_NAME = QT_TRANSLATE_NOOP("VCS", "CVS Commit Editor");
diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp
index 95db03faca..17f2bc36e6 100644
--- a/src/plugins/cvs/cvsplugin.cpp
+++ b/src/plugins/cvs/cvsplugin.cpp
@@ -42,9 +42,11 @@
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/basevcssubmiteditorfactory.h>
#include <vcsbase/vcsbaseoutputwindow.h>
+#include <vcsbase/vcsbaseeditorparameterwidget.h>
#include <locator/commandlocator.h>
#include <utils/synchronousprocess.h>
#include <utils/parameteraction.h>
+#include <utils/qtcassert.h>
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
@@ -152,14 +154,6 @@ static inline QString debugCodec(const QTextCodec *c)
return c ? QString::fromAscii(c->name()) : QString::fromAscii("Null codec");
}
-Core::IEditor* locateEditor(const char *property, const QString &entry)
-{
- foreach (Core::IEditor *ed, Core::EditorManager::instance()->openedEditors())
- if (ed->property(property).toString() == entry)
- return ed;
- return 0;
-}
-
static inline bool messageBoxQuestion(const QString &title, const QString &question, QWidget *parent = 0)
{
return QMessageBox::question(parent, title, question, QMessageBox::Yes|QMessageBox::No) == QMessageBox::Yes;
@@ -528,22 +522,75 @@ static inline void setDiffBaseDirectory(Core::IEditor *editor, const QString &db
ve->setDiffBaseDirectory(db);
}
+// Collect all parameters required for a diff to be able to associate them
+// with a diff editor and re-run the diff with parameters.
+struct CvsDiffParameters
+{
+ QString workingDir;
+ QStringList arguments;
+ QStringList files;
+};
+
+// Parameter widget controlling whitespace diff mode, associated with a parameter
+// struct.
+class CvsDiffParameterWidget : public VCSBase::VCSBaseEditorParameterWidget
+{
+ Q_OBJECT
+public:
+ explicit CvsDiffParameterWidget(const CvsDiffParameters &p, QWidget *parent = 0);
+
+signals:
+ void reRunDiff(const CVS::Internal::CvsDiffParameters &);
+
+public slots:
+ void triggerReRun();
+
+private:
+ const CvsDiffParameters m_parameters;
+};
+
+CvsDiffParameterWidget::CvsDiffParameterWidget(const CvsDiffParameters &p, QWidget *parent) :
+ VCSBase::VCSBaseEditorParameterWidget(parent), m_parameters(p)
+{
+ setBaseArguments(p.arguments);
+ addIgnoreWhiteSpaceButton(QLatin1String("-w"));
+ addIgnoreBlankLinesButton(QLatin1String("-B"));
+ connect(this, SIGNAL(argumentsChanged()),
+ this, SLOT(triggerReRun()));
+}
+
+void CvsDiffParameterWidget::triggerReRun()
+{
+ CvsDiffParameters effectiveParameters = m_parameters;
+ effectiveParameters.arguments = arguments();
+ emit reRunDiff(effectiveParameters);
+}
+
void CVSPlugin::cvsDiff(const QString &workingDir, const QStringList &files)
{
+ CvsDiffParameters p;
+ p.workingDir = workingDir;
+ p.files = files;
+ p.arguments = m_settings.cvsDiffOptions.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ cvsDiff(p);
+}
+
+void CVSPlugin::cvsDiff(const CvsDiffParameters &p)
+{
if (CVS::Constants::debug)
- qDebug() << Q_FUNC_INFO << files;
- const QString source = VCSBase::VCSBaseEditorWidget::getSource(workingDir, files);
- QTextCodec *codec = VCSBase::VCSBaseEditorWidget::getCodec(workingDir, files);
- const QString id = VCSBase::VCSBaseEditorWidget::getTitleId(workingDir, files);
+ qDebug() << Q_FUNC_INFO << p.files;
+ const QString source = VCSBase::VCSBaseEditorWidget::getSource(p.workingDir, p.files);
+ QTextCodec *codec = VCSBase::VCSBaseEditorWidget::getCodec(p.workingDir, p.files);
+ const QString id = VCSBase::VCSBaseEditorWidget::getTitleId(p.workingDir, p.files);
QStringList args(QLatin1String("diff"));
- args << m_settings.cvsDiffOptions;
- args.append(files);
+ args.append(p.arguments);
+ args.append(p.files);
// CVS returns the diff exit code (1 if files differ), which is
// undistinguishable from a "file not found" error, unfortunately.
const CVSResponse response =
- runCVS(workingDir, args, m_settings.timeOutMS(), 0, codec);
+ runCVS(p.workingDir, args, m_settings.timeOutMS(), 0, codec);
switch (response.result) {
case CVSResponse::NonNullExitCode:
case CVSResponse::Ok:
@@ -557,20 +604,30 @@ void CVSPlugin::cvsDiff(const QString &workingDir, const QStringList &files)
output = tr("The files do not differ.");
// diff of a single file? re-use an existing view if possible to support
// the common usage pattern of continuously changing and diffing a file
- if (files.count() == 1) {
- // Show in the same editor if diff has been executed before
- if (Core::IEditor *editor = locateEditor("originalFileName", id)) {
- editor->createNew(output);
- Core::EditorManager::instance()->activateEditor(editor, Core::EditorManager::ModeSwitch);
- setDiffBaseDirectory(editor, workingDir);
- return;
- }
+ // Show in the same editor if diff has been executed before
+ const QString tag = VCSBase::VCSBaseEditorWidget::editorTag(VCSBase::DiffOutput, p.workingDir, p.files);
+ if (Core::IEditor *existingEditor = VCSBase::VCSBaseEditorWidget::locateEditorByTag(tag)) {
+ existingEditor->createNew(output);
+ Core::EditorManager::instance()->activateEditor(existingEditor, Core::EditorManager::ModeSwitch);
+ setDiffBaseDirectory(existingEditor, p.workingDir);
+ return;
}
const QString title = QString::fromLatin1("cvs diff %1").arg(id);
Core::IEditor *editor = showOutputInEditor(title, output, VCSBase::DiffOutput, source, codec);
- if (files.count() == 1)
- editor->setProperty("originalFileName", id);
- setDiffBaseDirectory(editor, workingDir);
+ VCSBase::VCSBaseEditorWidget::tagEditor(editor, tag);
+ setDiffBaseDirectory(editor, p.workingDir);
+ CVSEditor *diffEditorWidget = qobject_cast<CVSEditor*>(editor->widget());
+ QTC_ASSERT(diffEditorWidget, return ; )
+
+ // Wire up the parameter widget to trigger a re-run on
+ // parameter change and 'revert' from inside the diff editor.
+ diffEditorWidget->setRevertDiffChunkEnabled(true);
+ CvsDiffParameterWidget *pw = new CvsDiffParameterWidget(p);
+ connect(pw, SIGNAL(reRunDiff(CVS::Internal::CvsDiffParameters)),
+ this, SLOT(cvsDiff(CVS::Internal::CvsDiffParameters)));
+ connect(diffEditorWidget, SIGNAL(diffChunkReverted(VCSBase::DiffChunk)),
+ pw, SLOT(triggerReRun()));
+ diffEditorWidget->setConfigurationWidget(pw);
}
CVSSubmitEditor *CVSPlugin::openCVSSubmitEditor(const QString &fileName)
@@ -822,13 +879,14 @@ void CVSPlugin::filelog(const QString &workingDir,
// Re-use an existing view if possible to support
// the common usage pattern of continuously changing and diffing a file
- if (Core::IEditor *editor = locateEditor("logFileName", id)) {
+ const QString tag = VCSBase::VCSBaseEditorWidget::editorTag(VCSBase::LogOutput, workingDir, files);
+ if (Core::IEditor *editor = VCSBase::VCSBaseEditorWidget::locateEditorByTag(tag)) {
editor->createNew(response.stdOut);
Core::EditorManager::instance()->activateEditor(editor, Core::EditorManager::ModeSwitch);
} else {
const QString title = QString::fromLatin1("cvs log %1").arg(id);
Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::LogOutput, source, codec);
- newEditor->setProperty("logFileName", id);
+ VCSBase::VCSBaseEditorWidget::tagEditor(newEditor, tag);
if (enableAnnotationContextMenu)
VCSBase::VCSBaseEditorWidget::getVcsBaseEditor(newEditor)->setFileLogAnnotateEnabled(true);
}
@@ -963,14 +1021,15 @@ void CVSPlugin::annotate(const QString &workingDir, const QString &file,
if (lineNumber < 1)
lineNumber = VCSBase::VCSBaseEditorWidget::lineNumberOfCurrentEditor(file);
- if (Core::IEditor *editor = locateEditor("annotateFileName", id)) {
+ const QString tag = VCSBase::VCSBaseEditorWidget::editorTag(VCSBase::AnnotateOutput, workingDir, QStringList(file), revision);
+ if (Core::IEditor *editor = VCSBase::VCSBaseEditorWidget::locateEditorByTag(tag)) {
editor->createNew(response.stdOut);
VCSBase::VCSBaseEditorWidget::gotoLineOfEditor(editor, lineNumber);
Core::EditorManager::instance()->activateEditor(editor, Core::EditorManager::ModeSwitch);
} else {
const QString title = QString::fromLatin1("cvs annotate %1").arg(id);
Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::AnnotateOutput, source, codec);
- newEditor->setProperty("annotateFileName", id);
+ VCSBase::VCSBaseEditorWidget::tagEditor(newEditor, tag);
VCSBase::VCSBaseEditorWidget::gotoLineOfEditor(newEditor, lineNumber);
}
}
@@ -1159,14 +1218,14 @@ bool CVSPlugin::describe(const QString &repositoryPath,
// Re-use an existing view if possible to support
// the common usage pattern of continuously changing and diffing a file
const QString commitId = entries.front().revisions.front().commitId;
- if (Core::IEditor *editor = locateEditor("describeChange", commitId)) {
+ if (Core::IEditor *editor = VCSBase::VCSBaseEditorWidget::locateEditorByTag(commitId)) {
editor->createNew(output);
Core::EditorManager::instance()->activateEditor(editor, Core::EditorManager::ModeSwitch);
setDiffBaseDirectory(editor, repositoryPath);
} else {
const QString title = QString::fromLatin1("cvs describe %1").arg(commitId);
Core::IEditor *newEditor = showOutputInEditor(title, output, VCSBase::DiffOutput, entries.front().file, codec);
- newEditor->setProperty("describeChange", commitId);
+ VCSBase::VCSBaseEditorWidget::tagEditor(newEditor, commitId);
setDiffBaseDirectory(newEditor, repositoryPath);
}
return true;
@@ -1338,3 +1397,5 @@ CVSControl *CVSPlugin::cvsVersionControl() const
}
}
Q_EXPORT_PLUGIN(CVS::Internal::CVSPlugin)
+
+#include "cvsplugin.moc"
diff --git a/src/plugins/cvs/cvsplugin.h b/src/plugins/cvs/cvsplugin.h
index 2eed524084..fac8611a6d 100644
--- a/src/plugins/cvs/cvsplugin.h
+++ b/src/plugins/cvs/cvsplugin.h
@@ -63,7 +63,7 @@ namespace Locator {
namespace CVS {
namespace Internal {
-
+struct CvsDiffParameters;
class CVSSubmitEditor;
class CVSControl;
@@ -131,6 +131,7 @@ private slots:
void editCurrentFile();
void uneditCurrentFile();
void uneditCurrentRepository();
+ void cvsDiff(const CVS::Internal::CvsDiffParameters &p);
protected:
virtual void updateActions(VCSBase::VCSBasePlugin::ActionState);
diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp
index a95beae115..d7e754b5ac 100644
--- a/src/plugins/debugger/breakhandler.cpp
+++ b/src/plugins/debugger/breakhandler.cpp
@@ -1057,7 +1057,9 @@ const BreakpointResponse &BreakHandler::response(BreakpointId id) const
{
static BreakpointResponse dummy;
ConstIterator it = m_storage.find(id);
- QTC_ASSERT(it != m_storage.end(), qDebug() << id; return dummy);
+ //QTC_ASSERT(it != m_storage.end(), qDebug() << id; return dummy);
+ if (it == m_storage.end())
+ return dummy;
return it->response;
}
@@ -1089,21 +1091,21 @@ void BreakHandler::setResponse(BreakpointId id,
updateMarker(id);
}
-void BreakHandler::setBreakpointData(BreakpointId id,
- const BreakpointParameters &data)
+void BreakHandler::changeBreakpointData(BreakpointId id,
+ const BreakpointParameters &data, BreakpointParts parts)
{
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->engine && it->state != BreakpointNew) {
- setState(id, BreakpointChangeRequested);
- scheduleSynchronization();
- } else {
+ if (parts == NoParts) {
it->destroyMarker();
updateMarker(id);
layoutChanged();
+ } else if (it->needsChange() && it->engine && it->state != BreakpointNew) {
+ setState(id, BreakpointChangeRequested);
+ scheduleSynchronization();
}
}
diff --git a/src/plugins/debugger/breakhandler.h b/src/plugins/debugger/breakhandler.h
index bdd1ba6afc..2911748f27 100644
--- a/src/plugins/debugger/breakhandler.h
+++ b/src/plugins/debugger/breakhandler.h
@@ -120,7 +120,8 @@ public:
quint64 address(BreakpointId id) const;
void setAddress(BreakpointId id, const quint64 &address);
int lineNumber(BreakpointId id) const;
- void setBreakpointData(BreakpointId id, const BreakpointParameters &data);
+ void changeBreakpointData(BreakpointId id, const BreakpointParameters &data,
+ BreakpointParts parts);
const BreakpointParameters &breakpointData(BreakpointId id) const;
BreakpointState state(BreakpointId id) const;
bool isEnabled(BreakpointId id) const;
diff --git a/src/plugins/debugger/breakpoint.cpp b/src/plugins/debugger/breakpoint.cpp
index 60369a3b65..8cc3042594 100644
--- a/src/plugins/debugger/breakpoint.cpp
+++ b/src/plugins/debugger/breakpoint.cpp
@@ -57,21 +57,42 @@ BreakpointParameters::BreakpointParameters(BreakpointType t)
tracepoint(false)
{}
+BreakpointParts BreakpointParameters::differencesTo
+ (const BreakpointParameters &rhs) const
+{
+ BreakpointParts parts = BreakpointParts();
+ if (type != rhs.type)
+ parts |= TypePart;
+ if (enabled != rhs.enabled)
+ parts |= EnabledPart;
+ if (pathUsage != rhs.pathUsage)
+ parts |= PathUsagePart;
+ if (fileName != rhs.fileName)
+ parts |= FileAndLinePart;
+ if (conditionsMatch(rhs.condition))
+ parts |= ConditionPart;
+ if (ignoreCount != rhs.ignoreCount)
+ parts |= IgnoreCountPart;
+ if (lineNumber != rhs.lineNumber)
+ parts |= FileAndLinePart;
+ if (address != rhs.address)
+ parts |= AddressPart;
+ if (threadSpec != rhs.threadSpec)
+ parts |= ThreadSpecPart;
+ if (functionName != rhs.functionName)
+ parts |= FunctionPart;
+ if (tracepoint != rhs.tracepoint)
+ parts |= TracePointPart;
+ if (module != rhs.module)
+ parts |= ModulePart;
+ if (command != rhs.command)
+ parts |= CommandPart;
+ return parts;
+}
+
bool BreakpointParameters::equals(const BreakpointParameters &rhs) const
{
- return type == rhs.type
- && enabled == rhs.enabled
- && pathUsage == rhs.pathUsage
- && fileName == rhs.fileName
- && conditionsMatch(rhs.condition)
- && ignoreCount == rhs.ignoreCount
- && lineNumber == rhs.lineNumber
- && address == rhs.address
- && threadSpec == rhs.threadSpec
- && functionName == rhs.functionName
- && tracepoint == rhs.tracepoint
- && module == rhs.module
- && command == rhs.command;
+ return !differencesTo(rhs);
}
bool BreakpointParameters::conditionsMatch(const QByteArray &other) const
diff --git a/src/plugins/debugger/breakpoint.h b/src/plugins/debugger/breakpoint.h
index b005b76248..6d32eaeb36 100644
--- a/src/plugins/debugger/breakpoint.h
+++ b/src/plugins/debugger/breakpoint.h
@@ -87,10 +87,40 @@ enum BreakpointPathUsage
BreakpointUseShortPath //!< Use filename only, in case source files are relocated.
};
+enum BreakpointParts
+{
+ NoParts = 0,
+ FileAndLinePart = 0x1,
+ FunctionPart = 0x2,
+ AddressPart = 0x4,
+ ConditionPart = 0x8,
+ IgnoreCountPart = 0x10,
+ ThreadSpecPart = 0x20,
+ AllConditionParts = ConditionPart|IgnoreCountPart|ThreadSpecPart,
+ ModulePart = 0x40,
+ TracePointPart = 0x80,
+
+ EnabledPart = 0x100,
+ TypePart = 0x200,
+ PathUsagePart = 0x400,
+ CommandPart = 0x400,
+
+ AllParts = FileAndLinePart|FunctionPart|AddressPart|ConditionPart
+ |IgnoreCountPart|ThreadSpecPart|ModulePart|TracePointPart
+ |EnabledPart|TypePart|PathUsagePart|CommandPart
+};
+
+inline void operator|=(BreakpointParts &p, BreakpointParts r)
+{
+ p = BreakpointParts(int(p) | int(r));
+}
+
+
class BreakpointParameters
{
public:
explicit BreakpointParameters(BreakpointType = UnknownType);
+ BreakpointParts differencesTo(const BreakpointParameters &rhs) const;
bool equals(const BreakpointParameters &rhs) const;
bool conditionsMatch(const QByteArray &other) const;
bool isWatchpoint() const { return type == Watchpoint; }
diff --git a/src/plugins/debugger/breakpointmarker.cpp b/src/plugins/debugger/breakpointmarker.cpp
index a88d944ad2..4790870b36 100644
--- a/src/plugins/debugger/breakpointmarker.cpp
+++ b/src/plugins/debugger/breakpointmarker.cpp
@@ -48,8 +48,11 @@ namespace Internal {
BreakpointMarker::BreakpointMarker(BreakpointId id,
const QString &fileName, int lineNumber)
- : BaseTextMark(fileName, lineNumber), m_id(id)
+ : m_id(id)
{
+ setLocation(fileName, lineNumber);
+ setIcon(breakHandler()->icon(m_id));
+ setPriority(TextEditor::ITextMark::NormalPriority);
//qDebug() << "CREATE MARKER " << fileName << lineNumber;
}
@@ -58,16 +61,6 @@ 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);
diff --git a/src/plugins/debugger/breakpointmarker.h b/src/plugins/debugger/breakpointmarker.h
index db74551c70..431ef5b33c 100644
--- a/src/plugins/debugger/breakpointmarker.h
+++ b/src/plugins/debugger/breakpointmarker.h
@@ -44,14 +44,12 @@ namespace Internal {
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);
- TextEditor::ITextMark::Priority priority() const { return TextEditor::ITextMark::NormalPriority; }
private:
BreakpointId m_id;
diff --git a/src/plugins/debugger/breakwindow.cpp b/src/plugins/debugger/breakwindow.cpp
index c9ab460a26..b338f8bc91 100644
--- a/src/plugins/debugger/breakwindow.cpp
+++ b/src/plugins/debugger/breakwindow.cpp
@@ -70,7 +70,7 @@ class BreakpointDialog : public QDialog
Q_OBJECT
public:
explicit BreakpointDialog(unsigned engineCapabilities, QWidget *parent = 0);
- bool showDialog(BreakpointParameters *data);
+ bool showDialog(BreakpointParameters *data, BreakpointParts *parts);
void setParameters(const BreakpointParameters &data);
BreakpointParameters parameters() const;
@@ -388,7 +388,8 @@ void BreakpointDialog::typeChanged(int)
}
}
-bool BreakpointDialog::showDialog(BreakpointParameters *data)
+bool BreakpointDialog::showDialog(BreakpointParameters *data,
+ BreakpointParts *parts)
{
setParameters(*data);
if (exec() != QDialog::Accepted)
@@ -396,7 +397,8 @@ bool BreakpointDialog::showDialog(BreakpointParameters *data)
// Check if changed.
const BreakpointParameters newParameters = parameters();
- if (data->equals(newParameters))
+ *parts = data->differencesTo(newParameters);
+ if (!*parts)
return false;
*data = newParameters;
@@ -654,17 +656,19 @@ void BreakWindow::editBreakpoint(BreakpointId id, QWidget *parent)
unsigned engineCapabilities = AllDebuggerCapabilities;
if (const DebuggerEngine *engine = breakHandler()->engine(id))
engineCapabilities = engine->debuggerCapabilities();
+ BreakpointParts parts = NoParts;
BreakpointDialog dialog(engineCapabilities, parent);
- if (dialog.showDialog(&data))
- breakHandler()->setBreakpointData(id, data);
+ if (dialog.showDialog(&data, &parts))
+ breakHandler()->changeBreakpointData(id, data, parts);
}
void BreakWindow::addBreakpoint()
{
BreakpointParameters data(BreakpointByFileAndLine);
+ BreakpointParts parts = NoParts;
BreakpointDialog dialog(AllDebuggerCapabilities, this);
dialog.setWindowTitle(tr("Add Breakpoint"));
- if (dialog.showDialog(&data))
+ if (dialog.showDialog(&data, &parts))
breakHandler()->appendBreakpoint(data);
}
diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp
index 2b60634ffc..b27f9f1f4a 100644
--- a/src/plugins/debugger/cdb/cdbengine.cpp
+++ b/src/plugins/debugger/cdb/cdbengine.cpp
@@ -182,11 +182,19 @@ struct MemoryChangeCookie
QByteArray data;
};
+struct ConditionalBreakPointCookie
+{
+ ConditionalBreakPointCookie(BreakpointId i = 0) : id(i) {}
+ BreakpointId id;
+ GdbMi stopReason;
+};
+
} // namespace Internal
} // namespace Debugger
Q_DECLARE_METATYPE(Debugger::Internal::MemoryViewCookie)
Q_DECLARE_METATYPE(Debugger::Internal::MemoryChangeCookie)
+Q_DECLARE_METATYPE(Debugger::Internal::ConditionalBreakPointCookie)
namespace Debugger {
namespace Internal {
@@ -300,7 +308,6 @@ static inline bool validMode(DebuggerStartMode sm)
{
switch (sm) {
case NoStartMode:
- case AttachTcf:
case AttachCore:
case StartRemoteGdb:
return false;
@@ -517,17 +524,25 @@ bool CdbEngine::setToolTipExpression(const QPoint &mousePos,
int line;
int column;
DebuggerToolTipContext context = contextIn;
- const QString exp = cppExpressionAt(editor, context.position, &line, &column, &context.function);
+ QString exp = cppExpressionAt(editor, context.position, &line, &column, &context.function);
// Are we in the current stack frame
if (context.function.isEmpty() || exp.isEmpty() || context.function != stackHandler()->currentFrame().function)
return false;
// No numerical or any other expressions [yet]
if (!(exp.at(0).isLetter() || exp.at(0) == QLatin1Char('_')))
return false;
- const QByteArray iname = QByteArray(localsPrefixC) + exp.toAscii();
- const QModelIndex index = watchHandler()->itemIndex(iname);
- if (!index.isValid())
- return false;
+ // Can this be found as a local variable?
+ const QByteArray localsPrefix(localsPrefixC);
+ QByteArray iname = localsPrefix + exp.toAscii();
+ QModelIndex index = watchHandler()->itemIndex(iname);
+ if (!index.isValid()) {
+ // Nope, try a 'local.this.m_foo'.
+ exp.prepend(QLatin1String("this."));
+ iname.insert(localsPrefix.size(), "this.");
+ index = watchHandler()->itemIndex(iname);
+ if (!index.isValid())
+ return false;
+ }
DebuggerTreeViewToolTipWidget *tw = new DebuggerTreeViewToolTipWidget;
tw->setContext(context);
tw->setDebuggerModel(LocalsWatch);
@@ -805,6 +820,7 @@ void CdbEngine::setupInferior()
qDebug("setupInferior");
attemptBreakpointSynchronization();
postCommand("sxn 0x4000001f", 0); // Do not break on WowX86 exceptions.
+ postCommand(".asm source_line", 0); // Source line in assembly
postExtensionCommand("pid", QByteArray(), 0, &CdbEngine::handlePid);
}
@@ -1049,6 +1065,7 @@ unsigned CdbEngine::debuggerCapabilities() const
|WatchpointCapability|JumpToLineCapability|AddWatcherCapability
|ReloadModuleCapability
|BreakOnThrowAndCatchCapability // Sort-of: Can break on throw().
+ |BreakConditionCapability|TracePointCapability
|BreakModuleCapability;
}
@@ -1490,10 +1507,7 @@ void CdbEngine::handleDisassembler(const CdbBuiltinCommandPtr &command)
{
QTC_ASSERT(qVariantCanConvert<DisassemblerAgent*>(command->cookie), return;)
DisassemblerAgent *agent = qvariant_cast<DisassemblerAgent*>(command->cookie);
- DisassemblerLines disassemblerLines;
- foreach(const QByteArray &line, command->reply)
- disassemblerLines.appendLine(DisassemblerLine(QString::fromLatin1(line)));
- agent->setContents(disassemblerLines);
+ agent->setContents(parseCdbDisassembler(command->reply));
}
void CdbEngine::fetchMemory(MemoryAgent *agent, QObject *editor, quint64 addr, quint64 length)
@@ -1642,7 +1656,7 @@ void CdbEngine::handleRegisters(const CdbExtensionCommandPtr &reply)
registers.reserve(value.childCount());
foreach (const GdbMi &gdbmiReg, value.children())
registers.push_back(parseRegister(gdbmiReg));
- registerHandler()->setRegisters(registers);
+ registerHandler()->setAndMarkRegisters(registers);
} else {
showMessage(QString::fromLatin1("Parse error in registers response."), LogError);
qWarning("Parse error in registers response:\n%s", reply->reply.constData());
@@ -1755,9 +1769,25 @@ enum StopActionFlags
StopShutdownInProgress = 0x80 // Shutdown in progress
};
+static inline QString msgTracePointTriggered(BreakpointId id, const int number,
+ const QString &threadId)
+{
+ return CdbEngine::tr("Trace point %1 (%2) in thread %3 triggered.")
+ .arg(id).arg(number).arg(threadId);
+}
+
+static inline QString msgCheckingConditionalBreakPoint(BreakpointId id, const int number,
+ const QByteArray &condition,
+ const QString &threadId)
+{
+ return CdbEngine::tr("Conditional breakpoint %1 (%2) in thread %3 triggered, examining expression '%4'.")
+ .arg(id).arg(number).arg(threadId, QString::fromAscii(condition));
+}
+
unsigned CdbEngine::examineStopReason(const GdbMi &stopReason,
QString *message,
- QString *exceptionBoxMessage)
+ QString *exceptionBoxMessage,
+ bool conditionalBreakPointTriggered)
{
// Report stop reason (GDBMI)
unsigned rc = 0;
@@ -1788,7 +1818,22 @@ unsigned CdbEngine::examineStopReason(const GdbMi &stopReason,
if (breakpointIdG.isValid()) {
id = breakpointIdG.data().toULongLong();
if (id && breakHandler()->engineBreakpointIds(this).contains(id)) {
- number = breakHandler()->response(id).number;
+ const BreakpointResponse parameters = breakHandler()->response(id);
+ // Trace point? Just report.
+ number = parameters.number;
+ if (parameters.tracepoint) {
+ *message = msgTracePointTriggered(id, number, QString::number(threadId));
+ return StopReportLog|StopIgnoreContinue;
+ }
+ // Trigger evaluation of BP expression unless we are already in the response.
+ if (!conditionalBreakPointTriggered && !parameters.condition.isEmpty()) {
+ *message = msgCheckingConditionalBreakPoint(id, number, parameters.condition,
+ QString::number(threadId));
+ ConditionalBreakPointCookie cookie(id);
+ cookie.stopReason = stopReason;
+ evaluateExpression(parameters.condition, qVariantFromValue(cookie));
+ return StopReportLog;
+ }
} else {
id = 0;
}
@@ -1879,14 +1924,19 @@ void CdbEngine::handleSessionIdle(const QByteArray &messageBA)
notifyEngineSetupOk();
return;
}
+ GdbMi stopReason;
+ stopReason.fromString(messageBA);
+ processStop(stopReason, false);
+}
+void CdbEngine::processStop(const GdbMi &stopReason, bool conditionalBreakPointTriggered)
+{
// Further examine stop and report to user
QString message;
QString exceptionBoxMessage;
- GdbMi stopReason;
- stopReason.fromString(messageBA);
int forcedThreadId = -1;
- const unsigned stopFlags = examineStopReason(stopReason, &message, &exceptionBoxMessage);
+ const unsigned stopFlags = examineStopReason(stopReason, &message, &exceptionBoxMessage,
+ conditionalBreakPointTriggered);
// Do the non-blocking log reporting
if (stopFlags & StopReportLog)
showMessage(message, LogMisc);
@@ -1894,7 +1944,7 @@ void CdbEngine::handleSessionIdle(const QByteArray &messageBA)
showStatusMessage(message);
if (stopFlags & StopReportParseError)
showMessage(message, LogError);
- // Ignore things like WOW64
+ // Ignore things like WOW64, report tracepoints.
if (stopFlags & StopIgnoreContinue) {
postCommand("g", 0);
return;
@@ -2513,6 +2563,41 @@ void CdbEngine::handleStackTrace(const CdbExtensionCommandPtr &command)
}
}
+void CdbEngine::handleExpression(const CdbExtensionCommandPtr &command)
+{
+ int value = 0;
+ if (command->success) {
+ value = command->reply.toInt();
+ } else {
+ showMessage(command->errorMessage, LogError);
+ }
+ // Is this a conditional breakpoint?
+ if (command->cookie.isValid() && qVariantCanConvert<ConditionalBreakPointCookie>(command->cookie)) {
+ const ConditionalBreakPointCookie cookie = qvariant_cast<ConditionalBreakPointCookie>(command->cookie);
+ const QString message = value ?
+ tr("Value %1 obtained from evaluating the condition of breakpoint %2, stopping.").
+ arg(value).arg(cookie.id) :
+ tr("Value 0 obtained from evaluating the condition of breakpoint %1, continuing.").
+ arg(cookie.id);
+ showMessage(message, LogMisc);
+ // Stop if evaluation is true, else continue
+ if (value) {
+ processStop(cookie.stopReason, true);
+ } else {
+ postCommand("g", 0);
+ }
+ }
+}
+
+void CdbEngine::evaluateExpression(QByteArray exp, const QVariant &cookie)
+{
+ if (exp.contains(' ') && !exp.startsWith('"')) {
+ exp.prepend('"');
+ exp.append('"');
+ }
+ postExtensionCommand("expression", exp, 0, &CdbEngine::handleExpression, 0, cookie);
+}
+
void CdbEngine::dummyHandler(const CdbBuiltinCommandPtr &command)
{
postCommandSequence(command->commandSequence);
diff --git a/src/plugins/debugger/cdb/cdbengine.h b/src/plugins/debugger/cdb/cdbengine.h
index c934b20499..b1b7b93756 100644
--- a/src/plugins/debugger/cdb/cdbengine.h
+++ b/src/plugins/debugger/cdb/cdbengine.h
@@ -190,7 +190,9 @@ private:
bool startConsole(const DebuggerStartParameters &sp, QString *errorMessage);
void init();
unsigned examineStopReason(const GdbMi &stopReason, QString *message,
- QString *exceptionBoxMessage);
+ QString *exceptionBoxMessage,
+ bool conditionalBreakPointTriggered = false);
+ void processStop(const GdbMi &stopReason, bool conditionalBreakPointTriggered = false);
bool commandsPending() const;
void handleExtensionMessage(char t, int token, const QByteArray &what, const QByteArray &message);
bool doSetupEngine(QString *errorMessage);
@@ -207,6 +209,7 @@ private:
void syncOperateByInstruction(bool operateByInstruction);
void postWidgetAtCommand();
void handleCustomSpecialStop(const QVariant &v);
+ void evaluateExpression(QByteArray exp, const QVariant &cookie = QVariant());
// Builtin commands
void dummyHandler(const CdbBuiltinCommandPtr &);
@@ -214,6 +217,7 @@ private:
void handleRegisters(const CdbBuiltinCommandPtr &);
void handleDisassembler(const CdbBuiltinCommandPtr &);
void handleJumpToLineAddressResolution(const CdbBuiltinCommandPtr &);
+ void handleExpression(const CdbExtensionCommandPtr &);
void jumpToAddress(quint64 address);
// Extension commands
void handleThreads(const CdbExtensionCommandPtr &);
diff --git a/src/plugins/debugger/cdb/cdbparsehelpers.cpp b/src/plugins/debugger/cdb/cdbparsehelpers.cpp
index a4d1e7ccbe..cca3c675ab 100644
--- a/src/plugins/debugger/cdb/cdbparsehelpers.cpp
+++ b/src/plugins/debugger/cdb/cdbparsehelpers.cpp
@@ -36,19 +36,22 @@
#include "registerhandler.h"
#include "bytearrayinputstream.h"
#include "gdb/gdbmi.h"
+#include "disassemblerlines.h"
#ifdef Q_OS_WIN
# include "shared/dbgwinutils.h"
#endif
+#include <utils/qtcassert.h>
+
#include <QtCore/QByteArray>
#include <QtCore/QVariant>
#include <QtCore/QString>
#include <QtCore/QDir>
#include <QtCore/QDebug>
-#include <utils/qtcassert.h>
-
#include <cctype>
+enum { debugDisAsm = 0 };
+
namespace Debugger {
namespace Internal {
@@ -434,5 +437,157 @@ QDebug operator<<(QDebug s, const WinException &e)
return s;
}
+/*!
+ \fn DisassemblerLines parseCdbDisassembler(const QList<QByteArray> &a)
+
+ \brief Parse CDB disassembler output into DisassemblerLines (with helpers)
+
+ Expected options (prepend source file line):
+ \code
+ .asm source_line
+ .lines
+ \endcode
+
+ should cause the 'u' command to produce:
+
+ \code
+gitgui!Foo::MainWindow::on_actionPtrs_triggered+0x1f9 [c:\qt\projects\gitgui\app\mainwindow.cpp @ 758]:
+ 225 00000001`3fcebfe9 488b842410050000 mov rax,qword ptr [rsp+510h]
+ 225 00000001`3fcebff1 8b4030 mov eax,dword ptr [rax+30h]
+ 226 00000001`3fcebff4 ffc0 inc eax
+ 00000001`3fcebff6 488b8c2410050000 mov rcx,qword ptr [rsp+510h]
+...
+QtCored4!QTextStreamPrivate::putString+0x34:
+ 10 00000000`6e5e7f64 90 nop
+...
+\endcode
+
+ The algorithm checks for a function line and grabs the function name, offset and (optional)
+ source file from it.
+ Instruction lines are checked for address and source line number.
+ When the source line changes, the source instruction is inserted.
+*/
+
+// Parse a function header line: Match: 'nsp::foo+0x<offset> [<file> @ <line>]:'
+// or 'nsp::foo+0x<offset>:', 'nsp::foo [<file> @ <line>]:'
+// Do not use regexp here as it is hard for functions like operator+, operator[].
+bool parseCdbDisassemblerFunctionLine(const QString &l,
+ QString *currentFunction, quint64 *functionOffset,
+ QString *sourceFile)
+{
+ if (l.isEmpty() || !l.endsWith(QLatin1Char(':')) || l.at(0).isDigit() || l.at(0).isSpace())
+ return false;
+ int functionEnd = l.indexOf(QLatin1Char(' '));
+ if (functionEnd < 0)
+ functionEnd = l.size() - 1; // Nothing at all, just ':'
+ const int offsetPos = l.indexOf(QLatin1String("+0x"));
+ if (offsetPos > 0) {
+ *currentFunction = l.left(offsetPos);
+ *functionOffset = l.mid(offsetPos + 3, functionEnd - offsetPos - 3).trimmed().toULongLong(0, 16);
+ } else { // No offset, directly at beginning.
+ *currentFunction = l.left(functionEnd);
+ *functionOffset = 0;
+ }
+ sourceFile->clear();
+ // Parse file and line.
+ const int filePos = l.indexOf(QLatin1Char('['), functionEnd);
+ if (filePos == -1)
+ return true; // No file
+ const int linePos = l.indexOf(QLatin1String(" @ "), filePos + 1);
+ if (linePos == -1)
+ return false;
+ *sourceFile = l.mid(filePos + 1, linePos - filePos - 1).trimmed();
+ if (debugDisAsm)
+ qDebug() << "Function with source: " << l << currentFunction
+ << functionOffset << sourceFile;
+ return true;
+}
+
+// Parse an instruction line:
+// ' 21 00000001`3fcebff1 8b4030 mov eax,dword ptr [rax+30h]'
+// '<source_line> <address> <raw data> <instruction>
+bool parseCdbDisassemblerLine(const QString &lineIn, DisassemblerLine *dLine, uint *sourceLine)
+{
+ *sourceLine = 0;
+ if (lineIn.size() < 6)
+ return false;
+ // Check source line: right-padded 5 digits
+ const bool hasSourceLine = lineIn.at(4).isDigit();
+ const QString line = lineIn.trimmed();
+ int addressPos = 0;
+ const QChar blank = QLatin1Char(' ');
+ // Optional source line.
+ if (hasSourceLine) {
+ const int sourceLineEnd = line.indexOf(blank);
+ if (sourceLineEnd == -1)
+ return false;
+ *sourceLine = line.left(sourceLineEnd).toUInt();
+ addressPos = sourceLineEnd + 1;
+ }
+ // Find positions of address/raw data/instruction
+ const int addressEnd = line.indexOf(blank, addressPos + 1);
+ if (addressEnd < 0)
+ return false;
+ const int rawDataPos = addressEnd + 1;
+ const int rawDataEnd = line.indexOf(blank, rawDataPos + 1);
+ if (rawDataEnd < 0)
+ return false;
+ const int instructionPos = rawDataEnd + 1;
+ bool ok;
+ QString addressS = line.mid(addressPos, addressEnd - addressPos);
+ if (addressS.size() > 9 && addressS.at(8) == QLatin1Char('`'))
+ addressS.remove(8, 1);
+ dLine->address = addressS.toULongLong(&ok, 16);
+ if (!ok)
+ return false;
+ dLine->rawData = QByteArray::fromHex(line.mid(rawDataPos, rawDataEnd - rawDataPos).toAscii());
+ dLine->data = line.right(line.size() - instructionPos).trimmed();
+ return true;
+}
+
+DisassemblerLines parseCdbDisassembler(const QList<QByteArray> &a)
+{
+ DisassemblerLines result;
+ quint64 functionAddress = 0;
+ uint lastSourceLine = 0;
+ QString currentFunction;
+ quint64 functionOffset = 0;
+ QString sourceFile;
+
+ foreach (const QByteArray &lineBA, a) {
+ const QString line = QString::fromLatin1(lineBA);
+ // New function. Append as comment line.
+ if (parseCdbDisassemblerFunctionLine(line, &currentFunction, &functionOffset, &sourceFile)) {
+ functionAddress = 0;
+ DisassemblerLine commentLine;
+ commentLine.data = line;
+ result.appendLine(commentLine);
+ } else {
+ DisassemblerLine disassemblyLine;
+ uint sourceLine;
+ if (parseCdbDisassemblerLine(line, &disassemblyLine, &sourceLine)) {
+ // New source line: Add source code if available.
+ if (sourceLine && sourceLine != lastSourceLine) {
+ lastSourceLine = sourceLine;
+ result.appendSourceLine(sourceFile, sourceLine);
+ }
+ } else {
+ qWarning("Unable to parse assembly line '%s'", lineBA.constData());
+ disassemblyLine.fromString(line);
+ }
+ // Determine address of function from the first assembler line after a
+ // function header line.
+ if (!functionAddress && disassemblyLine.address) {
+ functionAddress = disassemblyLine.address - functionOffset;
+ }
+ if (functionAddress && disassemblyLine.address)
+ disassemblyLine.offset = disassemblyLine.address - functionAddress;
+ disassemblyLine.function = currentFunction;
+ result.appendLine(disassemblyLine);
+ }
+ }
+ return result;
+}
+
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/cdb/cdbparsehelpers.h b/src/plugins/debugger/cdb/cdbparsehelpers.h
index edbb3502b6..3ef8c12f84 100644
--- a/src/plugins/debugger/cdb/cdbparsehelpers.h
+++ b/src/plugins/debugger/cdb/cdbparsehelpers.h
@@ -53,6 +53,7 @@ class BreakpointParameters;
struct ThreadData;
class Register;
class GdbMi;
+class DisassemblerLines;
// Perform mapping on parts of the source tree as reported by/passed to debugger
// in case the user has specified such mappings in the global settings.
@@ -80,6 +81,8 @@ QByteArray cdbWriteMemoryCommand(quint64 addr, const QByteArray &data);
QString debugByteArray(const QByteArray &a);
QString StringFromBase64EncodedUtf16(const QByteArray &a);
+DisassemblerLines parseCdbDisassembler(const QList<QByteArray> &a);
+
// Model EXCEPTION_RECORD + firstchance
struct WinException
{
diff --git a/src/plugins/debugger/commonoptionspage.cpp b/src/plugins/debugger/commonoptionspage.cpp
index 36f5dd33e5..8a2591003d 100644
--- a/src/plugins/debugger/commonoptionspage.cpp
+++ b/src/plugins/debugger/commonoptionspage.cpp
@@ -72,6 +72,8 @@ CommonOptionsPageWidget::CommonOptionsPageWidget
m_ui.checkBoxCloseBuffersOnExit);
m_group->insert(dc->action(SwitchModeOnExit),
m_ui.checkBoxSwitchModeOnExit);
+ m_group->insert(dc->action(FontSizeFollowsEditor),
+ m_ui.checkBoxFontSizeFollowsEditor);
m_group->insert(dc->action(AutoDerefPointers), 0);
m_group->insert(dc->action(UseToolTipsInLocalsView), 0);
m_group->insert(dc->action(AlwaysAdjustLocalsColumnWidths), 0);
@@ -109,6 +111,7 @@ QString CommonOptionsPageWidget::searchKeyWords() const
const QLatin1Char sep(' ');
QTextStream(&rc)
<< sep << m_ui.checkBoxUseAlternatingRowColors->text()
+ << sep << m_ui.checkBoxFontSizeFollowsEditor->text()
<< sep << m_ui.checkBoxUseToolTipsInMainEditor->text()
<< sep << m_ui.checkBoxListSourceFiles->text()
#ifdef Q_OS_WIN
diff --git a/src/plugins/debugger/commonoptionspage.ui b/src/plugins/debugger/commonoptionspage.ui
index 38547eb8a2..2051f59f5a 100644
--- a/src/plugins/debugger/commonoptionspage.ui
+++ b/src/plugins/debugger/commonoptionspage.ui
@@ -25,13 +25,23 @@
</widget>
</item>
<item row="2" column="0" colspan="2">
+ <widget class="QCheckBox" name="checkBoxFontSizeFollowsEditor">
+ <property name="text">
+ <string>Debugger font size follows main editor</string>
+ </property>
+ <property name="toolTip">
+ <string>Selecting this results in font size changes in the debugger views whenever the font size in the main editor changes.</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="checkBoxUseToolTipsInMainEditor">
<property name="text">
<string>Use tooltips in main editor while debugging</string>
</property>
</widget>
</item>
- <item row="3" column="0" colspan="2">
+ <item row="4" column="0" colspan="2">
<widget class="QCheckBox" name="checkBoxListSourceFiles">
<property name="toolTip">
<string>Checking this will populate the source file view automatically but might slow down debugger startup considerably.</string>
@@ -41,7 +51,7 @@
</property>
</widget>
</item>
- <item row="4" column="0" colspan="2">
+ <item row="5" column="0" colspan="2">
<widget class="QCheckBox" name="checkBoxRegisterForPostMortem">
<property name="toolTip">
<string>Register Qt Creator for debugging crashed applications.</string>
@@ -51,7 +61,7 @@
</property>
</widget>
</item>
- <item row="5" column="0" colspan="2">
+ <item row="6" column="0" colspan="2">
<widget class="QCheckBox" name="checkBoxCloseBuffersOnExit">
<property name="toolTip">
<string>Close temporary buffers on debugger exit.</string>
@@ -61,7 +71,7 @@
</property>
</widget>
</item>
- <item row="6" column="0" colspan="2">
+ <item row="7" column="0" colspan="2">
<widget class="QCheckBox" name="checkBoxSwitchModeOnExit">
<property name="toolTip">
<string>Switch to previous mode on debugger exit.</string>
@@ -71,7 +81,7 @@
</property>
</widget>
</item>
- <item row="7" column="0">
+ <item row="8" column="0">
<widget class="QLabel" name="labelMaximalStackDepth">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
@@ -84,7 +94,7 @@
</property>
</widget>
</item>
- <item row="7" column="1">
+ <item row="9" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSpinBox" name="spinBoxMaximalStackDepth">
diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro
index 7667804352..e77b89d19a 100644
--- a/src/plugins/debugger/debugger.pro
+++ b/src/plugins/debugger/debugger.pro
@@ -63,7 +63,8 @@ HEADERS += breakhandler.h \
debuggerruncontrolfactory.h \
debuggertooltipmanager.h \
debuggertoolchaincombobox.h \
- debuggersourcepathmappingwidget.h
+ debuggersourcepathmappingwidget.h \
+ memoryviewwidget.h
SOURCES += breakhandler.cpp \
breakpoint.cpp \
@@ -106,7 +107,8 @@ SOURCES += breakhandler.cpp \
watchdelegatewidgets.cpp \
debuggertooltipmanager.cpp \
debuggertoolchaincombobox.cpp \
- debuggersourcepathmappingwidget.cpp
+ debuggersourcepathmappingwidget.cpp \
+ memoryviewwidget.cpp
FORMS += attachexternaldialog.ui \
attachcoredialog.ui \
diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp
index 74f8f36ea3..f10cbb393f 100644
--- a/src/plugins/debugger/debuggeractions.cpp
+++ b/src/plugins/debugger/debuggeractions.cpp
@@ -176,6 +176,13 @@ DebuggerSettings::DebuggerSettings(QSettings *settings)
insertItem(UseAlternatingRowColors, item);
item = new SavedAction(this);
+ item->setText(tr("Debugger Font Size Follows Main Editor"));
+ item->setSettingsKey(debugModeGroup, QLatin1String("FontSizeFollowsEditor"));
+ item->setCheckable(true);
+ item->setDefaultValue(false);
+ insertItem(FontSizeFollowsEditor, item);
+
+ item = new SavedAction(this);
item->setText(tr("Show a Message Box When Receiving a Signal"));
item->setSettingsKey(debugModeGroup, QLatin1String("UseMessageBoxForSignals"));
item->setCheckable(true);
diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h
index eaa9c52d92..c59e22939c 100644
--- a/src/plugins/debugger/debuggeractions.h
+++ b/src/plugins/debugger/debuggeractions.h
@@ -90,6 +90,7 @@ enum DebuggerActionCode
// General
SettingsDialog,
UseAlternatingRowColors,
+ FontSizeFollowsEditor,
UseMessageBoxForSignals,
AutoQuit,
LockView,
diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h
index f226227c06..1ad90617dc 100644
--- a/src/plugins/debugger/debuggerconstants.h
+++ b/src/plugins/debugger/debuggerconstants.h
@@ -53,8 +53,6 @@ const char * const NEXT = "Debugger.NextLine";
const char * const REVERSE = "Debugger.ReverseDirection";
const char * const OPERATE_BY_INSTRUCTION = "Debugger.OperateByInstruction";
-const char * const M_DEBUG_VIEWS = "Debugger.Menu.View.Debug";
-
const char * const C_DEBUGMODE = "Debugger.DebugMode";
const char * const C_CPPDEBUGGER = "Gdb Debugger";
const char * const C_QMLDEBUGGER = "Qml/JavaScript Debugger";
@@ -70,7 +68,6 @@ const char * const DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON =
// 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";
@@ -149,7 +146,6 @@ enum DebuggerStartMode
StartExternal, // Start binary found in file system
AttachExternal, // Attach to running process by process id
AttachCrashedExternal, // Attach to crashed process by process id
- 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
@@ -219,6 +215,7 @@ enum ModelRoles
LocalsTypeFormatRole, // Used to communicate alternative formats to the view
LocalsIndividualFormatRole,
LocalsAddressRole, // Memory address of variable as quint64
+ LocalsSizeRole, // Size of variable as quint
LocalsRawValueRole, // Unformatted value as string
LocalsPointerValueRole, // Pointer value (address) as quint64
LocalsIsWatchpointAtAddressRole,
@@ -235,7 +232,6 @@ enum DebuggerEngineType
ScriptEngineType = 0x02,
CdbEngineType = 0x04,
PdbEngineType = 0x08,
- TcfEngineType = 0x10,
QmlEngineType = 0x20,
QmlCppEngineType = 0x40,
LldbEngineType = 0x80,
@@ -243,7 +239,6 @@ enum DebuggerEngineType
| ScriptEngineType
| CdbEngineType
| PdbEngineType
- | TcfEngineType
| QmlEngineType
| QmlCppEngineType
| LldbEngineType
diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp
index 93f0eefffc..db3bdd32d3 100644
--- a/src/plugins/debugger/debuggerengine.cpp
+++ b/src/plugins/debugger/debuggerengine.cpp
@@ -124,29 +124,6 @@ QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
}
-///////////////////////////////////////////////////////////////////////
-//
-// LocationMark
-//
-///////////////////////////////////////////////////////////////////////
-
-// Used in "real" editors
-class LocationMark : public TextEditor::BaseTextMark
-{
-public:
- LocationMark(const QString &fileName, int linenumber)
- : BaseTextMark(fileName, linenumber)
- {}
-
- QIcon icon() const { return debuggerCore()->locationMarkIcon(); }
- void updateLineNumber(int /*lineNumber*/) {}
- void updateBlock(const QTextBlock & /*block*/) {}
- void removedFromEditor() {}
- TextEditor::ITextMark::Priority priority() const { return TextEditor::ITextMark::HighPriority; }
-};
-
-
-
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
@@ -587,8 +564,12 @@ void DebuggerEngine::gotoLocation(const Location &loc)
if (texteditor)
texteditor->gotoLine(line, 0);
- if (loc.needsMarker())
- d->m_locationMark.reset(new LocationMark(file, line));
+ if (loc.needsMarker()) {
+ d->m_locationMark.reset(new TextEditor::BaseTextMark);
+ d->m_locationMark->setLocation(file, line);
+ d->m_locationMark->setIcon(debuggerCore()->locationMarkIcon());
+ d->m_locationMark->setPriority(TextEditor::ITextMark::HighPriority);
+ }
// FIXME: Breaks with split views.
if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
@@ -1591,6 +1572,11 @@ void DebuggerEngine::openMemoryView(quint64 address)
d->m_memoryAgent.createBinEditor(address);
}
+void DebuggerEngine::addMemoryView(Internal::MemoryViewWidget *w)
+{
+ d->m_memoryAgent.addMemoryView(w);
+}
+
void DebuggerEngine::updateMemoryViews()
{
d->m_memoryAgent.updateContents();
diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h
index 04e0b76b27..a717cfd068 100644
--- a/src/plugins/debugger/debuggerengine.h
+++ b/src/plugins/debugger/debuggerengine.h
@@ -81,6 +81,7 @@ class WatchHandler;
class BreakpointParameters;
class QmlCppEngine;
class DebuggerToolTipContext;
+class MemoryViewWidget;
struct WatchUpdateFlags
{
@@ -156,6 +157,7 @@ public:
virtual void watchPoint(const QPoint &);
virtual void openMemoryView(quint64 addr);
+ virtual void addMemoryView(Internal::MemoryViewWidget *w);
virtual void fetchMemory(Internal::MemoryAgent *, QObject *,
quint64 addr, quint64 length);
virtual void changeMemory(Internal::MemoryAgent *, QObject *,
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index 15c5dd3b6a..2874bd41b8 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -47,7 +47,7 @@
#include "breakhandler.h"
#include "breakwindow.h"
#include "consolewindow.h"
-#include "disassembleragent.h"
+#include "disassemblerlines.h"
#include "logwindow.h"
#include "moduleswindow.h"
#include "moduleshandler.h"
@@ -494,7 +494,16 @@ public:
class DebugMode : public IMode
{
public:
- DebugMode() : m_widget(0) { setObjectName(QLatin1String("DebugMode")); }
+ DebugMode()
+ {
+ setObjectName(QLatin1String("DebugMode"));
+ setContext(Context(CC::C_EDITORMANAGER, C_DEBUGMODE, CC::C_NAVIGATION_PANE));
+ setDisplayName(DebuggerPlugin::tr("Debug"));
+ setIcon(QIcon(QLatin1String(":/fancyactionbar/images/mode_Debug.png")));
+ setPriority(P_MODE_DEBUG);
+ setId(MODE_DEBUG);
+ setType(CC::MODE_EDIT_TYPE);
+ }
~DebugMode()
{
@@ -502,19 +511,6 @@ public:
//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;
};
@@ -1234,10 +1230,6 @@ bool DebuggerPluginPrivate::parseArgument(QStringList::const_iterator &it,
*enabledEngines &= ~ScriptEngineType;
return true;
}
- if (option == _("-disable-tcf")) {
- *enabledEngines &= ~TcfEngineType;
- return true;
- }
if (option == _("-disable-lldb")) {
*enabledEngines &= ~LldbEngineType;
return true;
@@ -1260,7 +1252,6 @@ bool DebuggerPluginPrivate::parseArguments(const QStringList &args,
return true;
}
-
bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
QString *errorMessage)
{
@@ -1626,7 +1617,7 @@ void DebuggerPluginPrivate::requestContextMenu(ITextEditor *editor,
.section('\n', lineNumber - 1, lineNumber - 1);
BreakpointResponse needle;
needle.type = BreakpointByAddress;
- needle.address = DisassemblerAgent::addressFromDisassemblyLine(line);
+ needle.address = DisassemblerLine::addressFromDisassemblyLine(line);
args.address = needle.address;
needle.lineNumber = -1;
id = breakHandler()->findSimilarBreakpoint(needle);
@@ -1709,7 +1700,7 @@ void DebuggerPluginPrivate::toggleBreakpoint()
if (textEditor->property("DisassemblerView").toBool()) {
QString line = textEditor->contents()
.section('\n', lineNumber - 1, lineNumber - 1);
- quint64 address = DisassemblerAgent::addressFromDisassemblyLine(line);
+ quint64 address = DisassemblerLine::addressFromDisassemblyLine(line);
toggleBreakpointByAddress(address);
} else if (lineNumber >= 0) {
toggleBreakpointByFileAndLine(textEditor->file()->fileName(), lineNumber);
@@ -1756,7 +1747,7 @@ void DebuggerPluginPrivate::requestMark(ITextEditor *editor, int lineNumber)
if (editor->property("DisassemblerView").toBool()) {
QString line = editor->contents()
.section('\n', lineNumber - 1, lineNumber - 1);
- quint64 address = DisassemblerAgent::addressFromDisassemblyLine(line);
+ quint64 address = DisassemblerLine::addressFromDisassemblyLine(line);
toggleBreakpointByAddress(address);
} else if (editor->file()) {
toggleBreakpointByFileAndLine(editor->file()->fileName(), lineNumber);
@@ -1822,6 +1813,8 @@ static void changeFontSize(QWidget *widget, qreal size)
void DebuggerPluginPrivate::fontSettingsChanged
(const TextEditor::FontSettings &settings)
{
+ if (!boolSetting(FontSizeFollowsEditor))
+ return;
qreal size = settings.fontZoom() * settings.fontSize() / 100.;
changeFontSize(m_breakWindow, size);
changeFontSize(m_logWindow, size);
@@ -2949,7 +2942,12 @@ void DebuggerPluginPrivate::extensionsInitialized()
// Debug mode setup
- m_plugin->addAutoReleasedObject(new DebugMode);
+ DebugMode *debugMode = new DebugMode;
+ QWidget *widget = m_mainWindow->createContents(debugMode);
+ widget->setFocusProxy(EditorManager::instance());
+ debugMode->setWidget(widget);
+
+ m_plugin->addAutoReleasedObject(debugMode);
//
// Connections
@@ -3164,16 +3162,6 @@ QAction *DebuggerPlugin::visibleDebugAction()
return theDebuggerCore->m_visibleDebugAction;
}
-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;
-}
-
} // namespace Debugger
#include "debuggerplugin.moc"
diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp
index 752ef20711..b0b2b60e04 100644
--- a/src/plugins/debugger/debuggerrunner.cpp
+++ b/src/plugins/debugger/debuggerrunner.cpp
@@ -110,8 +110,6 @@ static const char *engineTypeName(DebuggerEngineType et)
return "Cdb engine";
case Debugger::PdbEngineType:
return "Pdb engine";
- case Debugger::TcfEngineType:
- return "Tcf engine";
case Debugger::QmlEngineType:
return "QML engine";
case Debugger::QmlCppEngineType:
@@ -225,6 +223,11 @@ QString DebuggerRunControl::displayName() const
return d->m_engine->startParameters().displayName;
}
+QIcon DebuggerRunControl::icon() const
+{
+ return QIcon(ProjectExplorer::Constants::ICON_DEBUG_SMALL);
+}
+
void DebuggerRunControl::setCustomEnvironment(Utils::Environment env)
{
QTC_ASSERT(d->m_engine, return);
@@ -244,12 +247,12 @@ void DebuggerRunControl::start()
d->m_engine->startDebugger(this);
if (d->m_running)
- appendMessage(tr("Debugging starts"), NormalMessageFormat);
+ appendMessage(tr("Debugging starts\n"), NormalMessageFormat);
}
void DebuggerRunControl::startFailed()
{
- appendMessage(tr("Debugging has failed"), NormalMessageFormat);
+ appendMessage(tr("Debugging has failed\n"), NormalMessageFormat);
d->m_running = false;
emit finished();
d->m_engine->handleStartFailed();
@@ -257,7 +260,7 @@ void DebuggerRunControl::startFailed()
void DebuggerRunControl::handleFinished()
{
- appendMessage(tr("Debugging has finished"), NormalMessageFormat);
+ appendMessage(tr("Debugging has finished\n"), NormalMessageFormat);
if (d->m_engine)
d->m_engine->handleFinished();
debuggerCore()->runControlFinished(d->m_engine);
@@ -404,10 +407,10 @@ static QList<DebuggerEngineType> enginesForMode(DebuggerStartMode startMode,
{
QList<DebuggerEngineType> result;
switch (startMode) {
- case Debugger::NoStartMode:
+ case NoStartMode:
break;
- case Debugger::StartInternal:
- case Debugger::StartExternal:
+ case StartInternal:
+ case StartExternal:
case AttachExternal:
if (!hardConstraintsOnly) {
#ifdef Q_OS_WIN
@@ -416,11 +419,11 @@ static QList<DebuggerEngineType> enginesForMode(DebuggerStartMode startMode,
result.push_back(GdbEngineType);
}
break;
- case Debugger::AttachCore:
- case Debugger::StartRemoteGdb:
+ case AttachCore:
+ case StartRemoteGdb:
result.push_back(GdbEngineType);
break;
- case Debugger::AttachToRemote:
+ case AttachToRemote:
if (!hardConstraintsOnly) {
#ifdef Q_OS_WIN
result.push_back(CdbEngineType);
@@ -428,9 +431,6 @@ static QList<DebuggerEngineType> enginesForMode(DebuggerStartMode startMode,
result.push_back(GdbEngineType);
}
break;
- case AttachTcf:
- result.push_back(TcfEngineType);
- break;
case AttachCrashedExternal:
result.push_back(CdbEngineType); // Only CDB can do this
break;
@@ -487,7 +487,9 @@ ConfigurationCheck::ConfigurationCheck() :
ConfigurationCheck::operator bool() const
{
- return errorMessage.isEmpty() && errorDetails.isEmpty() && masterSlaveEngineTypes.first != NoEngineType;
+ return errorMessage.isEmpty()
+ && errorDetails.isEmpty()
+ && masterSlaveEngineTypes.first != NoEngineType;
}
QString ConfigurationCheck::errorDetailsString() const
@@ -510,9 +512,9 @@ static inline bool canUseEngine(DebuggerEngineType et,
}
// Configured.
switch (et) {
- case Debugger::CdbEngineType:
+ case CdbEngineType:
return checkCdbConfiguration(sp, result);
- case Debugger::GdbEngineType:
+ case GdbEngineType:
return checkGdbConfiguration(sp, result);
default:
break;
@@ -521,8 +523,7 @@ static inline bool canUseEngine(DebuggerEngineType et,
}
/*!
- \fn ConfigurationCheck checkDebugConfiguration(unsigned cmdLineEnabledEngines,
- const DebuggerStartParameters &sp)
+ \fn Debugger::ConfigurationCheck Debugger::checkDebugConfiguration(const DebuggerStartParameters &sp)
This is the master engine detection function that returns the
engine types for a given set of start parameters and checks their
@@ -753,11 +754,11 @@ DebuggerRunControl *DebuggerRunControlFactory::create
return new DebuggerRunControl(runConfiguration, sp, check.masterSlaveEngineTypes);
}
-DebuggerEngine *
- DebuggerRunControlFactory::createEngine(DebuggerEngineType et,
- const DebuggerStartParameters &sp,
- DebuggerEngine *masterEngine,
- QString *errorMessage)
+DebuggerEngine *DebuggerRunControlFactory::createEngine
+ (DebuggerEngineType et,
+ const DebuggerStartParameters &sp,
+ DebuggerEngine *masterEngine,
+ QString *errorMessage)
{
switch (et) {
case GdbEngineType:
@@ -766,13 +767,10 @@ DebuggerEngine *
return createScriptEngine(sp);
case CdbEngineType:
return createCdbEngine(sp, masterEngine, errorMessage);
- break;
case PdbEngineType:
return createPdbEngine(sp);
- break;
case QmlEngineType:
return createQmlEngine(sp, masterEngine);
- break;
case LldbEngineType:
return createLldbEngine(sp);
default:
diff --git a/src/plugins/debugger/debuggerrunner.h b/src/plugins/debugger/debuggerrunner.h
index 37b52240a3..adbf15b5f1 100644
--- a/src/plugins/debugger/debuggerrunner.h
+++ b/src/plugins/debugger/debuggerrunner.h
@@ -95,6 +95,7 @@ public:
StopResult stop(); // Called from SnapshotWindow.
bool isRunning() const;
QString displayName() const;
+ QIcon icon() const;
void setCustomEnvironment(Utils::Environment env);
void startFailed();
diff --git a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp
index e471cfadf6..38c545c562 100644
--- a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp
+++ b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp
@@ -52,15 +52,15 @@
// Qt's various build paths for unpatched versions.
#if defined(Q_OS_WIN)
-static const char *qtBuildPaths[] = {
- "C:/qt-greenhouse/Trolltech/Code_less_create_more/Trolltech/Code_less_create_more/Troll/4.6/qt",
+static const char* qtBuildPaths[] = {
+ "C:/qt-greenhouse/Trolltech/Code_less_create_more/"
+ "Trolltech/Code_less_create_more/Troll/4.6/qt",
"C:/iwmake/build_mingw_opensource",
- "C:/ndk_buildrepos/qt-desktop/src"
-};
+ "C:/ndk_buildrepos/qt-desktop/src"};
#elif defined(Q_OS_MAC)
-static const char *qtBuildPaths[] = {};
+static const char* qtBuildPaths[] = {};
#else
-static const char *qtBuildPaths[] = {"/var/tmp/qt-src"};
+static const char* qtBuildPaths[] = {"/var/tmp/qt-src"};
#endif
enum { SourceColumn, TargetColumn, ColumnCount };
@@ -68,8 +68,11 @@ enum { SourceColumn, TargetColumn, ColumnCount };
namespace Debugger {
namespace Internal {
+typedef QPair<QString, QString> Mapping;
+typedef DebuggerSourcePathMappingWidget::SourcePathMap SourcePathMap;
+
/*!
- \class SourcePathMappingModel
+ \class Debugger::Internal::SourcePathMappingModel
\brief Model for DebuggerSourcePathMappingWidget.
@@ -79,8 +82,6 @@ namespace Internal {
class SourcePathMappingModel : public QStandardItemModel
{
public:
- typedef QPair<QString, QString> Mapping;
- typedef DebuggerSourcePathMappingWidget::SourcePathMap SourcePathMap;
explicit SourcePathMappingModel(QObject *parent);
@@ -119,11 +120,11 @@ SourcePathMappingModel::SourcePathMappingModel(QObject *parent) :
setHorizontalHeaderLabels(headers);
}
-SourcePathMappingModel::SourcePathMap SourcePathMappingModel::sourcePathMap() const
+SourcePathMap SourcePathMappingModel::sourcePathMap() const
{
SourcePathMap rc;
const int rows = rowCount();
- for (int r = 0; r != rows; ++r) {
+ for (int r = 0; r < rows; ++r) {
const QPair<QString, QString> m = mappingAt(r); // Skip placeholders.
if (!m.first.isEmpty() && !m.second.isEmpty())
rc.insert(m.first, m.second);
@@ -136,27 +137,26 @@ bool SourcePathMappingModel::isNewPlaceHolder(const Mapping &m) const
{
const QLatin1Char lessThan('<');
const QLatin1Char greaterThan('<');
- return m.first.isEmpty()
- || m.first.startsWith(lessThan)
+ return m.first.isEmpty() || m.first.startsWith(lessThan)
|| m.first.endsWith(greaterThan)
|| m.first == m_newSourcePlaceHolder
- || m.second.isEmpty()
- || m.second.startsWith(lessThan)
+ || m.second.isEmpty() || m.second.startsWith(lessThan)
|| m.second.endsWith(greaterThan)
|| m.second == m_newTargetPlaceHolder;
}
// Return raw, unfixed mapping
-SourcePathMappingModel::Mapping SourcePathMappingModel::rawMappingAt(int row) const
+Mapping SourcePathMappingModel::rawMappingAt(int row) const
{
return Mapping(item(row, SourceColumn)->text(), item(row, TargetColumn)->text());
}
// Return mapping, empty if it is the place holder.
-SourcePathMappingModel::Mapping SourcePathMappingModel::mappingAt(int row) const
+Mapping SourcePathMappingModel::mappingAt(int row) const
{
const Mapping raw = rawMappingAt(row);
- return isNewPlaceHolder(raw) ? Mapping() : Mapping(QDir::cleanPath(raw.first), QDir::cleanPath(raw.second));
+ return isNewPlaceHolder(raw) ? Mapping()
+ : Mapping(QDir::cleanPath(raw.first), QDir::cleanPath(raw.second));
}
void SourcePathMappingModel::setSourcePathMap(const SourcePathMap &m)
@@ -193,7 +193,7 @@ void SourcePathMappingModel::setTarget(int row, const QString &t)
}
/*!
- \class DebuggerSourcePathMappingWidget
+ \class Debugger::Internal::DebuggerSourcePathMappingWidget
\brief Widget for maintaining a set of source path mappings for the debugger.
@@ -203,32 +203,37 @@ void SourcePathMappingModel::setTarget(int row, const QString &t)
DebuggerSourcePathMappingWidget::DebuggerSourcePathMappingWidget(QWidget *parent) :
QGroupBox(parent),
m_model(new SourcePathMappingModel(this)),
- m_treeView(new QTreeView),
- m_addButton(new QPushButton(tr("Add"))),
- m_addQtButton(new QPushButton(tr("Add Qt sources..."))),
- m_removeButton(new QPushButton(tr("Remove"))),
- m_sourceLineEdit(new QLineEdit),
- m_targetChooser(new Utils::PathChooser)
+ m_treeView(new QTreeView(this)),
+ m_addButton(new QPushButton(tr("Add"), this)),
+ m_addQtButton(new QPushButton(tr("Add Qt sources..."), this)),
+ m_removeButton(new QPushButton(tr("Remove"), this)),
+ m_sourceLineEdit(new QLineEdit(this)),
+ m_targetChooser(new Utils::PathChooser(this))
{
setTitle(tr("Source Paths Mapping"));
- setToolTip(tr("<html><head/><body><p>Mappings of source file folders to be used in the debugger can be entered here.</p>"
- "<p>This is useful when using a copy of the source tree at a location different from the one "
- "at which the modules where built, for example, while doing remote debugging.</body></html>"));
+ setToolTip(tr("<html><head/><body><p>Mappings of source file folders to "
+ "be used in the debugger can be entered here.</p>"
+ "<p>This is useful when using a copy of the source tree "
+ "at a location different from the one "
+ "at which the modules where built, for example, while "
+ "doing remote debugging.</body></html>"));
// Top list/left part.
m_treeView->setRootIsDecorated(false);
m_treeView->setUniformRowHeights(true);
m_treeView->setSelectionMode(QAbstractItemView::SingleSelection);
m_treeView->setSelectionBehavior(QAbstractItemView::SelectRows);
m_treeView->setModel(m_model);
- connect(m_treeView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
- this, SLOT(slotCurrentRowChanged(QModelIndex,QModelIndex)));
+ connect(m_treeView->selectionModel(),
+ SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
+ SLOT(slotCurrentRowChanged(QModelIndex,QModelIndex)));
// Top list/Right part: Buttons.
QVBoxLayout *buttonLayout = new QVBoxLayout;
buttonLayout->addWidget(m_addButton);
buttonLayout->addWidget(m_addQtButton);
m_addQtButton->setVisible(sizeof(qtBuildPaths) > 0);
- m_addQtButton->setToolTip(tr("Add a mapping for Qt's source folders when using an unpatched version of Qt."));
+ m_addQtButton->setToolTip(tr("Add a mapping for Qt's source folders "
+ "when using an unpatched version of Qt."));
buttonLayout->addWidget(m_removeButton);
connect(m_addButton, SIGNAL(clicked()), this, SLOT(slotAdd()));
connect(m_addQtButton, SIGNAL(clicked()), this, SLOT(slotAddQt()));
@@ -243,18 +248,21 @@ DebuggerSourcePathMappingWidget::DebuggerSourcePathMappingWidget(QWidget *parent
// Edit part
m_targetChooser->setExpectedKind(Utils::PathChooser::ExistingDirectory);
- connect(m_sourceLineEdit, SIGNAL(textChanged(QString)), this, SLOT(slotEditSourceFieldChanged()));
- connect(m_targetChooser, SIGNAL(changed(QString)), this, SLOT(slotEditTargetFieldChanged()));
+ connect(m_sourceLineEdit, SIGNAL(textChanged(QString)),
+ this, SLOT(slotEditSourceFieldChanged()));
+ connect(m_targetChooser, SIGNAL(changed(QString)),
+ this, SLOT(slotEditTargetFieldChanged()));
QFormLayout *editLayout = new QFormLayout;
const QString sourceToolTip = tr("The source path contained in the "
- "executable's debug information as reported by the debugger");
+ "debug information of the executable as reported by the debugger");
QLabel *editSourceLabel = new QLabel(tr("&Source path:"));
editSourceLabel->setToolTip(sourceToolTip);
m_sourceLineEdit->setToolTip(sourceToolTip);
editSourceLabel->setBuddy(m_sourceLineEdit);
editLayout->addRow(editSourceLabel, m_sourceLineEdit);
- const QString targetToolTip = tr("The actual location of the source tree on the local machine");
+ const QString targetToolTip = tr("The actual location of the source "
+ "tree on the local machine");
QLabel *editTargetLabel = new QLabel(tr("&Target path:"));
editTargetLabel->setToolTip(targetToolTip);
editTargetLabel->setBuddy(m_targetChooser);
@@ -279,15 +287,17 @@ QString DebuggerSourcePathMappingWidget::editTargetField() const
return m_targetChooser->path();
}
-void DebuggerSourcePathMappingWidget::setEditFieldMapping(const QPair<QString, QString> &m)
+void DebuggerSourcePathMappingWidget::setEditFieldMapping(const Mapping &m)
{
m_sourceLineEdit->setText(QDir::toNativeSeparators(m.first));
m_targetChooser->setPath(m.second);
}
-void DebuggerSourcePathMappingWidget::slotCurrentRowChanged(const QModelIndex &current,const QModelIndex &)
+void DebuggerSourcePathMappingWidget::slotCurrentRowChanged
+ (const QModelIndex &current, const QModelIndex &)
{
- setEditFieldMapping(current.isValid() ? m_model->mappingAt(current.row()) : QPair<QString, QString>());
+ setEditFieldMapping(current.isValid()
+ ? m_model->mappingAt(current.row()) : Mapping());
updateEnabled();
}
@@ -304,13 +314,14 @@ void DebuggerSourcePathMappingWidget::updateEnabled()
m_sourceLineEdit->setEnabled(hasCurrent);
m_targetChooser->setEnabled(hasCurrent);
m_removeButton->setEnabled(hasCurrent);
- // Allow for adding only if the current item no longer is the place holder for new items.
+ // Allow for adding only if the current item no longer is the place
+ // holder for new items.
const bool canAdd = !hasCurrent || !m_model->isNewPlaceHolderAt(row);
m_addButton->setEnabled(canAdd);
m_addQtButton->setEnabled(canAdd);
}
-DebuggerSourcePathMappingWidget::SourcePathMap DebuggerSourcePathMappingWidget::sourcePathMap() const
+SourcePathMap DebuggerSourcePathMappingWidget::sourcePathMap() const
{
return m_model->sourcePathMap();
}
@@ -345,11 +356,12 @@ void DebuggerSourcePathMappingWidget::slotAdd()
void DebuggerSourcePathMappingWidget::slotAddQt()
{
// Add a mapping for various Qt build locations in case of unpatched builds.
- const QString qtSourcesPath = QFileDialog::getExistingDirectory(this, tr("Qt Sources"));
+ const QString qtSourcesPath =
+ QFileDialog::getExistingDirectory(this, tr("Qt Sources"));
if (qtSourcesPath.isEmpty())
return;
const size_t buildPathCount = sizeof(qtBuildPaths)/sizeof(qtBuildPaths[0]);
- for (size_t i = 0; i != buildPathCount; ++i)
+ for (size_t i = 0; i < buildPathCount; ++i)
m_model->addMapping(QString::fromLatin1(qtBuildPaths[i]), qtSourcesPath);
resizeColumns();
setCurrentRow(m_model->rowCount() - 1);
@@ -387,11 +399,11 @@ DebuggerSourcePathMappingWidget::SourcePathMap
const SourcePathMap &in)
{
SourcePathMap rc = in;
- const size_t buildPathCount = sizeof(qtBuildPaths)/sizeof(qtBuildPaths[0]);
+ const size_t buildPathCount = sizeof(qtBuildPaths)/sizeof(const char *);
if (qtInstallPath.isEmpty() || buildPathCount == 0)
return rc;
- for (size_t i = 0; i != buildPathCount; i++) {
+ for (size_t i = 0; i < buildPathCount; i++) {
const QString buildPath = QString::fromLatin1(qtBuildPaths[i]);
if (!rc.contains(buildPath)) // Do not overwrite user settings.
rc.insert(buildPath, qtInstallPath);
diff --git a/src/plugins/debugger/debuggerstreamops.cpp b/src/plugins/debugger/debuggerstreamops.cpp
index 60d588f7a8..d691189cdb 100644
--- a/src/plugins/debugger/debuggerstreamops.cpp
+++ b/src/plugins/debugger/debuggerstreamops.cpp
@@ -224,6 +224,7 @@ QDataStream &operator<<(QDataStream &stream, const WatchData &wd)
stream << wd.displayedType;
stream << wd.variable;
stream << wd.address;
+ stream << wd.size;
stream << wd.hasChildren;
stream << wd.generation;
stream << wd.valueEnabled;
@@ -249,6 +250,7 @@ QDataStream &operator>>(QDataStream &stream, WatchData &wd)
stream >> wd.displayedType;
stream >> wd.variable;
stream >> wd.address;
+ stream >> wd.size;
stream >> wd.hasChildren;
stream >> wd.generation;
stream >> wd.valueEnabled;
@@ -262,6 +264,9 @@ QDataStream &operator>>(QDataStream &stream, WatchData &wd)
QDataStream &operator<<(QDataStream& stream, const DisassemblerLine &o)
{
stream << o.address;
+ stream << o.function;
+ stream << o.offset;
+ stream << o.lineNumber;
stream << o.data;
return stream;
}
@@ -269,6 +274,9 @@ QDataStream &operator<<(QDataStream& stream, const DisassemblerLine &o)
QDataStream &operator>>(QDataStream& stream, DisassemblerLine &o)
{
stream >> o.address;
+ stream >> o.function;
+ stream >> o.offset;
+ stream >> o.lineNumber;
stream >> o.data;
return stream;
}
diff --git a/src/plugins/debugger/debuggertooltipmanager.cpp b/src/plugins/debugger/debuggertooltipmanager.cpp
index d1cd62f9c8..c5d33b1278 100644
--- a/src/plugins/debugger/debuggertooltipmanager.cpp
+++ b/src/plugins/debugger/debuggertooltipmanager.cpp
@@ -442,7 +442,7 @@ private:
};
/*!
- \class PinnableToolTipWidget
+ \class Debugger::Internal::PinnableToolTipWidget
A pinnable tooltip that goes from State 'Unpinned' (button showing
'Pin') to 'Pinned' (button showing 'Close').
@@ -571,7 +571,7 @@ void DraggableLabel::mouseMoveEvent(QMouseEvent * event)
}
/*!
- \class DebuggerToolTipContext
+ \class Debugger::Internal::DebuggerToolTipContext
File name and position where the tooltip is anchored. Redundant position/line column
information is used to detect if the underlying file has been changed
@@ -605,7 +605,7 @@ QDebug operator<<(QDebug d, const DebuggerToolTipContext &c)
}
/*!
- \class AbstractDebuggerToolTipWidget
+ \class Debugger::Internal::AbstractDebuggerToolTipWidget
Base class for a tool tip widget associated with file name
and position with functionality to
@@ -851,8 +851,18 @@ void AbstractDebuggerToolTipWidget::saveSessionData(QXmlStreamWriter &w) const
w.writeEndElement();
}
-// Model for tooltips filtering a local variable using the locals model,
-// taking the expression. Suppress the tooltip data.
+/*!
+ \class Debugger::Internal::DebuggerToolTipExpressionFilterModel
+
+ \brief Model for tooltips filtering a local variable using the locals or tooltip model,
+ matching on the name.
+
+ Expressions/names can either be flat ('foo' will match at the root level)
+ or nested ('this.m_foo' will match 'this' at root level and 'm_foo' at level 1).
+
+ In addition, suppress the model's tooltip data to avoid a tooltip on a tooltip.
+*/
+
class DebuggerToolTipExpressionFilterModel : public QSortFilterProxyModel
{
public:
@@ -862,13 +872,14 @@ public:
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
private:
- const QString m_expression;
+ const QStringList m_expressions;
};
DebuggerToolTipExpressionFilterModel::DebuggerToolTipExpressionFilterModel(QAbstractItemModel *model,
const QString &exp,
QObject *parent) :
- QSortFilterProxyModel(parent), m_expression(exp)
+ QSortFilterProxyModel(parent),
+ m_expressions(exp.split(QLatin1Char('.')))
{
setSourceModel(model);
}
@@ -879,17 +890,27 @@ QVariant DebuggerToolTipExpressionFilterModel::data(const QModelIndex &index, in
QSortFilterProxyModel::data(index, role) : QVariant();
}
+// Return depth of a model index, that is, 0 for root index, 1 for level-1 children, etc.
+static inline int indexDepth(QModelIndex index)
+{
+ int depth = 0;
+ for ( ; index.isValid() ; index = index.parent())
+ depth++;
+ return depth;
+}
+
bool DebuggerToolTipExpressionFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
// Match on expression for top level, else pass through.
- if (sourceParent.isValid())
+ const int depth = indexDepth(sourceParent);
+ if (depth >= m_expressions.size()) // No filters at this level
return true;
- const QModelIndex expIndex = sourceModel()->index(sourceRow, 0, sourceParent);
- return expIndex.data().toString() == m_expression;
+ const QModelIndex nameIndex = sourceModel()->index(sourceRow, 0, sourceParent);
+ return nameIndex.data().toString() == m_expressions.at(depth);
}
/*!
- \class DebuggerToolTipTreeView
+ \class Debugger::Internal::DebuggerToolTipTreeView
A treeview that adapts its size to the model contents (also while expanding)
to be used within DebuggerTreeViewToolTipWidget.
@@ -986,7 +1007,7 @@ void DebuggerToolTipTreeView::computeSize()
}
/*!
- \class DebuggerTreeViewToolTipWidget
+ \class Debugger::Internal::DebuggerTreeViewToolTipWidget
Tool tip widget for tree views with functionality to save/restore tree
model contents to XML.
@@ -1024,7 +1045,21 @@ void DebuggerTreeViewToolTipWidget::doAcquireEngine(Debugger::DebuggerEngine *en
QTC_ASSERT(model, return);
DebuggerToolTipExpressionFilterModel *filterModel =
new DebuggerToolTipExpressionFilterModel(model, m_expression);
- m_treeView->swapModel(filterModel);
+ swapModel(filterModel);
+}
+
+QAbstractItemModel *DebuggerTreeViewToolTipWidget::swapModel(QAbstractItemModel *newModel)
+{
+ QAbstractItemModel *oldModel = m_treeView->swapModel(newModel);
+ // When looking at some 'this.m_foo.x', expand all items
+ if (newModel) {
+ if (const int level = m_expression.count(QLatin1Char('.'))) {
+ QModelIndex index = newModel->index(0, 0);
+ for (int i = 0; i < level && index.isValid(); i++, index = index.child(0, 0))
+ m_treeView->setExpanded(index, true);
+ }
+ }
+ return oldModel;
}
void DebuggerTreeViewToolTipWidget::doReleaseEngine()
@@ -1035,7 +1070,7 @@ void DebuggerTreeViewToolTipWidget::doReleaseEngine()
TreeModelCopyVisitor v(model, m_defaultModel);
v.run();
}
- delete m_treeView->swapModel(m_defaultModel);
+ delete swapModel(m_defaultModel);
}
void DebuggerTreeViewToolTipWidget::restoreTreeModel(QXmlStreamReader &r, QStandardItemModel *m)
@@ -1123,7 +1158,7 @@ QString DebuggerTreeViewToolTipWidget::clipboardContents() const
}
/*!
- \class DebuggerToolTipManager
+ \class Debugger::Internal::DebuggerToolTipManager
Manages the pinned tooltip widgets, listens on editor scroll and main window move
events and takes care of repositioning the tooltips.
diff --git a/src/plugins/debugger/debuggertooltipmanager.h b/src/plugins/debugger/debuggertooltipmanager.h
index 5fd989d225..be78c337c6 100644
--- a/src/plugins/debugger/debuggertooltipmanager.h
+++ b/src/plugins/debugger/debuggertooltipmanager.h
@@ -227,6 +227,7 @@ protected:
virtual QString clipboardContents() const;
private:
+ QAbstractItemModel *swapModel(QAbstractItemModel *newModel);
static void restoreTreeModel(QXmlStreamReader &r, QStandardItemModel *m);
int m_debuggerModel;
diff --git a/src/plugins/debugger/disassembleragent.cpp b/src/plugins/debugger/disassembleragent.cpp
index 804243b2fa..743f015ec2 100644
--- a/src/plugins/debugger/disassembleragent.cpp
+++ b/src/plugins/debugger/disassembleragent.cpp
@@ -57,6 +57,7 @@
#include <QtCore/QPointer>
using namespace Core;
+using namespace TextEditor;
namespace Debugger {
namespace Internal {
@@ -67,38 +68,6 @@ namespace Internal {
//
///////////////////////////////////////////////////////////////////////
-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() {}
- TextEditor::ITextMark::Priority priority() const
- { return TextEditor::ITextMark::HighPriority; }
-};
-
-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() {}
- TextEditor::ITextMark::Priority priority() const
- { return TextEditor::ITextMark::NormalPriority; }
-
-private:
- QIcon m_icon;
-};
-
-
class DisassemblerAgentPrivate
{
public:
@@ -111,8 +80,8 @@ public:
Location location;
bool tryMixed;
QPointer<DebuggerEngine> engine;
- TextEditor::ITextMark *locationMark;
- QList<TextEditor::ITextMark *> breakpointMarks;
+ ITextMark *locationMark;
+ QList<ITextMark *> breakpointMarks;
QHash<QString, DisassemblerLines> cache;
QString mimeType;
@@ -122,10 +91,12 @@ public:
DisassemblerAgentPrivate::DisassemblerAgentPrivate()
: editor(0),
tryMixed(true),
- locationMark(new LocationMark2),
mimeType(_("text/x-qtcreator-generic-asm")),
m_resetLocationScheduled(false)
{
+ locationMark = new ITextMark;
+ locationMark->setIcon(debuggerCore()->locationMarkIcon());
+ locationMark->setPriority(TextEditor::ITextMark::HighPriority);
}
DisassemblerAgentPrivate::~DisassemblerAgentPrivate()
@@ -282,13 +253,7 @@ void DisassemblerAgent::setContents(const DisassemblerLines &contents)
QString str;
for (int i = 0, n = contents.size(); i != n; ++i) {
- const DisassemblerLine &dl = contents.at(i);
- if (dl.address) {
- str += QLatin1String("0x");
- str += QString::number(dl.address, 16);
- str += QLatin1String(" ");
- }
- str += dl.data;
+ str += contents.at(i).toString();
str += QLatin1Char('\n');
}
plainTextEdit->setPlainText(str);
@@ -346,7 +311,9 @@ void DisassemblerAgent::updateBreakpointMarkers()
const int lineNumber = contents.lineForAddress(address);
if (!lineNumber)
continue;
- BreakpointMarker2 *marker = new BreakpointMarker2(handler->icon(id));
+ ITextMark *marker = new ITextMark;
+ marker->setIcon(handler->icon(id));
+ marker->setPriority(ITextMark::NormalPriority);
d->breakpointMarks.append(marker);
d->editor->markableInterface()->addMark(marker, lineNumber);
}
@@ -357,12 +324,6 @@ 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;
diff --git a/src/plugins/debugger/disassembleragent.h b/src/plugins/debugger/disassembleragent.h
index b06bad17c0..4a3055c41a 100644
--- a/src/plugins/debugger/disassembleragent.h
+++ b/src/plugins/debugger/disassembleragent.h
@@ -71,9 +71,6 @@ public:
void cleanup();
bool isMixed() const;
- // Return address of an assembly line "0x0dfd bla"
- static quint64 addressFromDisassemblyLine(const QString &data);
-
private:
DisassemblerAgentPrivate *d;
};
diff --git a/src/plugins/debugger/disassemblerlines.cpp b/src/plugins/debugger/disassemblerlines.cpp
index 1e991ee2dc..5c2732c348 100644
--- a/src/plugins/debugger/disassemblerlines.cpp
+++ b/src/plugins/debugger/disassemblerlines.cpp
@@ -31,14 +31,17 @@
**************************************************************************/
#include "disassemblerlines.h"
+#include "debuggerstringutils.h"
#include <QtCore/QDebug>
#include <QtCore/QRegExp>
+#include <QtCore/QFile>
+#include <QtCore/QTextStream>
namespace Debugger {
namespace Internal {
-DisassemblerLine::DisassemblerLine(const QString &unparsed)
+void DisassemblerLine::fromString(const QString &unparsed)
{
int pos = -1;
for (int i = 0; i != unparsed.size(); ++i) {
@@ -70,6 +73,13 @@ DisassemblerLine::DisassemblerLine(const QString &unparsed)
data = unparsed;
}
+quint64 DisassemblerLine::addressFromDisassemblyLine(const QString &line)
+{
+ DisassemblerLine l;
+ l.fromString(line);
+ return l.address;
+}
+
int DisassemblerLines::lineForAddress(quint64 address) const
{
return m_rowCache.value(address);
@@ -80,17 +90,113 @@ bool DisassemblerLines::coversAddress(quint64 address) const
return m_rowCache.value(address) != 0;
}
-void DisassemblerLines::appendComment(const QString &comment)
+void DisassemblerLines::appendLine(const DisassemblerLine &dl)
{
- DisassemblerLine dl;
- dl.data = comment;
m_data.append(dl);
+ m_rowCache[dl.address] = m_data.size();
}
-void DisassemblerLines::appendLine(const DisassemblerLine &dl)
+// Append source line: Cache current file
+struct SourceFileCache
{
- m_data.append(dl);
- m_rowCache[dl.address] = m_data.size();
+ QString fileName;
+ QStringList lines;
+};
+
+Q_GLOBAL_STATIC(SourceFileCache, sourceFileCache)
+
+void DisassemblerLines::appendSourceLine(const QString &fileName, uint lineNumber)
+{
+
+ if (fileName.isEmpty() || lineNumber == 0)
+ return;
+ lineNumber--; // fix 1..n range.
+ SourceFileCache *cache = sourceFileCache();
+ if (fileName != cache->fileName) {
+ cache->fileName = fileName;
+ cache->lines.clear();
+ QFile file(fileName);
+ if (file.open(QIODevice::ReadOnly)) {
+ QTextStream ts(&file);
+ cache->lines = ts.readAll().split(QLatin1Char('\n'));
+ } // open
+ } // different file
+ if (lineNumber >= uint(cache->lines.size()))
+ return;
+ DisassemblerLine dl;
+ dl.lineNumber = lineNumber;
+ dl.data = cache->lines.at(lineNumber);
+ appendLine(dl);
+}
+
+void DisassemblerLines::appendUnparsed(const QString &unparsed)
+{
+ QString line = unparsed.trimmed();
+ if (line.isEmpty())
+ return;
+ if (line.startsWith("Current language:"))
+ return;
+ if (line.startsWith("Dump of assembler")) {
+ m_lastFunction.clear();
+ return;
+ }
+ if (line.startsWith("The current source"))
+ return;
+ if (line.startsWith("End of assembler")) {
+ m_lastFunction.clear();
+ return;
+ }
+ if (line.startsWith("=> "))
+ line = line.mid(3);
+ if (line.startsWith("0x")) {
+ // Address line.
+ int pos1 = line.indexOf('<') + 1;
+ int pos2 = line.indexOf('+', pos1);
+ int pos3 = line.indexOf('>', pos1);
+ if (pos1 < pos2 && pos2 < pos3) {
+ QString function = line.mid(pos1, pos2 - pos1);
+ if (function != m_lastFunction) {
+ DisassemblerLine dl;
+ dl.data = _("Function: ") + function;
+ m_data.append(dl);
+ m_lastFunction = function;
+ }
+ //line.replace(pos1, pos2 - pos1, "");
+ }
+ DisassemblerLine dl;
+ dl.address = line.left(pos1 - 1).toULongLong(0, 0);
+ dl.function = m_lastFunction;
+ dl.offset = line.mid(pos2, pos3 - pos2).toUInt();
+ dl.data = line.mid(pos3 + 3).trimmed();
+ m_rowCache[dl.address] = m_data.size() + 1;
+ m_data.append(dl);
+ } else {
+ // Comment line.
+ DisassemblerLine dl;
+ dl.data = line;
+ m_data.append(dl);
+ }
+}
+
+QString DisassemblerLine::toString() const
+{
+ const QString someSpace = _(" ");
+ QString str;
+ if (isAssembler()) {
+ if (address)
+ str += _("0x%1 ").arg(address, 0, 16);
+ if (offset)
+ str += _("<+0x%1> ").arg(offset, 4, 16, QLatin1Char('0'));
+ str += _(" ");
+ str += data;
+ } else if (isCode()) {
+ str += someSpace;
+ str += data;
+ } else {
+ str += someSpace;
+ str += data;
+ }
+ return str;
}
} // namespace Internal
diff --git a/src/plugins/debugger/disassemblerlines.h b/src/plugins/debugger/disassemblerlines.h
index b4ecab4fc0..8fdbc73df7 100644
--- a/src/plugins/debugger/disassemblerlines.h
+++ b/src/plugins/debugger/disassemblerlines.h
@@ -33,22 +33,39 @@
#ifndef DEBUGGER_DISASSEMBLERLINES_H
#define DEBUGGER_DISASSEMBLERLINES_H
-#include <QtCore/QString>
+#include <QtCore/QStringList>
#include <QtCore/QHash>
#include <QtCore/QVector>
namespace Debugger {
namespace Internal {
+// A DisassemblerLine represents either
+// - an assembler instruction (address, offset, function, data fields), or
+// - a code line (lineNumber, data fields), or
+// - a comment line.
+
class DisassemblerLine
{
+ //DisassemblerLine(const QString &unparsed);
public:
- DisassemblerLine() : address(0) {}
- DisassemblerLine(const QString &unparsed);
+ DisassemblerLine() : address(0), offset(0), lineNumber(0) {}
+ bool isAssembler() const { return address != 0; }
+ bool isCode() const { return lineNumber != 0; }
+ bool isComment() const { return lineNumber == 0 && address == 0; }
+ QString toString() const;
+ void fromString(const QString &unparsed);
+
+ // Return address of an assembly line "0x0dfd bla".
+ static quint64 addressFromDisassemblyLine(const QString &line);
public:
- quint64 address;
- QString data;
+ quint64 address; // (ass) Address of instruction in memory/in binary.
+ QString function; // (ass) Function to which current instruction belongs.
+ uint offset; // (ass) Offset of instruction in relation to current function.
+ uint lineNumber; // (src) Line number in source.
+ QByteArray rawData; // (ass) Raw bytes of the instruction
+ QString data; // (ass) Instruction text, (src) source text, (cmt) arbitrary.
};
class DisassemblerLines
@@ -57,13 +74,17 @@ public:
DisassemblerLines() {}
bool coversAddress(quint64 address) const;
+ void appendUnparsed(const QString &line);
void appendLine(const DisassemblerLine &dl);
- void appendComment(const QString &comment);
+ // Mixed source/assembly: Retrieve contents of source (cached)
+ void appendSourceLine(const QString &fileName, uint line);
+
int size() const { return m_data.size(); }
const DisassemblerLine &at(int i) const { return m_data.at(i); }
int lineForAddress(quint64 address) const;
private:
+ QString m_lastFunction;
QVector<DisassemblerLine> m_data;
QHash<quint64, int> m_rowCache;
};
diff --git a/src/plugins/debugger/gdb/abstractgdbadapter.cpp b/src/plugins/debugger/gdb/abstractgdbadapter.cpp
index a12b3af269..b649c9c11a 100644
--- a/src/plugins/debugger/gdb/abstractgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/abstractgdbadapter.cpp
@@ -43,8 +43,8 @@
namespace Debugger {
namespace Internal {
-AbstractGdbAdapter::AbstractGdbAdapter(GdbEngine *engine, QObject *parent)
- : QObject(parent), m_engine(engine)
+AbstractGdbAdapter::AbstractGdbAdapter(GdbEngine *engine)
+ : m_engine(engine)
{
}
diff --git a/src/plugins/debugger/gdb/abstractgdbadapter.h b/src/plugins/debugger/gdb/abstractgdbadapter.h
index b9d4837721..509e3e15e8 100644
--- a/src/plugins/debugger/gdb/abstractgdbadapter.h
+++ b/src/plugins/debugger/gdb/abstractgdbadapter.h
@@ -66,7 +66,7 @@ public:
DumperLoadedByGdb
};
- explicit AbstractGdbAdapter(GdbEngine *engine, QObject *parent = 0);
+ explicit AbstractGdbAdapter(GdbEngine *engine);
virtual ~AbstractGdbAdapter();
virtual void write(const QByteArray &data);
@@ -98,6 +98,7 @@ public:
protected:
DebuggerState state() const;
+ GdbEngine *engine() const { return m_engine; }
const DebuggerStartParameters &startParameters() const;
DebuggerStartParameters &startParameters();
void showMessage(const QString &msg, int channel = LogDebug, int timeout = 1);
diff --git a/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp b/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp
index e195c4b927..a33a115e9e 100644
--- a/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp
+++ b/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp
@@ -51,9 +51,8 @@ namespace Internal {
static_cast<GdbEngine::AdapterCallback>(&AbstractPlainGdbAdapter::callback), \
STRINGIFY(callback)
-AbstractPlainGdbAdapter::AbstractPlainGdbAdapter(GdbEngine *engine,
- QObject *parent)
- : AbstractGdbAdapter(engine, parent)
+AbstractPlainGdbAdapter::AbstractPlainGdbAdapter(GdbEngine *engine)
+ : AbstractGdbAdapter(engine)
{
}
diff --git a/src/plugins/debugger/gdb/abstractplaingdbadapter.h b/src/plugins/debugger/gdb/abstractplaingdbadapter.h
index a4393a11b3..8de51a707a 100644
--- a/src/plugins/debugger/gdb/abstractplaingdbadapter.h
+++ b/src/plugins/debugger/gdb/abstractplaingdbadapter.h
@@ -44,7 +44,7 @@ class AbstractPlainGdbAdapter : public AbstractGdbAdapter
Q_OBJECT
public:
- explicit AbstractPlainGdbAdapter(GdbEngine *engine, QObject *parent = 0);
+ explicit AbstractPlainGdbAdapter(GdbEngine *engine);
virtual void setupInferior();
void runEngine();
diff --git a/src/plugins/debugger/gdb/attachgdbadapter.cpp b/src/plugins/debugger/gdb/attachgdbadapter.cpp
index d70932975a..b9960e1b30 100644
--- a/src/plugins/debugger/gdb/attachgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/attachgdbadapter.cpp
@@ -54,8 +54,8 @@ namespace Internal {
//
///////////////////////////////////////////////////////////////////////
-AttachGdbAdapter::AttachGdbAdapter(GdbEngine *engine, QObject *parent)
- : AbstractGdbAdapter(engine, parent)
+AttachGdbAdapter::AttachGdbAdapter(GdbEngine *engine)
+ : AbstractGdbAdapter(engine)
{
}
diff --git a/src/plugins/debugger/gdb/attachgdbadapter.h b/src/plugins/debugger/gdb/attachgdbadapter.h
index 5dd9d608ed..0bebb6222e 100644
--- a/src/plugins/debugger/gdb/attachgdbadapter.h
+++ b/src/plugins/debugger/gdb/attachgdbadapter.h
@@ -50,7 +50,7 @@ class AttachGdbAdapter : public AbstractGdbAdapter
Q_OBJECT
public:
- explicit AttachGdbAdapter(GdbEngine *engine, QObject *parent = 0);
+ explicit AttachGdbAdapter(GdbEngine *engine);
private:
DumperHandling dumperHandling() const { return DumperLoadedByGdb; }
diff --git a/src/plugins/debugger/gdb/classicgdbengine.cpp b/src/plugins/debugger/gdb/classicgdbengine.cpp
index d3ffd42f61..c9aa896661 100644
--- a/src/plugins/debugger/gdb/classicgdbengine.cpp
+++ b/src/plugins/debugger/gdb/classicgdbengine.cpp
@@ -55,22 +55,618 @@
#define PRECONDITION QTC_ASSERT(!hasPython(), /**/)
-#define CB(callback) &GdbEngine::callback, STRINGIFY(callback)
-
-//#define DEBUG_PENDING 1
-//#define DEBUG_SUBITEM 1
+#define CB(callback) &GdbEngine::callback, STRINGIFY(callback)
-#if DEBUG_PENDING
-# define PENDING_DEBUG(s) qDebug() << s
-#else
-# define PENDING_DEBUG(s)
-#endif
-#define PENDING_DEBUGX(s) qDebug() << s
+enum {
+ debugPending = 0,
+ debugSubItem = 0,
+ debug = 0
+};
namespace Debugger {
namespace Internal {
+// ----------------- QtDumperHelper::TypeData
+DumperHelper::TypeData::TypeData() :
+ type(UnknownType),
+ isTemplate(false)
+{
+}
+
+void DumperHelper::TypeData::clear()
+{
+ isTemplate = false;
+ type = UnknownType;
+ tmplate.clear();
+ inner.clear();
+}
+
+// ----------------- QtDumperHelper
+DumperHelper::DumperHelper() :
+ m_qtVersion(0),
+ m_dumperVersion(1.0)
+{
+ qFill(m_specialSizes, m_specialSizes + SpecialSizeCount, 0);
+ setQClassPrefixes(QByteArray());
+}
+
+void DumperHelper::clear()
+{
+ m_nameTypeMap.clear();
+ m_qtVersion = 0;
+ m_dumperVersion = 1.0;
+ m_qtNamespace.clear();
+ m_sizeCache.clear();
+ qFill(m_specialSizes, m_specialSizes + SpecialSizeCount, 0);
+ m_expressionCache.clear();
+ setQClassPrefixes(QByteArray());
+}
+
+QString DumperHelper::msgDumperOutdated(double requiredVersion, double currentVersion)
+{
+ return QCoreApplication::translate("QtDumperHelper",
+ "Found an outdated version of the debugging helper library (%1); "
+ "version %2 is required.").
+ arg(currentVersion).arg(requiredVersion);
+}
+
+static inline void formatQtVersion(int v, QTextStream &str)
+{
+ str << ((v >> 16) & 0xFF) << '.' << ((v >> 8) & 0xFF) << '.' << (v & 0xFF);
+}
+
+QString DumperHelper::toString(bool debug) const
+{
+ if (debug) {
+ QString rc;
+ QTextStream str(&rc);
+ str << "version=";
+ formatQtVersion(m_qtVersion, str);
+ str << "dumperversion='" << m_dumperVersion << "' namespace='" << m_qtNamespace << "'," << m_nameTypeMap.size() << " known types <type enum>: ";
+ const NameTypeMap::const_iterator cend = m_nameTypeMap.constEnd();
+ for (NameTypeMap::const_iterator it = m_nameTypeMap.constBegin(); it != cend; ++it) {
+ str <<",[" << it.key() << ',' << it.value() << ']';
+ }
+ str << "\nSpecial size: ";
+ for (int i = 0; i < SpecialSizeCount; i++)
+ str << ' ' << m_specialSizes[i];
+ str << "\nSize cache: ";
+ const SizeCache::const_iterator scend = m_sizeCache.constEnd();
+ for (SizeCache::const_iterator it = m_sizeCache.constBegin(); it != scend; ++it) {
+ str << ' ' << it.key() << '=' << it.value() << '\n';
+ }
+ str << "\nExpression cache: (" << m_expressionCache.size() << ")\n";
+ const ExpressionCache::const_iterator excend = m_expressionCache.constEnd();
+ for (ExpressionCache::const_iterator it = m_expressionCache.constBegin(); it != excend; ++it)
+ str << " " << it.key() << ' ' << it.value() << '\n';
+ return rc;
+ }
+ const QString nameSpace = m_qtNamespace.isEmpty()
+ ? QCoreApplication::translate("QtDumperHelper", "<none>") : m_qtNamespace;
+ return QCoreApplication::translate("QtDumperHelper",
+ "%n known types, Qt version: %1, Qt namespace: %2 Dumper version: %3",
+ 0, QCoreApplication::CodecForTr,
+ m_nameTypeMap.size()).arg(qtVersionString(), nameSpace).arg(m_dumperVersion);
+}
+
+DumperHelper::Type DumperHelper::simpleType(const QByteArray &simpleType) const
+{
+ return m_nameTypeMap.value(simpleType, UnknownType);
+}
+
+int DumperHelper::qtVersion() const
+{
+ return m_qtVersion;
+}
+
+QByteArray DumperHelper::qtNamespace() const
+{
+ return m_qtNamespace;
+}
+
+int DumperHelper::typeCount() const
+{
+ return m_nameTypeMap.size();
+}
+
+// Look up unnamespaced 'std' types.
+static DumperHelper::Type stdType(const QByteArray &type)
+{
+ if (type == "vector")
+ return DumperHelper::StdVectorType;
+ if (type == "deque")
+ return DumperHelper::StdDequeType;
+ if (type == "set")
+ return DumperHelper::StdSetType;
+ if (type == "stack")
+ return DumperHelper::StdStackType;
+ if (type == "map")
+ return DumperHelper::StdMapType;
+ if (type == "basic_string")
+ return DumperHelper::StdStringType;
+ return DumperHelper::UnknownType;
+}
+
+static DumperHelper::Type specialType(QByteArray type)
+{
+ // Std classes.
+ if (type.startsWith("std::"))
+ return stdType(type.mid(5));
+
+ // Strip namespace
+ // FIXME: that's not a good idea as it makes all namespaces equal.
+ const int namespaceIndex = type.lastIndexOf("::");
+ if (namespaceIndex == -1) {
+ // None ... check for std..
+ const DumperHelper::Type sType = stdType(type);
+ if (sType != DumperHelper::UnknownType)
+ return sType;
+ } else {
+ type = type.mid(namespaceIndex + 2);
+ }
+
+ if (type == "QAbstractItem")
+ return DumperHelper::QAbstractItemType;
+ if (type == "QMap")
+ return DumperHelper::QMapType;
+ if (type == "QMapNode")
+ return DumperHelper::QMapNodeType;
+ if (type == "QMultiMap")
+ return DumperHelper::QMultiMapType;
+ if (type == "QObject")
+ return DumperHelper::QObjectType;
+ if (type == "QObjectSignal")
+ return DumperHelper::QObjectSignalType;
+ if (type == "QObjectSlot")
+ return DumperHelper::QObjectSlotType;
+ if (type == "QStack")
+ return DumperHelper::QStackType;
+ if (type == "QVector")
+ return DumperHelper::QVectorType;
+ if (type == "QWidget")
+ return DumperHelper::QWidgetType;
+ return DumperHelper::UnknownType;
+}
+
+QByteArray DumperHelper::qtVersionString() const
+{
+ QString rc;
+ QTextStream str(&rc);
+ formatQtVersion(m_qtVersion, str);
+ return rc.toLatin1();
+}
+
+// Parse a list of types.
+typedef QList<QByteArray> QByteArrayList;
+
+static QByteArray qClassName(const QByteArray &qtNamespace, const char *className)
+{
+ if (qtNamespace.isEmpty())
+ return className;
+ QByteArray rc = qtNamespace;
+ rc += "::";
+ rc += className;
+ return rc;
+}
+
+static double getDumperVersion(const GdbMi &contents)
+{
+ const GdbMi dumperVersionG = contents.findChild("dumperversion");
+ if (dumperVersionG.type() != GdbMi::Invalid) {
+ bool ok;
+ const double v = QString::fromAscii(dumperVersionG.data()).toDouble(&ok);
+ if (ok)
+ return v;
+ }
+ return 1.0;
+}
+
+
+void DumperHelper::setQClassPrefixes(const QByteArray &qNamespace)
+{
+ // Prefixes with namespaces
+ m_qPointerPrefix = qClassName(qNamespace, "QPointer");
+ m_qSharedPointerPrefix = qClassName(qNamespace, "QSharedPointer");
+ m_qSharedDataPointerPrefix = qClassName(qNamespace, "QSharedDataPointer");
+ m_qWeakPointerPrefix = qClassName(qNamespace, "QWeakPointer");
+ m_qListPrefix = qClassName(qNamespace, "QList");
+ m_qLinkedListPrefix = qClassName(qNamespace, "QLinkedList");
+ m_qVectorPrefix = qClassName(qNamespace, "QVector");
+ m_qQueuePrefix = qClassName(qNamespace, "QQueue");
+}
+
+bool DumperHelper::parseQuery(const GdbMi &contents)
+{
+ clear();
+ if (debug > 1)
+ qDebug() << "parseQuery" << contents.toString(true, 2);
+
+ // Common info, dumper version, etc
+ QByteArray ns = contents.findChild("namespace").data();
+ setQtNamespace(ns);
+ int qtv = 0;
+ const GdbMi qtversion = contents.findChild("qtversion");
+ if (qtversion.children().size() == 3) {
+ qtv = (qtversion.childAt(0).data().toInt() << 16)
+ + (qtversion.childAt(1).data().toInt() << 8)
+ + qtversion.childAt(2).data().toInt();
+ }
+ m_qtVersion = qtv;
+ // Get list of helpers
+ QByteArrayList availableSimpleDebuggingHelpers;
+ foreach (const GdbMi &item, contents.findChild("dumpers").children())
+ availableSimpleDebuggingHelpers.append(item.data());
+
+ // Parse types
+ m_nameTypeMap.clear();
+ foreach (const QByteArray &type, availableSimpleDebuggingHelpers) {
+ const Type t = specialType(type);
+ m_nameTypeMap.insert(type, t != UnknownType ? t : SupportedType);
+ }
+
+ m_dumperVersion = getDumperVersion(contents);
+ // Parse sizes
+ foreach (const GdbMi &sizesList, contents.findChild("sizes").children()) {
+ const int childCount = sizesList.childCount();
+ if (childCount > 1) {
+ const int size = sizesList.childAt(0).data().toInt();
+ for (int c = 1; c < childCount; c++)
+ addSize(sizesList.childAt(c).data(), size);
+ }
+ }
+ // Parse expressions
+ foreach (const GdbMi &exprList, contents.findChild("expressions").children())
+ if (exprList.childCount() == 2)
+ m_expressionCache.insert(exprList.childAt(0).data(),
+ exprList.childAt(1).data());
+ return true;
+}
+
+void DumperHelper::addSize(const QByteArray &name, int size)
+{
+ // Special interest cases
+ if (name == "char*") {
+ m_specialSizes[PointerSize] = size;
+ return;
+ }
+ const SpecialSizeType st = specialSizeType(name);
+ if (st != SpecialSizeCount) {
+ m_specialSizes[st] = size;
+ return;
+ }
+ do {
+ // CDB helpers
+ if (name == "std::string") {
+ m_sizeCache.insert("std::basic_string<char,std::char_traits<char>,std::allocator<char> >", size);
+ m_sizeCache.insert("basic_string<char,char_traits<char>,allocator<char> >", size);
+ break;
+ }
+ if (name == "std::wstring") {
+ m_sizeCache.insert("basic_string<unsigned short,char_traits<unsignedshort>,allocator<unsignedshort> >", size);
+ m_sizeCache.insert("std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >", size);
+ break;
+ }
+ } while (false);
+ m_sizeCache.insert(name, size);
+}
+
+DumperHelper::Type DumperHelper::type(const QByteArray &typeName) const
+{
+ const DumperHelper::TypeData td = typeData(typeName);
+ return td.type;
+}
+
+static bool extractTemplate(const QByteArray &type, QByteArray *tmplate, QByteArray *inner)
+{
+ // Input "Template<Inner1,Inner2,...>::Foo" will return "Template::Foo" in
+ // 'tmplate' and "Inner1@Inner2@..." etc in 'inner'. Result indicates
+ // whether parsing was successful
+ // Gdb inserts a blank after each comma which we would like to avoid
+ tmplate->clear();
+ inner->clear();
+ if (!type.contains('<'))
+ return false;
+ int level = 0;
+ bool skipSpace = false;
+ const int size = type.size();
+
+ for (int i = 0; i != size; ++i) {
+ const char c = type.at(i);
+ switch (c) {
+ case '<':
+ *(level == 0 ? tmplate : inner) += c;
+ ++level;
+ break;
+ case '>':
+ --level;
+ *(level == 0 ? tmplate : inner) += c;
+ break;
+ case ',':
+ *inner += (level == 1) ? '@' : ',';
+ skipSpace = true;
+ break;
+ default:
+ if (!skipSpace || c != ' ') {
+ *(level == 0 ? tmplate : inner) += c;
+ skipSpace = false;
+ }
+ break;
+ }
+ }
+ *tmplate = tmplate->trimmed();
+ tmplate->replace("<>", "");
+ *inner = inner->trimmed();
+ // qDebug() << "EXTRACT TEMPLATE: " << *tmplate << *inner << " FROM " << type;
+ return !inner->isEmpty();
+}
+
+DumperHelper::TypeData DumperHelper::typeData(const QByteArray &typeName) const
+{
+ TypeData td;
+ td.type = UnknownType;
+ const Type st = simpleType(typeName);
+ if (st != UnknownType) {
+ td.isTemplate = false;
+ td.type = st;
+ return td;
+ }
+ // Try template
+ td.isTemplate = extractTemplate(typeName, &td.tmplate, &td.inner);
+ if (!td.isTemplate)
+ return td;
+ // Check the template type QMap<X,Y> -> 'QMap'
+ td.type = simpleType(td.tmplate);
+ return td;
+}
+
+static QByteArray sizeofTypeExpression(const QByteArray &type)
+{
+ if (type.endsWith('*'))
+ return "sizeof(void*)";
+ if (type.endsWith('>'))
+ return "sizeof(" + type + ')';
+ return "sizeof(" + gdbQuoteTypes(type) + ')';
+}
+
+// Format an expression to have the debugger query the
+// size. Use size cache if possible
+QByteArray DumperHelper::evaluationSizeofTypeExpression(const QByteArray &typeName) const
+{
+ // Look up special size types
+ const SpecialSizeType st = specialSizeType(typeName);
+ if (st != SpecialSizeCount) {
+ if (const int size = m_specialSizes[st])
+ return QByteArray::number(size);
+ }
+ // Look up size cache
+ const SizeCache::const_iterator sit = m_sizeCache.constFind(typeName);
+ if (sit != m_sizeCache.constEnd())
+ return QByteArray::number(sit.value());
+ // Finally have the debugger evaluate
+ return sizeofTypeExpression(typeName);
+}
+
+DumperHelper::SpecialSizeType DumperHelper::specialSizeType(const QByteArray &typeName) const
+{
+ if (isPointerType(typeName))
+ return PointerSize;
+ if (typeName == "int")
+ return IntSize;
+ if (typeName.startsWith("std::allocator"))
+ return StdAllocatorSize;
+ if (typeName.startsWith(m_qPointerPrefix))
+ return QPointerSize;
+ if (typeName.startsWith(m_qSharedPointerPrefix))
+ return QSharedPointerSize;
+ if (typeName.startsWith(m_qSharedDataPointerPrefix))
+ return QSharedDataPointerSize;
+ if (typeName.startsWith(m_qWeakPointerPrefix))
+ return QWeakPointerSize;
+ if (typeName.startsWith(m_qListPrefix))
+ return QListSize;
+ if (typeName.startsWith(m_qLinkedListPrefix))
+ return QLinkedListSize;
+ if (typeName.startsWith(m_qVectorPrefix))
+ return QVectorSize;
+ if (typeName.startsWith(m_qQueuePrefix))
+ return QQueueSize;
+ return SpecialSizeCount;
+}
+
+static inline bool isInteger(const QString &n)
+{
+ const int size = n.size();
+ if (!size)
+ return false;
+ for (int i = 0; i < size; i++)
+ if (!n.at(i).isDigit())
+ return false;
+ return true;
+}
+
+// Return debugger expression to get the offset of a map node.
+static inline QByteArray qMapNodeValueOffsetExpression(const QByteArray &type)
+{
+ return "(size_t)&(('" + type + "'*)0)->value";
+}
+
+void DumperHelper::evaluationParameters(const WatchData &data,
+ const TypeData &td, QByteArray *inBuffer, QByteArrayList *extraArgsIn) const
+{
+ enum { maxExtraArgCount = 4 };
+
+ QByteArrayList &extraArgs = *extraArgsIn;
+
+ // See extractTemplate for parameters
+ QByteArrayList inners = td.inner.split('@');
+ if (inners.at(0).isEmpty())
+ inners.clear();
+ for (int i = 0; i != inners.size(); ++i)
+ inners[i] = inners[i].simplified();
+
+ QString outertype = td.isTemplate ? td.tmplate : data.type;
+ // adjust the data extract
+ if (outertype == m_qtNamespace + "QWidget")
+ outertype = m_qtNamespace + "QObject";
+
+ QString inner = td.inner;
+ const QByteArray zero = "0";
+
+ extraArgs.clear();
+
+ if (!inners.empty()) {
+ // "generic" template dumpers: passing sizeof(argument)
+ // gives already most information the dumpers need
+ const int count = qMin(int(maxExtraArgCount), inners.size());
+ for (int i = 0; i < count; i++)
+ extraArgs.push_back(evaluationSizeofTypeExpression(inners.at(i)));
+ }
+
+ // Pad with zeros
+ while (extraArgs.size() < maxExtraArgCount)
+ extraArgs.push_back("0");
+
+ // in rare cases we need more or less:
+ switch (td.type) {
+ case QAbstractItemType:
+ if (data.dumperFlags.isEmpty()) {
+ qWarning("Internal error: empty dumper state '%s'.", data.iname.constData());
+ } else {
+ inner = data.dumperFlags.mid(1);
+ }
+ break;
+ case QObjectSlotType:
+ case QObjectSignalType: {
+ // we need the number out of something like
+ // iname="local.ob.slots.2" // ".deleteLater()"?
+ const int pos = data.iname.lastIndexOf('.');
+ const QByteArray slotNumber = data.iname.mid(pos + 1);
+ QTC_ASSERT(slotNumber.toInt() != -1, /**/);
+ extraArgs[0] = slotNumber;
+ }
+ break;
+ case QMapType:
+ case QMultiMapType: {
+ QByteArray nodetype;
+ if (m_qtVersion >= 0x040500) {
+ nodetype = m_qtNamespace + "QMapNode";
+ nodetype += data.type.mid(outertype.size());
+ } else {
+ // FIXME: doesn't work for QMultiMap
+ nodetype = data.type + "::Node";
+ }
+ //qDebug() << "OUTERTYPE: " << outertype << " NODETYPE: " << nodetype
+ // << "QT VERSION" << m_qtVersion << ((4 << 16) + (5 << 8) + 0);
+ extraArgs[2] = evaluationSizeofTypeExpression(nodetype);
+ extraArgs[3] = qMapNodeValueOffsetExpression(nodetype);
+ }
+ break;
+ case QMapNodeType:
+ extraArgs[2] = evaluationSizeofTypeExpression(data.type);
+ extraArgs[3] = qMapNodeValueOffsetExpression(data.type);
+ break;
+ case StdVectorType:
+ //qDebug() << "EXTRACT TEMPLATE: " << outertype << inners;
+ if (inners.at(0) == "bool")
+ outertype = "std::vector::bool";
+ break;
+ case StdDequeType:
+ extraArgs[1] = "0";
+ break;
+ case StdStackType:
+ // remove 'std::allocator<...>':
+ extraArgs[1] = "0";
+ break;
+ case StdSetType:
+ // remove 'std::less<...>':
+ extraArgs[1] = "0";
+ // remove 'std::allocator<...>':
+ extraArgs[2] = "0";
+ break;
+ case StdMapType: {
+ // We need the offset of the second item in the value pair.
+ // We read the type of the pair from the allocator argument because
+ // that gets the constness "right" (in the sense that gdb/cdb can
+ // read it back: "std::allocator<std::pair<Key,Value> >"
+ // -> "std::pair<Key,Value>". Different debuggers have varying
+ // amounts of terminating blanks...
+ extraArgs[2].clear();
+ extraArgs[3] = "0";
+ QByteArray pairType = inners.at(3);
+ int bracketPos = pairType.indexOf('<');
+ if (bracketPos != -1)
+ pairType.remove(0, bracketPos + 1);
+ // We don't want the comparator and the allocator confuse gdb.
+ const char closingBracket = '>';
+ bracketPos = pairType.lastIndexOf(closingBracket);
+ if (bracketPos != -1)
+ bracketPos = pairType.lastIndexOf(closingBracket, bracketPos - pairType.size() - 1);
+ if (bracketPos != -1)
+ pairType.truncate(bracketPos + 1);
+ extraArgs[2] = "(size_t)&(('";
+ extraArgs[2] += pairType;
+ extraArgs[2] += "'*)0)->second";
+ }
+ break;
+ case StdStringType:
+ //qDebug() << "EXTRACT TEMPLATE: " << outertype << inners;
+ if (inners.at(0) == "char")
+ outertype = "std::string";
+ else if (inners.at(0) == "wchar_t")
+ outertype = "std::wstring";
+ qFill(extraArgs, zero);
+ break;
+ case UnknownType:
+ qWarning("Unknown type encountered in %s.\n", Q_FUNC_INFO);
+ break;
+ case SupportedType:
+ case QVectorType:
+ case QStackType:
+ case QObjectType:
+ case QWidgetType:
+ break;
+ }
+
+ // Look up expressions in the cache
+ if (!m_expressionCache.empty()) {
+ const ExpressionCache::const_iterator excCend = m_expressionCache.constEnd();
+ const QByteArrayList::iterator eend = extraArgs.end();
+ for (QByteArrayList::iterator it = extraArgs.begin(); it != eend; ++it) {
+ QByteArray &e = *it;
+ if (!e.isEmpty() && e != zero && !isInteger(e)) {
+ const ExpressionCache::const_iterator eit = m_expressionCache.constFind(e);
+ if (eit != excCend)
+ e = eit.value();
+ }
+ }
+ }
+
+ inBuffer->clear();
+ inBuffer->append(outertype.toUtf8());
+ inBuffer->append('\0');
+ inBuffer->append(data.iname);
+ inBuffer->append('\0');
+ inBuffer->append(data.exp);
+ inBuffer->append('\0');
+ inBuffer->append(inner.toUtf8());
+ inBuffer->append('\0');
+ inBuffer->append(data.iname);
+ inBuffer->append('\0');
+
+ if (debug)
+ qDebug() << '\n' << Q_FUNC_INFO << '\n' << data.toString() << "\n-->" << outertype << td.type << extraArgs;
+}
+
+QDebug operator<<(QDebug in, const DumperHelper::TypeData &d)
+{
+ QDebug nsp = in.nospace();
+ nsp << " type=" << d.type << " tpl=" << d.isTemplate;
+ if (d.isTemplate)
+ nsp << d.tmplate << '<' << d.inner << '>';
+ return in;
+}
+
static bool isAccessSpecifier(const QByteArray &ba)
{
return ba == "private" || ba == "protected" || ba == "public";
@@ -98,25 +694,13 @@ static bool parseConsoleStream(const GdbResponse &response, GdbMi *contents)
return contents->isValid();
}
-static double getDumperVersion(const GdbMi &contents)
-{
- const GdbMi dumperVersionG = contents.findChild("dumperversion");
- if (dumperVersionG.type() != GdbMi::Invalid) {
- bool ok;
- const double v = QString::fromAscii(dumperVersionG.data()).toDouble(&ok);
- if (ok)
- return v;
- }
- return 1.0;
-}
-
-
void GdbEngine::updateLocalsClassic(const QVariant &cookie)
{
PRECONDITION;
m_processedNames.clear();
- //PENDING_DEBUG("\nRESET PENDING");
+ if (0 && debugPending)
+ qDebug() << "\nRESET PENDING";
//m_toolTipCache.clear();
clearToolTip();
watchHandler()->beginCycle();
@@ -178,7 +762,7 @@ void GdbEngine::runDebuggingHelperClassic(const WatchData &data0, bool dumpChild
QByteArray params;
QList<QByteArray> extraArgs;
- const QtDumperHelper::TypeData td = m_dumperHelper.typeData(data0.type);
+ const DumperHelper::TypeData td = m_dumperHelper.typeData(data0.type);
m_dumperHelper.evaluationParameters(data, td, &params, &extraArgs);
//int protocol = (data.iname.startsWith("watch") && data.type == "QImage") ? 3 : 2;
@@ -235,9 +819,8 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0)
{
PRECONDITION;
WatchData data = data0;
-# if DEBUG_SUBITEM
- qDebug() << "UPDATE SUBITEM:" << data.toString();
-# endif
+ if (debugSubItem)
+ qDebug() << "UPDATE SUBITEM:" << data.toString();
QTC_ASSERT(data.isValid(), return);
// in any case we need the type first
@@ -271,10 +854,9 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0)
// A common case that can be easily solved.
if (data.isChildrenNeeded() && isPointerType(data.type)
&& !hasDebuggingHelperForType(data.type)) {
- // We sometimes know what kind of children pointers have
-# if DEBUG_SUBITEM
- qDebug() << "IT'S A POINTER";
-# endif
+ // We sometimes know what kind of children pointers have.
+ if (debugSubItem)
+ qDebug() << "IT'S A POINTER";
if (debuggerCore()->boolSetting(AutoDerefPointers)) {
// Try automatic dereferentiation
@@ -297,9 +879,8 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0)
}
if (data.isValueNeeded() && hasDebuggingHelperForType(data.type)) {
-# if DEBUG_SUBITEM
- qDebug() << "UPDATE SUBITEM: CUSTOMVALUE";
-# endif
+ if (debugSubItem)
+ qDebug() << "UPDATE SUBITEM: CUSTOMVALUE";
runDebuggingHelperClassic(data,
watchHandler()->isExpandedIName(data.iname));
return;
@@ -307,9 +888,8 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0)
/*
if (data.isValueNeeded() && data.exp.isEmpty()) {
-# if DEBUG_SUBITEM
- qDebug() << "UPDATE SUBITEM: NO EXPRESSION?";
-# endif
+ if (debugSubItem)
+ qDebug() << "UPDATE SUBITEM: NO EXPRESSION?";
data.setError("<no expression given>");
insertData(data);
return;
@@ -317,9 +897,8 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0)
*/
if (data.isValueNeeded() && data.variable.isEmpty()) {
-# if DEBUG_SUBITEM
- qDebug() << "UPDATE SUBITEM: VARIABLE NEEDED FOR VALUE";
-# endif
+ if (debugSubItem)
+ qDebug() << "UPDATE SUBITEM: VARIABLE NEEDED FOR VALUE";
createGdbVariableClassic(data);
// the WatchVarCreate handler will re-insert a WatchData
// item, with valueNeeded() set.
@@ -328,9 +907,8 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0)
if (data.isValueNeeded()) {
QTC_ASSERT(!data.variable.isEmpty(), return); // tested above
-# if DEBUG_SUBITEM
- qDebug() << "UPDATE SUBITEM: VALUE";
-# endif
+ if (debugSubItem)
+ qDebug() << "UPDATE SUBITEM: VALUE";
QByteArray cmd = "-var-evaluate-expression \"" + data.iname + '"';
postCommand(cmd, WatchUpdate,
CB(handleEvaluateExpressionClassic), QVariant::fromValue(data));
@@ -338,17 +916,15 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0)
}
if (data.isChildrenNeeded() && hasDebuggingHelperForType(data.type)) {
-# if DEBUG_SUBITEM
- qDebug() << "UPDATE SUBITEM: CUSTOMVALUE WITH CHILDREN";
-# endif
+ if (debugSubItem)
+ qDebug() << "UPDATE SUBITEM: CUSTOMVALUE WITH CHILDREN";
runDebuggingHelperClassic(data, true);
return;
}
if (data.isChildrenNeeded() && data.variable.isEmpty()) {
-# if DEBUG_SUBITEM
- qDebug() << "UPDATE SUBITEM: VARIABLE NEEDED FOR CHILDREN";
-# endif
+ if (debugSubItem)
+ qDebug() << "UPDATE SUBITEM: VARIABLE NEEDED FOR CHILDREN";
createGdbVariableClassic(data);
// the WatchVarCreate handler will re-insert a WatchData
// item, with childrenNeeded() set.
@@ -364,18 +940,16 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0)
}
if (data.isHasChildrenNeeded() && hasDebuggingHelperForType(data.type)) {
-# if DEBUG_SUBITEM
- qDebug() << "UPDATE SUBITEM: CUSTOMVALUE WITH CHILDREN";
-# endif
+ if (debugSubItem)
+ qDebug() << "UPDATE SUBITEM: CUSTOMVALUE WITH CHILDREN";
runDebuggingHelperClassic(data, watchHandler()->isExpandedIName(data.iname));
return;
}
//#if !X
if (data.isHasChildrenNeeded() && data.variable.isEmpty()) {
-# if DEBUG_SUBITEM
- qDebug() << "UPDATE SUBITEM: VARIABLE NEEDED FOR CHILDCOUNT";
-# endif
+ if (debugSubItem)
+ qDebug() << "UPDATE SUBITEM: VARIABLE NEEDED FOR CHILDCOUNT";
createGdbVariableClassic(data);
// the WatchVarCreate handler will re-insert a WatchData
// item, with childrenNeeded() set.
@@ -519,7 +1093,8 @@ void GdbEngine::tryLoadDebuggingHelpersClassic()
return;
}
- PENDING_DEBUG("TRY LOAD CUSTOM DUMPERS");
+ if (debugPending)
+ qDebug() << "TRY LOAD CUSTOM DUMPERS";
m_debuggingHelperState = DebuggingHelperUnavailable;
if (!checkDebuggingHelpersClassic())
return;
@@ -574,7 +1149,8 @@ void GdbEngine::tryQueryDebuggingHelpersClassic()
void GdbEngine::updateAllClassic()
{
PRECONDITION;
- PENDING_DEBUG("UPDATING ALL\n");
+ if (debugPending)
+ qDebug() << "UPDATING ALL\n";
QTC_ASSERT(state() == InferiorUnrunnable || state() == InferiorStopOk,
qDebug() << state());
tryLoadDebuggingHelpersClassic();
@@ -709,7 +1285,7 @@ void GdbEngine::handleQueryDebuggingHelperClassic(const GdbResponse &response)
const double dumperVersion = getDumperVersion(contents);
if (dumperVersion < dumperVersionRequired) {
showQtDumperLibraryWarning(
- QtDumperHelper::msgDumperOutdated(dumperVersionRequired, dumperVersion));
+ DumperHelper::msgDumperOutdated(dumperVersionRequired, dumperVersion));
m_debuggingHelperState = DebuggingHelperUnavailable;
return;
}
@@ -790,7 +1366,7 @@ void GdbEngine::handleVarListChildrenHelperClassic(const GdbMi &item,
data.variable = name;
setWatchDataType(data, item.findChild("type"));
setWatchDataValue(data, item);
- setWatchDataAddress(data, item.findChild("addr"));
+ setWatchDataAddress(data, item.findChild("addr"), GdbMi());
data.setHasChildren(false);
insertData(data);
} else if (parent.iname.endsWith('.')) {
@@ -814,7 +1390,7 @@ void GdbEngine::handleVarListChildrenHelperClassic(const GdbMi &item,
data.sortId = sortId;
setWatchDataType(data, item.findChild("type"));
setWatchDataValue(data, item);
- setWatchDataAddress(data, item.findChild("addr"));
+ setWatchDataAddress(data, item.findChild("addr"), GdbMi());
setWatchDataChildCount(data, item.findChild("numchild"));
if (!watchHandler()->isExpandedIName(data.iname))
data.setChildrenUnneeded();
diff --git a/src/plugins/debugger/gdb/coregdbadapter.cpp b/src/plugins/debugger/gdb/coregdbadapter.cpp
index f848317e43..6405f4a816 100644
--- a/src/plugins/debugger/gdb/coregdbadapter.cpp
+++ b/src/plugins/debugger/gdb/coregdbadapter.cpp
@@ -64,8 +64,8 @@ static QByteArray coreName(const DebuggerStartParameters &sp)
return fi.absoluteFilePath().toLocal8Bit();
}
-CoreGdbAdapter::CoreGdbAdapter(GdbEngine *engine, QObject *parent)
- : AbstractGdbAdapter(engine, parent),
+CoreGdbAdapter::CoreGdbAdapter(GdbEngine *engine)
+ : AbstractGdbAdapter(engine),
m_executable(startParameters().executable),
m_coreName(coreName(startParameters()))
{}
diff --git a/src/plugins/debugger/gdb/coregdbadapter.h b/src/plugins/debugger/gdb/coregdbadapter.h
index 9672d7ff5e..10a6447a65 100644
--- a/src/plugins/debugger/gdb/coregdbadapter.h
+++ b/src/plugins/debugger/gdb/coregdbadapter.h
@@ -50,7 +50,7 @@ class CoreGdbAdapter : public AbstractGdbAdapter
Q_OBJECT
public:
- explicit CoreGdbAdapter(GdbEngine *engine, QObject *parent = 0);
+ explicit CoreGdbAdapter(GdbEngine *engine);
private:
DumperHandling dumperHandling() const { return DumperNotAvailable; }
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 14e3bf9826..f184fe5505 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -328,6 +328,12 @@ void GdbEngine::readDebugeeOutput(const QByteArray &data)
showMessage(msg, AppOutput);
}
+static bool isNameChar(char c)
+{
+ // could be 'stopped' or 'shlibs-added'
+ return (c >= 'a' && c <= 'z') || c == '-';
+}
+
void GdbEngine::handleResponse(const QByteArray &buff)
{
showMessage(QString::fromLocal8Bit(buff, buff.length()), LogOutput);
@@ -1002,15 +1008,13 @@ void GdbEngine::handleResultRecord(GdbResponse *response)
// (response->resultClass == GdbResultDone && (cmd.flags & RunRequest));
if (!isExpectedResult) {
-#ifdef Q_OS_WIN
- // Ignore spurious 'running' responses to 'attach'
- const bool warning = !((startParameters().startMode == AttachExternal
- || startParameters().useTerminal)
- && cmd.command.startsWith("attach"));
-#else
- const bool warning = true;
-#endif
- if (warning) {
+ const DebuggerStartParameters &sp = startParameters();
+ if (sp.toolChainAbi.os() == Abi::WindowsOS
+ && cmd.command.startsWith("attach")
+ && (sp.startMode == AttachExternal || sp.useTerminal))
+ {
+ // Ignore spurious 'running' responses to 'attach'.
+ } else {
QByteArray rsp = GdbResponse::stringFromResultClass(response->resultClass);
rsp = "UNEXPECTED RESPONSE '" + rsp + "' TO COMMAND '" + cmd.command + "'";
qWarning() << rsp << " AT " __FILE__ ":" STRINGIFY(__LINE__);
@@ -1193,14 +1197,6 @@ void GdbEngine::handleAqcuiredInferior()
}
#endif
-#ifdef Q_OS_UNIX
-# define STOP_SIGNAL "SIGINT"
-# define CROSS_STOP_SIGNAL "SIGTRAP"
-#else
-# define STOP_SIGNAL "SIGTRAP"
-# define CROSS_STOP_SIGNAL "SIGINT"
-#endif
-
void GdbEngine::handleStopResponse(const GdbMi &data)
{
// This is gdb 7+'s initial *stopped in response to attach.
@@ -1306,9 +1302,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
notifyInferiorStopOk();
}
- // FIXME: Replace the #ifdef by the "target" architecture.
-#ifdef Q_OS_LINUX
- if (!m_entryPoint.isEmpty()) {
+ if (startParameters().toolChainAbi.os() == Abi::LinuxOS && !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:
@@ -1329,9 +1323,6 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
// We are past the initial stop(s). No need to waste time on further checks.
m_entryPoint.clear();
}
-#endif
-
- //qDebug() << "STOP: " << m_qmlBreakpointNumbers;
if (isQmlStepBreakpoint1(bkptno))
return;
@@ -1339,6 +1330,11 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
handleStop0(data);
}
+static QByteArray stopSignal(Abi abi)
+{
+ return (abi.os() == Abi::WindowsOS) ? QByteArray("SIGTRAP") : QByteArray("SIGINT");
+}
+
void GdbEngine::handleStop0(const GdbMi &data)
{
#if 0 // See http://vladimir_prus.blogspot.com/2007/12/debugger-stories-pending-breakpoints.html
@@ -1434,10 +1430,9 @@ void GdbEngine::handleStop0(const GdbMi &data)
if (initHelpers
&& m_gdbAdapter->dumperHandling() != AbstractGdbAdapter::DumperLoadedByGdbPreload
&& reason == "signal-received") {
- QByteArray name = data.findChild("signal-name").data();
- if (name != STOP_SIGNAL
- && (startParameters().startMode != AttachToRemote
- || name != CROSS_STOP_SIGNAL))
+ const QByteArray name = data.findChild("signal-name").data();
+ const DebuggerStartParameters &sp = startParameters();
+ if (name != stopSignal(sp.toolChainAbi))
initHelpers = false;
}
if (isSynchronous())
@@ -1466,17 +1461,20 @@ void GdbEngine::handleStop1(const GdbMi &data)
return;
}
- QByteArray reason = data.findChild("reason").data();
+ const QByteArray reason = data.findChild("reason").data();
+ const DebuggerStartParameters &sp = startParameters();
+ const Abi abi = sp.toolChainAbi;
-#ifdef Q_OS_WIN
- if (startParameters().useTerminal && reason == "signal-received"
- && data.findChild("signal-name").data() == "SIGTRAP") {
+ if (abi.os() == Abi::WindowsOS
+ && sp.useTerminal
+ && reason == "signal-received"
+ && data.findChild("signal-name").data() == "SIGTRAP")
+ {
// Command line start up trap
showMessage(_("INTERNAL CONTINUE"), LogMisc);
continueInferiorInternal();
return;
}
-#endif
// This is for display only.
if (m_modulesListOutdated)
@@ -1527,11 +1525,8 @@ void GdbEngine::handleStop1(const GdbMi &data)
QByteArray meaning = data.findChild("signal-meaning").data();
// Ignore these as they are showing up regularly when
// stopping debugging.
- 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."));
+ if (name == stopSignal(sp.toolChainAbi)) {
+ showMessage(_(name + " CONSIDERED HARMLESS. CONTINUING."));
} else {
showMessage(_("HANDLING SIGNAL" + name));
if (debuggerCore()->boolSetting(UseMessageBoxForSignals))
@@ -1639,20 +1634,19 @@ void GdbEngine::handleHasPython(const GdbResponse &response)
void GdbEngine::pythonDumpersFailed()
{
m_hasPython = false;
- if (m_gdbAdapter->dumperHandling()
- == AbstractGdbAdapter::DumperLoadedByGdbPreload
+ const DebuggerStartParameters &sp = startParameters();
+ 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 += LD_PRELOAD_ENV_VAR;
+ if (sp.toolChainAbi.os() == Abi::MacOS)
+ cmd += "DYLD_INSERT_LIBRARIES";
+ else
+ cmd += "LD_PRELOAD";
cmd += ' ';
- cmd += startParameters().startMode == StartRemoteGdb
- ? startParameters().remoteDumperLib
- : qtDumperLibraryName().toLocal8Bit();
+ if (sp.startMode == StartRemoteGdb)
+ cmd += sp.remoteDumperLib;
+ else
+ cmd += qtDumperLibraryName().toLocal8Bit();
postCommand(cmd);
m_debuggingHelperState = DebuggingHelperLoadTried;
}
@@ -1707,14 +1701,16 @@ QString GdbEngine::fullName(const QString &fileName)
QString GdbEngine::cleanupFullName(const QString &fileName)
{
QString cleanFilePath = 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.
- QFileInfo fi(fileName);
- if (fi.isReadable())
- cleanFilePath = QDir::cleanPath(fi.absoluteFilePath());
-#endif
+
+ const Abi abi = startParameters().toolChainAbi;
+ if (abi.os() == Abi::WindowsOS) {
+ QTC_ASSERT(!fileName.isEmpty(), return QString())
+ // Gdb on windows often delivers "fullnames" which
+ // (a) have no drive letter and (b) are not normalized.
+ QFileInfo fi(fileName);
+ if (fi.isReadable())
+ cleanFilePath = QDir::cleanPath(fi.absoluteFilePath());
+ }
if (startMode() == StartRemoteGdb) {
cleanFilePath.replace(0, startParameters().remoteMountPoint.length(),
startParameters().localMountDir);
@@ -1824,7 +1820,7 @@ int GdbEngine::currentFrame() const
return stackHandler()->currentIndex();
}
-QString msgNoGdbBinaryForToolChain(const ProjectExplorer::Abi &tc)
+QString msgNoGdbBinaryForToolChain(const Abi &tc)
{
return GdbEngine::tr("There is no gdb binary available for binaries in format '%1'")
.arg(tc.toString());
@@ -1833,7 +1829,7 @@ QString msgNoGdbBinaryForToolChain(const ProjectExplorer::Abi &tc)
AbstractGdbAdapter *GdbEngine::createAdapter()
{
const DebuggerStartParameters &sp = startParameters();
- if (sp.toolChainAbi.os() == ProjectExplorer::Abi::SymbianOS) {
+ if (sp.toolChainAbi.os() == Abi::SymbianOS) {
// FIXME: 1 of 3 testing hacks.
if (sp.debugClient == DebuggerStartParameters::DebugClientCoda)
return new CodaGdbAdapter(this);
@@ -1845,7 +1841,7 @@ AbstractGdbAdapter *GdbEngine::createAdapter()
case AttachCore:
return new CoreGdbAdapter(this);
case AttachToRemote:
- return new RemoteGdbServerAdapter(this, sp.toolChainAbi);
+ return new RemoteGdbServerAdapter(this);
case StartRemoteGdb:
return new RemotePlainGdbAdapter(this);
case AttachExternal:
@@ -2267,13 +2263,10 @@ QByteArray GdbEngine::breakpointLocation(BreakpointId id)
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 == BreakpointAtMain) {
+ const Abi abi = startParameters().toolChainAbi;
+ return (abi.os() == Abi::WindowsOS) ? "qMain" : "main";
+ }
if (data.type == BreakpointByFunction)
return data.functionName.toUtf8();
if (data.type == BreakpointByAddress)
@@ -2953,7 +2946,7 @@ void GdbEngine::handleModulesList(const GdbResponse &response)
Modules modules;
if (response.resultClass == GdbResultDone) {
// That's console-based output, likely Linux or Windows,
- // but we can avoid the #ifdef here.
+ // but we can avoid the target dependency here.
QString data = QString::fromLocal8Bit(
response.data.findChild("consolestreamoutput").data());
QTextStream ts(&data, QIODevice::ReadOnly);
@@ -3615,7 +3608,7 @@ bool GdbEngine::hasDebuggingHelperForType(const QByteArray &type) const
return false;
// Simple types.
- return m_dumperHelper.type(type) != QtDumperHelper::UnknownType;
+ return m_dumperHelper.type(type) != DumperHelper::UnknownType;
}
@@ -4125,6 +4118,8 @@ static DisassemblerLine parseLine(const GdbMi &line)
QByteArray address = line.findChild("address").data();
dl.address = address.toULongLong(0, 0);
dl.data = _(line.findChild("inst").data());
+ dl.function = _(line.findChild("func-name").data());
+ dl.offset = line.findChild("offset").data().toUInt();
return dl;
}
@@ -4144,26 +4139,14 @@ DisassemblerLines GdbEngine::parseMiDisassembler(const GdbMi &lines)
// ^done,asm_insns={
// {address="0x0d8f69e0",func-name="...",offset="1952",inst="add $0x0,%al"},..}
- QStringList fileContents;
- bool fileLoaded = false;
DisassemblerLines result;
// FIXME: Performance?
foreach (const GdbMi &child, lines.children()) {
if (child.hasName("src_and_asm_line")) {
- // Mixed mode.
- if (!fileLoaded) {
- QString fileName = QFile::decodeName(child.findChild("file").data());
- fileName = cleanupFullName(fileName);
- QFile file(fileName);
- file.open(QIODevice::ReadOnly);
- QTextStream ts(&file);
- fileContents = ts.readAll().split(QLatin1Char('\n'));
- fileLoaded = true;
- }
- int line = child.findChild("line").data().toInt();
- if (line >= 1 && line <= fileContents.size())
- result.appendComment(fileContents.at(line - 1));
+ const QString fileName = QFile::decodeName(child.findChild("file").data());
+ const uint line = child.findChild("line").data().toUInt();
+ result.appendSourceLine(fileName, line);
GdbMi insn = child.findChild("line_asm_insn");
foreach (const GdbMi &item, insn.children())
result.appendLine(parseLine(item));
@@ -4181,45 +4164,8 @@ DisassemblerLines GdbEngine::parseCliDisassembler(const GdbMi &output)
// First line is something like
// "Dump of assembler code from 0xb7ff598f to 0xb7ff5a07:"
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('<') + 1;
- int pos2 = line.indexOf('+', pos1);
- 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, "");
- }
- if (pos3 - pos2 == 1)
- line.insert(pos2 + 1, "000");
- if (pos3 - pos2 == 2)
- line.insert(pos2 + 1, "00");
- if (pos3 - pos2 == 3)
- line.insert(pos2 + 1, "0");
- dlines.appendLine(DisassemblerLine(_(line)));
- continue;
- }
- dlines.appendComment(someSpace + _(line));
- }
+ foreach (const QByteArray &line, output.data().split('\n'))
+ dlines.appendUnparsed(_(line));
return dlines;
}
@@ -4321,14 +4267,9 @@ static QString gdbBinary(const DebuggerStartParameters &sp)
return QString::fromLocal8Bit(envBinary);
// 2) Command explicitly specified.
if (!sp.debuggerCommand.isEmpty()) {
-#ifdef Q_OS_WIN
// Do not use a CDB binary if we got started for a project with MSVC runtime.
- const bool abiMatch = sp.toolChainAbi.os() != ProjectExplorer::Abi::WindowsOS
- || sp.toolChainAbi.osFlavor() == ProjectExplorer::Abi::WindowsMSysFlavor;
-#else
- const bool abiMatch = true;
-#endif
- if (abiMatch)
+ const Abi abi = sp.toolChainAbi;
+ if (abi.os() != Abi::WindowsOS || abi.osFlavor() == Abi::WindowsMSysFlavor)
return sp.debuggerCommand;
}
// 3) Find one from tool chains.
@@ -4340,20 +4281,18 @@ bool checkGdbConfiguration(const DebuggerStartParameters &sp, ConfigurationCheck
const QString binary = gdbBinary(sp);
if (gdbBinary(sp).isEmpty()) {
check->errorDetails.push_back(msgNoGdbBinaryForToolChain(sp.toolChainAbi));
- check->settingsCategory = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
- check->settingsPage = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
+ check->settingsCategory = _(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
+ check->settingsPage = _(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
return false;
}
-#ifdef Q_OS_WIN
+ if (sp.toolChainAbi.os() == Abi::WindowsOS && !QFileInfo(binary).isAbsolute()) {
// See initialization below, we need an absolute path to be able to locate Python on Windows.
- if (!QFileInfo(binary).isAbsolute()) {
check->errorDetails.push_back(GdbEngine::tr("The gdb location must be given as an "
- "absolute path in the debugger settings (%1).").arg(binary));
- check->settingsCategory = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
- check->settingsPage = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
+ "absolute path in the debugger settings (%1).").arg(binary));
+ check->settingsCategory = _(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
+ check->settingsPage = _(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
return false;
}
-#endif
return true;
}
@@ -4380,46 +4319,46 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &settingsIdHint)
gdbArgs << _("-n");
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);
- QTC_ASSERT(fi.isAbsolute(), return false; )
-
- const QString winPythonVersion = _(winPythonVersionC);
- const QDir dir = fi.absoluteDir();
-
- QProcessEnvironment environment = gdbProc()->processEnvironment();
- const QString pythonPathVariable = _("PYTHONPATH");
- QString pythonPath;
-
- const QString environmentPythonPath = environment.value(pythonPathVariable);
- if (dir.exists(winPythonVersion)) {
- pythonPath = QDir::toNativeSeparators(dir.absoluteFilePath(winPythonVersion));
- } else if (dir.exists(_("lib"))) {
- // Needed for our gdb 7.2 packages
- pythonPath = QDir::toNativeSeparators(dir.absoluteFilePath(_("lib")));
- } else {
- pythonPath = environmentPythonPath;
- }
- if (pythonPath.isEmpty()) {
- const QString nativeGdb = QDir::toNativeSeparators(m_gdb);
- showMessage(_("GDB %1 CANNOT FIND THE PYTHON INSTALLATION.").arg(nativeGdb));
- showStatusMessage(_("%1 cannot find python").arg(nativeGdb));
- const QString msg = tr("The GDB installed at %1 cannot "
- "find a valid python installation in its %2 subdirectory.\n"
- "You may set the environment variable PYTHONPATH to point to your installation.")
- .arg(nativeGdb).arg(winPythonVersion);
- handleAdapterStartFailed(msg, settingsIdHint);
- return false;
- }
- showMessage(_("Python path: %1").arg(pythonPath), LogMisc);
- // Apply to process
- if (pythonPath != environmentPythonPath) {
- environment.insert(pythonPathVariable, pythonPath);
- gdbProc()->setProcessEnvironment(environment);
+ if (sp.toolChainAbi.osFlavor() == Abi::WindowsMSysFlavor) {
+ // 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);
+ QTC_ASSERT(fi.isAbsolute(), return false; )
+
+ const QString winPythonVersion = _(winPythonVersionC);
+ const QDir dir = fi.absoluteDir();
+
+ QProcessEnvironment environment = gdbProc()->processEnvironment();
+ const QString pythonPathVariable = _("PYTHONPATH");
+ QString pythonPath;
+
+ const QString environmentPythonPath = environment.value(pythonPathVariable);
+ if (dir.exists(winPythonVersion)) {
+ pythonPath = QDir::toNativeSeparators(dir.absoluteFilePath(winPythonVersion));
+ } else if (dir.exists(_("lib"))) {
+ // Needed for our gdb 7.2 packages
+ pythonPath = QDir::toNativeSeparators(dir.absoluteFilePath(_("lib")));
+ } else {
+ pythonPath = environmentPythonPath;
+ }
+ if (pythonPath.isEmpty()) {
+ const QString nativeGdb = QDir::toNativeSeparators(m_gdb);
+ showMessage(_("GDB %1 CANNOT FIND THE PYTHON INSTALLATION.").arg(nativeGdb));
+ showStatusMessage(_("%1 cannot find python").arg(nativeGdb));
+ const QString msg = tr("The GDB installed at %1 cannot "
+ "find a valid python installation in its %2 subdirectory.\n"
+ "You may set the environment variable PYTHONPATH to point to your installation.")
+ .arg(nativeGdb).arg(winPythonVersion);
+ handleAdapterStartFailed(msg, settingsIdHint);
+ return false;
+ }
+ showMessage(_("Python path: %1").arg(pythonPath), LogMisc);
+ // Apply to process
+ if (pythonPath != environmentPythonPath) {
+ environment.insert(pythonPathVariable, pythonPath);
+ gdbProc()->setProcessEnvironment(environment);
+ }
}
-#endif
connect(gdbProc(), SIGNAL(error(QProcess::ProcessError)),
SLOT(handleGdbError(QProcess::ProcessError)));
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 32872e21e6..4d9862f11f 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -80,6 +80,122 @@ enum DebuggingHelperState
};
+/* This is only used with Mac gdb since 2.2
+ *
+ * "Custom dumper" is a library compiled against the current
+ * Qt containing functions to evaluate values of Qt classes
+ * (such as QString, taking pointers to their addresses).
+ * The library must be loaded into the debuggee.
+ * It provides a function that takes input from an input buffer
+ * and some parameters and writes output into an output buffer.
+ * Parameter 1 is the protocol:
+ * 1) Query. Fills output buffer with known types, Qt version and namespace.
+ * This information is parsed and stored by this class (special type
+ * enumeration).
+ * 2) Evaluate symbol, taking address and some additional parameters
+ * depending on type. */
+
+class DumperHelper
+{
+public:
+ enum Type {
+ UnknownType,
+ SupportedType, // A type that requires no special handling by the dumper
+ // Below types require special handling
+ QAbstractItemType,
+ QObjectType, QWidgetType, QObjectSlotType, QObjectSignalType,
+ QVectorType, QMapType, QMultiMapType, QMapNodeType, QStackType,
+ StdVectorType, StdDequeType, StdSetType, StdMapType, StdStackType,
+ StdStringType
+ };
+
+ // Type/Parameter struct required for building a value query
+ struct TypeData {
+ TypeData();
+ void clear();
+
+ Type type;
+ bool isTemplate;
+ QByteArray tmplate;
+ QByteArray inner;
+ };
+
+ DumperHelper();
+ void clear();
+
+ double dumperVersion() const { return m_dumperVersion; }
+
+ int typeCount() const;
+ // Look up a simple, non-template type
+ Type simpleType(const QByteArray &simpleType) const;
+ // Look up a (potentially) template type and fill parameter struct
+ TypeData typeData(const QByteArray &typeName) const;
+ Type type(const QByteArray &typeName) const;
+
+ int qtVersion() const;
+ QByteArray qtVersionString() const;
+ QByteArray qtNamespace() const;
+ void setQtNamespace(const QByteArray &ba)
+ { if (!ba.isEmpty()) m_qtNamespace = ba; }
+
+ // Complete parse of "query" (protocol 1) response from debuggee buffer.
+ // 'data' excludes the leading indicator character.
+ bool parseQuery(const GdbMi &data);
+ // Sizes can be added as the debugger determines them
+ void addSize(const QByteArray &type, int size);
+
+ // Determine the parameters required for an "evaluate" (protocol 2) call
+ void evaluationParameters(const WatchData &data,
+ const TypeData &td,
+ QByteArray *inBuffer,
+ QList<QByteArray> *extraParameters) const;
+
+ QString toString(bool debug = false) const;
+
+ static QString msgDumperOutdated(double requiredVersion, double currentVersion);
+
+private:
+ typedef QMap<QString, Type> NameTypeMap;
+ typedef QMap<QByteArray, int> SizeCache;
+
+ // Look up a simple (namespace) type
+ QByteArray evaluationSizeofTypeExpression(const QByteArray &typeName) const;
+
+ NameTypeMap m_nameTypeMap;
+ SizeCache m_sizeCache;
+
+ // The initial dumper query function returns sizes of some special
+ // types to aid CDB since it cannot determine the size of classes.
+ // They are not complete (std::allocator<X>).
+ enum SpecialSizeType { IntSize, PointerSize, StdAllocatorSize,
+ QSharedPointerSize, QSharedDataPointerSize,
+ QWeakPointerSize, QPointerSize,
+ QListSize, QLinkedListSize, QVectorSize, QQueueSize,
+ SpecialSizeCount };
+
+ // Resolve name to enumeration or SpecialSizeCount (invalid)
+ SpecialSizeType specialSizeType(const QByteArray &type) const;
+
+ int m_specialSizes[SpecialSizeCount];
+
+ typedef QMap<QByteArray, QByteArray> ExpressionCache;
+ ExpressionCache m_expressionCache;
+ int m_qtVersion;
+ double m_dumperVersion;
+ QByteArray m_qtNamespace;
+
+ void setQClassPrefixes(const QByteArray &qNamespace);
+
+ QByteArray m_qPointerPrefix;
+ QByteArray m_qSharedPointerPrefix;
+ QByteArray m_qSharedDataPointerPrefix;
+ QByteArray m_qWeakPointerPrefix;
+ QByteArray m_qListPrefix;
+ QByteArray m_qLinkedListPrefix;
+ QByteArray m_qVectorPrefix;
+ QByteArray m_qQueuePrefix;
+};
+
class GdbEngine : public Debugger::DebuggerEngine
{
Q_OBJECT
@@ -543,6 +659,14 @@ private: ////////// View & Data Stuff //////////
void handleStackListArgumentsClassic(const GdbResponse &response);
QSet<QByteArray> m_processedNames;
+ struct TypeInfo
+ {
+ TypeInfo(uint s = 0) : size(s) {}
+
+ uint size;
+ };
+
+ QHash<QByteArray, TypeInfo> m_typeInfoCache;
//
// Dumper Management
@@ -554,7 +678,7 @@ private: ////////// View & Data Stuff //////////
Q_SLOT void setUseDebuggingHelpers(const QVariant &on);
DebuggingHelperState m_debuggingHelperState;
- QtDumperHelper m_dumperHelper;
+ DumperHelper m_dumperHelper;
QString m_gdb;
//
diff --git a/src/plugins/debugger/gdb/localplaingdbadapter.cpp b/src/plugins/debugger/gdb/localplaingdbadapter.cpp
index 080bdb0eff..7c25016288 100644
--- a/src/plugins/debugger/gdb/localplaingdbadapter.cpp
+++ b/src/plugins/debugger/gdb/localplaingdbadapter.cpp
@@ -53,8 +53,8 @@ namespace Internal {
//
///////////////////////////////////////////////////////////////////////
-LocalPlainGdbAdapter::LocalPlainGdbAdapter(GdbEngine *engine, QObject *parent)
- : AbstractPlainGdbAdapter(engine, parent)
+LocalPlainGdbAdapter::LocalPlainGdbAdapter(GdbEngine *engine)
+ : AbstractPlainGdbAdapter(engine)
{
// Output
connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)),
diff --git a/src/plugins/debugger/gdb/localplaingdbadapter.h b/src/plugins/debugger/gdb/localplaingdbadapter.h
index 9a9e010eca..e431357998 100644
--- a/src/plugins/debugger/gdb/localplaingdbadapter.h
+++ b/src/plugins/debugger/gdb/localplaingdbadapter.h
@@ -51,7 +51,7 @@ class LocalPlainGdbAdapter : public AbstractPlainGdbAdapter
Q_OBJECT
public:
- explicit LocalPlainGdbAdapter(GdbEngine *engine, QObject *parent = 0);
+ explicit LocalPlainGdbAdapter(GdbEngine *engine);
private:
void startAdapter();
diff --git a/src/plugins/debugger/gdb/pythongdbengine.cpp b/src/plugins/debugger/gdb/pythongdbengine.cpp
index 6dba4892e1..cd66adb2ee 100644
--- a/src/plugins/debugger/gdb/pythongdbengine.cpp
+++ b/src/plugins/debugger/gdb/pythongdbengine.cpp
@@ -55,9 +55,8 @@ void GdbEngine::updateLocalsPython(bool tryPartial, const QByteArray &varList)
{
PRECONDITION;
m_processedNames.clear();
- watchHandler()->beginCycle(!tryPartial);
- //m_toolTipExpression.clear();
WatchHandler *handler = watchHandler();
+ handler->beginCycle(!tryPartial);
QByteArray expanded = "expanded:" + handler->expansionRequests() + ' ';
expanded += "typeformats:" + handler->typeFormatRequests() + ' ';
@@ -67,8 +66,8 @@ void GdbEngine::updateLocalsPython(bool tryPartial, const QByteArray &varList)
const QString fileName = stackHandler()->currentFrame().file;
const QString function = stackHandler()->currentFrame().function;
if (!fileName.isEmpty()) {
- QStringList expressions =
- DebuggerToolTipManager::instance()->treeWidgetExpressions(fileName, objectName(), function);
+ QStringList expressions = DebuggerToolTipManager::instance()
+ ->treeWidgetExpressions(fileName, objectName(), function);
const QString currentExpression = tooltipExpression();
if (!currentExpression.isEmpty() && !expressions.contains(currentExpression))
expressions.push_back(currentExpression);
@@ -131,11 +130,9 @@ void GdbEngine::handleStackFramePython(const GdbResponse &response)
PRECONDITION;
if (response.resultClass == GdbResultDone) {
const bool partial = response.cookie.toBool();
- //qDebug() << "READING " << (partial ? "PARTIAL" : "FULL");
QByteArray out = response.data.findChild("consolestreamoutput").data();
while (out.endsWith(' ') || out.endsWith('\n'))
out.chop(1);
- //qDebug() << "SECOND CHUNK: " << out;
int pos = out.indexOf("data=");
if (pos != 0) {
showMessage(_("DISCARDING JUNK AT BEGIN OF RESPONSE: "
@@ -144,7 +141,6 @@ void GdbEngine::handleStackFramePython(const GdbResponse &response)
}
GdbMi all;
all.fromStringMultiple(out);
- //qDebug() << "ALL: " << all.toString();
GdbMi data = all.findChild("data");
QList<WatchData> list;
@@ -153,55 +149,32 @@ void GdbEngine::handleStackFramePython(const GdbResponse &response)
dummy.iname = child.findChild("iname").data();
GdbMi wname = child.findChild("wname");
if (wname.isValid()) {
- // Happens (only) for watched expressions. They are encoded as.
+ // Happens (only) for watched expressions. They are encoded as
// base64 encoded 8 bit data, without quotes
- dummy.name = decodeData(wname.data(), 5);
+ dummy.name = decodeData(wname.data(), Base64Encoded8Bit);
dummy.exp = dummy.name.toUtf8();
} else {
dummy.name = _(child.findChild("name").data());
}
- //qDebug() << "CHILD: " << child.toString();
parseWatchData(watchHandler()->expandedINames(), dummy, child, &list);
}
- watchHandler()->insertBulkData(list);
- //for (int i = 0; i != list.size(); ++i)
- // qDebug() << "LOCAL: " << list.at(i).toString();
-
-#if 0
- data = all.findChild("bkpts");
- if (data.isValid()) {
- BreakHandler *handler = breakHandler();
- foreach (const GdbMi &child, data.children()) {
- int bpNumber = child.findChild("number").data().toInt();
- int found = handler->findBreakpoint(bpNumber);
- if (found != -1) {
- BreakpointData *bp = handler->at(found);
- GdbMi addr = child.findChild("addr");
- if (addr.isValid()) {
- bp->bpAddress = child.findChild("addr").data();
- bp->pending = false;
- } else {
- bp->bpAddress = "<PENDING>";
- bp->pending = true;
- }
- bp->bpFuncName = child.findChild("func").data();
- bp->bpLineNumber = child.findChild("line").data();
- bp->bpFileName = child.findChild("file").data();
- bp->markerLineNumber = bp->bpLineNumber.toInt();
- bp->markerFileName = bp->bpFileName;
- // Happens with moved/symlinked sources.
- if (!bp->fileName.isEmpty()
- && !bp->bpFileName.isEmpty()
- && bp->fileName != bp->bpFileName)
- bp->markerFileName = bp->fileName;
- } else {
- QTC_ASSERT(false, qDebug() << child.toString() << bpNumber);
- //bp->bpNumber = "<unavailable>";
- }
+ const GdbMi typeInfo = all.findChild("typeinfo");
+ if (typeInfo.type() == GdbMi::List) {
+ foreach (const GdbMi &s, typeInfo.children()) {
+ const GdbMi name = s.findChild("name");
+ const GdbMi size = s.findChild("size");
+ if (name.isValid() && size.isValid())
+ m_typeInfoCache.insert(QByteArray::fromBase64(name.data()),
+ TypeInfo(size.data().toUInt()));
}
- handler->updateMarkers();
}
-#endif
+ for (int i = 0; i != list.size(); ++i) {
+ const TypeInfo ti = m_typeInfoCache.value(list.at(i).type);
+ if (ti.size)
+ list[i].size = ti.size;
+ }
+
+ watchHandler()->insertBulkData(list);
//PENDING_DEBUG("AFTER handleStackFrame()");
// FIXME: This should only be used when updateLocals() was
diff --git a/src/plugins/debugger/gdb/remotegdbprocess.cpp b/src/plugins/debugger/gdb/remotegdbprocess.cpp
index 09c5173109..30c53a6942 100644
--- a/src/plugins/debugger/gdb/remotegdbprocess.cpp
+++ b/src/plugins/debugger/gdb/remotegdbprocess.cpp
@@ -36,12 +36,13 @@
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
+#include <utils/ssh/sshconnectionmanager.h>
#include <QtCore/QFileInfo>
#include <ctype.h>
-using namespace Core;
+using namespace Utils;
namespace Debugger {
namespace Internal {
@@ -90,11 +91,15 @@ void RemoteGdbProcess::realStart(const QString &cmd, const QStringList &args,
m_gdbOutput.clear();
m_errorOutput.clear();
m_inputToSend.clear();
- m_conn = Utils::SshConnection::create();
- connect(m_conn.data(), SIGNAL(connected()), this, SLOT(handleConnected()));
+ m_conn = SshConnectionManager::instance().acquireConnection(m_connParams);
connect(m_conn.data(), SIGNAL(error(Utils::SshError)), this,
SLOT(handleConnectionError()));
- m_conn->connectToHost(m_connParams);
+ if (m_conn->state() == SshConnection::Connected) {
+ handleConnected();
+ } else {
+ connect(m_conn.data(), SIGNAL(connected()), this, SLOT(handleConnected()));
+ m_conn->connectToHost();
+ }
}
void RemoteGdbProcess::handleConnected()
@@ -385,7 +390,8 @@ void RemoteGdbProcess::setState(State newState)
m_fifoCreator = Utils::SshRemoteProcess::Ptr();
}
disconnect(m_conn.data(), 0, this, 0);
- m_conn->disconnectFromHost();
+ SshConnectionManager::instance().releaseConnection(m_conn);
+ m_conn.clear();
}
}
diff --git a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp
index 157f37f1d9..036017515c 100644
--- a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp
+++ b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp
@@ -58,11 +58,8 @@ namespace Internal {
//
///////////////////////////////////////////////////////////////////////
-RemoteGdbServerAdapter::RemoteGdbServerAdapter(GdbEngine *engine,
- const ProjectExplorer::Abi &abi,
- QObject *parent) :
- AbstractGdbAdapter(engine, parent),
- m_abi(abi)
+RemoteGdbServerAdapter::RemoteGdbServerAdapter(GdbEngine *engine)
+ : AbstractGdbAdapter(engine)
{
connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)),
SLOT(uploadProcError(QProcess::ProcessError)));
@@ -76,9 +73,11 @@ RemoteGdbServerAdapter::RemoteGdbServerAdapter(GdbEngine *engine,
AbstractGdbAdapter::DumperHandling RemoteGdbServerAdapter::dumperHandling() const
{
- if (m_abi.os() == ProjectExplorer::Abi::SymbianOS
- || m_abi.os() == ProjectExplorer::Abi::WindowsOS
- || m_abi.binaryFormat() == ProjectExplorer::Abi::ElfFormat)
+ using namespace ProjectExplorer;
+ const Abi abi = startParameters().toolChainAbi;
+ if (abi.os() == Abi::SymbianOS
+ || abi.os() == Abi::WindowsOS
+ || abi.binaryFormat() == Abi::ElfFormat)
return DumperLoadedByGdb;
return DumperLoadedByGdbPreload;
}
diff --git a/src/plugins/debugger/gdb/remotegdbserveradapter.h b/src/plugins/debugger/gdb/remotegdbserveradapter.h
index 1235f971ec..c33bc198ac 100644
--- a/src/plugins/debugger/gdb/remotegdbserveradapter.h
+++ b/src/plugins/debugger/gdb/remotegdbserveradapter.h
@@ -36,8 +36,6 @@
#include "abstractgdbadapter.h"
#include "localgdbprocess.h"
-#include <projectexplorer/abi.h>
-
namespace Debugger {
namespace Internal {
@@ -52,7 +50,7 @@ class RemoteGdbServerAdapter : public AbstractGdbAdapter
Q_OBJECT
public:
- RemoteGdbServerAdapter(GdbEngine *engine, const ProjectExplorer::Abi &abi, QObject *parent = 0);
+ RemoteGdbServerAdapter(GdbEngine *engine);
private:
DumperHandling dumperHandling() const;
@@ -94,8 +92,6 @@ private:
void handleTargetRemote(const GdbResponse &response);
void handleInterruptInferior(const GdbResponse &response);
- const ProjectExplorer::Abi m_abi;
-
QProcess m_uploadProc;
LocalGdbProcess m_gdbProc;
};
diff --git a/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp b/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp
index 5450943720..e5dc2c84fc 100644
--- a/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp
+++ b/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp
@@ -41,8 +41,8 @@
namespace Debugger {
namespace Internal {
-RemotePlainGdbAdapter::RemotePlainGdbAdapter(GdbEngine *engine, QObject *parent)
- : AbstractPlainGdbAdapter(engine, parent),
+RemotePlainGdbAdapter::RemotePlainGdbAdapter(GdbEngine *engine)
+ : AbstractPlainGdbAdapter(engine),
m_gdbProc(engine->startParameters().connParams, this)
{
connect(&m_gdbProc, SIGNAL(started()), this, SLOT(handleGdbStarted()));
diff --git a/src/plugins/debugger/gdb/remoteplaingdbadapter.h b/src/plugins/debugger/gdb/remoteplaingdbadapter.h
index 751f89dbe5..f90af9ed40 100644
--- a/src/plugins/debugger/gdb/remoteplaingdbadapter.h
+++ b/src/plugins/debugger/gdb/remoteplaingdbadapter.h
@@ -45,7 +45,7 @@ class RemotePlainGdbAdapter : public AbstractPlainGdbAdapter
public:
friend class RemoteGdbProcess;
- explicit RemotePlainGdbAdapter(GdbEngine *engine, QObject *parent = 0);
+ explicit RemotePlainGdbAdapter(GdbEngine *engine);
private slots:
void handleGdbStarted();
diff --git a/src/plugins/debugger/gdb/termgdbadapter.cpp b/src/plugins/debugger/gdb/termgdbadapter.cpp
index 6c599d35a1..38b22e803b 100644
--- a/src/plugins/debugger/gdb/termgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/termgdbadapter.cpp
@@ -62,8 +62,8 @@ namespace Internal {
//
///////////////////////////////////////////////////////////////////////
-TermGdbAdapter::TermGdbAdapter(GdbEngine *engine, QObject *parent)
- : AbstractGdbAdapter(engine, parent)
+TermGdbAdapter::TermGdbAdapter(GdbEngine *engine)
+ : AbstractGdbAdapter(engine)
{
m_stubProc.setMode(Utils::ConsoleProcess::Debug);
#ifdef Q_OS_UNIX
diff --git a/src/plugins/debugger/gdb/termgdbadapter.h b/src/plugins/debugger/gdb/termgdbadapter.h
index d117cb2604..7a16fd242e 100644
--- a/src/plugins/debugger/gdb/termgdbadapter.h
+++ b/src/plugins/debugger/gdb/termgdbadapter.h
@@ -52,7 +52,7 @@ class TermGdbAdapter : public AbstractGdbAdapter
Q_OBJECT
public:
- explicit TermGdbAdapter(GdbEngine *engine, QObject *parent = 0);
+ explicit TermGdbAdapter(GdbEngine *engine);
~TermGdbAdapter();
private:
diff --git a/src/plugins/debugger/memoryagent.cpp b/src/plugins/debugger/memoryagent.cpp
index c091f4998c..08cdce27ba 100644
--- a/src/plugins/debugger/memoryagent.cpp
+++ b/src/plugins/debugger/memoryagent.cpp
@@ -33,7 +33,9 @@
#include "memoryagent.h"
#include "debuggerengine.h"
+#include "debuggerstartparameters.h"
#include "debuggercore.h"
+#include "memoryviewwidget.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
@@ -43,6 +45,9 @@
#include <utils/qtcassert.h>
#include <QtGui/QMessageBox>
+#include <QtGui/QMainWindow>
+
+#include <cstring>
using namespace Core;
@@ -80,6 +85,33 @@ MemoryAgent::~MemoryAgent()
EditorManager::instance()->closeEditors(editors);
}
+void MemoryAgent::openMemoryView(quint64 address, quint64 length, const QPoint &pos)
+{
+ MemoryViewWidget *w = new MemoryViewWidget(Core::ICore::instance()->mainWindow());
+ w->setUpdateOnInferiorStop(true);
+ w->move(pos);
+ w->requestMemory(address, length);
+ addMemoryView(w);
+}
+
+void MemoryAgent::addMemoryView(MemoryViewWidget *w)
+{
+ w->setAbi(m_engine->startParameters().toolChainAbi);
+ connect(w, SIGNAL(memoryRequested(quint64,quint64)),
+ this, SLOT(updateMemoryView(quint64,quint64)));
+ connect(m_engine, SIGNAL(stateChanged(Debugger::DebuggerState)),
+ w, SLOT(engineStateChanged(Debugger::DebuggerState)));
+ connect(w, SIGNAL(openViewRequested(quint64,quint64,QPoint)),
+ this, SLOT(openMemoryView(quint64,quint64,QPoint)));
+ w->requestMemory();
+ w->show();
+}
+
+void MemoryAgent::updateMemoryView(quint64 address, quint64 length)
+{
+ m_engine->fetchMemory(this, sender(), address, length);
+}
+
void MemoryAgent::createBinEditor(quint64 addr)
{
EditorManager *editorManager = EditorManager::instance();
@@ -132,11 +164,16 @@ void MemoryAgent::fetchLazyData(IEditor *editor, quint64 block)
void MemoryAgent::addLazyData(QObject *editorToken, quint64 addr,
const QByteArray &ba)
{
- IEditor *editor = qobject_cast<IEditor *>(editorToken);
- if (editor && editor->widget()) {
- QMetaObject::invokeMethod(editor->widget(), "addData",
- Q_ARG(quint64, addr / BinBlockSize), Q_ARG(QByteArray, ba));
+
+ if (IEditor *editor = qobject_cast<IEditor *>(editorToken)) {
+ if (QWidget *editorWidget = editor->widget()) {
+ QMetaObject::invokeMethod(editorWidget , "addData",
+ Q_ARG(quint64, addr / BinBlockSize), Q_ARG(QByteArray, ba));
+ }
+ return;
}
+ if (MemoryViewWidget *mvw = qobject_cast<MemoryViewWidget*>(editorToken))
+ mvw->setData(ba);
}
void MemoryAgent::provideNewRange(IEditor *editor, quint64 address)
@@ -184,5 +221,42 @@ bool MemoryAgent::hasVisibleEditor() const
return false;
}
+bool MemoryAgent::isBigEndian(const ProjectExplorer::Abi &a)
+{
+ switch (a.architecture()) {
+ case ProjectExplorer::Abi::UnknownArchitecture:
+ case ProjectExplorer::Abi::X86Architecture:
+ case ProjectExplorer::Abi::ItaniumArchitecture: // Configureable
+ case ProjectExplorer::Abi::ArmArchitecture: // Configureable
+ break;
+ case ProjectExplorer::Abi::MipsArcitecture: // Configureable
+ case ProjectExplorer::Abi::PowerPCArchitecture: // Configureable
+ return true;
+ }
+ return false;
+}
+
+// Read a POD variable from a memory location. Swap bytes if endianness differs
+template <class POD> POD readPod(const unsigned char *data, bool swapByteOrder)
+{
+ POD pod = 0;
+ if (swapByteOrder) {
+ unsigned char *target = reinterpret_cast<unsigned char *>(&pod) + sizeof(POD) - 1;
+ for (size_t i = 0; i < sizeof(POD); i++)
+ *target-- = data[i];
+ } else {
+ std::memcpy(&pod, data, sizeof(POD));
+ }
+ return pod;
+}
+
+// Read memory from debuggee
+quint64 MemoryAgent::readInferiorPointerValue(const unsigned char *data, const ProjectExplorer::Abi &a)
+{
+ const bool swapByteOrder = isBigEndian(a) != isBigEndian(ProjectExplorer::Abi::hostAbi());
+ return a.wordWidth() == 32 ? readPod<quint32>(data, swapByteOrder) :
+ readPod<quint64>(data, swapByteOrder);
+}
+
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/memoryagent.h b/src/plugins/debugger/memoryagent.h
index 302cb47170..7d005cfe8c 100644
--- a/src/plugins/debugger/memoryagent.h
+++ b/src/plugins/debugger/memoryagent.h
@@ -36,15 +36,22 @@
#include <QtCore/QObject>
#include <QtCore/QPointer>
+QT_FORWARD_DECLARE_CLASS(QPoint)
+
namespace Core {
class IEditor;
}
+namespace ProjectExplorer {
+class Abi;
+}
+
namespace Debugger {
class DebuggerEngine;
namespace Internal {
+class MemoryViewWidget;
class MemoryAgent : public QObject
{
@@ -57,9 +64,14 @@ public:
enum { BinBlockSize = 1024 };
bool hasVisibleEditor() const;
+ static bool isBigEndian(const ProjectExplorer::Abi &a);
+ static quint64 readInferiorPointerValue(const unsigned char *data, const ProjectExplorer::Abi &a);
+
public slots:
// Called by engine to create a new view.
void createBinEditor(quint64 startAddr);
+ // Called by engine to create a tooltip.
+ void addMemoryView(MemoryViewWidget *w);
// Called by engine to trigger update of contents.
void updateContents();
// Called by engine to pass updated contents.
@@ -72,6 +84,8 @@ private slots:
void handleEndOfFileRequested(Core::IEditor *editor);
void handleDataChanged(Core::IEditor *editor, quint64 address,
const QByteArray &data);
+ void updateMemoryView(quint64 address, quint64 length);
+ void openMemoryView(quint64 address, quint64 length, const QPoint &pos);
private:
QList<QPointer<Core::IEditor> > m_editors;
diff --git a/src/plugins/debugger/memoryviewwidget.cpp b/src/plugins/debugger/memoryviewwidget.cpp
new file mode 100644
index 0000000000..3b622d962d
--- /dev/null
+++ b/src/plugins/debugger/memoryviewwidget.cpp
@@ -0,0 +1,666 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "memoryviewwidget.h"
+#include "memoryagent.h"
+#include "registerhandler.h"
+
+#include <coreplugin/coreconstants.h>
+#include <texteditor/fontsettings.h>
+
+#include <QtGui/QLabel>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QPlainTextEdit>
+#include <QtGui/QScrollBar>
+#include <QtGui/QToolButton>
+#include <QtGui/QToolBar>
+#include <QtGui/QTextCursor>
+#include <QtGui/QTextBlock>
+#include <QtGui/QTextDocument>
+#include <QtGui/QIcon>
+#include <QtGui/QFont>
+#include <QtGui/QFontMetrics>
+#include <QtGui/QMenu>
+
+#include <QtCore/QTextStream>
+#include <QtCore/QDebug>
+#include <QtCore/QVariant>
+
+#include <cctype>
+
+enum { debug = 0 };
+
+// Formatting: 'aaaa:aaaa 0f ab... ASC..'
+enum
+{
+ bytesPerLine = 16,
+ lineWidth = 11 + 4 * bytesPerLine
+};
+
+namespace Debugger {
+namespace Internal {
+
+/*!
+ \class Debugger::Internal::MemoryViewWidget
+ \brief Base class for memory view tool windows
+
+ Small tool-window that stays on top and displays a chunk of memory.
+ Provides next/previous browsing.
+
+ Constructed by passing an instance to \c DebuggerEngine::addMemoryView()
+ which will pass it on to \c Debugger::Internal::MemoryAgent::addMemoryView()
+ to set up the signal connections to the engine.
+
+ Provides API for marking text with a special format/color.
+ The formatting is stored as a list of struct MemoryViewWidget::Markup and applied
+ by converting into extra selections once data arrives in setData().
+
+ Provides a context menu that offers to open a subview from a pointer value
+ obtained from the memory shown (converted using the Abi).
+
+ \sa Debugger::Internal::MemoryAgent, Debugger::DebuggerEngine
+ \sa ProjectExplorer::Abi
+*/
+
+const quint64 MemoryViewWidget::defaultLength = 128;
+
+MemoryViewWidget::MemoryViewWidget(QWidget *parent) :
+ QWidget(parent, Qt::Tool|Qt::WindowStaysOnTopHint),
+ m_previousButton(new QToolButton),
+ m_nextButton(new QToolButton),
+ m_textEdit(new QPlainTextEdit),
+ m_content(new QLabel),
+ m_address(0),
+ m_length(0),
+ m_requestedAddress(0),
+ m_requestedLength(0),
+ m_updateOnInferiorStop(false)
+{
+ setAttribute(Qt::WA_DeleteOnClose);
+ QVBoxLayout *layout = new QVBoxLayout(this);
+
+ QToolBar *toolBar = new QToolBar;
+ toolBar->setObjectName(QLatin1String("MemoryViewWidgetToolBar"));
+ toolBar->setProperty("_q_custom_style_disabled", QVariant(true));
+ toolBar->setIconSize(QSize(16, 16));
+ m_previousButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_PREV)));
+ connect(m_previousButton, SIGNAL(clicked()), this, SLOT(slotPrevious()));
+ toolBar->addWidget(m_previousButton);
+ m_nextButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_NEXT)));
+ connect(m_nextButton, SIGNAL(clicked()), this, SLOT(slotNext()));
+ toolBar->addWidget(m_nextButton);
+
+ layout->addWidget(toolBar);
+ m_textEdit->setObjectName(QLatin1String("MemoryViewWidgetTextEdit"));
+ m_textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ m_textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ m_textEdit->setReadOnly(true);
+ m_textEdit->setWordWrapMode(QTextOption::NoWrap);
+ m_textEdit->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(m_textEdit, SIGNAL(customContextMenuRequested(QPoint)),
+ this, SLOT(slotContextMenuRequested(QPoint)));
+ // Text: Pick a fixed font and set minimum size to accommodate default length with vertical scrolling
+ const QFont fixedFont(TextEditor::FontSettings::defaultFixedFontFamily(), TextEditor::FontSettings::defaultFontSize());
+ const QFontMetrics metrics(fixedFont);
+ const QSize lineSize = metrics.size(Qt::TextSingleLine , QString(lineWidth, QLatin1Char('0')));
+ int defaultLineCount = defaultLength / bytesPerLine;
+ if (defaultLength % bytesPerLine)
+ defaultLineCount++;
+ const QSize textSize(lineSize.width() + m_textEdit->verticalScrollBar()->width() + 10,
+ lineSize.height() * defaultLineCount + 10);
+ m_textEdit->setFont(fixedFont);
+ m_textEdit->setMinimumSize(textSize);
+ m_textEdit->installEventFilter(this);
+ layout->addWidget(m_textEdit);
+}
+
+void MemoryViewWidget::engineStateChanged(Debugger::DebuggerState s)
+{
+ switch (s) {
+ case Debugger::InferiorUnrunnable:
+ setBrowsingEnabled(true);
+ break;
+ case Debugger::InferiorStopOk:
+ setBrowsingEnabled(true);
+ if (m_updateOnInferiorStop)
+ requestMemory();
+ break;
+ case Debugger::DebuggerFinished:
+ close();
+ break;
+ default:
+ setBrowsingEnabled(false);
+ break;
+ }
+}
+
+void MemoryViewWidget::setBrowsingEnabled(bool b)
+{
+ m_previousButton->setEnabled(b && m_address >= m_length);
+ m_nextButton->setEnabled(b);
+}
+
+void MemoryViewWidget::clear()
+{
+ m_data.clear();
+ m_textEdit->setExtraSelections(QList<QTextEdit::ExtraSelection>());
+ m_textEdit->setPlainText(tr("No data available."));
+ setBrowsingEnabled(false);
+ updateTitle();
+}
+
+void MemoryViewWidget::requestMemory()
+{
+ requestMemory(m_address, m_length);
+}
+
+void MemoryViewWidget::requestMemory(quint64 address, quint64 length)
+{
+ m_requestedAddress = address;
+ m_requestedLength = length;
+
+ // For RegisterMemoryViewWidget, the register values sometimes switch to 0
+ // while stepping, handle gracefully.
+ if (!address || !length) {
+ m_address = address;
+ m_length = length;
+ clear();
+ return;
+ }
+
+ // Is this the first request and no data available yet? -> Set initial state.
+ if (m_data.isEmpty() && !m_address && !m_length) {
+ m_address = address;
+ m_length = length;
+ updateTitle();
+ m_textEdit->setPlainText(tr("Fetching %1 bytes...").arg(length));
+ setBrowsingEnabled(false);
+ }
+ if (debug)
+ qDebug() << this << "requestMemory()" << m_requestedAddress << m_requestedLength
+ << " currently at: " << m_address << m_length;
+ emit memoryRequested(m_requestedAddress, m_requestedLength);
+}
+
+void MemoryViewWidget::setTitle(const QString &t)
+{
+ setWindowTitle(t);
+}
+
+void MemoryViewWidget::slotNext()
+{
+ requestMemory(m_address + m_length, m_length);
+}
+
+void MemoryViewWidget::slotPrevious()
+{
+ if (m_address >= m_length)
+ requestMemory(m_address - m_length, m_length);
+}
+
+// Convert address to line and column in range 0..(n - 1), return false
+// if out of range.
+bool MemoryViewWidget::addressToLineColumn(quint64 posAddress,
+ int *lineIn /* = 0 */, int *columnIn /* = 0 */,
+ quint64 *lineStartIn /* = 0 */) const
+{
+ if (posAddress < m_address)
+ return false;
+ const quint64 offset = posAddress - m_address;
+ if (offset >= quint64(m_data.size()))
+ return false;
+ const quint64 line = offset / bytesPerLine;
+ const quint64 lineStart = m_address + line * bytesPerLine;
+ if (lineStartIn)
+ *lineStartIn = lineStart;
+ if (lineIn)
+ *lineIn = int(line);
+ const int column = 3 * int(offset % bytesPerLine) + 10;
+ if (columnIn)
+ *columnIn = column;
+ if (debug)
+ qDebug() << this << "at" << m_address << " addressToLineColumn "
+ << posAddress << "->" << line << ',' << column << " lineAt" << lineStart;
+ return true;
+}
+
+// Return address at position
+quint64 MemoryViewWidget::addressAt(const QPoint &textPos) const
+{
+ QTextCursor cursor = m_textEdit->cursorForPosition(textPos);
+ if (cursor.isNull())
+ return 0;
+ const int line = cursor.blockNumber();
+ const int column = cursor.columnNumber() - 1;
+ const quint64 lineAddress = m_address + line * bytesPerLine;
+ const int byte = (qMax(0, column - 9)) / 3;
+ if (byte >= bytesPerLine) // Within ASC part
+ return 0;
+ return lineAddress + byte;
+}
+
+void MemoryViewWidget::slotContextMenuRequested(const QPoint &pos)
+{
+ QMenu *menu = m_textEdit->createStandardContextMenu();
+ menu->addSeparator();
+ // Add action offering to open a sub-view with a pointer read from the memory
+ // at the location: Dereference the chunk of memory as pointer address.
+ QAction *derefPointerAction = 0;
+ quint64 pointerValue = 0;
+ if (!m_data.isEmpty()) {
+ const quint64 pointerSize = m_abi.wordWidth() / 8;
+ quint64 contextAddress = addressAt(pos);
+ if (const quint64 remainder = contextAddress % pointerSize) // Pad pointer location.
+ contextAddress -= remainder;
+ // Dereference pointer from location
+ if (contextAddress) {
+ const quint64 dataOffset = contextAddress - address();
+ if (pointerSize && (dataOffset + pointerSize) <= quint64(m_data.size())) {
+ const unsigned char *data = reinterpret_cast<const unsigned char *>(m_data.constData() + dataOffset);
+ pointerValue = MemoryAgent::readInferiorPointerValue(data, m_abi);
+ }
+ }
+ } // has data
+ if (pointerValue) {
+ const QString msg = tr("Open Memory View at Pointer Value 0x%1")
+ .arg(pointerValue, 0, 16);
+ derefPointerAction = menu->addAction(msg);
+ } else {
+ derefPointerAction = menu->addAction("Open Memory View at Pointer Value");
+ derefPointerAction->setEnabled(false);
+ }
+ const QPoint globalPos = m_textEdit->mapToGlobal(pos);
+ QAction *action = menu->exec(globalPos);
+ if (!action)
+ return;
+ if (action == derefPointerAction) {
+ emit openViewRequested(pointerValue, MemoryViewWidget::defaultLength, globalPos);
+ return;
+ }
+}
+
+// Format address as in binary editor '0000:00AB' onto a stream set up for hex output.
+static inline void formatAddressToHexStream(QTextStream &hexStream, quint64 address)
+{
+ hexStream.setFieldWidth(4);
+ hexStream << ((address >> 16) & 0xFFFF);
+ hexStream.setFieldWidth(1);
+ hexStream << ':';
+ hexStream.setFieldWidth(4);
+ hexStream << (address & 0xFFFF);
+}
+
+// Return formatted address for window title: Prefix + binary editor format: '0x0000:00AB'
+static inline QString formattedAddress(quint64 a)
+{
+ QString rc = QLatin1String("0x");
+ QTextStream str(&rc);
+ str.setIntegerBase(16);
+ str.setPadChar(QLatin1Char('0'));
+ formatAddressToHexStream(str, a);
+ return rc;
+}
+
+// Format data as in binary editor '0000:00AB 0A A3 ..ccc'
+QString MemoryViewWidget::formatData(quint64 startAddress, const QByteArray &data)
+{
+ QString rc;
+ rc.reserve(5 * data.size());
+ const quint64 endAddress = startAddress + data.size();
+ QTextStream str(&rc);
+ str.setIntegerBase(16);
+ str.setPadChar(QLatin1Char('0'));
+ str.setFieldAlignment(QTextStream::AlignRight);
+ for (quint64 address = startAddress; address < endAddress; address += 16) {
+ formatAddressToHexStream(str, address);
+ // Format hex bytes
+ const int dataStart = int(address - startAddress);
+ const int dataEnd = qMin(dataStart + int(bytesPerLine), data.size());
+ for (int i = dataStart; i < dataEnd; i++) {
+ str.setFieldWidth(1);
+ str << ' ';
+ str.setFieldWidth(2);
+ const char c = data.at(i);
+ unsigned char uc = c;
+ str << unsigned(uc);
+ }
+ // Pad for character part
+ str.setFieldWidth(1);
+ if (const int remainder = int(bytesPerLine) - (dataEnd - dataStart))
+ str << QString(3 * remainder, QLatin1Char(' '));
+ // Format characters
+ str << ' ';
+ for (int i = dataStart; i < dataEnd; i++) {
+ const char c = data.at(i);
+ str << (c >= 0 && std::isprint(c) ? c : '.'); // MSVC has an assert on c>=0.
+ }
+ str << '\n';
+ }
+ return rc;
+}
+
+void MemoryViewWidget::updateTitle()
+{
+ const QString title = tr("Memory at %1").arg(formattedAddress(address()));
+ setTitle(title);
+}
+
+// Convert an markup range into a list of selections for the bytes,
+// resulting in a rectangular selection in the bytes area (provided range
+// is within data available).
+bool MemoryViewWidget::markUpToSelections(const Markup &r,
+ QList<QTextEdit::ExtraSelection> *extraSelections) const
+{
+ // Fully covered?
+ if (r.address < m_address)
+ return false;
+ const quint64 rangeEnd = r.address + r.size;
+ if (rangeEnd > (m_address + quint64(m_data.size())))
+ return false;
+
+ QTextCursor cursor = m_textEdit->textCursor();
+ cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
+
+ // Goto first position
+ int line;
+ int column;
+ quint64 lineStartAddress;
+
+ if (!addressToLineColumn(r.address, &line, &column, &lineStartAddress))
+ return false;
+
+ if (line)
+ cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, line);
+ if (column)
+ cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, column - 1);
+
+ quint64 current = r.address;
+ // Mark rectangular area in the bytes section
+ while (true) {
+ // Mark in current line
+ quint64 nextLineAddress = lineStartAddress + bytesPerLine;
+ const int numberOfCharsToMark = 3 * int(qMin(nextLineAddress, rangeEnd) - current);
+ cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, numberOfCharsToMark);
+ QTextEdit::ExtraSelection sel;
+ sel.cursor = cursor;
+ sel.format = r.format;
+ extraSelections->push_back(sel);
+ if (nextLineAddress >= rangeEnd)
+ break;
+ // Goto beginning of next line, past address.
+ cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, 9);
+ lineStartAddress += bytesPerLine;
+ current = lineStartAddress;
+ }
+ return true;
+}
+
+void MemoryViewWidget::clearMarkup()
+{
+ m_markup.clear();
+ m_textEdit->setExtraSelections(QList<QTextEdit::ExtraSelection>());
+}
+
+void MemoryViewWidget::addMarkup(quint64 begin, quint64 size,
+ const QTextCharFormat &fmt, const QString &toolTip)
+{
+ m_markup.push_back(Markup(begin, size, fmt, toolTip));
+}
+
+void MemoryViewWidget::addMarkup(quint64 begin, quint64 size,
+ const QColor &background, const QString &toolTip)
+{
+ QTextCharFormat format = textCharFormat();
+ format.setBackground(QBrush(background));
+ addMarkup(begin, size, format, toolTip);
+}
+
+QTextCharFormat MemoryViewWidget::textCharFormat() const
+{
+ return m_textEdit->currentCharFormat();
+}
+
+void MemoryViewWidget::setData(const QByteArray &a)
+{
+ if (debug)
+ qDebug() << this << m_requestedAddress << m_requestedLength << "received" << a.size();
+
+ if (quint64(a.size()) < m_requestedLength) {
+ const QString msg = QString::fromLatin1("Warning: %1 received only %2 bytes of %3 at 0x%4")
+ .arg(QString::fromAscii(metaObject()->className()))
+ .arg(a.size()).arg(m_requestedLength).arg(m_requestedAddress, 0, 16);
+ qWarning("%s", qPrintable(msg));
+ }
+
+ if (m_address != m_requestedAddress || m_length != m_requestedLength) {
+ m_address = m_requestedAddress;
+ m_length = m_requestedLength;
+ updateTitle();
+ }
+
+ if (a.isEmpty()) {
+ clear();
+ return;
+ }
+
+ m_data = a;
+
+ QList<QTextEdit::ExtraSelection> extra;
+ m_textEdit->setExtraSelections(extra);
+ m_textEdit->setPlainText(MemoryViewWidget::formatData(address(), a));
+ // Do markup which is in visible range now.
+ foreach (const Markup &r, m_markup)
+ markUpToSelections(r, &extra);
+ if (!extra.isEmpty())
+ m_textEdit->setExtraSelections(extra);
+ setBrowsingEnabled(true);
+}
+
+// Find markup by address.
+int MemoryViewWidget::indexOfMarkup(quint64 address) const
+{
+ const int size = m_markup.size();
+ for (int m = 0; m < size; m++)
+ if (m_markup.at(m).covers(address))
+ return m;
+ return -1;
+}
+
+bool MemoryViewWidget::eventFilter(QObject *o, QEvent *e)
+{
+ if (o != m_textEdit || e->type() != QEvent::ToolTip)
+ return QWidget::eventFilter(o, e);
+ // ToolTip handling: is the cursor over an address range that has a tooltip
+ // defined in the markup list?
+ const QHelpEvent *he = static_cast<const QHelpEvent *>(e);
+ if (const quint64 toolTipAddress = addressAt(he->pos())) {
+ const int mIndex = indexOfMarkup(toolTipAddress);
+ if (mIndex != -1) {
+ m_textEdit->setToolTip(m_markup.at(mIndex).toolTip);
+ } else {
+ m_textEdit->setToolTip(QString());
+ }
+ }
+ return QWidget::eventFilter(o, e);
+}
+
+/*!
+ \class Debugger::Internal::LocalsMemoryViewWidget
+ \brief Memory view that shows the memory at the location of a local variable.
+
+ Refreshes whenever Debugger::InferiorStopOk is reported.
+
+ \sa Debugger::Internal::WatchWindow
+ \sa Debugger::Internal::MemoryAgent, Debugger::DebuggerEngine
+*/
+
+LocalsMemoryViewWidget::LocalsMemoryViewWidget(QWidget *parent) :
+ MemoryViewWidget(parent), m_variableAddress(0)
+{
+ setUpdateOnInferiorStop(true);
+}
+
+void LocalsMemoryViewWidget::init(quint64 variableAddress, quint64 size, const QString &name)
+{
+ m_variableAddress = variableAddress;
+ m_variableSize = size;
+ m_variableName = name;
+ // Size may be 0.
+ addMarkup(variableAddress, qMax(size, quint64(1)), Qt::lightGray);
+ requestMemory(m_variableAddress, qMax(size, quint64(defaultLength)));
+ if (debug)
+ qDebug() << this << "init" << variableAddress << m_variableName << m_variableSize;
+}
+
+void LocalsMemoryViewWidget::updateTitle()
+{
+ const QString variableAddress = formattedAddress(m_variableAddress);
+ if (address() == m_variableAddress) {
+ const QString title = tr("Memory at '%1' (%2)")
+ .arg(m_variableName, variableAddress);
+ setTitle(title);
+ } else if (address() > m_variableAddress) {
+ const QString title = tr("Memory at '%1' (%2 + %3)")
+ .arg(m_variableName, variableAddress)
+ .arg(address() - m_variableAddress);
+ setTitle(title);
+ } else if (address() < m_variableAddress) {
+ const QString title = tr("Memory at '%1' (%2 - %3)")
+ .arg(m_variableName, variableAddress)
+ .arg(m_variableAddress - address());
+ setTitle(title);
+ }
+}
+
+/*!
+ \class Debugger::Internal::RegisterMemoryViewWidget
+ \brief Memory view that shows the memory around the contents of a register
+ (such as stack pointer, program counter),
+ tracking changes of the register value.
+
+ Connects to Debugger::Internal::RegisterHandler to listen for changes
+ of the register value.
+
+ \sa Debugger::Internal::RegisterHandler, Debugger::Internal::RegisterWindow
+ \sa Debugger::Internal::MemoryAgent, Debugger::DebuggerEngine
+*/
+
+RegisterMemoryViewWidget::Markup::Markup(quint64 a, quint64 s,
+ const QTextCharFormat &fmt, const QString &tt) :
+ address(a), size(s), format(fmt), toolTip(tt)
+{
+}
+
+RegisterMemoryViewWidget::RegisterMemoryViewWidget(QWidget *parent) :
+ MemoryViewWidget(parent),
+ m_registerIndex(-1),
+ m_registerAddress(0),
+ m_offset(0)
+{
+ setUpdateOnInferiorStop(false); // We update on register changed.
+}
+
+void RegisterMemoryViewWidget::updateTitle()
+{
+ const quint64 shownAddress = address() + m_offset;
+ const QString registerAddress = formattedAddress(m_registerAddress);
+ if (shownAddress == m_registerAddress) {
+ const QString title = tr("Memory at Register '%1' (%2)")
+ .arg(m_registerName, registerAddress);
+ setTitle(title);
+ } else if (shownAddress > m_registerAddress) {
+ const QString title = tr("Memory at Register '%1' (%2 + %3)")
+ .arg(m_registerName, registerAddress)
+ .arg(shownAddress - m_registerAddress);
+ setTitle(title);
+ } else if (shownAddress < m_registerAddress) {
+ const QString title = tr("Memory at Register '%1' (%2 - %3)")
+ .arg(m_registerName, registerAddress)
+ .arg(m_registerAddress - shownAddress);
+ setTitle(title);
+ }
+}
+
+void RegisterMemoryViewWidget::setRegisterAddress(quint64 a)
+{
+ if (!a) { // Registers might switch to 0 (for example, 'rsi' while stepping out).
+ m_offset = m_registerAddress = a;
+ requestMemory(0, 0);
+ return;
+ }
+ if (m_registerAddress == a) { // Same value: just re-fetch
+ requestMemory();
+ return;
+ }
+ // Show an area around that register
+ m_registerAddress = a;
+ const quint64 range = MemoryViewWidget::defaultLength / 2;
+ const quint64 end = a + range;
+ const quint64 begin = a >= range ? a - range : 0;
+ m_offset = m_registerAddress - begin;
+ // Mark one byte showing the register
+ clearMarkup();
+ addMarkup(m_registerAddress, 1, Qt::lightGray, tr("Register %1").arg(m_registerName));
+ requestMemory(begin, end - begin);
+}
+
+void RegisterMemoryViewWidget::slotRegisterSet(const QModelIndex &index)
+{
+ if (m_registerIndex != index.row())
+ return;
+ const QVariant newAddressV = index.data(Qt::EditRole);
+ if (newAddressV.type() == QVariant::ULongLong) {
+ if (debug)
+ qDebug() << this << m_registerIndex << m_registerName << "slotRegisterSet" << newAddressV;
+ setRegisterAddress(newAddressV.toULongLong());
+ }
+}
+
+void RegisterMemoryViewWidget::init(int registerIndex, RegisterHandler *h)
+{
+ m_registerIndex = registerIndex;
+ m_registerName = QString::fromAscii(h->registerAt(registerIndex).name);
+ if (debug)
+ qDebug() << this << "init" << registerIndex << m_registerName;
+ // Known issue: CDB might reset the model by changing the special
+ // registers it reports.
+ connect(h, SIGNAL(modelReset()), this, SLOT(close()));
+ connect(h, SIGNAL(registerSet(QModelIndex)),
+ this, SLOT(slotRegisterSet(QModelIndex)));
+ setRegisterAddress(h->registerAt(m_registerIndex).editValue().toULongLong());
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/memoryviewwidget.h b/src/plugins/debugger/memoryviewwidget.h
new file mode 100644
index 0000000000..505bad2bdd
--- /dev/null
+++ b/src/plugins/debugger/memoryviewwidget.h
@@ -0,0 +1,187 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 MEMORYTOOLTIP_H
+#define MEMORYTOOLTIP_H
+
+#include "debuggerconstants.h"
+
+#include <projectexplorer/abi.h>
+
+#include <QtGui/QTextEdit> // QTextEdit::ExtraSelection
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+class QLabel;
+class QModelIndex;
+class QPlainTextEdit;
+class QToolButton;
+class QTextCharFormat;
+QT_END_NAMESPACE
+
+namespace Debugger {
+class DebuggerEngine;
+namespace Internal {
+class RegisterHandler;
+
+// Documentation inside.
+class MemoryViewWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ // Address range to be marked with special format
+ struct Markup
+ {
+ Markup(quint64 a = 0, quint64 s = 0,
+ const QTextCharFormat &fmt = QTextCharFormat(),
+ const QString &toolTip = QString());
+ bool covers(quint64 a) const { return a >= address && a < (address + size); }
+
+ quint64 address;
+ quint64 size;
+ QTextCharFormat format;
+ QString toolTip;
+ };
+
+ explicit MemoryViewWidget(QWidget *parent = 0);
+
+ quint64 address() const { return m_address; }
+ quint64 length() const { return m_length; }
+
+ // How read an address used for 'dereference pointer at' context menu action
+ void setAbi(const ProjectExplorer::Abi &a) { m_abi = a; }
+ ProjectExplorer::Abi abi() const { return m_abi; }
+
+ bool updateOnInferiorStop() const { return m_updateOnInferiorStop; }
+ void setUpdateOnInferiorStop(bool v) { m_updateOnInferiorStop = v ; }
+
+ QTextCharFormat textCharFormat() const;
+
+ QList<Markup> markup() const { return m_markup; }
+ void setMarkup(const QList<Markup> &m) { clearMarkup(); m_markup = m; }
+
+ static QString formatData(quint64 address, const QByteArray &d);
+
+ static const quint64 defaultLength;
+
+ virtual bool eventFilter(QObject *, QEvent *);
+
+signals:
+ // Fetch memory and use setData().
+ void memoryRequested(quint64 address, quint64 length);
+ // Open a (sub) view from context menu
+ void openViewRequested(quint64 address, quint64 length, const QPoint &pos);
+
+public slots:
+ void setData(const QByteArray &a); // Set to empty to indicate non-available data
+ void engineStateChanged(Debugger::DebuggerState s);
+ void addMarkup(quint64 begin, quint64 size, const QTextCharFormat &,
+ const QString &toolTip = QString());
+ void addMarkup(quint64 begin, quint64 size, const QColor &background,
+ const QString &toolTip = QString());
+ void clear();
+ void clearMarkup();
+ void requestMemory();
+ void requestMemory(quint64 address, quint64 length);
+
+protected:
+ virtual void updateTitle();
+ void setTitle(const QString &);
+
+private slots:
+ void slotNext();
+ void slotPrevious();
+ void slotContextMenuRequested(const QPoint &pos);
+
+private:
+ void setBrowsingEnabled(bool);
+ quint64 addressAt(const QPoint &textPos) const;
+ bool addressToLineColumn(quint64 address, int *line = 0, int *column = 0,
+ quint64 *lineStart = 0) const;
+ bool markUpToSelections(const Markup &r,
+ QList<QTextEdit::ExtraSelection> *extraSelections) const;
+ int indexOfMarkup(quint64 address) const;
+
+ QToolButton *m_previousButton;
+ QToolButton *m_nextButton;
+ QPlainTextEdit *m_textEdit;
+ QLabel *m_content;
+ quint64 m_address;
+ quint64 m_length;
+ quint64 m_requestedAddress;
+ quint64 m_requestedLength;
+ ProjectExplorer::Abi m_abi;
+ QByteArray m_data;
+ bool m_updateOnInferiorStop;
+ QList<Markup> m_markup;
+};
+
+class LocalsMemoryViewWidget : public MemoryViewWidget
+{
+ Q_OBJECT
+public:
+ explicit LocalsMemoryViewWidget(QWidget *parent = 0);
+ void init(quint64 variableAddress, quint64 size, const QString &name);
+
+private:
+ virtual void updateTitle();
+
+ quint64 m_variableAddress;
+ quint64 m_variableSize;
+ QString m_variableName;
+};
+
+class RegisterMemoryViewWidget : public MemoryViewWidget
+{
+ Q_OBJECT
+public:
+ explicit RegisterMemoryViewWidget(QWidget *parent = 0);
+ void init(int registerIndex, RegisterHandler *h);
+
+private slots:
+ void slotRegisterSet(const QModelIndex &);
+
+private:
+ virtual void updateTitle();
+ void setRegisterAddress(quint64 a);
+
+ int m_registerIndex;
+ quint64 m_registerAddress;
+ quint64 m_offset;
+ QString m_registerName;
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // MEMORYTOOLTIP_H
diff --git a/src/plugins/debugger/qml/qmladapter.cpp b/src/plugins/debugger/qml/qmladapter.cpp
index 941902762f..7d6636d2b8 100644
--- a/src/plugins/debugger/qml/qmladapter.cpp
+++ b/src/plugins/debugger/qml/qmladapter.cpp
@@ -99,7 +99,7 @@ void QmlAdapter::closeConnection()
d->m_connectionTimer.stop();
} else {
if (d->m_conn) {
- d->m_conn->disconnectFromHost();
+ d->m_conn->close();
}
}
}
@@ -126,11 +126,23 @@ void QmlAdapter::connectToViewer()
|| (d->m_conn && d->m_conn->state() != QAbstractSocket::UnconnectedState))
return;
- QString address = d->m_engine.data()->startParameters().qmlServerAddress;
- quint16 port = d->m_engine.data()->startParameters().qmlServerPort;
- showConnectionStatusMessage(
- tr("Connect to debug server %1:%2").arg(address).arg(QString::number(port)));
- d->m_conn->connectToHost(address, port);
+ const DebuggerStartParameters &parameters = d->m_engine.data()->startParameters();
+ if (parameters.communicationChannel == DebuggerStartParameters::CommunicationChannelUsb) {
+ if (parameters.debugClient == DebuggerStartParameters::DebugClientTrk) {
+ d->m_connectionTimer.stop();
+ showConnectionErrorMessage(tr("QML debugging is not supported when using TRK!"));
+ emit connectionStartupFailed();
+ return;
+ }
+ const QString &port = parameters.remoteChannel;
+ showConnectionStatusMessage(tr("Connecting to debug server on %1").arg(port));
+ d->m_conn->connectToOst(port);
+ } else {
+ const QString &address = parameters.qmlServerAddress;
+ quint16 port = parameters.qmlServerPort;
+ showConnectionStatusMessage(tr("Connecting to debug server %1:%2").arg(address).arg(QString::number(port)));
+ d->m_conn->connectToHost(address, port);
+ }
}
void QmlAdapter::sendMessage(const QByteArray &msg)
@@ -146,7 +158,7 @@ void QmlAdapter::sendMessage(const QByteArray &msg)
void QmlAdapter::connectionErrorOccurred(QAbstractSocket::SocketError socketError)
{
showConnectionStatusMessage(tr("Error: (%1) %2", "%1=error code, %2=error message")
- .arg(d->m_conn->error()).arg(d->m_conn->errorString()));
+ .arg(socketError).arg(d->m_conn->errorString()));
// this is only an error if we are already connected and something goes wrong.
if (isConnected())
diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp
index 72df4e46c9..ecc8f8b99d 100644
--- a/src/plugins/debugger/qml/qmlengine.cpp
+++ b/src/plugins/debugger/qml/qmlengine.cpp
@@ -299,9 +299,9 @@ void QmlEngine::filterApplicationMessage(const QString &msg, int /*channel*/)
QString status = msg;
status.remove(0, index + qddserver.length()); // chop of 'QDeclarativeDebugServer: '
- static QString waitingForConnection = QLatin1String("Waiting for connection on port");
- static QString unableToListen = QLatin1String("Unable to listen on port");
- static QString debuggingNotEnabled = QLatin1String("Ignoring \"-qmljsdebugger=port:");
+ static QString waitingForConnection = QLatin1String("Waiting for connection ");
+ static QString unableToListen = QLatin1String("Unable to listen ");
+ static QString debuggingNotEnabled = QLatin1String("Ignoring \"-qmljsdebugger=");
static QString connectionEstablished = QLatin1String("Connection established");
QString errorMessage;
diff --git a/src/plugins/debugger/registerhandler.cpp b/src/plugins/debugger/registerhandler.cpp
index 514dbf18bf..1acd4343b5 100644
--- a/src/plugins/debugger/registerhandler.cpp
+++ b/src/plugins/debugger/registerhandler.cpp
@@ -33,7 +33,6 @@
#include "registerhandler.h"
#include "watchdelegatewidgets.h"
-
//////////////////////////////////////////////////////////////////
//
// RegisterHandler
@@ -145,21 +144,45 @@ bool RegisterHandler::isEmpty() const
return m_registers.isEmpty();
}
+// Compare register sets by name
+static inline bool compareRegisterSet(const Registers &r1, const Registers &r2)
+{
+ if (r1.size() != r2.size())
+ return false;
+ const int size = r1.size();
+ for (int r = 0; r < size; r++)
+ if (r1.at(r).name != r2.at(r).name)
+ return false;
+ return true;
+}
+
void RegisterHandler::setRegisters(const Registers &registers)
{
m_registers = registers;
+ const int size = m_registers.size();
+ for (int r = 0; r < size; r++)
+ m_registers[r].changed = false;
calculateWidth();
reset();
}
void RegisterHandler::setAndMarkRegisters(const Registers &registers)
{
- const Registers old = m_registers;
- m_registers = registers;
- for (int i = qMin(m_registers.size(), old.size()); --i >= 0; )
- m_registers[i].changed = m_registers[i].value != old[i].value;
- calculateWidth();
- reset();
+ if (!compareRegisterSet(m_registers, registers)) {
+ setRegisters(registers);
+ return;
+ }
+ const int size = m_registers.size();
+ for (int r = 0; r < size; r++) {
+ const QModelIndex regIndex = index(r, 1);
+ if (m_registers.at(r).value != registers.at(r).value) {
+ // Indicate red if values change, keep changed.
+ m_registers[r].changed = m_registers[r].changed || !m_registers.at(r).value.isEmpty();
+ m_registers[r].value = registers.at(r).value;
+ emit dataChanged(regIndex, regIndex);
+ }
+ emit registerSet(regIndex); // notify attached memory views.
+ }
}
Registers RegisterHandler::registers() const
diff --git a/src/plugins/debugger/registerhandler.h b/src/plugins/debugger/registerhandler.h
index 422a977f3e..232e64a836 100644
--- a/src/plugins/debugger/registerhandler.h
+++ b/src/plugins/debugger/registerhandler.h
@@ -70,7 +70,9 @@ public:
QAbstractItemModel *model() { return this; }
bool isEmpty() const; // nothing known so far?
+ // Set up register names (gdb)
void setRegisters(const Registers &registers);
+ // Set register values
void setAndMarkRegisters(const Registers &registers);
Registers registers() const;
Register registerAt(int i) const { return m_registers.at(i); }
@@ -78,6 +80,9 @@ public:
Q_SLOT void setNumberBase(int base);
int numberBase() const { return m_base; }
+signals:
+ void registerSet(const QModelIndex &r); // Register was set, for memory views
+
private:
void calculateWidth();
int rowCount(const QModelIndex &parent = QModelIndex()) const;
diff --git a/src/plugins/debugger/registerwindow.cpp b/src/plugins/debugger/registerwindow.cpp
index 6d48741d39..664c527de8 100644
--- a/src/plugins/debugger/registerwindow.cpp
+++ b/src/plugins/debugger/registerwindow.cpp
@@ -31,7 +31,7 @@
**************************************************************************/
#include "registerwindow.h"
-
+#include "memoryviewwidget.h"
#include "debuggeractions.h"
#include "debuggerconstants.h"
#include "debuggercore.h"
@@ -172,11 +172,7 @@ RegisterWindow::RegisterWindow(QWidget *parent)
connect(debuggerCore()->action(AlwaysAdjustRegistersColumnWidths),
SIGNAL(toggled(bool)),
SLOT(setAlwaysResizeColumnsToContents(bool)));
-}
-
-void RegisterWindow::resizeEvent(QResizeEvent *ev)
-{
- QTreeView::resizeEvent(ev);
+ setObjectName(QLatin1String("RegisterWindow"));
}
void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev)
@@ -196,16 +192,24 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev)
menu.addSeparator();
- QModelIndex idx = indexAt(ev->pos());
- QString address = handler->registers().at(idx.row()).value;
- QAction *actShowMemory = menu.addAction(QString());
- if (address.isEmpty()) {
- actShowMemory->setText(tr("Open Memory Editor"));
- actShowMemory->setEnabled(false);
+ const QModelIndex idx = indexAt(ev->pos());
+ if (!idx.isValid())
+ return;
+ const Register &aRegister = handler->registers().at(idx.row());
+ const QVariant addressV = aRegister.editValue();
+ const quint64 address = addressV.type() == QVariant::ULongLong ? addressV.toULongLong() : 0;
+ QAction *actViewMemory = menu.addAction(QString());
+ QAction *actEditMemory = menu.addAction(QString());
+ if (address) {
+ const bool canShow = actionsEnabled && (engineCapabilities & ShowMemoryCapability);
+ actEditMemory->setText(tr("Open Memory Editor at 0x%1").arg(address, 0, 16));
+ actEditMemory->setEnabled(canShow);
+ actViewMemory->setText(tr("Open Memory View at Value of Register %1 0x%2")
+ .arg(QString::fromAscii(aRegister.name)).arg(address, 0, 16));
} else {
- actShowMemory->setText(tr("Open Memory Editor at %1").arg(address));
- actShowMemory->setEnabled(actionsEnabled
- && (engineCapabilities & ShowMemoryCapability));
+ actEditMemory->setText(tr("Open Memory Editor"));
+ actViewMemory->setText(tr("Open Memory View at Value of Register"));
+ actEditMemory->setEnabled(false);
}
menu.addSeparator();
@@ -230,15 +234,21 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev)
menu.addAction(debuggerCore()->action(SettingsDialog));
- QAction *act = menu.exec(ev->globalPos());
+ const QPoint position = ev->globalPos();
+ QAction *act = menu.exec(position);
if (act == actAdjust)
resizeColumnsToContents();
else if (act == actReload)
engine->reloadRegisters();
- else if (act == actShowMemory)
- engine->openMemoryView(address.toULongLong(0, 0));
- else if (act == act16)
+ else if (act == actEditMemory)
+ engine->openMemoryView(address);
+ else if (act == actViewMemory) {
+ RegisterMemoryViewWidget *w = new RegisterMemoryViewWidget(this);
+ w->move(position);
+ w->init(idx.row(), handler);
+ engine->addMemoryView(w);
+ } else if (act == act16)
handler->setNumberBase(16);
else if (act == act10)
handler->setNumberBase(10);
diff --git a/src/plugins/debugger/registerwindow.h b/src/plugins/debugger/registerwindow.h
index 0458da12cb..0d51f19a51 100644
--- a/src/plugins/debugger/registerwindow.h
+++ b/src/plugins/debugger/registerwindow.h
@@ -53,8 +53,7 @@ public slots:
void reloadRegisters();
private:
- void resizeEvent(QResizeEvent *ev);
- void contextMenuEvent(QContextMenuEvent *ev);
+ virtual void contextMenuEvent(QContextMenuEvent *ev);
};
} // namespace Internal
diff --git a/src/plugins/debugger/shared/shared.pri b/src/plugins/debugger/shared/shared.pri
index c0f63a7602..4df723050e 100644
--- a/src/plugins/debugger/shared/shared.pri
+++ b/src/plugins/debugger/shared/shared.pri
@@ -13,7 +13,7 @@ SOURCES += $$PWD/peutils.cpp \
HEADERS += $$PWD/peutils.h \
$$PWD/dbgwinutils.h
-contains(QMAKE_CXX, cl) {
+win32-msvc* {
# For the Privilege manipulation functions in sharedlibraryinjector.cpp.
LIBS += -ladvapi32
}
diff --git a/src/plugins/debugger/sourceagent.cpp b/src/plugins/debugger/sourceagent.cpp
index 156de0398f..62f4b41aa1 100644
--- a/src/plugins/debugger/sourceagent.cpp
+++ b/src/plugins/debugger/sourceagent.cpp
@@ -73,20 +73,6 @@ 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() {}
- TextEditor::ITextMark::Priority priority() const
- { return TextEditor::ITextMark::HighPriority; }
-};
-
class SourceAgentPrivate
{
public:
@@ -103,9 +89,11 @@ public:
SourceAgentPrivate::SourceAgentPrivate()
: editor(0)
- , locationMark(new LocationMarkFoo)
, producer("remote")
{
+ locationMark = new TextEditor::ITextMark;
+ locationMark->setIcon(debuggerCore()->locationMarkIcon());
+ locationMark->setPriority(TextEditor::ITextMark::HighPriority);
}
SourceAgentPrivate::~SourceAgentPrivate()
diff --git a/src/plugins/debugger/watchdata.cpp b/src/plugins/debugger/watchdata.cpp
index dd1cf8c9fa..dc1caaa255 100644
--- a/src/plugins/debugger/watchdata.cpp
+++ b/src/plugins/debugger/watchdata.cpp
@@ -44,13 +44,6 @@
namespace Debugger {
namespace Internal {
-enum GuessChildrenResult
-{
- HasChildren,
- HasNoChildren,
- HasPossiblyChildren
-};
-
static QString htmlEscape(const QString &plain)
{
QString rich;
@@ -126,24 +119,13 @@ 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),
+ referencingAddress(0),
+ size(0),
bitpos(0),
bitsize(0),
generation(-1),
@@ -169,6 +151,7 @@ bool WatchData::isEqual(const WatchData &other) const
&& displayedType == other.displayedType
&& variable == other.variable
&& address == other.address
+ && size == other.size
&& hasChildren == other.hasChildren
&& valueEnabled == other.valueEnabled
&& valueEditable == other.valueEditable
@@ -230,6 +213,21 @@ void WatchData::setValueToolTip(const QString &tooltip)
valuetooltip = tooltip;
}
+enum GuessChildrenResult { HasChildren, HasNoChildren, HasPossiblyChildren };
+
+static 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;
+}
+
void WatchData::setType(const QByteArray &str, bool guessChildrenFromType)
{
type = str.trimmed();
@@ -306,6 +304,11 @@ QString WatchData::toString() const
str << "addr=\"0x" << address << doubleQuoteComma;
str.setIntegerBase(10);
}
+ if (referencingAddress) {
+ str.setIntegerBase(16);
+ str << "referencingaddr=\"0x" << referencingAddress << doubleQuoteComma;
+ str.setIntegerBase(10);
+ }
if (!exp.isEmpty())
str << "exp=\"" << exp << doubleQuoteComma;
@@ -369,6 +372,12 @@ QString WatchData::toToolTip() const
formatToolTipRow(str, tr("Value"), val);
formatToolTipRow(str, tr("Object Address"),
QString::fromAscii(hexAddress()));
+ if (referencingAddress)
+ formatToolTipRow(str, tr("Referencing Address"),
+ QString::fromAscii(hexReferencingAddress()));
+ if (size)
+ formatToolTipRow(str, tr("Size"),
+ QString::number(size));
formatToolTipRow(str, tr("Internal ID"), iname);
formatToolTipRow(str, tr("Generation"),
QString::number(generation));
@@ -409,6 +418,11 @@ QByteArray WatchData::hexAddress() const
return address ? (QByteArray("0x") + QByteArray::number(address, 16)) : QByteArray();
}
+QByteArray WatchData::hexReferencingAddress() const
+{
+ return referencingAddress ? (QByteArray("0x") + QByteArray::number(referencingAddress, 16)) : QByteArray();
+}
+
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/watchdata.h b/src/plugins/debugger/watchdata.h
index 04465e4c31..137ba0e845 100644
--- a/src/plugins/debugger/watchdata.h
+++ b/src/plugins/debugger/watchdata.h
@@ -112,6 +112,7 @@ public:
quint64 coreAddress() const;
QByteArray hexAddress() const;
+ QByteArray hexReferencingAddress() const;
public:
quint64 id; // Token for the engine for internal mapping
@@ -127,6 +128,8 @@ public:
QByteArray type; // Type for further processing
QString displayedType;// Displayed type (optional)
quint64 address; // Displayed address
+ quint64 referencingAddress; // Address of the pointer referencing this item (gdb auto-deref)
+ uint size; // Size
uint bitpos; // Position within bit fields
uint bitsize; // Size in case of bit fields
qint32 generation; // When updated?
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index ea135f2216..817cd2f090 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -640,6 +640,10 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
case 1:
result = removeInitialNamespace(truncateValue(
formattedValue(data, itemFormat(data))), ns);
+ if (data.referencingAddress) {
+ result += QLatin1String(" @");
+ result += QString::fromLatin1(data.hexAddress());
+ }
break;
case 2:
result = removeNamespaces(displayType(data), ns);
@@ -691,16 +695,16 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
return m_handler->m_expandedINames.contains(data.iname);
case LocalsTypeFormatListRole: {
- if (isIntType(data.type) && data.type != "bool")
- return QStringList() << tr("decimal") << tr("hexadecimal")
- << tr("binary") << tr("octal");
- if (data.type.endsWith('*'))
+ if (data.referencingAddress || data.type.endsWith('*'))
return QStringList()
<< tr("Raw pointer")
<< tr("Latin1 string")
<< tr("UTF8 string")
<< tr("UTF16 string")
<< tr("UCS4 string");
+ if (isIntType(data.type) && data.type != "bool")
+ return QStringList() << tr("decimal") << tr("hexadecimal")
+ << tr("binary") << tr("octal");
// Hack: Compensate for namespaces.
QString type = data.type;
int pos = type.indexOf("::Q");
@@ -734,6 +738,8 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
case LocalsAddressRole:
return data.coreAddress();
+ case LocalsSizeRole:
+ return QVariant(data.size);
case LocalsIsWatchpointAtPointerValueRole:
if (isPointerType(data.type)) {
diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp
index 000c667ffe..0cba72e52a 100644
--- a/src/plugins/debugger/watchutils.cpp
+++ b/src/plugins/debugger/watchutils.cpp
@@ -495,76 +495,11 @@ QByteArray gdbQuoteTypes(const QByteArray &type)
return result;
}
-bool extractTemplate(const QByteArray &type, QByteArray *tmplate, QByteArray *inner)
-{
- // Input "Template<Inner1,Inner2,...>::Foo" will return "Template::Foo" in
- // 'tmplate' and "Inner1@Inner2@..." etc in 'inner'. Result indicates
- // whether parsing was successful
- // Gdb inserts a blank after each comma which we would like to avoid
- tmplate->clear();
- inner->clear();
- if (!type.contains('<'))
- return false;
- int level = 0;
- bool skipSpace = false;
- const int size = type.size();
-
- for (int i = 0; i != size; ++i) {
- const char c = type.at(i);
- switch (c) {
- case '<':
- *(level == 0 ? tmplate : inner) += c;
- ++level;
- break;
- case '>':
- --level;
- *(level == 0 ? tmplate : inner) += c;
- break;
- case ',':
- *inner += (level == 1) ? '@' : ',';
- skipSpace = true;
- break;
- default:
- if (!skipSpace || c != ' ') {
- *(level == 0 ? tmplate : inner) += c;
- skipSpace = false;
- }
- break;
- }
- }
- *tmplate = tmplate->trimmed();
- tmplate->replace("<>", "");
- *inner = inner->trimmed();
- // qDebug() << "EXTRACT TEMPLATE: " << *tmplate << *inner << " FROM " << type;
- return !inner->isEmpty();
-}
-
-QString extractTypeFromPTypeOutput(const QString &str)
-{
- int pos0 = str.indexOf(QLatin1Char('='));
- int pos1 = str.indexOf(QLatin1Char('{'));
- int pos2 = str.lastIndexOf(QLatin1Char('}'));
- QString res = str;
- if (pos0 != -1 && pos1 != -1 && pos2 != -1)
- res = str.mid(pos0 + 2, pos1 - 1 - pos0)
- + QLatin1String(" ... ") + str.right(str.size() - pos2);
- return res.simplified();
-}
-
bool isSymbianIntType(const QByteArray &type)
{
return type == "TInt" || type == "TBool";
}
-QByteArray sizeofTypeExpression(const QByteArray &type)
-{
- if (type.endsWith('*'))
- return "sizeof(void*)";
- if (type.endsWith('>'))
- return "sizeof(" + type + ')';
- return "sizeof(" + gdbQuoteTypes(type) + ')';
-}
-
// Utilities to decode string data returned by the dumper helpers.
QString quoteUnprintableLatin1(const QByteArray &ba)
@@ -586,16 +521,16 @@ QString quoteUnprintableLatin1(const QByteArray &ba)
QString decodeData(const QByteArray &ba, int encoding)
{
switch (encoding) {
- case 0: // unencoded 8 bit data
+ case Unencoded8Bit: // 0
return quoteUnprintableLatin1(ba);
- case 1: { // base64 encoded 8 bit data, used for QByteArray
+ case Base64Encoded8BitWithQuotes: { // 1, used for QByteArray
const QChar doubleQuote(QLatin1Char('"'));
QString rc = doubleQuote;
rc += quoteUnprintableLatin1(QByteArray::fromBase64(ba));
rc += doubleQuote;
return rc;
}
- case 2: { // base64 encoded 16 bit data, used for QString
+ case Base64Encoded16BitWithQuotes: { // 2, used for QString
const QChar doubleQuote(QLatin1Char('"'));
const QByteArray decodedBa = QByteArray::fromBase64(ba);
QString rc = doubleQuote;
@@ -604,7 +539,7 @@ QString decodeData(const QByteArray &ba, int encoding)
rc += doubleQuote;
return rc;
}
- case 3: { // base64 encoded 32 bit data
+ case Base64Encoded32BitWithQuotes: { // 3
const QByteArray decodedBa = QByteArray::fromBase64(ba);
const QChar doubleQuote(QLatin1Char('"'));
QString rc = doubleQuote;
@@ -613,41 +548,41 @@ QString decodeData(const QByteArray &ba, int encoding)
rc += doubleQuote;
return rc;
}
- case 4: { // base64 encoded 16 bit data, without quotes (see 2)
+ case Base64Encoded16Bit: { // 4, without quotes (see 2)
const QByteArray decodedBa = QByteArray::fromBase64(ba);
return QString::fromUtf16(reinterpret_cast<const ushort *>
(decodedBa.data()), decodedBa.size() / 2);
}
- case 5: { // base64 encoded 8 bit data, without quotes (see 1)
+ case Base64Encoded8Bit: { // 5, without quotes (see 1)
return quoteUnprintableLatin1(QByteArray::fromBase64(ba));
}
- case 6: { // %02x encoded 8 bit Latin1 data
+ case Hex2EncodedLatin1: { // 6, %02x encoded 8 bit Latin1 data
const QChar doubleQuote(QLatin1Char('"'));
const QByteArray decodedBa = QByteArray::fromHex(ba);
//qDebug() << quoteUnprintableLatin1(decodedBa) << "\n\n";
return doubleQuote + QString::fromLatin1(decodedBa) + doubleQuote;
}
- case 7: { // %04x encoded 16 bit data, Little Endian
+ case Hex4EncodedLittleEndian: { // 7, %04x encoded 16 bit data
const QChar doubleQuote(QLatin1Char('"'));
const QByteArray decodedBa = QByteArray::fromHex(ba);
//qDebug() << quoteUnprintableLatin1(decodedBa) << "\n\n";
return doubleQuote + QString::fromUtf16(reinterpret_cast<const ushort *>
(decodedBa.data()), decodedBa.size() / 2) + doubleQuote;
}
- case 8: { // %08x encoded 32 bit data, Little Endian
+ case Hex8EncodedLittleEndian: { // 8, %08x encoded 32 bit data
const QChar doubleQuote(QLatin1Char('"'));
const QByteArray decodedBa = QByteArray::fromHex(ba);
//qDebug() << quoteUnprintableLatin1(decodedBa) << "\n\n";
return doubleQuote + QString::fromUcs4(reinterpret_cast<const uint *>
(decodedBa.data()), decodedBa.size() / 4) + doubleQuote;
}
- case 9: { // %02x encoded 8 bit Utf-8 data
+ case Hex2EncodedUtf8: { // 9, %02x encoded 8 bit Utf-8 data
const QChar doubleQuote(QLatin1Char('"'));
const QByteArray decodedBa = QByteArray::fromHex(ba);
//qDebug() << quoteUnprintableLatin1(decodedBa) << "\n\n";
return doubleQuote + QString::fromUtf8(decodedBa) + doubleQuote;
}
- case 10: { // %08x encoded 32 bit data, Big Endian
+ case Hex8EncodedBigEndian: { // 10, %08x encoded 32 bit data
const QChar doubleQuote(QLatin1Char('"'));
QByteArray decodedBa = QByteArray::fromHex(ba);
for (int i = 0; i < decodedBa.size(); i += 4) {
@@ -662,7 +597,7 @@ QString decodeData(const QByteArray &ba, int encoding)
return doubleQuote + QString::fromUcs4(reinterpret_cast<const uint *>
(decodedBa.data()), decodedBa.size() / 4) + doubleQuote;
}
- case 11: { // %04x encoded 16 bit data, Big Endian
+ case Hex4EncodedBigEndian: { // 11, %04x encoded 16 bit data
const QChar doubleQuote(QLatin1Char('"'));
QByteArray decodedBa = QByteArray::fromHex(ba);
for (int i = 0; i < decodedBa.size(); i += 2) {
@@ -674,7 +609,7 @@ QString decodeData(const QByteArray &ba, int encoding)
return doubleQuote + QString::fromUtf16(reinterpret_cast<const ushort *>
(decodedBa.data()), decodedBa.size() / 2) + doubleQuote;
}
- case 12: { // %04x encoded 16 bit data, Little Endian, without quotes (see 7)
+ case Hex4EncodedLittleEndianWithoutQuotes: { // 12, see 7, without quotes
const QByteArray decodedBa = QByteArray::fromHex(ba);
//qDebug() << quoteUnprintableLatin1(decodedBa) << "\n\n";
return QString::fromUtf16(reinterpret_cast<const ushort *>
@@ -744,552 +679,6 @@ QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos,
}
-// ----------------- QtDumperHelper::TypeData
-QtDumperHelper::TypeData::TypeData() :
- type(UnknownType),
- isTemplate(false)
-{
-}
-
-void QtDumperHelper::TypeData::clear()
-{
- isTemplate = false;
- type = UnknownType;
- tmplate.clear();
- inner.clear();
-}
-
-// ----------------- QtDumperHelper
-QtDumperHelper::QtDumperHelper() :
- m_qtVersion(0),
- m_dumperVersion(1.0)
-{
- qFill(m_specialSizes, m_specialSizes + SpecialSizeCount, 0);
- setQClassPrefixes(QByteArray());
-}
-
-void QtDumperHelper::clear()
-{
- m_nameTypeMap.clear();
- m_qtVersion = 0;
- m_dumperVersion = 1.0;
- m_qtNamespace.clear();
- m_sizeCache.clear();
- qFill(m_specialSizes, m_specialSizes + SpecialSizeCount, 0);
- m_expressionCache.clear();
- setQClassPrefixes(QByteArray());
-}
-
-QString QtDumperHelper::msgDumperOutdated(double requiredVersion, double currentVersion)
-{
- return QCoreApplication::translate("QtDumperHelper",
- "Found an outdated version of the debugging helper library (%1); "
- "version %2 is required.").
- arg(currentVersion).arg(requiredVersion);
-}
-
-static inline void formatQtVersion(int v, QTextStream &str)
-{
- str << ((v >> 16) & 0xFF) << '.' << ((v >> 8) & 0xFF) << '.' << (v & 0xFF);
-}
-
-QString QtDumperHelper::toString(bool debug) const
-{
- if (debug) {
- QString rc;
- QTextStream str(&rc);
- str << "version=";
- formatQtVersion(m_qtVersion, str);
- str << "dumperversion='" << m_dumperVersion << "' namespace='" << m_qtNamespace << "'," << m_nameTypeMap.size() << " known types <type enum>: ";
- const NameTypeMap::const_iterator cend = m_nameTypeMap.constEnd();
- for (NameTypeMap::const_iterator it = m_nameTypeMap.constBegin(); it != cend; ++it) {
- str <<",[" << it.key() << ',' << it.value() << ']';
- }
- str << "\nSpecial size: ";
- for (int i = 0; i < SpecialSizeCount; i++)
- str << ' ' << m_specialSizes[i];
- str << "\nSize cache: ";
- const SizeCache::const_iterator scend = m_sizeCache.constEnd();
- for (SizeCache::const_iterator it = m_sizeCache.constBegin(); it != scend; ++it) {
- str << ' ' << it.key() << '=' << it.value() << '\n';
- }
- str << "\nExpression cache: (" << m_expressionCache.size() << ")\n";
- const ExpressionCache::const_iterator excend = m_expressionCache.constEnd();
- for (ExpressionCache::const_iterator it = m_expressionCache.constBegin(); it != excend; ++it)
- str << " " << it.key() << ' ' << it.value() << '\n';
- return rc;
- }
- const QString nameSpace = m_qtNamespace.isEmpty()
- ? QCoreApplication::translate("QtDumperHelper", "<none>") : m_qtNamespace;
- return QCoreApplication::translate("QtDumperHelper",
- "%n known types, Qt version: %1, Qt namespace: %2 Dumper version: %3",
- 0, QCoreApplication::CodecForTr,
- m_nameTypeMap.size()).arg(qtVersionString(), nameSpace).arg(m_dumperVersion);
-}
-
-QtDumperHelper::Type QtDumperHelper::simpleType(const QByteArray &simpleType) const
-{
- return m_nameTypeMap.value(simpleType, UnknownType);
-}
-
-int QtDumperHelper::qtVersion() const
-{
- return m_qtVersion;
-}
-
-QByteArray QtDumperHelper::qtNamespace() const
-{
- return m_qtNamespace;
-}
-
-int QtDumperHelper::typeCount() const
-{
- return m_nameTypeMap.size();
-}
-
-// Look up unnamespaced 'std' types.
-static QtDumperHelper::Type stdType(const QByteArray &type)
-{
- if (type == "vector")
- return QtDumperHelper::StdVectorType;
- if (type == "deque")
- return QtDumperHelper::StdDequeType;
- if (type == "set")
- return QtDumperHelper::StdSetType;
- if (type == "stack")
- return QtDumperHelper::StdStackType;
- if (type == "map")
- return QtDumperHelper::StdMapType;
- if (type == "basic_string")
- return QtDumperHelper::StdStringType;
- return QtDumperHelper::UnknownType;
-}
-
-static QtDumperHelper::Type specialType(QByteArray type)
-{
- // Std classes.
- if (type.startsWith("std::"))
- return stdType(type.mid(5));
-
- // Strip namespace
- // FIXME: that's not a good idea as it makes all namespaces equal.
- const int namespaceIndex = type.lastIndexOf("::");
- if (namespaceIndex == -1) {
- // None ... check for std..
- const QtDumperHelper::Type sType = stdType(type);
- if (sType != QtDumperHelper::UnknownType)
- return sType;
- } else {
- type = type.mid(namespaceIndex + 2);
- }
-
- if (type == "QAbstractItem")
- return QtDumperHelper::QAbstractItemType;
- if (type == "QMap")
- return QtDumperHelper::QMapType;
- if (type == "QMapNode")
- return QtDumperHelper::QMapNodeType;
- if (type == "QMultiMap")
- return QtDumperHelper::QMultiMapType;
- if (type == "QObject")
- return QtDumperHelper::QObjectType;
- if (type == "QObjectSignal")
- return QtDumperHelper::QObjectSignalType;
- if (type == "QObjectSlot")
- return QtDumperHelper::QObjectSlotType;
- if (type == "QStack")
- return QtDumperHelper::QStackType;
- if (type == "QVector")
- return QtDumperHelper::QVectorType;
- if (type == "QWidget")
- return QtDumperHelper::QWidgetType;
- return QtDumperHelper::UnknownType;
-}
-
-QByteArray QtDumperHelper::qtVersionString() const
-{
- QString rc;
- QTextStream str(&rc);
- formatQtVersion(m_qtVersion, str);
- return rc.toLatin1();
-}
-
-// Parse a list of types.
-typedef QList<QByteArray> QByteArrayList;
-
-static inline QByteArray qClassName(const QByteArray &qtNamespace, const char *className)
-{
- if (qtNamespace.isEmpty())
- return className;
- QByteArray rc = qtNamespace;
- rc += "::";
- rc += className;
- return rc;
-}
-
-void QtDumperHelper::setQClassPrefixes(const QByteArray &qNamespace)
-{
- // Prefixes with namespaces
- m_qPointerPrefix = qClassName(qNamespace, "QPointer");
- m_qSharedPointerPrefix = qClassName(qNamespace, "QSharedPointer");
- m_qSharedDataPointerPrefix = qClassName(qNamespace, "QSharedDataPointer");
- m_qWeakPointerPrefix = qClassName(qNamespace, "QWeakPointer");
- m_qListPrefix = qClassName(qNamespace, "QList");
- m_qLinkedListPrefix = qClassName(qNamespace, "QLinkedList");
- m_qVectorPrefix = qClassName(qNamespace, "QVector");
- m_qQueuePrefix = qClassName(qNamespace, "QQueue");
-}
-
-static inline double getDumperVersion(const GdbMi &contents)
-{
- const GdbMi dumperVersionG = contents.findChild("dumperversion");
- if (dumperVersionG.type() != GdbMi::Invalid) {
- bool ok;
- const double v = QString::fromAscii(dumperVersionG.data()).toDouble(&ok);
- if (ok)
- return v;
- }
- return 1.0;
-}
-
-bool QtDumperHelper::parseQuery(const GdbMi &contents)
-{
- clear();
- if (debug > 1)
- qDebug() << "parseQuery" << contents.toString(true, 2);
-
- // Common info, dumper version, etc
- QByteArray ns = contents.findChild("namespace").data();
- setQtNamespace(ns);
- int qtv = 0;
- const GdbMi qtversion = contents.findChild("qtversion");
- if (qtversion.children().size() == 3) {
- qtv = (qtversion.childAt(0).data().toInt() << 16)
- + (qtversion.childAt(1).data().toInt() << 8)
- + qtversion.childAt(2).data().toInt();
- }
- m_qtVersion = qtv;
- // Get list of helpers
- QByteArrayList availableSimpleDebuggingHelpers;
- foreach (const GdbMi &item, contents.findChild("dumpers").children())
- availableSimpleDebuggingHelpers.append(item.data());
-
- // Parse types
- m_nameTypeMap.clear();
- foreach (const QByteArray &type, availableSimpleDebuggingHelpers) {
- const Type t = specialType(type);
- m_nameTypeMap.insert(type, t != UnknownType ? t : SupportedType);
- }
-
- m_dumperVersion = getDumperVersion(contents);
- // Parse sizes
- foreach (const GdbMi &sizesList, contents.findChild("sizes").children()) {
- const int childCount = sizesList.childCount();
- if (childCount > 1) {
- const int size = sizesList.childAt(0).data().toInt();
- for (int c = 1; c < childCount; c++)
- addSize(sizesList.childAt(c).data(), size);
- }
- }
- // Parse expressions
- foreach (const GdbMi &exprList, contents.findChild("expressions").children())
- if (exprList.childCount() == 2)
- m_expressionCache.insert(exprList.childAt(0).data(),
- exprList.childAt(1).data());
- return true;
-}
-
-void QtDumperHelper::addSize(const QByteArray &name, int size)
-{
- // Special interest cases
- if (name == "char*") {
- m_specialSizes[PointerSize] = size;
- return;
- }
- const SpecialSizeType st = specialSizeType(name);
- if (st != SpecialSizeCount) {
- m_specialSizes[st] = size;
- return;
- }
- do {
- // CDB helpers
- if (name == "std::string") {
- m_sizeCache.insert("std::basic_string<char,std::char_traits<char>,std::allocator<char> >", size);
- m_sizeCache.insert("basic_string<char,char_traits<char>,allocator<char> >", size);
- break;
- }
- if (name == "std::wstring") {
- m_sizeCache.insert("basic_string<unsigned short,char_traits<unsignedshort>,allocator<unsignedshort> >", size);
- m_sizeCache.insert("std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >", size);
- break;
- }
- } while (false);
- m_sizeCache.insert(name, size);
-}
-
-QtDumperHelper::Type QtDumperHelper::type(const QByteArray &typeName) const
-{
- const QtDumperHelper::TypeData td = typeData(typeName);
- return td.type;
-}
-
-QtDumperHelper::TypeData QtDumperHelper::typeData(const QByteArray &typeName) const
-{
- TypeData td;
- td.type = UnknownType;
- const Type st = simpleType(typeName);
- if (st != UnknownType) {
- td.isTemplate = false;
- td.type = st;
- return td;
- }
- // Try template
- td.isTemplate = extractTemplate(typeName, &td.tmplate, &td.inner);
- if (!td.isTemplate)
- return td;
- // Check the template type QMap<X,Y> -> 'QMap'
- td.type = simpleType(td.tmplate);
- return td;
-}
-
-// Format an expression to have the debugger query the
-// size. Use size cache if possible
-QByteArray QtDumperHelper::evaluationSizeofTypeExpression(const QByteArray &typeName) const
-{
- // Look up special size types
- const SpecialSizeType st = specialSizeType(typeName);
- if (st != SpecialSizeCount) {
- if (const int size = m_specialSizes[st])
- return QByteArray::number(size);
- }
- // Look up size cache
- const SizeCache::const_iterator sit = m_sizeCache.constFind(typeName);
- if (sit != m_sizeCache.constEnd())
- return QByteArray::number(sit.value());
- // Finally have the debugger evaluate
- return sizeofTypeExpression(typeName);
-}
-
-QtDumperHelper::SpecialSizeType QtDumperHelper::specialSizeType(const QByteArray &typeName) const
-{
- if (isPointerType(typeName))
- return PointerSize;
- if (typeName == "int")
- return IntSize;
- if (typeName.startsWith("std::allocator"))
- return StdAllocatorSize;
- if (typeName.startsWith(m_qPointerPrefix))
- return QPointerSize;
- if (typeName.startsWith(m_qSharedPointerPrefix))
- return QSharedPointerSize;
- if (typeName.startsWith(m_qSharedDataPointerPrefix))
- return QSharedDataPointerSize;
- if (typeName.startsWith(m_qWeakPointerPrefix))
- return QWeakPointerSize;
- if (typeName.startsWith(m_qListPrefix))
- return QListSize;
- if (typeName.startsWith(m_qLinkedListPrefix))
- return QLinkedListSize;
- if (typeName.startsWith(m_qVectorPrefix))
- return QVectorSize;
- if (typeName.startsWith(m_qQueuePrefix))
- return QQueueSize;
- return SpecialSizeCount;
-}
-
-static inline bool isInteger(const QString &n)
-{
- const int size = n.size();
- if (!size)
- return false;
- for (int i = 0; i < size; i++)
- if (!n.at(i).isDigit())
- return false;
- return true;
-}
-
-// Return debugger expression to get the offset of a map node.
-static inline QByteArray qMapNodeValueOffsetExpression(const QByteArray &type)
-{
- return "(size_t)&(('" + type + "'*)0)->value";
-}
-
-void QtDumperHelper::evaluationParameters(const WatchData &data,
- const TypeData &td, QByteArray *inBuffer, QByteArrayList *extraArgsIn) const
-{
- enum { maxExtraArgCount = 4 };
-
- QByteArrayList &extraArgs = *extraArgsIn;
-
- // See extractTemplate for parameters
- QByteArrayList inners = td.inner.split('@');
- if (inners.at(0).isEmpty())
- inners.clear();
- for (int i = 0; i != inners.size(); ++i)
- inners[i] = inners[i].simplified();
-
- QString outertype = td.isTemplate ? td.tmplate : data.type;
- // adjust the data extract
- if (outertype == m_qtNamespace + "QWidget")
- outertype = m_qtNamespace + "QObject";
-
- QString inner = td.inner;
- const QByteArray zero = "0";
-
- extraArgs.clear();
-
- if (!inners.empty()) {
- // "generic" template dumpers: passing sizeof(argument)
- // gives already most information the dumpers need
- const int count = qMin(int(maxExtraArgCount), inners.size());
- for (int i = 0; i < count; i++)
- extraArgs.push_back(evaluationSizeofTypeExpression(inners.at(i)));
- }
-
- // Pad with zeros
- while (extraArgs.size() < maxExtraArgCount)
- extraArgs.push_back("0");
-
- // in rare cases we need more or less:
- switch (td.type) {
- case QAbstractItemType:
- if (data.dumperFlags.isEmpty()) {
- qWarning("Internal error: empty dumper state '%s'.", data.iname.constData());
- } else {
- inner = data.dumperFlags.mid(1);
- }
- break;
- case QObjectSlotType:
- case QObjectSignalType: {
- // we need the number out of something like
- // iname="local.ob.slots.2" // ".deleteLater()"?
- const int pos = data.iname.lastIndexOf('.');
- const QByteArray slotNumber = data.iname.mid(pos + 1);
- QTC_ASSERT(slotNumber.toInt() != -1, /**/);
- extraArgs[0] = slotNumber;
- }
- break;
- case QMapType:
- case QMultiMapType: {
- QByteArray nodetype;
- if (m_qtVersion >= 0x040500) {
- nodetype = m_qtNamespace + "QMapNode";
- nodetype += data.type.mid(outertype.size());
- } else {
- // FIXME: doesn't work for QMultiMap
- nodetype = data.type + "::Node";
- }
- //qDebug() << "OUTERTYPE: " << outertype << " NODETYPE: " << nodetype
- // << "QT VERSION" << m_qtVersion << ((4 << 16) + (5 << 8) + 0);
- extraArgs[2] = evaluationSizeofTypeExpression(nodetype);
- extraArgs[3] = qMapNodeValueOffsetExpression(nodetype);
- }
- break;
- case QMapNodeType:
- extraArgs[2] = evaluationSizeofTypeExpression(data.type);
- extraArgs[3] = qMapNodeValueOffsetExpression(data.type);
- break;
- case StdVectorType:
- //qDebug() << "EXTRACT TEMPLATE: " << outertype << inners;
- if (inners.at(0) == "bool")
- outertype = "std::vector::bool";
- break;
- case StdDequeType:
- extraArgs[1] = "0";
- break;
- case StdStackType:
- // remove 'std::allocator<...>':
- extraArgs[1] = "0";
- break;
- case StdSetType:
- // remove 'std::less<...>':
- extraArgs[1] = "0";
- // remove 'std::allocator<...>':
- extraArgs[2] = "0";
- break;
- case StdMapType: {
- // We need the offset of the second item in the value pair.
- // We read the type of the pair from the allocator argument because
- // that gets the constness "right" (in the sense that gdb/cdb can
- // read it back: "std::allocator<std::pair<Key,Value> >"
- // -> "std::pair<Key,Value>". Different debuggers have varying
- // amounts of terminating blanks...
- extraArgs[2].clear();
- extraArgs[3] = "0";
- QByteArray pairType = inners.at(3);
- int bracketPos = pairType.indexOf('<');
- if (bracketPos != -1)
- pairType.remove(0, bracketPos + 1);
- // We don't want the comparator and the allocator confuse gdb.
- const char closingBracket = '>';
- bracketPos = pairType.lastIndexOf(closingBracket);
- if (bracketPos != -1)
- bracketPos = pairType.lastIndexOf(closingBracket, bracketPos - pairType.size() - 1);
- if (bracketPos != -1)
- pairType.truncate(bracketPos + 1);
- extraArgs[2] = "(size_t)&(('";
- extraArgs[2] += pairType;
- extraArgs[2] += "'*)0)->second";
- }
- break;
- case StdStringType:
- //qDebug() << "EXTRACT TEMPLATE: " << outertype << inners;
- if (inners.at(0) == "char")
- outertype = "std::string";
- else if (inners.at(0) == "wchar_t")
- outertype = "std::wstring";
- qFill(extraArgs, zero);
- break;
- case UnknownType:
- qWarning("Unknown type encountered in %s.\n", Q_FUNC_INFO);
- break;
- case SupportedType:
- case QVectorType:
- case QStackType:
- case QObjectType:
- case QWidgetType:
- break;
- }
-
- // Look up expressions in the cache
- if (!m_expressionCache.empty()) {
- const ExpressionCache::const_iterator excCend = m_expressionCache.constEnd();
- const QByteArrayList::iterator eend = extraArgs.end();
- for (QByteArrayList::iterator it = extraArgs.begin(); it != eend; ++it) {
- QByteArray &e = *it;
- if (!e.isEmpty() && e != zero && !isInteger(e)) {
- const ExpressionCache::const_iterator eit = m_expressionCache.constFind(e);
- if (eit != excCend)
- e = eit.value();
- }
- }
- }
-
- inBuffer->clear();
- inBuffer->append(outertype.toUtf8());
- inBuffer->append('\0');
- inBuffer->append(data.iname);
- inBuffer->append('\0');
- inBuffer->append(data.exp);
- inBuffer->append('\0');
- inBuffer->append(inner.toUtf8());
- inBuffer->append('\0');
- inBuffer->append(data.iname);
- inBuffer->append('\0');
-
- if (debug)
- qDebug() << '\n' << Q_FUNC_INFO << '\n' << data.toString() << "\n-->" << outertype << td.type << extraArgs;
-}
-
-QDebug operator<<(QDebug in, const QtDumperHelper::TypeData &d)
-{
- QDebug nsp = in.nospace();
- nsp << " type=" << d.type << " tpl=" << d.isTemplate;
- if (d.isTemplate)
- nsp << d.tmplate << '<' << d.inner << '>';
- return in;
-}
-
//////////////////////////////////////////////////////////////////////
//
// GdbMi interaction
@@ -1328,7 +717,7 @@ void setWatchDataValueEnabled(WatchData &data, const GdbMi &mi)
data.valueEnabled = false;
}
-void setWatchDataValueEditable(WatchData &data, const GdbMi &mi)
+static void setWatchDataValueEditable(WatchData &data, const GdbMi &mi)
{
if (mi.data() == "true")
data.valueEditable = true;
@@ -1336,29 +725,49 @@ void setWatchDataValueEditable(WatchData &data, const GdbMi &mi)
data.valueEditable = false;
}
-void setWatchDataExpression(WatchData &data, const GdbMi &mi)
+static void setWatchDataExpression(WatchData &data, const GdbMi &mi)
{
if (mi.isValid())
data.exp = mi.data();
}
-void setWatchDataAddress(WatchData &data, const GdbMi &mi)
-{
- if (mi.isValid())
- setWatchDataAddressHelper(data, mi.data());
-}
-
-void setWatchDataAddressHelper(WatchData &data, const QByteArray &addr)
+static void setWatchDataAddress(WatchData &data, quint64 address , quint64 origAddress = 0)
{
- if (addr.startsWith("0x")) { // Item model dumpers pull tricks
- data.setHexAddress(addr);
+ if (origAddress) { // Gdb dumpers reports the dereferenced address as origAddress
+ data.address = origAddress;
+ data.referencingAddress = address;
} else {
- data.dumperFlags = addr;
+ data.address = address;
}
if (data.exp.isEmpty() && !data.dumperFlags.startsWith('$'))
data.exp = "*(" + gdbQuoteTypes(data.type) + "*)" +data.hexAddress();
}
+void setWatchDataAddress(WatchData &data, const GdbMi &addressMi, const GdbMi &origAddressMi)
+{
+ if (!addressMi.isValid())
+ return;
+ const QByteArray addressBA = addressMi.data();
+ if (!addressBA.startsWith("0x")) { // Item model dumpers pull tricks.
+ data.dumperFlags = addressBA;
+ return;
+ }
+ const quint64 address = addressBA.toULongLong(0, 16);
+ const quint64 origAddress = origAddressMi.isValid() ?
+ origAddressMi.data().toULongLong(0, 16) : quint64(0);
+ setWatchDataAddress(data, address, origAddress);
+}
+
+static void setWatchDataSize(WatchData &data, const GdbMi &mi)
+{
+ if (mi.isValid()) {
+ bool ok = false;
+ const unsigned size = mi.data().toUInt(&ok);
+ if (ok)
+ data.size = size;
+ }
+}
+
// Find the "type" and "displayedtype" children of root and set up type.
void setWatchDataType(WatchData &data, const GdbMi &item)
{
@@ -1406,7 +815,8 @@ void parseWatchData(const QSet<QByteArray> &expandedINames,
data.bitsize = mi.data().toInt();
setWatchDataValue(data, item);
- setWatchDataAddress(data, item.findChild("addr"));
+ setWatchDataAddress(data, item.findChild("addr"), item.findChild("origaddr"));
+ setWatchDataSize(data, item.findChild("size"));
setWatchDataExpression(data, item.findChild("exp"));
setWatchDataValueEnabled(data, item.findChild("valueenabled"));
setWatchDataValueEditable(data, item.findChild("valueeditable"));
@@ -1444,8 +854,7 @@ void parseWatchData(const QSet<QByteArray> &expandedINames,
if (!data1.name.isEmpty() && data1.name.at(0).isDigit())
data1.name = _c('[') + data1.name + _c(']');
if (addressStep) {
- const QByteArray addr = "0x" + QByteArray::number(addressBase, 16);
- setWatchDataAddressHelper(data1, addr);
+ setWatchDataAddress(data1, addressBase);
addressBase += addressStep;
}
QByteArray key = child.findChild("key").data();
diff --git a/src/plugins/debugger/watchutils.h b/src/plugins/debugger/watchutils.h
index c3205fa888..65a4850926 100644
--- a/src/plugins/debugger/watchutils.h
+++ b/src/plugins/debugger/watchutils.h
@@ -34,11 +34,6 @@
#include <QtCore/QSet>
#include <QtCore/QString>
-#include <QtCore/QMap>
-
-QT_BEGIN_NAMESPACE
-class QDebug;
-QT_END_NAMESPACE
namespace TextEditor {
class ITextEditor;
@@ -58,18 +53,30 @@ namespace Internal {
class WatchData;
class GdbMi;
+// Keep in sync with dumper.py
+enum DebuggerEncoding
+{
+ Unencoded8Bit = 0,
+ Base64Encoded8BitWithQuotes = 1,
+ Base64Encoded16BitWithQuotes = 2,
+ Base64Encoded32BitWithQuotes = 3,
+ Base64Encoded16Bit = 4,
+ Base64Encoded8Bit = 5,
+ Hex2EncodedLatin1 = 6,
+ Hex4EncodedLittleEndian = 7,
+ Hex8EncodedLittleEndian = 8,
+ Hex2EncodedUtf8 = 9,
+ Hex8EncodedBigEndian = 10,
+ Hex4EncodedBigEndian = 11,
+ Hex4EncodedLittleEndianWithoutQuotes = 12
+};
+
bool isEditorDebuggable(Core::IEditor *editor);
QByteArray dotEscape(QByteArray str);
QString currentTime();
bool isSkippableFunction(const QString &funcName, const QString &fileName);
bool isLeavableFunction(const QString &funcName, const QString &fileName);
-inline bool isNameChar(char c)
-{
- // could be 'stopped' or 'shlibs-added'
- return (c >= 'a' && c <= 'z') || c == '-';
-}
-
bool hasLetterOrNumber(const QString &exp);
bool hasSideEffects(const QString &exp);
bool isKeyWord(const QString &exp);
@@ -78,16 +85,11 @@ bool isCharPointerType(const QByteArray &type);
bool startsWithDigit(const QString &str);
QByteArray stripPointerType(QByteArray type);
QByteArray gdbQuoteTypes(const QByteArray &type);
-bool extractTemplate(const QString &type, QString *tmplate, QString *inner);
-QString extractTypeFromPTypeOutput(const QString &str);
bool isFloatType(const QByteArray &type);
bool isIntOrFloatType(const QByteArray &type);
bool isIntType(const QByteArray &type);
bool isSymbianIntType(const QByteArray &type);
-enum GuessChildrenResult { HasChildren, HasNoChildren, HasPossiblyChildren };
-GuessChildrenResult guessChildren(const QByteArray &type);
-
QString quoteUnprintableLatin1(const QByteArray &ba);
// Editor tooltip support
@@ -102,131 +104,8 @@ QString decodeData(const QByteArray &baIn, int encoding);
// of a function from the code model. Shadowed variables will
// be reported using the debugger naming conventions '<shadowed n>'
bool getUninitializedVariables(const CPlusPlus::Snapshot &snapshot,
- const QString &function,
- const QString &file,
- int line,
- QStringList *uninitializedVariables);
-
-/* Attempt to put common code of the dumper handling into a helper
- * class.
- * "Custom dumper" is a library compiled against the current
- * Qt containing functions to evaluate values of Qt classes
- * (such as QString, taking pointers to their addresses).
- * The library must be loaded into the debuggee.
- * It provides a function that takes input from an input buffer
- * and some parameters and writes output into an output buffer.
- * Parameter 1 is the protocol:
- * 1) Query. Fills output buffer with known types, Qt version and namespace.
- * This information is parsed and stored by this class (special type
- * enumeration).
- * 2) Evaluate symbol, taking address and some additional parameters
- * depending on type. */
-
-class QtDumperHelper
-{
-public:
- enum Type {
- UnknownType,
- SupportedType, // A type that requires no special handling by the dumper
- // Below types require special handling
- QAbstractItemType,
- QObjectType, QWidgetType, QObjectSlotType, QObjectSignalType,
- QVectorType, QMapType, QMultiMapType, QMapNodeType, QStackType,
- StdVectorType, StdDequeType, StdSetType, StdMapType, StdStackType,
- StdStringType
- };
-
- // Type/Parameter struct required for building a value query
- struct TypeData {
- TypeData();
- void clear();
-
- Type type;
- bool isTemplate;
- QByteArray tmplate;
- QByteArray inner;
- };
-
- QtDumperHelper();
- void clear();
-
- double dumperVersion() const { return m_dumperVersion; }
-
- int typeCount() const;
- // Look up a simple, non-template type
- Type simpleType(const QByteArray &simpleType) const;
- // Look up a (potentially) template type and fill parameter struct
- TypeData typeData(const QByteArray &typeName) const;
- Type type(const QByteArray &typeName) const;
-
- int qtVersion() const;
- QByteArray qtVersionString() const;
- QByteArray qtNamespace() const;
- void setQtNamespace(const QByteArray &ba)
- { if (!ba.isEmpty()) m_qtNamespace = ba; }
-
- // Complete parse of "query" (protocol 1) response from debuggee buffer.
- // 'data' excludes the leading indicator character.
- bool parseQuery(const GdbMi &data);
- // Sizes can be added as the debugger determines them
- void addSize(const QByteArray &type, int size);
-
- // Determine the parameters required for an "evaluate" (protocol 2) call
- void evaluationParameters(const WatchData &data,
- const TypeData &td,
- QByteArray *inBuffer,
- QList<QByteArray> *extraParameters) const;
-
- QString toString(bool debug = false) const;
-
- static QString msgDumperOutdated(double requiredVersion, double currentVersion);
-
-private:
- typedef QMap<QString, Type> NameTypeMap;
- typedef QMap<QByteArray, int> SizeCache;
-
- // Look up a simple (namespace) type
- QByteArray evaluationSizeofTypeExpression(const QByteArray &typeName) const;
-
- NameTypeMap m_nameTypeMap;
- SizeCache m_sizeCache;
-
- // The initial dumper query function returns sizes of some special
- // types to aid CDB since it cannot determine the size of classes.
- // They are not complete (std::allocator<X>).
- enum SpecialSizeType { IntSize, PointerSize, StdAllocatorSize,
- QSharedPointerSize, QSharedDataPointerSize,
- QWeakPointerSize, QPointerSize,
- QListSize, QLinkedListSize, QVectorSize, QQueueSize,
- SpecialSizeCount };
-
- // Resolve name to enumeration or SpecialSizeCount (invalid)
- SpecialSizeType specialSizeType(const QByteArray &type) const;
-
- int m_specialSizes[SpecialSizeCount];
-
- typedef QMap<QByteArray, QByteArray> ExpressionCache;
- ExpressionCache m_expressionCache;
- int m_qtVersion;
- double m_dumperVersion;
- QByteArray m_qtNamespace;
-
- void setQClassPrefixes(const QByteArray &qNamespace);
-
- QByteArray m_qPointerPrefix;
- QByteArray m_qSharedPointerPrefix;
- QByteArray m_qSharedDataPointerPrefix;
- QByteArray m_qWeakPointerPrefix;
- QByteArray m_qListPrefix;
- QByteArray m_qLinkedListPrefix;
- QByteArray m_qVectorPrefix;
- QByteArray m_qQueuePrefix;
-};
-
-QDebug operator<<(QDebug in, const QtDumperHelper::TypeData &d);
-
-// remove the default template argument in std:: containers
-QString removeDefaultTemplateArguments(QString type);
+ const QString &function, const QString &file, int line,
+ QStringList *uninitializedVariables);
//
@@ -238,10 +117,7 @@ void setWatchDataValueToolTip(WatchData &data, const GdbMi &mi,
int encoding);
void setWatchDataChildCount(WatchData &data, const GdbMi &mi);
void setWatchDataValueEnabled(WatchData &data, const GdbMi &mi);
-void setWatchDataValueEditable(WatchData &data, const GdbMi &mi);
-void setWatchDataExpression(WatchData &data, const GdbMi &mi);
-void setWatchDataAddress(WatchData &data, const GdbMi &mi);
-void setWatchDataAddressHelper(WatchData &data, const QByteArray &addr);
+void setWatchDataAddress(WatchData &data, const GdbMi &addressMi, const GdbMi &origAddressMi);
void setWatchDataType(WatchData &data, const GdbMi &mi);
void setWatchDataDisplayedType(WatchData &data, const GdbMi &mi);
diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp
index 3595cefb16..c874238c8a 100644
--- a/src/plugins/debugger/watchwindow.cpp
+++ b/src/plugins/debugger/watchwindow.cpp
@@ -38,9 +38,11 @@
#include "debuggercore.h"
#include "debuggerdialogs.h"
#include "debuggerengine.h"
+#include "debuggerstartparameters.h"
#include "watchdelegatewidgets.h"
#include "watchhandler.h"
#include "debuggertooltipmanager.h"
+#include "memoryviewwidget.h"
#include <utils/qtcassert.h>
#include <utils/savedaction.h>
@@ -51,6 +53,7 @@
#include <QtCore/QVariant>
#include <QtGui/QApplication>
+#include <QtGui/QPalette>
#include <QtGui/QClipboard>
#include <QtGui/QContextMenuEvent>
#include <QtGui/QHeaderView>
@@ -139,6 +142,192 @@ private:
WatchWindow *m_watchWindow;
};
+// Watch model query helpers.
+static inline quint64 addressOf(const QModelIndex &m)
+ { return m.data(LocalsAddressRole).toULongLong(); }
+static inline quint64 pointerValueOf(const QModelIndex &m)
+ { return m.data(LocalsPointerValueRole).toULongLong(); }
+static inline QString nameOf(const QModelIndex &m)
+ { return m.data().toString(); }
+static inline uint sizeOf(const QModelIndex &m)
+ { return m.data(LocalsSizeRole).toUInt(); }
+
+// Helper functionality to indicate the area of a member variable in
+// a vector representing the memory area by a unique color
+// number and tooltip. Parts of it will be overwritten when recursing
+// over the children.
+
+typedef QPair<int, QString> ColorNumberToolTipPair;
+typedef QVector<ColorNumberToolTipPair> ColorNumberToolTipVector;
+
+static int memberVariableRecursion(const QModelIndex &m,
+ const QString &name,
+ quint64 start, quint64 end,
+ int *colorNumberIn,
+ ColorNumberToolTipVector *cnmv)
+{
+ int childCount = 0;
+ const int rowCount = m.model()->rowCount(m);
+ if (!rowCount)
+ return childCount;
+ const QString nameRoot = name + QLatin1Char('.');
+ for (int r = 0; r < rowCount; r++) {
+ const QModelIndex childIndex = m.child(r, 0);
+ const quint64 childAddress = addressOf(childIndex);
+ const uint childSize = sizeOf(childIndex);
+ if (childAddress && childAddress >= start
+ && (childAddress + childSize) <= end) { // Non-static, within area?
+ const QString childName = nameRoot + nameOf(childIndex);
+ const quint64 childOffset = childAddress - start;
+ const QString toolTip = WatchWindow::tr("%1 at #%2").arg(childName).arg(childOffset);
+ const ColorNumberToolTipPair colorNumberNamePair((*colorNumberIn)++, toolTip);
+ const ColorNumberToolTipVector::iterator begin = cnmv->begin() + childOffset;
+ qFill(begin, begin + childSize, colorNumberNamePair);
+ childCount++;
+ childCount += memberVariableRecursion(childIndex, childName, start, end, colorNumberIn, cnmv);
+ }
+ }
+ return childCount;
+}
+
+/*!
+ \fn variableMemoryMarkup()
+
+ \brief Creates markup for a variable in the memory view.
+
+ Marks the visible children with alternating colors in the parent, that is, for
+ \code
+ struct Foo {
+ char c1
+ char c2
+ int x2;
+ QPair<int, int> pair
+ }
+ \endcode
+ create something like:
+ \code
+ 0 memberColor1
+ 1 memberColor2
+ 2 base color (padding area of parent)
+ 3 base color
+ 4 member color1
+ ...
+ 8 memberColor2 (pair.first)
+ ...
+ 12 memberColor1 (pair.second)
+ \endcode
+
+ Fixme: When dereferencing a pointer, the size of the pointee is not
+ known, currently. So, we take an area of 1024 and fill the background
+ with the default color so that just the members are shown
+ (sizeIsEstimate=true). This could be fixed by passing the pointee size
+ as well from the debugger, but would require expensive type manipulation.
+
+ \sa Debugger::Internal::MemoryViewWidget
+*/
+
+typedef QList<MemoryViewWidget::Markup> MemoryViewWidgetMarkup;
+
+static inline MemoryViewWidgetMarkup
+ variableMemoryMarkup(const QModelIndex &m, quint64 address, quint64 size,
+ bool sizeIsEstimate,
+ const QTextCharFormat &defaultFormat,
+ const QColor &defaultBackground)
+{
+ enum { debug = 0 };
+
+ // Starting out from base, create an array representing the area filled with base
+ // color. Fill children with some unique color numbers,
+ // leaving the padding areas of the parent colored with the base color.
+ MemoryViewWidgetMarkup result;
+ const QString name = nameOf(m);
+ int colorNumber = 0;
+ ColorNumberToolTipVector ranges(size, ColorNumberToolTipPair(colorNumber, name));
+ const int childCount = memberVariableRecursion(m, name, address, address + size, &colorNumber, &ranges);
+ if (sizeIsEstimate && !childCount)
+ return result; // Fixme: Exact size not known, no point in filling if no children.
+ if (debug) {
+ QDebug dbg = qDebug().nospace();
+ dbg << name << ' ' << address << ' ' << size << '\n';
+ QString name;
+ for (unsigned i = 0; i < size; i++)
+ if (name != ranges.at(i).second) {
+ dbg << ",[" << i << ' ' << ranges.at(i).first << ' ' << ranges.at(i).second << ']';
+ name = ranges.at(i).second;
+ }
+ }
+
+ // Condense ranges of identical color into markup ranges. Assign member colors
+ // interchangeably.
+ const QColor baseColor = sizeIsEstimate ? defaultBackground : Qt::lightGray;
+ QColor memberColor1 = QColor(Qt::yellow).lighter();
+ QColor memberColor2 = QColor(Qt::cyan).lighter();
+
+ int lastColorNumber = 0;
+ int childNumber = 0;
+ for (unsigned i = 0; i < size; i++) {
+ const ColorNumberToolTipPair &range = ranges.at(i);
+ if (result.isEmpty() || lastColorNumber != range.first) {
+ lastColorNumber = range.first;
+ QTextCharFormat format = defaultFormat;
+ if (range.first == 0) { // Base color: Parent
+ format.setBackground(QBrush(baseColor));
+ } else {
+ if (childNumber++ & 1) { // Alternating member colors.
+ format.setBackground(QBrush(memberColor1));
+ memberColor1 = memberColor1.darker(120);
+ } else {
+ format.setBackground(QBrush(memberColor2));
+ memberColor2 = memberColor2.darker(120);
+ }
+ } // color switch
+ result.push_back(MemoryViewWidget::Markup(address + i, 1, format, range.second));
+ } else {
+ result.back().size++;
+ }
+ }
+
+ if (debug) {
+ QDebug dbg = qDebug().nospace();
+ dbg << name << ' ' << address << ' ' << size << '\n';
+ QString name;
+ for (unsigned i = 0; i < size; i++)
+ if (name != ranges.at(i).second) {
+ dbg << ',' << i << ' ' << ranges.at(i).first << ' ' << ranges.at(i).second;
+ name = ranges.at(i).second;
+ }
+ dbg << '\n';
+ foreach (const MemoryViewWidget::Markup &m, result)
+ dbg << m.address << ' ' << m.size << ' ' << m.toolTip << '\n';
+ }
+
+ return result;
+}
+
+// Convenience to create a memory view of a variable.
+static void addVariableMemoryView(DebuggerEngine *engine,
+ const QModelIndex &m, bool deferencePointer,
+ const QPoint &p, QWidget *parent)
+{
+ const QColor background = parent->palette().color(QPalette::Normal, QPalette::Base);
+ LocalsMemoryViewWidget *w = new LocalsMemoryViewWidget(parent);
+ const quint64 address = deferencePointer ? pointerValueOf(m) : addressOf(m);
+ // Fixme: Get the size of pointee (see variableMemoryMarkup())?
+ // Also, gdb does not report the size yet as of 8.4.2011
+ const quint64 typeSize = sizeOf(m);
+ const bool sizeIsEstimate = deferencePointer || !typeSize;
+ const quint64 size = sizeIsEstimate ? 1024 : typeSize;
+ if (!address)
+ return;
+ const MemoryViewWidgetMarkup markup
+ = variableMemoryMarkup(m, address, size, sizeIsEstimate,
+ w->textCharFormat(), background);
+ w->init(address, qMax(size, LocalsMemoryViewWidget::defaultLength), nameOf(m));
+ w->setMarkup(markup);
+ w->move(p);
+ engine->addMemoryView(w);
+}
+
/////////////////////////////////////////////////////////////////////
//
// WatchWindow
@@ -149,6 +338,7 @@ WatchWindow::WatchWindow(Type type, QWidget *parent)
: QTreeView(parent),
m_type(type)
{
+ setObjectName(QLatin1String("WatchWindow"));
m_grabbing = false;
setFrameStyle(QFrame::NoFrame);
@@ -268,6 +458,15 @@ static inline QString removeWatchActionText(QString exp)
return WatchWindow::tr("Remove Watch Expression \"%1\"").arg(exp);
}
+static inline void copyToClipboard(const QString &clipboardText)
+{
+ QClipboard *clipboard = QApplication::clipboard();
+#ifdef Q_WS_X11
+ clipboard->setText(clipboardText, QClipboard::Selection);
+#endif
+ clipboard->setText(clipboardText, QClipboard::Clipboard);
+}
+
void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
{
DebuggerEngine *engine = currentEngine();
@@ -277,8 +476,9 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
const QModelIndex mi0 = idx.sibling(idx.row(), 0);
const QModelIndex mi1 = idx.sibling(idx.row(), 1);
const QModelIndex mi2 = idx.sibling(idx.row(), 2);
- const quint64 address = mi0.data(LocalsAddressRole).toULongLong();
- const quint64 pointerValue = mi0.data(LocalsPointerValueRole).toULongLong();
+ const quint64 address = addressOf(mi0);
+ const uint size = sizeOf(mi0);
+ const quint64 pointerValue = pointerValueOf(mi0);
const QString exp = mi0.data(LocalsExpressionRole).toString();
const QString type = mi2.data().toString();
@@ -317,40 +517,40 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
const QString spacer = QLatin1String(" ");
formatMenu.addSeparator();
QAction *dummy = formatMenu.addAction(
- tr("Change Display for Type \"%1\":").arg(type));
+ tr("Change Display for Object Named \"%1\":").arg(mi0.data().toString()));
dummy->setEnabled(false);
- clearTypeFormatAction = formatMenu.addAction(spacer + tr("Automatic"));
- //clearTypeFormatAction->setEnabled(typeFormat != -1);
- //clearTypeFormatAction->setEnabled(individualFormat != -1);
- clearTypeFormatAction->setCheckable(true);
- clearTypeFormatAction->setChecked(typeFormat == -1);
+ clearIndividualFormatAction
+ = formatMenu.addAction(spacer + tr("Use Display Format Based on Type"));
+ //clearIndividualFormatAction->setEnabled(individualFormat != -1);
+ clearIndividualFormatAction->setCheckable(true);
+ clearIndividualFormatAction->setChecked(effectiveIndividualFormat == -1);
for (int i = 0; i != alternativeFormats.size(); ++i) {
const QString format = spacer + alternativeFormats.at(i);
QAction *act = new QAction(format, &formatMenu);
act->setCheckable(true);
- //act->setEnabled(individualFormat != -1);
- if (i == typeFormat)
+ if (i == effectiveIndividualFormat)
act->setChecked(true);
formatMenu.addAction(act);
- typeFormatActions.append(act);
+ individualFormatActions.append(act);
}
formatMenu.addSeparator();
dummy = formatMenu.addAction(
- tr("Change Display for Object Named \"%1\":").arg(mi0.data().toString()));
+ tr("Change Display for Type \"%1\":").arg(type));
dummy->setEnabled(false);
- clearIndividualFormatAction
- = formatMenu.addAction(spacer + tr("Use Display Format Based on Type"));
- //clearIndividualFormatAction->setEnabled(individualFormat != -1);
- clearIndividualFormatAction->setCheckable(true);
- clearIndividualFormatAction->setChecked(effectiveIndividualFormat == -1);
+ clearTypeFormatAction = formatMenu.addAction(spacer + tr("Automatic"));
+ //clearTypeFormatAction->setEnabled(typeFormat != -1);
+ //clearTypeFormatAction->setEnabled(individualFormat != -1);
+ clearTypeFormatAction->setCheckable(true);
+ clearTypeFormatAction->setChecked(typeFormat == -1);
for (int i = 0; i != alternativeFormats.size(); ++i) {
const QString format = spacer + alternativeFormats.at(i);
QAction *act = new QAction(format, &formatMenu);
act->setCheckable(true);
- if (i == effectiveIndividualFormat)
+ //act->setEnabled(individualFormat != -1);
+ if (i == typeFormat)
act->setChecked(true);
formatMenu.addAction(act);
- individualFormatActions.append(act);
+ typeFormatActions.append(act);
}
} else {
QAction *dummy = formatMenu.addAction(
@@ -423,26 +623,42 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
QAction *actOpenMemoryEditAtVariableAddress = new QAction(&memoryMenu);
QAction *actOpenMemoryEditAtPointerValue = new QAction(&memoryMenu);
QAction *actOpenMemoryEditor = new QAction(&memoryMenu);
+ QAction *actOpenMemoryViewAtVariableAddress = new QAction(&memoryMenu);
+ QAction *actOpenMemoryViewAtPointerValue = 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));
+ actOpenMemoryViewAtVariableAddress->setText(
+ tr("Open Memory View at Object's Address (0x%1)")
+ .arg(address, 0, 16));
} else {
actOpenMemoryEditAtVariableAddress->setText(
tr("Open Memory Editor at Object's Address"));
actOpenMemoryEditAtVariableAddress->setEnabled(false);
+ actOpenMemoryViewAtVariableAddress->setText(
+ tr("Open Memory View at Object's Address"));
+ actOpenMemoryViewAtVariableAddress->setEnabled(false);
}
if (createPointerActions) {
actOpenMemoryEditAtPointerValue->setText(
tr("Open Memory Editor at Referenced Address (0x%1)")
.arg(pointerValue, 0, 16));
+ actOpenMemoryViewAtPointerValue->setText(
+ tr("Open Memory View at Referenced Address (0x%1)")
+ .arg(pointerValue, 0, 16));
} else {
actOpenMemoryEditAtPointerValue->setText(
tr("Open Memory Editor at Referenced Address"));
actOpenMemoryEditAtPointerValue->setEnabled(false);
+ actOpenMemoryViewAtPointerValue->setText(
+ tr("Open Memory View at Referenced Address"));
+ actOpenMemoryViewAtPointerValue->setEnabled(false);
}
+ memoryMenu.addAction(actOpenMemoryViewAtVariableAddress);
+ memoryMenu.addAction(actOpenMemoryViewAtPointerValue);
memoryMenu.addAction(actOpenMemoryEditAtVariableAddress);
memoryMenu.addAction(actOpenMemoryEditAtPointerValue);
memoryMenu.addAction(actOpenMemoryEditor);
@@ -451,6 +667,9 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
}
QAction *actCopy = new QAction(tr("Copy Contents to Clipboard"), &menu);
+ QAction *actCopyValue = new QAction(tr("Copy Value to Clipboard"), &menu);
+ actCopyValue->setEnabled(idx.isValid());
+
menu.addAction(actInsertNewWatchItem);
menu.addAction(actSelectWidgetToWatch);
@@ -459,7 +678,8 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
menu.addAction(actSetWatchpointAtVariableAddress);
if (actSetWatchpointAtPointerValue)
menu.addAction(actSetWatchpointAtPointerValue);
- menu.addAction(actCopy );
+ menu.addAction(actCopy);
+ menu.addAction(actCopyValue);
menu.addSeparator();
menu.addAction(debuggerCore()->action(UseDebuggingHelpers));
@@ -511,10 +731,14 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
AddressDialog dialog;
if (dialog.exec() == QDialog::Accepted)
currentEngine()->openMemoryView(dialog.address());
+ } else if (act == actOpenMemoryViewAtVariableAddress) {
+ addVariableMemoryView(currentEngine(), mi0, false, ev->globalPos(), this);
+ } else if (act == actOpenMemoryViewAtPointerValue) {
+ addVariableMemoryView(currentEngine(), mi0, true, ev->globalPos(), this);
} else if (act == actSetWatchpointAtVariableAddress) {
- setWatchpoint(address);
+ setWatchpoint(address, size);
} else if (act == actSetWatchpointAtPointerValue) {
- setWatchpoint(pointerValue);
+ setWatchpoint(pointerValue, 1);
} else if (act == actSelectWidgetToWatch) {
grabMouse(Qt::CrossCursor);
m_grabbing = true;
@@ -522,13 +746,10 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
watchExpression(exp);
} else if (act == actRemoveWatchExpression) {
removeWatchExpression(exp);
- } else if (act == actCopy ) {
- const QString clipboardText = DebuggerTreeViewToolTipWidget::treeModelClipboardContents(model());
- QClipboard *clipboard = QApplication::clipboard();
-#ifdef Q_WS_X11
- clipboard->setText(clipboardText, QClipboard::Selection);
-#endif
- clipboard->setText(clipboardText, QClipboard::Clipboard);
+ } else if (act == actCopy) {
+ copyToClipboard(DebuggerTreeViewToolTipWidget::treeModelClipboardContents(model()));
+ } else if (act == actCopyValue) {
+ copyToClipboard(mi1.data().toString());
} else if (act == actRemoveWatches) {
currentEngine()->watchHandler()->clearWatches();
} else if (act == actClearCodeModelSnapshot) {
@@ -660,10 +881,11 @@ void WatchWindow::setModelData
model()->setData(index, value, role);
}
-void WatchWindow::setWatchpoint(quint64 address)
+void WatchWindow::setWatchpoint(quint64 address, unsigned size)
{
BreakpointParameters data(Watchpoint);
data.address = address;
+ data.size = size;
BreakpointId id = breakHandler()->findWatchpoint(data);
if (id) {
qDebug() << "WATCHPOINT EXISTS";
diff --git a/src/plugins/debugger/watchwindow.h b/src/plugins/debugger/watchwindow.h
index 6eb72216cc..a69fe572c0 100644
--- a/src/plugins/debugger/watchwindow.h
+++ b/src/plugins/debugger/watchwindow.h
@@ -78,7 +78,7 @@ private:
void editItem(const QModelIndex &idx);
void resetHelper(const QModelIndex &idx);
- void setWatchpoint(quint64 address);
+ void setWatchpoint(quint64 address, unsigned size);
void setModelData(int role, const QVariant &value = QVariant(),
const QModelIndex &index = QModelIndex());
diff --git a/src/plugins/designer/designerconstants.h b/src/plugins/designer/designerconstants.h
index a23ead0f2c..de0da9faef 100644
--- a/src/plugins/designer/designerconstants.h
+++ b/src/plugins/designer/designerconstants.h
@@ -51,11 +51,7 @@ const char * const SETTINGS_CPP_SETTINGS_NAME = QT_TRANSLATE_NOOP("Designer", "C
// context
const char * const C_FORMEDITOR = "FormEditor.FormEditor";
-const char * const FORMEDITOR_ID = "FormEditor";
-const char * const C_FORMEDITOR_DISPLAY_NAME = QT_TRANSLATE_NOOP("Designer", "Form Editor");
-const char * const T_FORMEDITOR = "FormEditor.Toolbar";
const char * const M_FORMEDITOR = "FormEditor.Menu";
-const char * const M_FORMEDITOR_VIEWS = "FormEditor.Menu.Views";
const char * const M_FORMEDITOR_PREVIEW = "FormEditor.Menu.Preview";
// Wizard type
diff --git a/src/plugins/designer/designercontext.cpp b/src/plugins/designer/designercontext.cpp
index 0516ba3363..84d8a8151b 100644
--- a/src/plugins/designer/designercontext.cpp
+++ b/src/plugins/designer/designercontext.cpp
@@ -46,23 +46,12 @@ enum { debug = 0 };
namespace Designer {
namespace Internal {
-DesignerContext::DesignerContext(const Core::Context &contexts,
- QWidget *widget,
- QObject *parent) :
- Core::IContext(parent),
- m_context(contexts),
- m_widget(widget)
+DesignerContext::DesignerContext(const Core::Context &context,
+ QWidget *widget, QObject *parent)
+ : Core::IContext(parent)
{
-}
-
-Core::Context DesignerContext::context() const
-{
- return m_context;
-}
-
-QWidget *DesignerContext::widget()
-{
- return m_widget;
+ setContext(context);
+ setWidget(widget);
}
QString DesignerContext::contextHelpId() const
diff --git a/src/plugins/designer/designercontext.h b/src/plugins/designer/designercontext.h
index 82d28e80f9..920d67238d 100644
--- a/src/plugins/designer/designercontext.h
+++ b/src/plugins/designer/designercontext.h
@@ -52,13 +52,7 @@ public:
QWidget *widget,
QObject *parent = 0);
- virtual Core::Context context() const;
- virtual QWidget *widget();
virtual QString contextHelpId() const;
-
-private:
- const Core::Context m_context;
- QWidget *m_widget;
};
} // namespace Internal
diff --git a/src/plugins/designer/formwindoweditor.cpp b/src/plugins/designer/formwindoweditor.cpp
index 16544d1924..17f2d59bac 100644
--- a/src/plugins/designer/formwindoweditor.cpp
+++ b/src/plugins/designer/formwindoweditor.cpp
@@ -58,28 +58,25 @@ namespace Designer {
struct FormWindowEditorPrivate
{
- explicit FormWindowEditorPrivate(Internal::DesignerXmlEditor *editor,
- QDesignerFormWindowInterface *form);
+ FormWindowEditorPrivate(Internal::DesignerXmlEditor *editor,
+ QDesignerFormWindowInterface *form)
+ : m_textEditor(editor), m_file(form)
+ {}
TextEditor::PlainTextEditor m_textEditor;
Internal::FormWindowFile m_file;
- Core::Context m_context;
};
-FormWindowEditorPrivate::FormWindowEditorPrivate(Internal::DesignerXmlEditor *editor,
- QDesignerFormWindowInterface *form) :
- m_textEditor(editor), m_file(form)
-{
-}
-
FormWindowEditor::FormWindowEditor(Internal::DesignerXmlEditor *editor,
QDesignerFormWindowInterface *form,
QObject *parent) :
Core::IEditor(parent),
d(new FormWindowEditorPrivate(editor, form))
{
- d->m_context.add(Designer::Constants::K_DESIGNER_XML_EDITOR_ID);
- d->m_context.add(Designer::Constants::C_DESIGNER_XML_EDITOR);
+ setContext(Core::Context(Designer::Constants::K_DESIGNER_XML_EDITOR_ID,
+ Designer::Constants::C_DESIGNER_XML_EDITOR));
+ setWidget(d->m_textEditor.widget());
+
connect(form, SIGNAL(changed()), this, SIGNAL(changed()));
// Revert to saved/load externally modified files.
connect(&d->m_file, SIGNAL(reload(QString)), this, SLOT(slotOpen(QString)));
@@ -238,16 +235,6 @@ bool FormWindowEditor::restoreState(const QByteArray &state)
return d->m_textEditor.restoreState(state);
}
-Core::Context FormWindowEditor::context() const
-{
- return d->m_context;
-}
-
-QWidget *FormWindowEditor::widget()
-{
- return d->m_textEditor.widget();
-}
-
bool FormWindowEditor::isTemporary() const
{
return false;
diff --git a/src/plugins/designer/formwindoweditor.h b/src/plugins/designer/formwindoweditor.h
index 9673540900..f7304af204 100644
--- a/src/plugins/designer/formwindoweditor.h
+++ b/src/plugins/designer/formwindoweditor.h
@@ -40,10 +40,6 @@ QT_BEGIN_NAMESPACE
class QDesignerFormWindowInterface;
QT_END_NAMESPACE
-namespace Core {
- class IMode;
-}
-
namespace TextEditor {
class BaseTextDocument;
class PlainTextEditor;
@@ -93,10 +89,6 @@ public:
virtual QString preferredModeType() const;
- // IContext
- virtual Core::Context context() const;
- virtual QWidget *widget();
-
// For uic code model support
QString contents() const;
diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp
index 9218a079fb..4acbc53ea1 100644
--- a/src/plugins/fakevim/fakevimhandler.cpp
+++ b/src/plugins/fakevim/fakevimhandler.cpp
@@ -128,6 +128,17 @@ namespace Internal {
#define EDITOR(s) (m_textedit ? m_textedit->s : m_plaintextedit->s)
+enum {
+#ifdef Q_WS_MAC
+ RealControlModifier = Qt::MetaModifier
+#else
+ RealControlModifier = Qt::ControlModifier
+#endif
+};
+// Enforce use of RealControlModifier by breaking the compilation.
+#define MetaModifier // Use RealControlModifier instead
+#define ControlModifier // Use RealControlModifier instead
+
const int ParagraphSeparator = 0x00002029;
typedef QLatin1String _;
@@ -408,23 +419,12 @@ public:
bool is(int c) const
{
- return m_xkey == c && m_modifiers !=
-#ifdef Q_WS_MAC
- Qt::MetaModifier
-#else
- Qt::ControlModifier
-#endif
- ;
+ return m_xkey == c && m_modifiers != RealControlModifier;
}
bool isControl(int c) const
{
- return m_modifiers ==
-#ifdef Q_WS_MAC
- Qt::MetaModifier
-#else
- Qt::ControlModifier
-#endif
+ return m_modifiers == RealControlModifier
&& (m_xkey == c || m_xkey + 32 == c || m_xkey + 64 == c || m_xkey + 96 == c);
}
@@ -500,8 +500,11 @@ void Inputs::parseFrom(const QString &str)
if (c0 == '<') {
if ((c1 == 'C' || c1 == 'c') && c2 == '-' && c4 == '>') {
uint c = (c3 < 90 ? c3 : c3 - 32);
- append(Input(c, Qt::ControlModifier, QString(QChar(c - 64))));
+ append(Input(c, RealControlModifier, QString(QChar(c - 64))));
i += 4;
+ } else if (c1 == 'C' && c2 == 'R' && c3 == '>') {
+ append(Input(Key_Return, Qt::NoModifier, QString(QChar(13))));
+ i += 3;
} else {
append(Input(QLatin1Char(c0)));
}
@@ -954,6 +957,7 @@ public:
bool handleExSourceCommand(const ExCommand &cmd);
bool handleExSubstituteCommand(const ExCommand &cmd);
bool handleExWriteCommand(const ExCommand &cmd);
+ bool handleExEchoCommand(const ExCommand &cmd);
void timerEvent(QTimerEvent *ev);
@@ -1050,12 +1054,7 @@ bool FakeVimHandler::Private::wantsOverride(QKeyEvent *ev)
}
// We are interested in overriding most Ctrl key combinations
- if (mods ==
-#ifdef Q_WS_MAC
- Qt::MetaModifier
-#else
- Qt::ControlModifier
-#endif
+ if (mods == RealControlModifier
&& !config(ConfigPassControlKey).toBool()
&& ((key >= Key_A && key <= Key_Z && key != Key_K)
|| key == Key_BracketLeft || key == Key_BracketRight)) {
@@ -1100,6 +1099,13 @@ EventResult FakeVimHandler::Private::handleEvent(QKeyEvent *ev)
return EventPassedToCore;
}
+ bool inSnippetMode = false;
+ QMetaObject::invokeMethod(editor(),
+ "inSnippetMode", Q_ARG(bool *, &inSnippetMode));
+
+ if (inSnippetMode)
+ return EventPassedToCore;
+
// Fake "End of line"
//m_tc = cursor();
@@ -1136,7 +1142,7 @@ EventResult FakeVimHandler::Private::handleEvent(QKeyEvent *ev)
if (m_fakeEnd)
moveRight();
- //if ((mods & Qt::ControlModifier) != 0) {
+ //if ((mods & RealControlModifier) != 0) {
// if (key >= Key_A && key <= Key_Z)
// key = shift(key); // make it lower case
// key = control(key);
@@ -1249,13 +1255,7 @@ void FakeVimHandler::Private::importSelection()
// Import new selection.
Qt::KeyboardModifiers mods = QApplication::keyboardModifiers();
if (cursor().hasSelection()) {
- if (mods &
-#ifdef Q_WS_MAC
- Qt::MetaModifier
-#else
- Qt::ControlModifier
-#endif
- )
+ if (mods & RealControlModifier)
m_visualMode = VisualBlockMode;
else if (mods & Qt::AltModifier)
m_visualMode = VisualBlockMode;
@@ -1298,7 +1298,7 @@ void FakeVimHandler::Private::restoreWidget(int tabSize)
EventResult FakeVimHandler::Private::handleKey(const Input &input)
{
- KEY_DEBUG("HANDLE INPUT: " << input);
+ KEY_DEBUG("HANDLE INPUT: " << input << " MODE: " << mode);
if (m_mode == ExMode)
return handleExMode(input);
if (m_subsubmode == SearchSubSubMode)
@@ -3245,7 +3245,7 @@ bool FakeVimHandler::Private::handleExMapCommand(const ExCommand &cmd0) // :map
if (pos == -1) {
// FIXME: Dump mappings here.
//qDebug() << g.mappings;
- return true;;
+ return true;
}
QString lhs = cmd0.args.left(pos);
@@ -3598,6 +3598,15 @@ bool FakeVimHandler::Private::handleExSourceCommand(const ExCommand &cmd)
return true;
}
+bool FakeVimHandler::Private::handleExEchoCommand(const ExCommand &cmd)
+{
+ // :echo
+ if (cmd.cmd != "echo")
+ return false;
+ m_currentMessage = cmd.args;
+ return true;
+}
+
void FakeVimHandler::Private::handleExCommand(const QString &line0)
{
QString line = line0; // Make sure we have a copy to prevent aliasing.
@@ -3650,7 +3659,8 @@ bool FakeVimHandler::Private::handleExCommandHelper(const ExCommand &cmd)
|| handleExShiftCommand(cmd)
|| handleExSourceCommand(cmd)
|| handleExSubstituteCommand(cmd)
- || handleExWriteCommand(cmd);
+ || handleExWriteCommand(cmd)
+ || handleExEchoCommand(cmd);
}
bool FakeVimHandler::Private::handleExPluginCommand(const ExCommand &cmd)
@@ -4238,11 +4248,11 @@ QString FakeVimHandler::Private::selectText(const Range &range) const
QTextCursor tc = cursor();
int firstPos = firstPositionInLine(lineForPosition(range.beginPos));
int lastLine = lineForPosition(range.endPos);
- int lastPos = lastLine == document()->lastBlock().blockNumber() + 1
- ? lastPositionInDocument() : firstPositionInLine(lastLine + 1);
+ bool endOfDoc = lastLine == document()->lastBlock().blockNumber() + 1;
+ int lastPos = endOfDoc ? lastPositionInDocument() : firstPositionInLine(lastLine + 1);
tc.setPosition(firstPos, MoveAnchor);
tc.setPosition(lastPos, KeepAnchor);
- return tc.selection().toPlainText();
+ return tc.selection().toPlainText() + QString((endOfDoc? "\n" : ""));
}
// FIXME: Performance?
int beginLine = lineForPosition(range.beginPos);
@@ -4446,14 +4456,30 @@ void FakeVimHandler::Private::pasteText(bool afterCursor)
case RangeLineModeExclusive: {
moveToStartOfLine();
m_targetColumn = 0;
+ beginEditBlock();
+ QTextCursor tc = cursor();
for (int i = count(); --i >= 0; ) {
- if (afterCursor)
+ bool lastLine = document()->lastBlock() == this->block();
+ if (afterCursor) {
+ if (lastLine) {
+ tc.movePosition(EndOfLine, MoveAnchor);
+ tc.insertBlock();
+ }
moveDown();
+ }
setAnchor();
insertText(text);
- moveUp(lines.size() - 1);
+ if (afterCursor && lastLine) {
+ tc.movePosition(Left, KeepAnchor);
+ tc.removeSelectedText();
+ setAnchor();
+ moveUp(lines.size() - 2);
+ } else {
+ moveUp(lines.size() - 1);
+ }
}
moveToFirstNonBlankOnLine();
+ endEditBlock();
break;
}
case RangeBlockAndTailMode:
@@ -4727,7 +4753,7 @@ void FakeVimHandler::Private::replay(const QString &command, int n)
//qDebug() << "REPLAY: " << quoteUnprintable(command);
for (int i = n; --i >= 0; ) {
foreach (QChar c, command) {
- //qDebug() << " REPLAY: " << QString(c);
+ //qDebug() << " REPLAY: " << c.unicode();
handleKey(Input(c));
}
}
@@ -4945,6 +4971,17 @@ void FakeVimHandler::handleReplay(const QString &keys)
d->replay(keys, 1);
}
+void FakeVimHandler::handleInput(const QString &keys)
+{
+ Mode oldMode = d->m_mode;
+ d->m_mode = CommandMode;
+ Inputs inputs;
+ inputs.parseFrom(keys);
+ foreach (const Input &input, inputs)
+ d->handleKey(input);
+ d->m_mode = oldMode;
+}
+
void FakeVimHandler::setCurrentFileName(const QString &fileName)
{
d->m_currentFileName = fileName;
diff --git a/src/plugins/fakevim/fakevimhandler.h b/src/plugins/fakevim/fakevimhandler.h
index 283c2d1c4f..f2b4f6d8c7 100644
--- a/src/plugins/fakevim/fakevimhandler.h
+++ b/src/plugins/fakevim/fakevimhandler.h
@@ -100,6 +100,7 @@ public slots:
// information from the current widget.
void handleCommand(const QString &cmd);
void handleReplay(const QString &keys);
+ void handleInput(const QString &keys);
void installEventFilter();
diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp
index 78bd5f4ece..cb9f1ab724 100644
--- a/src/plugins/fakevim/fakevimplugin.cpp
+++ b/src/plugins/fakevim/fakevimplugin.cpp
@@ -75,6 +75,7 @@
#include <cpptools/cpptoolsconstants.h>
+#include <QtCore/QAbstractTableModel>
#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QtPlugin>
@@ -83,6 +84,7 @@
#include <QtCore/QTextStream>
#include <QtGui/QDesktopServices>
+#include <QtGui/QItemDelegate>
#include <QtGui/QMessageBox>
#include <QtGui/QPlainTextEdit>
#include <QtGui/QShortcut>
@@ -105,6 +107,7 @@ const char * const SETTINGS_CATEGORY = "D.FakeVim";
const char * const SETTINGS_CATEGORY_FAKEVIM_ICON = ":/core/images/category_fakevim.png";
const char * const SETTINGS_ID = "A.General";
const char * const SETTINGS_EX_CMDS_ID = "B.ExCommands";
+const char * const SETTINGS_USER_CMDS_ID = "C.UserCommands";
} // namespace Constants
} // namespace FakeVim
@@ -119,7 +122,8 @@ namespace Internal {
//
///////////////////////////////////////////////////////////////////////
-typedef QMap<QString, QRegExp> CommandMap;
+typedef QMap<QString, QRegExp> ExCommandMap;
+typedef QMap<int, QString> UserCommandMap;
typedef QLatin1String _;
class FakeVimOptionPage : public Core::IOptionsPage
@@ -295,8 +299,8 @@ public:
QWidget *createPage(QWidget *parent);
void initialize();
- CommandMap &exCommandMap();
- CommandMap &defaultExCommandMap();
+ ExCommandMap &exCommandMap();
+ ExCommandMap &defaultExCommandMap();
public slots:
void commandChanged(QTreeWidgetItem *current);
@@ -306,7 +310,6 @@ public slots:
void defaultAction();
private:
- //QList<QTreeWidgetItem *> m_citems;
FakeVimPluginPrivate *m_q;
};
@@ -336,7 +339,6 @@ void FakeVimExCommandsPage::initialize()
QTreeWidgetItem *item = new QTreeWidgetItem;
item->setData(0, CommandRole, int(c->id()));
- //m_citems.append(item);
const QString name = uidm->stringForUniqueIdentifier(c->id());
const int pos = name.indexOf(QLatin1Char('.'));
@@ -401,11 +403,7 @@ void FakeVimExCommandsPage::targetIdentifierChanged()
exCommandMap()[name] = QRegExp(regex);
}
- if (regex != defaultExCommandMap()[name].pattern())
- setModified(current, true);
- else
- setModified(current, false);
-
+ setModified(current, regex != defaultExCommandMap()[name].pattern());
}
void FakeVimExCommandsPage::resetTargetIdentifier()
@@ -449,6 +447,133 @@ void FakeVimExCommandsPage::defaultAction()
}
}
+///////////////////////////////////////////////////////////////////////
+//
+// FakeVimUserCommandsPage
+//
+///////////////////////////////////////////////////////////////////////
+
+class FakeVimUserCommandsModel : public QAbstractTableModel
+{
+public:
+ FakeVimUserCommandsModel(FakeVimPluginPrivate *q) : m_q(q) {}
+ ~FakeVimUserCommandsModel() {}
+
+ 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 &data, int role);
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+
+private:
+ FakeVimPluginPrivate *m_q;
+};
+
+int FakeVimUserCommandsModel::rowCount(const QModelIndex &parent) const
+{
+ return parent.isValid() ? 0 : 9;
+}
+
+int FakeVimUserCommandsModel::columnCount(const QModelIndex &parent) const
+{
+ return parent.isValid() ? 0 : 2;
+}
+
+
+QVariant FakeVimUserCommandsModel::headerData(int section,
+ Qt::Orientation orient, int role) const
+{
+ if (orient == Qt::Horizontal && role == Qt::DisplayRole) {
+ switch (section) {
+ case 0: return tr("Action");
+ case 1: return tr("Command");
+ };
+ }
+ return QVariant();
+}
+
+Qt::ItemFlags FakeVimUserCommandsModel::flags(const QModelIndex &index) const
+{
+ if (index.column() == 1)
+ return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
+ return QAbstractTableModel::flags(index);
+}
+
+class FakeVimUserCommandsDelegate : public QItemDelegate
+{
+public:
+ explicit FakeVimUserCommandsDelegate(QObject *parent)
+ : QItemDelegate(parent)
+ {}
+
+ QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &,
+ const QModelIndex &) const
+ {
+ QLineEdit *lineEdit = new QLineEdit(parent);
+ lineEdit->setFrame(false);
+ return lineEdit;
+ }
+
+ void setModelData(QWidget *editor, QAbstractItemModel *model,
+ const QModelIndex &index) const
+ {
+ QLineEdit *lineEdit = qobject_cast<QLineEdit *>(editor);
+ QTC_ASSERT(lineEdit, return);
+ model->setData(index, lineEdit->text(), Qt::EditRole);
+ }
+};
+
+class FakeVimUserCommandsPage : public Core::IOptionsPage
+{
+ Q_OBJECT
+
+public:
+ FakeVimUserCommandsPage(FakeVimPluginPrivate *q) : m_q(q) {}
+ ~FakeVimUserCommandsPage() {}
+
+ // IOptionsPage
+ QString id() const { return _(Constants::SETTINGS_USER_CMDS_ID); }
+ QString displayName() const { return tr("User Command Mapping"); }
+ QString category() const { return _(Constants::SETTINGS_CATEGORY); }
+ QString displayCategory() const { return tr("FakeVim"); }
+ QIcon categoryIcon() const { return QIcon(); }
+ void apply();
+ void finish() {}
+
+ QWidget *createPage(QWidget *parent);
+ void initialize() {}
+ UserCommandMap &userCommandMap();
+ UserCommandMap &defaultUserCommandMap();
+
+private:
+ FakeVimPluginPrivate *m_q;
+};
+
+QWidget *FakeVimUserCommandsPage::createPage(QWidget *parent)
+{
+ QGroupBox *box = new QGroupBox(parent);
+
+ FakeVimUserCommandsModel *model = new FakeVimUserCommandsModel(m_q);
+ QTreeView *widget = new QTreeView;
+ widget->setModel(model);
+ widget->resizeColumnToContents(0);
+
+ FakeVimUserCommandsDelegate *delegate = new FakeVimUserCommandsDelegate(widget);
+ widget->setItemDelegateForColumn(1, delegate);
+
+ QGridLayout *layout = new QGridLayout(box);
+ layout->addWidget(widget, 0, 0);
+ box->setLayout(layout);
+
+ return box;
+}
+
+void FakeVimUserCommandsPage::apply()
+{
+ //m_q->writeSettings();
+}
+
///////////////////////////////////////////////////////////////////////
//
@@ -621,6 +746,8 @@ public:
~FakeVimPluginPrivate();
friend class FakeVimPlugin;
friend class FakeVimExCommandsPage;
+ friend class FakeVimUserCommandsPage;
+ friend class FakeVimUserCommandsModel;
bool initialize();
void aboutToShutdown();
@@ -631,6 +758,7 @@ private slots:
void editorAboutToClose(Core::IEditor *);
void setUseFakeVim(const QVariant &value);
+ void setUseFakeVimInternal(bool on);
void quitFakeVim();
void triggerCompletions();
void triggerSimpleCompletions(const QString &needle, bool forward);
@@ -655,6 +783,7 @@ private slots:
void handleDelayedQuitAll(bool forced);
void handleDelayedQuit(bool forced, Core::IEditor *editor);
+ void userActionTriggered();
void switchToFile(int n);
int currentFile() const;
@@ -667,6 +796,7 @@ private:
FakeVimPlugin *q;
FakeVimOptionPage *m_fakeVimOptionsPage;
FakeVimExCommandsPage *m_fakeVimExCommandsPage;
+ FakeVimUserCommandsPage *m_fakeVimUserCommandsPage;
QHash<Core::IEditor *, FakeVimHandler *> m_editorToHandler;
QPointer<Core::ICore> m_core;
QPointer<Core::EditorManager> m_editorManager;
@@ -681,19 +811,52 @@ private:
typedef int (*DistFunction)(const QRect &cursor, const QRect &other);
void moveSomewhere(DistFunction f);
- CommandMap &exCommandMap() { return m_exCommandMap; }
- CommandMap &defaultExCommandMap() { return m_defaultExCommandMap; }
- CommandMap m_exCommandMap;
- CommandMap m_defaultExCommandMap;
+ ExCommandMap &exCommandMap() { return m_exCommandMap; }
+ ExCommandMap &defaultExCommandMap() { return m_defaultExCommandMap; }
+ ExCommandMap m_exCommandMap;
+ ExCommandMap m_defaultExCommandMap;
+
+ UserCommandMap &userCommandMap() { return m_userCommandMap; }
+ UserCommandMap &defaultUserCommandMap() { return m_defaultUserCommandMap; }
+ UserCommandMap m_userCommandMap;
+ UserCommandMap m_defaultUserCommandMap;
+
Core::StatusBarWidget *m_statusBar;
WordCompletion *m_wordCompletion;
};
+QVariant FakeVimUserCommandsModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ if (role == Qt::DisplayRole || role == Qt::EditRole) {
+ switch (index.column()) {
+ case 0: // Action
+ return tr("User command #%1").arg(index.row() + 1);
+ case 1: // Command
+ return m_q->userCommandMap().value(index.row() + 1);
+ }
+ }
+
+ return QVariant();
+}
+
+bool FakeVimUserCommandsModel::setData(const QModelIndex &index,
+ const QVariant &data, int role)
+{
+ if (role == Qt::DisplayRole || role == Qt::EditRole)
+ if (index.column() == 1)
+ m_q->userCommandMap()[index.row() + 1] = data.toString();
+ return true;
+}
+
FakeVimPluginPrivate::FakeVimPluginPrivate(FakeVimPlugin *plugin)
{
q = plugin;
m_fakeVimOptionsPage = 0;
m_fakeVimExCommandsPage = 0;
+ m_fakeVimUserCommandsPage = 0;
defaultExCommandMap()[CppTools::Constants::SWITCH_HEADER_SOURCE] =
QRegExp("^A$");
defaultExCommandMap()["Coreplugin.OutputPane.previtem"] =
@@ -706,6 +869,12 @@ FakeVimPluginPrivate::FakeVimPluginPrivate(FakeVimPlugin *plugin)
QRegExp("^pop?$");
defaultExCommandMap()[_("QtCreator.Locate")] =
QRegExp("^e$");
+
+ for (int i = 1; i < 10; ++i) {
+ QString cmd = QString::fromLatin1(":echo User command %1 executed.<CR>");
+ defaultUserCommandMap().insert(i, cmd.arg(i));
+ }
+
m_statusBar = 0;
}
@@ -719,6 +888,10 @@ FakeVimPluginPrivate::~FakeVimPluginPrivate()
q->removeObject(m_fakeVimExCommandsPage);
delete m_fakeVimExCommandsPage;
m_fakeVimExCommandsPage = 0;
+
+ q->removeObject(m_fakeVimUserCommandsPage);
+ delete m_fakeVimUserCommandsPage;
+ m_fakeVimUserCommandsPage = 0;
}
void FakeVimPluginPrivate::onCoreAboutToClose()
@@ -758,6 +931,10 @@ bool FakeVimPluginPrivate::initialize()
m_fakeVimExCommandsPage = new FakeVimExCommandsPage(this);
q->addObject(m_fakeVimExCommandsPage);
+
+ m_fakeVimUserCommandsPage = new FakeVimUserCommandsPage(this);
+ q->addObject(m_fakeVimUserCommandsPage);
+
readSettings();
Core::Command *cmd = 0;
@@ -765,6 +942,17 @@ bool FakeVimPluginPrivate::initialize()
Constants::INSTALL_HANDLER, globalcontext);
cmd->setDefaultKeySequence(QKeySequence(Constants::INSTALL_KEY));
+ for (int i = 1; i < 10; ++i) {
+ QAction *act = new QAction(this);
+ act->setText(QString("Execute User Action #%1").arg(i));
+ act->setData(i);
+ QString id = QString("FakeVim.UserAction%1").arg(i);
+ QString keys = QString("Alt+V,%1").arg(i);
+ cmd = actionManager()->registerAction(act, id, globalcontext);
+ cmd->setDefaultKeySequence(QKeySequence(keys));
+ connect(act, SIGNAL(triggered()), SLOT(userActionTriggered()));
+ }
+
ActionContainer *advancedMenu =
actionManager()->actionContainer(Core::Constants::M_EDIT_ADVANCED);
advancedMenu->addAction(cmd, Core::Constants::G_EDIT_EDITOR);
@@ -793,8 +981,25 @@ bool FakeVimPluginPrivate::initialize()
return true;
}
+void FakeVimPluginPrivate::userActionTriggered()
+{
+ QAction *act = qobject_cast<QAction *>(sender());
+ if (!act)
+ return;
+ const int key = act->data().toInt();
+ if (!key)
+ return;
+ QString cmd = userCommandMap().value(key);
+ IEditor *editor = editorManager()->currentEditor();
+ FakeVimHandler *handler = m_editorToHandler[editor];
+ if (handler)
+ handler->handleInput(cmd);
+}
+
static const char *exCommandMapGroup = "FakeVimExCommand";
+static const char *userCommandMapGroup = "FakeVimUserCommand";
static const char *reKey = "RegEx";
+static const char *cmdKey = "Cmd";
static const char *idKey = "Command";
void FakeVimPluginPrivate::writeSettings()
@@ -803,9 +1008,10 @@ void FakeVimPluginPrivate::writeSettings()
theFakeVimSettings()->writeSettings(settings);
+ { // block
settings->beginWriteArray(_(exCommandMapGroup));
int count = 0;
- typedef CommandMap::const_iterator Iterator;
+ typedef ExCommandMap::const_iterator Iterator;
const Iterator end = exCommandMap().constEnd();
for (Iterator it = exCommandMap().constBegin(); it != end; ++it) {
const QString id = it.key();
@@ -819,8 +1025,29 @@ void FakeVimPluginPrivate::writeSettings()
++count;
}
}
+ settings->endArray();
+ } // block
+ { // block
+ settings->beginWriteArray(_(userCommandMapGroup));
+ int count = 0;
+ typedef UserCommandMap::const_iterator Iterator;
+ const Iterator end = userCommandMap().constEnd();
+ for (Iterator it = userCommandMap().constBegin(); it != end; ++it) {
+ const int key = it.key();
+ const QString cmd = it.value();
+
+ if ((defaultUserCommandMap().contains(key)
+ && defaultUserCommandMap()[key] != cmd)
+ || (!defaultUserCommandMap().contains(key) && !cmd.isEmpty())) {
+ settings->setArrayIndex(count);
+ settings->setValue(_(idKey), key);
+ settings->setValue(_(cmdKey), cmd);
+ ++count;
+ }
+ }
settings->endArray();
+ } // block
}
void FakeVimPluginPrivate::readSettings()
@@ -838,6 +1065,16 @@ void FakeVimPluginPrivate::readSettings()
exCommandMap()[id] = QRegExp(re);
}
settings->endArray();
+
+ userCommandMap() = defaultUserCommandMap();
+ size = settings->beginReadArray(_(userCommandMapGroup));
+ for (int i = 0; i < size; ++i) {
+ settings->setArrayIndex(i);
+ const int id = settings->value(_(idKey)).toInt();
+ const QString cmd = settings->value(_(cmdKey)).toString();
+ userCommandMap()[id] = cmd;
+ }
+ settings->endArray();
}
void FakeVimPluginPrivate::maybeReadVimRc()
@@ -1139,6 +1376,11 @@ void FakeVimPluginPrivate::setUseFakeVim(const QVariant &value)
bool on = value.toBool();
if (Find::FindPlugin::instance())
Find::FindPlugin::instance()->setUseFakeVim(on);
+ setUseFakeVimInternal(on);
+}
+
+void FakeVimPluginPrivate::setUseFakeVimInternal(bool on)
+{
if (on) {
//ICore *core = ICore::instance();
//core->updateAdditionalContexts(Core::Context(FAKEVIM_CONTEXT),
@@ -1295,7 +1537,7 @@ void FakeVimPluginPrivate::handleExCommand(bool *handled, const ExCommand &cmd)
triggerAction(Core::Constants::REMOVE_CURRENT_SPLIT);
} else {
// Check whether one of the configure commands matches.
- typedef CommandMap::const_iterator Iterator;
+ typedef ExCommandMap::const_iterator Iterator;
const Iterator end = exCommandMap().constEnd();
for (Iterator it = exCommandMap().constBegin(); it != end; ++it) {
const QString &id = it.key();
@@ -1450,16 +1692,26 @@ void FakeVimPluginPrivate::switchToFile(int n)
editorManager()->activateEditorForIndex(model->index(n, 0));
}
-CommandMap &FakeVimExCommandsPage::exCommandMap()
+ExCommandMap &FakeVimExCommandsPage::exCommandMap()
{
return m_q->exCommandMap();
}
-CommandMap &FakeVimExCommandsPage::defaultExCommandMap()
+ExCommandMap &FakeVimExCommandsPage::defaultExCommandMap()
{
return m_q->defaultExCommandMap();
}
+UserCommandMap &FakeVimUserCommandsPage::userCommandMap()
+{
+ return m_q->userCommandMap();
+}
+
+UserCommandMap &FakeVimUserCommandsPage::defaultUserCommandMap()
+{
+ return m_q->defaultUserCommandMap();
+}
+
///////////////////////////////////////////////////////////////////////
//
// FakeVimPlugin
diff --git a/src/plugins/find/searchresultwindow.cpp b/src/plugins/find/searchresultwindow.cpp
index 8de0d184ea..fe5d033af2 100644
--- a/src/plugins/find/searchresultwindow.cpp
+++ b/src/plugins/find/searchresultwindow.cpp
@@ -621,7 +621,7 @@ void SearchResultWindow::setTextEditorFont(const QFont &font)
}
/*!
- \fn void SearchResultWindow::handleJumpToSearchResult(int index, bool)
+ \fn void SearchResultWindow::handleJumpToSearchResult(const SearchResultItem &item)
\internal
*/
void SearchResultWindow::handleJumpToSearchResult(const SearchResultItem &item)
@@ -657,7 +657,7 @@ void SearchResultWindow::addResult(const QString &fileName, int lineNumber, cons
}
/*!
- \fn void SearchResultWindow::addResults(QList<SearchResultItem> &items)
+ \fn void SearchResultWindow::addResults(QList<SearchResultItem> &items, AddMode mode)
\brief Adds all of the given search result \a items to the search
results window.
diff --git a/src/plugins/find/textfindconstants.h b/src/plugins/find/textfindconstants.h
index 0d38124595..293a381170 100644
--- a/src/plugins/find/textfindconstants.h
+++ b/src/plugins/find/textfindconstants.h
@@ -49,11 +49,9 @@ const char * const G_FIND_FLAGS = "Find.FindMenu.Flags";
const char * const G_FIND_ACTIONS = "Find.FindMenu.Actions";
const char * const ADVANCED_FIND = "Find.Dialog";
-const char * const FIND = "Find.FindReplace";
const char * const FIND_IN_DOCUMENT = "Find.FindInCurrentDocument";
const char * const FIND_NEXT = "Find.FindNext";
const char * const FIND_PREVIOUS = "Find.FindPrevious";
-const char * const FIND_ALL = "Find.FindAll";
const char * const REPLACE = "Find.Replace";
const char * const REPLACE_NEXT = "Find.ReplaceNext";
const char * const REPLACE_PREVIOUS = "Find.ReplacePrevious";
diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp
index 19713331a9..9d4d1ee5b1 100644
--- a/src/plugins/genericprojectmanager/genericproject.cpp
+++ b/src/plugins/genericprojectmanager/genericproject.cpp
@@ -44,7 +44,9 @@
#include <cplusplus/ModelManagerInterface.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/pathchooser.h>
+#include <utils/qtcassert.h>
#include <coreplugin/icore.h>
+#include <coreplugin/icontext.h>
#include <QtCore/QDir>
#include <QtCore/QProcessEnvironment>
@@ -70,6 +72,9 @@ GenericProject::GenericProject(Manager *manager, const QString &fileName)
m_fileName(fileName),
m_toolChain(0)
{
+ setProjectContext(Core::Context(GenericProjectManager::Constants::PROJECTCONTEXT));
+ setProjectLanguage(Core::Context(ProjectExplorer::Constants::LANG_CXX));
+
QFileInfo fileInfo(m_fileName);
QDir dir = fileInfo.dir();
@@ -99,13 +104,19 @@ GenericTarget *GenericProject::activeTarget() const
}
QString GenericProject::filesFileName() const
-{ return m_filesFileName; }
+{
+ return m_filesFileName;
+}
QString GenericProject::includesFileName() const
-{ return m_includesFileName; }
+{
+ return m_includesFileName;
+}
QString GenericProject::configFileName() const
-{ return m_configFileName; }
+{
+ return m_configFileName;
+}
static QStringList readLines(const QString &absoluteFileName)
{
@@ -306,22 +317,34 @@ QStringList GenericProject::allIncludePaths() const
}
QStringList GenericProject::projectIncludePaths() const
-{ return m_projectIncludePaths; }
+{
+ return m_projectIncludePaths;
+}
QStringList GenericProject::files() const
-{ return m_files; }
+{
+ return m_files;
+}
QStringList GenericProject::generated() const
-{ return m_generated; }
+{
+ return m_generated;
+}
QStringList GenericProject::includePaths() const
-{ return m_includePaths; }
+{
+ return m_includePaths;
+}
void GenericProject::setIncludePaths(const QStringList &includePaths)
-{ m_includePaths = includePaths; }
+{
+ m_includePaths = includePaths;
+}
QByteArray GenericProject::defines() const
-{ return m_defines; }
+{
+ return m_defines;
+}
void GenericProject::setToolChain(ToolChain *tc)
{
@@ -586,7 +609,7 @@ void GenericProjectFile::rename(const QString &newName)
{
// Can't happen
Q_UNUSED(newName);
- Q_ASSERT(false);
+ QTC_ASSERT(false, /**/);
}
Core::IFile::ReloadBehavior GenericProjectFile::reloadBehavior(ChangeTrigger state, ChangeType type) const
diff --git a/src/plugins/genericprojectmanager/genericprojectconstants.h b/src/plugins/genericprojectmanager/genericprojectconstants.h
index 589388d47a..b9425c12a4 100644
--- a/src/plugins/genericprojectmanager/genericprojectconstants.h
+++ b/src/plugins/genericprojectmanager/genericprojectconstants.h
@@ -38,23 +38,17 @@ namespace Constants {
const char *const PROJECTCONTEXT = "GenericProject.ProjectContext";
const char *const GENERICMIMETYPE = "text/x-generic-project"; // ### FIXME
-const char *const MAKESTEP = "GenericProjectManager.MakeStep";
// contexts
const char *const C_FILESEDITOR = ".files Editor";
-// kinds
-const char *const PROJECT_KIND = "Generic";
-
const char *const FILES_EDITOR_ID = "QT4.FilesEditor";
const char *const FILES_EDITOR_DISPLAY_NAME = QT_TRANSLATE_NOOP("OpenWith::Editors", ".files Editor");
const char *const FILES_MIMETYPE = "application/vnd.nokia.qt.generic.files";
-const char *const INCLUDES_EDITOR = ".includes Editor";
const char *const INCLUDES_MIMETYPE = "application/vnd.nokia.qt.generic.includes";
-const char *const CONFIG_EDITOR = ".config Editor";
const char *const CONFIG_MIMETYPE = "application/vnd.nokia.qt.generic.config";
// Project
diff --git a/src/plugins/genericprojectmanager/genericprojectfileseditor.cpp b/src/plugins/genericprojectmanager/genericprojectfileseditor.cpp
index c29c90aed8..14bde8135b 100644
--- a/src/plugins/genericprojectmanager/genericprojectfileseditor.cpp
+++ b/src/plugins/genericprojectmanager/genericprojectfileseditor.cpp
@@ -58,10 +58,6 @@ ProjectFilesFactory::ProjectFilesFactory(Manager *manager,
m_mimeTypes.append(QLatin1String(Constants::CONFIG_MIMETYPE));
}
-ProjectFilesFactory::~ProjectFilesFactory()
-{
-}
-
Manager *ProjectFilesFactory::manager() const
{
return m_manager;
@@ -104,16 +100,9 @@ Core::IFile *ProjectFilesFactory::open(const QString &fileName)
////////////////////////////////////////////////////////////////////////////////////////
ProjectFilesEditor::ProjectFilesEditor(ProjectFilesEditorWidget *editor)
- : TextEditor::BaseTextEditor(editor),
- m_context(Constants::C_FILESEDITOR)
-{ }
-
-ProjectFilesEditor::~ProjectFilesEditor()
-{ }
-
-Core::Context ProjectFilesEditor::context() const
+ : TextEditor::BaseTextEditor(editor)
{
- return m_context;
+ setContext(Core::Context(Constants::C_FILESEDITOR));
}
QString ProjectFilesEditor::id() const
diff --git a/src/plugins/genericprojectmanager/genericprojectfileseditor.h b/src/plugins/genericprojectmanager/genericprojectfileseditor.h
index 50f8f50f84..d9d56d9cc0 100644
--- a/src/plugins/genericprojectmanager/genericprojectfileseditor.h
+++ b/src/plugins/genericprojectmanager/genericprojectfileseditor.h
@@ -57,7 +57,6 @@ class ProjectFilesFactory: public Core::IEditorFactory
public:
ProjectFilesFactory(Manager *manager, TextEditor::TextEditorActionHandler *handler);
- virtual ~ProjectFilesFactory();
Manager *manager() const;
@@ -80,18 +79,11 @@ class ProjectFilesEditor : public TextEditor::BaseTextEditor
public:
ProjectFilesEditor(ProjectFilesEditorWidget *editorWidget);
- virtual ~ProjectFilesEditor();
- virtual Core::Context context() const;
virtual QString id() const;
-
virtual bool duplicateSupported() const;
virtual Core::IEditor *duplicate(QWidget *parent);
-
virtual bool isTemporary() const { return false; }
-
-private:
- Core::Context m_context;
};
class ProjectFilesEditorWidget : public TextEditor::BaseTextEditorWidget
diff --git a/src/plugins/genericprojectmanager/genericprojectmanager.cpp b/src/plugins/genericprojectmanager/genericprojectmanager.cpp
index c3ad5cd53d..85a24940d2 100644
--- a/src/plugins/genericprojectmanager/genericprojectmanager.cpp
+++ b/src/plugins/genericprojectmanager/genericprojectmanager.cpp
@@ -45,22 +45,12 @@
using namespace GenericProjectManager::Internal;
Manager::Manager()
-{
- m_projectContext = Core::Context(GenericProjectManager::Constants::PROJECTCONTEXT);
- m_projectLanguage = Core::Context(ProjectExplorer::Constants::LANG_CXX);
-}
-
-Manager::~Manager()
{ }
-Core::Context Manager::projectContext() const
-{ return m_projectContext; }
-
-Core::Context Manager::projectLanguage() const
-{ return m_projectLanguage; }
-
QString Manager::mimeType() const
-{ return QLatin1String(Constants::GENERICMIMETYPE); }
+{
+ return QLatin1String(Constants::GENERICMIMETYPE);
+}
ProjectExplorer::Project *Manager::openProject(const QString &fileName)
{
@@ -82,19 +72,22 @@ ProjectExplorer::Project *Manager::openProject(const QString &fileName)
}
void Manager::registerProject(GenericProject *project)
-{ m_projects.append(project); }
+{
+ m_projects.append(project);
+}
void Manager::unregisterProject(GenericProject *project)
-{ m_projects.removeAll(project); }
+{
+ m_projects.removeAll(project);
+}
void Manager::notifyChanged(const QString &fileName)
{
foreach (GenericProject *project, m_projects) {
if (fileName == project->filesFileName()) {
project->refresh(GenericProject::Files);
- }
- else if (fileName == project->includesFileName() ||
- fileName == project->configFileName()) {
+ } else if (fileName == project->includesFileName()
+ || fileName == project->configFileName()) {
project->refresh(GenericProject::Configuration);
}
}
diff --git a/src/plugins/genericprojectmanager/genericprojectmanager.h b/src/plugins/genericprojectmanager/genericprojectmanager.h
index efee381fc9..27f0a0b969 100644
--- a/src/plugins/genericprojectmanager/genericprojectmanager.h
+++ b/src/plugins/genericprojectmanager/genericprojectmanager.h
@@ -34,7 +34,6 @@
#define GENERICPROJECTMANAGER_H
#include <projectexplorer/iprojectmanager.h>
-#include <coreplugin/icontext.h>
namespace GenericProjectManager {
namespace Internal {
@@ -47,10 +46,6 @@ class Manager : public ProjectExplorer::IProjectManager
public:
Manager();
- virtual ~Manager();
-
- virtual Core::Context projectContext() const;
- virtual Core::Context projectLanguage() const;
virtual QString mimeType() const;
virtual ProjectExplorer::Project *openProject(const QString &fileName);
@@ -61,8 +56,6 @@ public:
void unregisterProject(GenericProject *project);
private:
- Core::Context m_projectContext;
- Core::Context m_projectLanguage;
QList<GenericProject *> m_projects;
};
diff --git a/src/plugins/genericprojectmanager/genericprojectnodes.cpp b/src/plugins/genericprojectmanager/genericprojectnodes.cpp
index 847e3c8f8d..03f194342a 100644
--- a/src/plugins/genericprojectmanager/genericprojectnodes.cpp
+++ b/src/plugins/genericprojectmanager/genericprojectnodes.cpp
@@ -49,14 +49,15 @@ GenericProjectNode::GenericProjectNode(GenericProject *project, Core::IFile *pro
setDisplayName(QFileInfo(projectFile->fileName()).completeBaseName());
}
-GenericProjectNode::~GenericProjectNode()
-{ }
-
Core::IFile *GenericProjectNode::projectFile() const
-{ return m_projectFile; }
+{
+ return m_projectFile;
+}
QString GenericProjectNode::projectFilePath() const
-{ return m_projectFile->fileName(); }
+{
+ return m_projectFile->fileName();
+}
void GenericProjectNode::refresh()
{
@@ -114,8 +115,10 @@ void GenericProjectNode::refresh()
filesInPath[relativeFilePath].append(absoluteFileName);
}
+ FolderByName folderByName;
foreach (const QString &filePath, filePaths) {
- FolderNode *folder = findOrCreateFolderByName(filePath);
+ QStringList components = filePath.split(QLatin1Char('/'));
+ FolderNode *folder = findOrCreateFolderByName(&folderByName, components, components.size());
QList<FileNode *> fileNodes;
foreach (const QString &file, filesInPath.value(filePath)) {
@@ -126,13 +129,12 @@ void GenericProjectNode::refresh()
addFileNodes(fileNodes, folder);
}
-
- m_folderByName.clear();
}
-ProjectExplorer::FolderNode *GenericProjectNode::findOrCreateFolderByName(const QStringList &components, int end)
+ProjectExplorer::FolderNode *GenericProjectNode::findOrCreateFolderByName
+ (FolderByName *folderByName, const QStringList &components, int end)
{
- if (! end)
+ if (!end)
return 0;
QString folderName;
@@ -146,28 +148,22 @@ ProjectExplorer::FolderNode *GenericProjectNode::findOrCreateFolderByName(const
if (component.isEmpty())
return this;
- else if (FolderNode *folder = m_folderByName.value(folderName))
+ else if (FolderNode *folder = folderByName->value(folderName))
return folder;
const QString baseDir = QFileInfo(path()).path();
FolderNode *folder = new FolderNode(baseDir + QLatin1Char('/') + folderName);
folder->setDisplayName(component);
- m_folderByName.insert(folderName, folder);
+ folderByName->insert(folderName, folder);
- FolderNode *parent = findOrCreateFolderByName(components, end - 1);
- if (! parent)
+ FolderNode *parent = findOrCreateFolderByName(folderByName, components, end - 1);
+ if (!parent)
parent = this;
addFolderNodes(QList<FolderNode*>() << folder, parent);
return folder;
}
-ProjectExplorer::FolderNode *GenericProjectNode::findOrCreateFolderByName(const QString &filePath)
-{
- QStringList components = filePath.split(QLatin1Char('/'));
- return findOrCreateFolderByName(components, components.length());
-}
-
bool GenericProjectNode::hasBuildTargets() const
{
return true;
diff --git a/src/plugins/genericprojectmanager/genericprojectnodes.h b/src/plugins/genericprojectmanager/genericprojectnodes.h
index 9cd0faef5a..75b90dadfd 100644
--- a/src/plugins/genericprojectmanager/genericprojectnodes.h
+++ b/src/plugins/genericprojectmanager/genericprojectnodes.h
@@ -51,7 +51,6 @@ class GenericProjectNode : public ProjectExplorer::ProjectNode
{
public:
GenericProjectNode(GenericProject *project, Core::IFile *projectFile);
- virtual ~GenericProjectNode();
Core::IFile *projectFile() const;
QString projectFilePath() const;
@@ -84,13 +83,13 @@ public:
void refresh();
private:
- FolderNode *findOrCreateFolderByName(const QString &filePath);
- FolderNode *findOrCreateFolderByName(const QStringList &components, int end);
+ typedef QHash<QString, FolderNode *> FolderByName;
+ FolderNode *findOrCreateFolderByName(FolderByName *folderByName,
+ const QStringList &components, int end);
private:
GenericProject *m_project;
Core::IFile *m_projectFile;
- QHash<QString, FolderNode *> m_folderByName;
};
} // namespace Internal
diff --git a/src/plugins/genericprojectmanager/generictarget.cpp b/src/plugins/genericprojectmanager/generictarget.cpp
index ece78bbc58..e3bcc60139 100644
--- a/src/plugins/genericprojectmanager/generictarget.cpp
+++ b/src/plugins/genericprojectmanager/generictarget.cpp
@@ -57,18 +57,13 @@ using namespace GenericProjectManager::Internal;
GenericTarget::GenericTarget(GenericProject *parent) :
ProjectExplorer::Target(parent, QLatin1String(GENERIC_DESKTOP_TARGET_ID)),
- m_buildConfigurationFactory(new GenericBuildConfigurationFactory(this)),
- m_deployConfigurationFactory(new ProjectExplorer::DeployConfigurationFactory(this))
+ m_buildConfigurationFactory(new GenericBuildConfigurationFactory(this))
{
setDefaultDisplayName(QApplication::translate("GenericProjectManager::GenericTarget",
GENERIC_DESKTOP_TARGET_DISPLAY_NAME));
setIcon(qApp->style()->standardIcon(QStyle::SP_ComputerIcon));
}
-GenericTarget::~GenericTarget()
-{
-}
-
ProjectExplorer::BuildConfigWidget *GenericTarget::createConfigWidget()
{
return new GenericBuildSettingsWidget(this);
@@ -84,11 +79,6 @@ GenericBuildConfigurationFactory *GenericTarget::buildConfigurationFactory() con
return m_buildConfigurationFactory;
}
-ProjectExplorer::DeployConfigurationFactory *GenericTarget::deployConfigurationFactory() const
-{
- return m_deployConfigurationFactory;
-}
-
GenericBuildConfiguration *GenericTarget::activeBuildConfiguration() const
{
return static_cast<GenericBuildConfiguration *>(Target::activeBuildConfiguration());
@@ -111,10 +101,6 @@ GenericTargetFactory::GenericTargetFactory(QObject *parent) :
{
}
-GenericTargetFactory::~GenericTargetFactory()
-{
-}
-
bool GenericTargetFactory::supportsTargetId(const QString &id) const
{
return id == QLatin1String(GENERIC_DESKTOP_TARGET_ID);
@@ -164,7 +150,7 @@ GenericTarget *GenericTargetFactory::create(ProjectExplorer::Project *parent, co
t->addBuildConfiguration(bc);
- t->addDeployConfiguration(t->deployConfigurationFactory()->create(t, ProjectExplorer::Constants::DEFAULT_DEPLOYCONFIGURATION_ID));
+ t->addDeployConfiguration(t->createDeployConfiguration(ProjectExplorer::Constants::DEFAULT_DEPLOYCONFIGURATION_ID));
// Add a runconfiguration. The CustomExecutableRC one will query the user
// for its settings, so it is a good choice here.
diff --git a/src/plugins/genericprojectmanager/generictarget.h b/src/plugins/genericprojectmanager/generictarget.h
index 3e66cf37ac..62b2106fe3 100644
--- a/src/plugins/genericprojectmanager/generictarget.h
+++ b/src/plugins/genericprojectmanager/generictarget.h
@@ -62,14 +62,12 @@ class GenericTarget : public ProjectExplorer::Target
public:
explicit GenericTarget(GenericProject *parent);
- ~GenericTarget();
ProjectExplorer::BuildConfigWidget *createConfigWidget();
GenericProject *genericProject() const;
GenericBuildConfigurationFactory *buildConfigurationFactory() const;
- ProjectExplorer::DeployConfigurationFactory *deployConfigurationFactory() const;
GenericBuildConfiguration *activeBuildConfiguration() const;
protected:
@@ -77,7 +75,6 @@ protected:
private:
GenericBuildConfigurationFactory *m_buildConfigurationFactory;
- ProjectExplorer::DeployConfigurationFactory *m_deployConfigurationFactory;
};
class GenericTargetFactory : public ProjectExplorer::ITargetFactory
@@ -86,7 +83,6 @@ class GenericTargetFactory : public ProjectExplorer::ITargetFactory
public:
explicit GenericTargetFactory(QObject *parent = 0);
- ~GenericTargetFactory();
bool supportsTargetId(const QString &id) const;
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 6de1e5acaf..95e16ddeb4 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -520,6 +520,8 @@ void GitClient::diff(const QString &workingDirectory,
editor = createVCSEditor(editorId, title,
workingDirectory, true, "originalFileName", workingDirectory, argWidget);
+ connect(editor, SIGNAL(diffChunkReverted(VCSBase::DiffChunk)), argWidget, SLOT(redoCommand()));
+ editor->setRevertDiffChunkEnabled(true);
}
editor->setDiffBaseDirectory(workingDirectory);
@@ -574,6 +576,8 @@ void GitClient::diff(const QString &workingDirectory,
userDiffArgs = argWidget->arguments();
editor = createVCSEditor(editorId, title, sourceFile, true, "originalFileName", sourceFile, argWidget);
+ connect(editor, SIGNAL(diffChunkReverted(VCSBase::DiffChunk)), argWidget, SLOT(redoCommand()));
+ editor->setRevertDiffChunkEnabled(true);
}
QStringList cmdArgs;
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index c837a73810..f58fc474c2 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -305,6 +305,8 @@ public:
const QStringList &args);
virtual QStringList arguments() const = 0;
+
+public slots:
virtual void redoCommand() = 0;
protected slots:
diff --git a/src/plugins/git/gitconstants.h b/src/plugins/git/gitconstants.h
index 413f40df8a..a8c9582e0a 100644
--- a/src/plugins/git/gitconstants.h
+++ b/src/plugins/git/gitconstants.h
@@ -59,7 +59,6 @@ const char * const DIFF_SELECTED = "Git.DiffSelectedFilesInLog";
const char * const SUBMIT_MIMETYPE = "application/vnd.nokia.text.git.submit";
const char * const GIT_BINARY = "git";
-const char * const DIFF_FILE_INDICATOR = "--- ";
enum { debug = 0 };
} // namespace Constants
diff --git a/src/plugins/glsleditor/glsleditor.cpp b/src/plugins/glsleditor/glsleditor.cpp
index 6cd2deb6a5..d77ad8b64a 100644
--- a/src/plugins/glsleditor/glsleditor.cpp
+++ b/src/plugins/glsleditor/glsleditor.cpp
@@ -212,11 +212,6 @@ bool GLSLEditorEditable::open(const QString &fileName)
return b;
}
-Core::Context GLSLEditorEditable::context() const
-{
- return m_context;
-}
-
void GLSLTextEditorWidget::setFontSettings(const TextEditor::FontSettings &fs)
{
TextEditor::BaseTextEditorWidget::setFontSettings(fs);
diff --git a/src/plugins/glsleditor/glsleditor.h b/src/plugins/glsleditor/glsleditor.h
index 91b353983a..8b76bf4af9 100644
--- a/src/plugins/glsleditor/glsleditor.h
+++ b/src/plugins/glsleditor/glsleditor.h
@@ -120,8 +120,6 @@ private:
void setSelectedElements();
QString wordUnderCursor() const;
- const Core::Context m_context;
-
QTimer *m_updateDocumentTimer;
QComboBox *m_outlineCombo;
Document::Ptr m_glslDocument;
diff --git a/src/plugins/glsleditor/glsleditorconstants.h b/src/plugins/glsleditor/glsleditorconstants.h
index 4492aea202..c619eb5408 100644
--- a/src/plugins/glsleditor/glsleditorconstants.h
+++ b/src/plugins/glsleditor/glsleditorconstants.h
@@ -46,11 +46,8 @@ 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";
diff --git a/src/plugins/glsleditor/glsleditoreditable.cpp b/src/plugins/glsleditor/glsleditoreditable.cpp
index 6833434174..7ea97215fd 100644
--- a/src/plugins/glsleditor/glsleditoreditable.cpp
+++ b/src/plugins/glsleditor/glsleditoreditable.cpp
@@ -49,8 +49,8 @@ namespace Internal {
GLSLEditorEditable::GLSLEditorEditable(GLSLTextEditorWidget *editor)
: BaseTextEditor(editor)
{
- m_context.add(GLSLEditor::Constants::C_GLSLEDITOR_ID);
- m_context.add(TextEditor::Constants::C_TEXTEDITOR);
+ setContext(Core::Context(GLSLEditor::Constants::C_GLSLEDITOR_ID,
+ TextEditor::Constants::C_TEXTEDITOR));
}
QString GLSLEditorEditable::preferredModeType() const
diff --git a/src/plugins/glsleditor/glsleditoreditable.h b/src/plugins/glsleditor/glsleditoreditable.h
index 5a2d2c7e44..59823c8340 100644
--- a/src/plugins/glsleditor/glsleditoreditable.h
+++ b/src/plugins/glsleditor/glsleditoreditable.h
@@ -46,17 +46,13 @@ class GLSLEditorEditable : public TextEditor::BaseTextEditor
public:
explicit GLSLEditorEditable(GLSLTextEditorWidget *);
- 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 bool open(const QString &fileName);
virtual QString preferredModeType() const;
-
-private:
- Core::Context m_context;
};
} // namespace Internal
diff --git a/src/plugins/helloworld/helloworldplugin.cpp b/src/plugins/helloworld/helloworldplugin.cpp
index b89fae8086..078375a4e4 100644
--- a/src/plugins/helloworld/helloworldplugin.cpp
+++ b/src/plugins/helloworld/helloworldplugin.cpp
@@ -55,19 +55,17 @@ namespace Internal {
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;
+ HelloMode()
+ {
+ setWidget(new QPushButton(tr("Hello World PushButton!")));
+ setContext(Core::Context("HelloWorld.MainView"));
+ setDisplayName(tr("Hello world!"));
+ setIcon(QIcon());
+ setPriority(0);
+ setId(QLatin1String("HelloWorld.HelloWorldMode"));
+ setType(QLatin1String("HelloWorld.HelloWorldMode"));
+ setContextHelpId(QString());
+ }
};
diff --git a/src/plugins/help/helpmode.cpp b/src/plugins/help/helpmode.cpp
index 37430e64c5..2fda129a2c 100644
--- a/src/plugins/help/helpmode.cpp
+++ b/src/plugins/help/helpmode.cpp
@@ -39,29 +39,12 @@ using namespace Help;
using namespace Help::Internal;
HelpMode::HelpMode(QObject *parent)
- : Core::IMode(parent),
- m_widget(0),
- m_icon(QLatin1String(":/fancyactionbar/images/mode_Reference.png"))
+ : Core::IMode(parent)
{
setObjectName(QLatin1String("HelpMode"));
-}
-
-QString HelpMode::displayName() const
-{
- return QCoreApplication::translate("Help::Internal::HelpMode", "Help");
-}
-
-int HelpMode::priority() const
-{
- return Constants::P_MODE_HELP;
-}
-
-QString HelpMode::id() const
-{
- return QLatin1String(Constants::ID_MODE_HELP);
-}
-
-Core::Context HelpMode::context() const
-{
- return Core::Context(Constants::C_MODE_HELP);
+ setContext(Core::Context(Constants::C_MODE_HELP));
+ setIcon(QIcon(QLatin1String(":/fancyactionbar/images/mode_Reference.png")));
+ setDisplayName(QCoreApplication::translate("Help::Internal::HelpMode", "Help"));
+ setPriority(Constants::P_MODE_HELP);
+ setId(Constants::ID_MODE_HELP);
}
diff --git a/src/plugins/help/helpmode.h b/src/plugins/help/helpmode.h
index 52aa3228df..7ba98fb1de 100644
--- a/src/plugins/help/helpmode.h
+++ b/src/plugins/help/helpmode.h
@@ -45,20 +45,6 @@ class HelpMode : public Core::IMode
{
public:
explicit HelpMode(QObject *parent = 0);
-
- QString displayName() const;
- QIcon icon() const { return m_icon; }
- int priority() const;
- QWidget *widget() { return m_widget; }
- QString id() const;
- QString type() const { return QString(); }
- Core::Context context() const;
- 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 89d006c920..6f6317a481 100644
--- a/src/plugins/help/helpplugin.cpp
+++ b/src/plugins/help/helpplugin.cpp
@@ -69,7 +69,6 @@
#include <find/findplugin.h>
#include <texteditor/texteditorconstants.h>
#include <utils/styledbar.h>
-#include <welcome/welcomemode.h>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
@@ -579,8 +578,10 @@ void HelpPlugin::createRightPaneContextViewer()
agg->add(new HelpViewerFindSupport(m_helpViewerForSideBar));
Core::Context context(Constants::C_HELP_SIDEBAR);
- m_core->addContextObject(new Core::BaseContext(m_helpViewerForSideBar,
- context, this));
+ Core::IContext *icontext = new Core::IContext(this);
+ icontext->setContext(context);
+ icontext->setWidget(m_helpViewerForSideBar);
+ m_core->addContextObject(icontext);
QAction *copy = new QAction(this);
Core::Command *cmd = m_core->actionManager()->registerAction(copy,
diff --git a/src/plugins/imageviewer/imageviewer.cpp b/src/plugins/imageviewer/imageviewer.cpp
index af7336573d..c6f760a164 100644
--- a/src/plugins/imageviewer/imageviewer.cpp
+++ b/src/plugins/imageviewer/imageviewer.cpp
@@ -53,11 +53,6 @@ namespace Internal {
struct ImageViewerPrivate
{
- ImageViewerPrivate()
- : context(Constants::IMAGEVIEWER_ID)
- {}
-
- Core::Context context;
QString displayName;
ImageViewerFile *file;
ImageView *imageView;
@@ -70,9 +65,11 @@ ImageViewer::ImageViewer(QWidget *parent)
d_ptr(new ImageViewerPrivate)
{
d_ptr->file = new ImageViewerFile(this);
-
d_ptr->imageView = new ImageView();
+ setContext(Core::Context(Constants::IMAGEVIEWER_ID));
+ setWidget(d_ptr->imageView);
+
// toolbar
d_ptr->toolbar = new QWidget();
d_ptr->ui_toolbar.setupUi(d_ptr->toolbar);
@@ -113,16 +110,6 @@ ImageViewer::~ImageViewer()
delete d_ptr->toolbar;
}
-Core::Context ImageViewer::context() const
-{
- return d_ptr->context;
-}
-
-QWidget *ImageViewer::widget()
-{
- return d_ptr->imageView;
-}
-
bool ImageViewer::createNew(const QString &contents)
{
Q_UNUSED(contents)
diff --git a/src/plugins/imageviewer/imageviewer.h b/src/plugins/imageviewer/imageviewer.h
index d3b6cf317e..b1656e58a2 100644
--- a/src/plugins/imageviewer/imageviewer.h
+++ b/src/plugins/imageviewer/imageviewer.h
@@ -55,9 +55,6 @@ public:
explicit ImageViewer(QWidget *parent = 0);
~ImageViewer();
- Core::Context context() const;
- QWidget *widget();
-
bool createNew(const QString &contents = QString());
bool open(const QString &fileName = QString());
Core::IFile *file();
diff --git a/src/plugins/macros/macrosconstants.h b/src/plugins/macros/macrosconstants.h
index 629e034d28..c6e5971daf 100644
--- a/src/plugins/macros/macrosconstants.h
+++ b/src/plugins/macros/macrosconstants.h
@@ -49,7 +49,6 @@ const char * const M_OPTIONS_TR_PAGE =
QT_TRANSLATE_NOOP("Macros", "Macros");
const char * const M_STATUS_BUFFER = "Macros.Status";
-const char * const M_INFO_BUFFER = "Macros.Info";
const char * const M_EXTENSION = "mac";
diff --git a/src/plugins/memcheck/memcheckconfigwidget.cpp b/src/plugins/memcheck/memcheckconfigwidget.cpp
index 7633574d4c..8452f83baa 100644
--- a/src/plugins/memcheck/memcheckconfigwidget.cpp
+++ b/src/plugins/memcheck/memcheckconfigwidget.cpp
@@ -44,7 +44,7 @@
#include <QtGui/QFileDialog>
#include <QtCore/QDebug>
-using namespace Analyzer::Internal;
+using namespace Memcheck::Internal;
MemcheckConfigWidget::MemcheckConfigWidget(AbstractMemcheckSettings *settings, QWidget *parent)
: QWidget(parent),
diff --git a/src/plugins/memcheck/memcheckconfigwidget.h b/src/plugins/memcheck/memcheckconfigwidget.h
index 6f3eff49db..c522a76f68 100644
--- a/src/plugins/memcheck/memcheckconfigwidget.h
+++ b/src/plugins/memcheck/memcheckconfigwidget.h
@@ -40,14 +40,14 @@
QT_BEGIN_NAMESPACE
class QStandardItemModel;
+QT_END_NAMESPACE
+
+namespace Memcheck {
+namespace Internal {
namespace Ui {
class MemcheckConfigWidget;
}
-QT_END_NAMESPACE
-
-namespace Analyzer {
-namespace Internal {
class AbstractMemcheckSettings;
diff --git a/src/plugins/memcheck/memcheckconfigwidget.ui b/src/plugins/memcheck/memcheckconfigwidget.ui
index fbc111cf35..8b0ebf6de5 100644
--- a/src/plugins/memcheck/memcheckconfigwidget.ui
+++ b/src/plugins/memcheck/memcheckconfigwidget.ui
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
- <class>MemcheckConfigWidget</class>
- <widget class="QWidget" name="MemcheckConfigWidget">
+ <class>Memcheck::Internal::MemcheckConfigWidget</class>
+ <widget class="QWidget" name="Memcheck::Internal::MemcheckConfigWidget">
<property name="geometry">
<rect>
<x>0</x>
@@ -39,7 +39,7 @@
<item row="3" column="0">
<widget class="QLabel" name="label">
<property name="text">
- <string>Suppressions:</string>
+ <string>Suppression files:</string>
</property>
<property name="buddy">
<cstring>suppressionList</cstring>
@@ -66,7 +66,7 @@
<item>
<widget class="QPushButton" name="addSuppression">
<property name="text">
- <string>Add</string>
+ <string>Add...</string>
</property>
</widget>
</item>
diff --git a/src/plugins/memcheck/memcheckengine.cpp b/src/plugins/memcheck/memcheckengine.cpp
index 680152799f..fe0b6e42ea 100644
--- a/src/plugins/memcheck/memcheckengine.cpp
+++ b/src/plugins/memcheck/memcheckengine.cpp
@@ -43,11 +43,15 @@
#include <utils/qtcassert.h>
-using namespace Analyzer::Internal;
+using namespace Analyzer;
+using namespace Memcheck;
using namespace Valgrind::XmlProtocol;
-MemcheckEngine::MemcheckEngine(ProjectExplorer::RunConfiguration *runConfiguration)
- : ValgrindEngine(runConfiguration)
+using namespace Memcheck::Internal;
+
+MemcheckEngine::MemcheckEngine(const Analyzer::AnalyzerStartParameters &sp,
+ ProjectExplorer::RunConfiguration *runConfiguration)
+ : ValgrindEngine(sp, runConfiguration)
{
connect(&m_parser, SIGNAL(error(const Valgrind::XmlProtocol::Error &)),
SIGNAL(parserError(const Valgrind::XmlProtocol::Error &)));
diff --git a/src/plugins/memcheck/memcheckengine.h b/src/plugins/memcheck/memcheckengine.h
index 804f5ab7f9..a70e748bdb 100644
--- a/src/plugins/memcheck/memcheckengine.h
+++ b/src/plugins/memcheck/memcheckengine.h
@@ -40,14 +40,15 @@
#include <valgrindtoolbase/valgrindengine.h>
-namespace Analyzer {
+namespace Memcheck {
namespace Internal {
-class MemcheckEngine : public ValgrindEngine
+class MemcheckEngine : public Valgrind::Internal::ValgrindEngine
{
Q_OBJECT
public:
- explicit MemcheckEngine(ProjectExplorer::RunConfiguration *runConfiguration);
+ explicit MemcheckEngine(const Analyzer::AnalyzerStartParameters &sp,
+ ProjectExplorer::RunConfiguration *runConfiguration);
void start();
void stop();
@@ -59,20 +60,21 @@ signals:
void parserError(const Valgrind::XmlProtocol::Error &error);
void suppressionCount(const QString &name, qint64 count);
+protected:
+ virtual QString progressTitle() const;
+ virtual QStringList toolArguments() const;
+ virtual Valgrind::ValgrindRunner *runner();
+
private slots:
void receiveLogMessage(const QByteArray &);
void status(const Valgrind::XmlProtocol::Status &status);
private:
- QString progressTitle() const;
- QStringList toolArguments() const;
- Valgrind::ValgrindRunner *runner();
-
Valgrind::XmlProtocol::ThreadedParser m_parser;
Valgrind::Memcheck::MemcheckRunner m_runner;
};
} // namespace Internal
-} // namespace Analyzer
+} // namespace Memcheck
#endif // MEMCHECKENGINE_H
diff --git a/src/plugins/memcheck/memcheckerrorview.cpp b/src/plugins/memcheck/memcheckerrorview.cpp
index 51fb496523..57ba7cf5a8 100644
--- a/src/plugins/memcheck/memcheckerrorview.cpp
+++ b/src/plugins/memcheck/memcheckerrorview.cpp
@@ -67,8 +67,8 @@
#include <QtGui/QApplication>
#include <QtGui/QMenu>
-using namespace Analyzer;
-using namespace Analyzer::Internal;
+using namespace Memcheck;
+using namespace Memcheck::Internal;
using namespace Valgrind::XmlProtocol;
MemcheckErrorDelegate::MemcheckErrorDelegate(QListView *parent)
@@ -151,7 +151,7 @@ static QString makeFrameName(const Frame &frame, const QString &relativeTo,
}
if (!fn.isEmpty())
- return QCoreApplication::translate("Analyzer::Internal", "%1 in %2").arg(Qt::escape(fn), path);
+ return QCoreApplication::translate("Memcheck::Internal", "%1 in %2").arg(Qt::escape(fn), path);
else if (!path.isEmpty())
return path;
else
@@ -175,14 +175,14 @@ QString errorLocation(const QModelIndex &index, const Error &error,
bool link = false, const QString &linkAttr = QString())
{
const ErrorListModel *model = 0;
- const QAbstractProxyModel *proxy = qobject_cast<const QAbstractProxyModel*>(index.model());
+ const QAbstractProxyModel *proxy = qobject_cast<const QAbstractProxyModel *>(index.model());
while(!model && proxy) {
- model = qobject_cast<const ErrorListModel*>(proxy->sourceModel());
- proxy = qobject_cast<const QAbstractProxyModel*>(proxy->sourceModel());
+ model = qobject_cast<const ErrorListModel *>(proxy->sourceModel());
+ proxy = qobject_cast<const QAbstractProxyModel *>(proxy->sourceModel());
};
QTC_ASSERT(model, return QString());
- return QCoreApplication::translate("Analyzer::Internal", "in %1").
+ return QCoreApplication::translate("Memcheck::Internal", "in %1").
arg(makeFrameName(model->findRelevantFrame(error), relativeToPath(),
link, linkAttr));
}
@@ -473,7 +473,7 @@ QString MemcheckErrorView::defaultSuppressionFile() const
// slot, can (for now) be invoked either when the settings were modified *or* when the active
// settings object has changed.
-void MemcheckErrorView::settingsChanged(AnalyzerSettings *settings)
+void MemcheckErrorView::settingsChanged(Analyzer::AnalyzerSettings *settings)
{
QTC_ASSERT(settings, return);
diff --git a/src/plugins/memcheck/memcheckerrorview.h b/src/plugins/memcheck/memcheckerrorview.h
index 6f4b2c02bf..516b66e125 100644
--- a/src/plugins/memcheck/memcheckerrorview.h
+++ b/src/plugins/memcheck/memcheckerrorview.h
@@ -44,14 +44,16 @@ class QListView;
class QVBoxLayout;
QT_END_NAMESPACE
+namespace Analyzer
+{
+class AnalyzerSettings;
+}
+
namespace ProjectExplorer {
class Project;
}
-namespace Analyzer {
-
-class AnalyzerSettings;
-
+namespace Memcheck {
namespace Internal {
class MemcheckErrorDelegate : public QStyledItemDelegate
@@ -102,13 +104,13 @@ public:
void setDefaultSuppressionFile(const QString &suppFile);
QString defaultSuppressionFile() const;
- AnalyzerSettings *settings() const { return m_settings; }
+ Analyzer::AnalyzerSettings *settings() const { return m_settings; }
signals:
void resized();
public slots:
- void settingsChanged(AnalyzerSettings *settings);
+ void settingsChanged(Analyzer::AnalyzerSettings *settings);
private slots:
void suppressError();
@@ -121,10 +123,10 @@ private:
QAction *m_copyAction;
QAction *m_suppressAction;
QString m_defaultSuppFile;
- AnalyzerSettings *m_settings;
+ Analyzer::AnalyzerSettings *m_settings;
};
} // namespace Internal
-} // namespace Analyzer
+} // namespace Memcheck
#endif // MEMCHECKERRORVIEW_H
diff --git a/src/plugins/memcheck/memcheckplugin.cpp b/src/plugins/memcheck/memcheckplugin.cpp
index ab8e1e54d8..3f09db7364 100644
--- a/src/plugins/memcheck/memcheckplugin.cpp
+++ b/src/plugins/memcheck/memcheckplugin.cpp
@@ -44,7 +44,9 @@
#include <QtCore/QtPlugin>
using namespace Analyzer;
-using namespace Analyzer::Internal;
+using namespace Memcheck;
+
+using namespace Memcheck::Internal;
MemcheckPlugin::MemcheckPlugin()
{
diff --git a/src/plugins/memcheck/memcheckplugin.h b/src/plugins/memcheck/memcheckplugin.h
index 096ea31b99..a6ac4d2967 100644
--- a/src/plugins/memcheck/memcheckplugin.h
+++ b/src/plugins/memcheck/memcheckplugin.h
@@ -37,7 +37,7 @@
#include <extensionsystem/iplugin.h>
-namespace Analyzer {
+namespace Memcheck {
namespace Internal {
class MemcheckPlugin : public ExtensionSystem::IPlugin
@@ -53,6 +53,6 @@ public:
};
} // namespace Internal
-} // namespace Analyzer
+} // namespace Memcheck
#endif // MEMCHECKPLUGIN_H
diff --git a/src/plugins/memcheck/memchecksettings.cpp b/src/plugins/memcheck/memchecksettings.cpp
index 93336fee6a..fbfb66dcfe 100644
--- a/src/plugins/memcheck/memchecksettings.cpp
+++ b/src/plugins/memcheck/memchecksettings.cpp
@@ -39,8 +39,10 @@
#include <utils/qtcassert.h>
-using namespace Analyzer::Internal;
using namespace Analyzer;
+using namespace Memcheck;
+
+using namespace Memcheck::Internal;
static const QLatin1String numCallersC("Analyzer.Valgrind.NumCallers");
static const QLatin1String trackOriginsC("Analyzer.Valgrind.TrackOrigins");
@@ -151,7 +153,7 @@ QString AbstractMemcheckSettings::displayName() const
return tr("Memory Analysis");
}
-QWidget* AbstractMemcheckSettings::createConfigWidget(QWidget *parent)
+QWidget *AbstractMemcheckSettings::createConfigWidget(QWidget *parent)
{
return new MemcheckConfigWidget(this, parent);
}
diff --git a/src/plugins/memcheck/memchecksettings.h b/src/plugins/memcheck/memchecksettings.h
index aa6a147cde..586aa10a58 100644
--- a/src/plugins/memcheck/memchecksettings.h
+++ b/src/plugins/memcheck/memchecksettings.h
@@ -37,13 +37,13 @@
#include <analyzerbase/analyzersettings.h>
-namespace Analyzer {
+namespace Memcheck {
namespace Internal {
/**
* Generic memcheck settings
*/
-class AbstractMemcheckSettings : public AbstractAnalyzerSubConfig
+class AbstractMemcheckSettings : public Analyzer::AbstractAnalyzerSubConfig
{
Q_OBJECT
public:
diff --git a/src/plugins/memcheck/memchecktool.cpp b/src/plugins/memcheck/memchecktool.cpp
index a7132a356f..1eb66d4d22 100644
--- a/src/plugins/memcheck/memchecktool.cpp
+++ b/src/plugins/memcheck/memchecktool.cpp
@@ -39,6 +39,7 @@
#include <analyzerbase/analyzermanager.h>
#include <analyzerbase/analyzerconstants.h>
+#include <analyzerbase/ianalyzeroutputpaneadapter.h>
#include <valgrind/xmlprotocol/errorlistmodel.h>
#include <valgrind/xmlprotocol/stackmodel.h>
@@ -90,9 +91,10 @@
#include <QtGui/QCheckBox>
#include <utils/stylehelper.h>
+using namespace Analyzer;
using namespace Valgrind::XmlProtocol;
-namespace Analyzer {
+namespace Memcheck {
namespace Internal {
// Adapter for output pane.
@@ -242,7 +244,7 @@ MemcheckTool::MemcheckTool(QObject *parent) :
void MemcheckTool::settingsDestroyed(QObject *settings)
{
- Q_ASSERT(m_settings == settings);
+ QTC_ASSERT(m_settings == settings, return);
m_settings = AnalyzerGlobalSettings::instance();
}
@@ -330,14 +332,16 @@ public:
return Frame();
//find the first frame belonging to the project
- foreach(const Frame &frame, frames) {
- if (frame.directory().isEmpty() || frame.file().isEmpty())
- continue;
-
- //filepaths can contain "..", clean them:
- const QString f = QFileInfo(frame.directory() + QLatin1Char('/') + frame.file()).absoluteFilePath();
- if (m_projectFiles.contains(f))
- return frame;
+ if (!m_projectFiles.isEmpty()) {
+ foreach(const Frame &frame, frames) {
+ if (frame.directory().isEmpty() || frame.file().isEmpty())
+ continue;
+
+ //filepaths can contain "..", clean them:
+ const QString f = QFileInfo(frame.directory() + QLatin1Char('/') + frame.file()).absoluteFilePath();
+ if (m_projectFiles.contains(f))
+ return frame;
+ }
}
//if no frame belonging to the project was found, return the first one that is not malloc/new
@@ -417,14 +421,15 @@ void MemcheckTool::initialize(ExtensionSystem::IPlugin */*plugin*/)
maybeActiveRunConfigurationChanged();
}
-IAnalyzerEngine *MemcheckTool::createEngine(ProjectExplorer::RunConfiguration *runConfiguration)
+IAnalyzerEngine *MemcheckTool::createEngine(const AnalyzerStartParameters &sp,
+ ProjectExplorer::RunConfiguration *runConfiguration)
{
- m_frameFinder->setFiles(runConfiguration->target()->project()->files(ProjectExplorer::Project::AllFiles));
+ m_frameFinder->setFiles(runConfiguration ? runConfiguration->target()->project()->files(ProjectExplorer::Project::AllFiles) : QStringList());
- MemcheckEngine *engine = new MemcheckEngine(runConfiguration);
+ MemcheckEngine *engine = new MemcheckEngine(sp, runConfiguration);
- connect(engine, SIGNAL(starting(const IAnalyzerEngine*)),
- this, SLOT(engineStarting(const IAnalyzerEngine*)));
+ connect(engine, SIGNAL(starting(const Analyzer::IAnalyzerEngine*)),
+ this, SLOT(engineStarting(const Analyzer::IAnalyzerEngine*)));
connect(engine, SIGNAL(parserError(Valgrind::XmlProtocol::Error)),
this, SLOT(parserError(Valgrind::XmlProtocol::Error)));
connect(engine, SIGNAL(internalParserError(QString)),
@@ -438,12 +443,15 @@ void MemcheckTool::engineStarting(const IAnalyzerEngine *engine)
{
clearErrorView();
- const QString dir = engine->runConfiguration()->target()->project()->projectDirectory();
- const MemcheckEngine *mEngine = dynamic_cast<const MemcheckEngine*>(engine);
+ QString dir;
+ if (ProjectExplorer::RunConfiguration *rc = engine->runConfiguration())
+ dir = rc->target()->project()->projectDirectory() + QDir::separator();
+
+ const MemcheckEngine *mEngine = dynamic_cast<const MemcheckEngine *>(engine);
QTC_ASSERT(mEngine, return);
const QString name = QFileInfo(mEngine->executable()).fileName();
- m_errorView->setDefaultSuppressionFile(dir + QDir::separator() + name + QLatin1String(".supp"));
+ m_errorView->setDefaultSuppressionFile(dir + name + QLatin1String(".supp"));
QMenu *menu = filterMenu();
QTC_ASSERT(menu, return);
@@ -461,14 +469,14 @@ QMenu *MemcheckTool::filterMenu() const
{
QTC_ASSERT(m_suppressionSeparator, return 0; )
foreach (QWidget *w, m_suppressionSeparator->associatedWidgets())
- if (QMenu *menu = qobject_cast<QMenu*>(w))
+ if (QMenu *menu = qobject_cast<QMenu *>(w))
return menu;
return 0;
}
void MemcheckTool::suppressionActionTriggered()
{
- QAction *action = qobject_cast<QAction*>(sender());
+ QAction *action = qobject_cast<QAction *>(sender());
QTC_ASSERT(action, return);
const QString file = action->data().toString();
QTC_ASSERT(!file.isEmpty(), return);
@@ -530,5 +538,10 @@ void MemcheckTool::finished()
AnalyzerManager::instance()->showStatusMessage(msg);
}
+bool MemcheckTool::canRunRemotely() const
+{
+ return true;
+}
+
} // namespace Internal
-} // namespace Analyzer
+} // namespace Memcheck
diff --git a/src/plugins/memcheck/memchecktool.h b/src/plugins/memcheck/memchecktool.h
index f0f8cd980b..ee7a4c55c7 100644
--- a/src/plugins/memcheck/memchecktool.h
+++ b/src/plugins/memcheck/memchecktool.h
@@ -57,8 +57,12 @@ class Error;
}
}
-namespace Analyzer {
+namespace Analyzer
+{
class AnalyzerSettings;
+}
+
+namespace Memcheck {
namespace Internal {
class MemCheckOutputPaneAdapter;
class MemcheckErrorView;
@@ -81,7 +85,7 @@ private:
bool m_filterExternalIssues;
};
-class MemcheckTool : public IAnalyzerTool
+class MemcheckTool : public Analyzer::IAnalyzerTool
{
Q_OBJECT
public:
@@ -92,29 +96,35 @@ public:
ToolMode mode() const;
void initialize(ExtensionSystem::IPlugin *plugin);
+ virtual void extensionsInitialized() {}
- virtual IAnalyzerOutputPaneAdapter *outputPaneAdapter();
- IAnalyzerEngine *createEngine(ProjectExplorer::RunConfiguration *runConfiguration);
+ virtual Analyzer::IAnalyzerOutputPaneAdapter *outputPaneAdapter();
+ virtual Analyzer::IAnalyzerEngine *createEngine(const Analyzer::AnalyzerStartParameters &sp,
+ ProjectExplorer::RunConfiguration *runConfiguration = 0);
// For the output pane adapter.
MemcheckErrorView *ensurePaneErrorView();
QWidget *createPaneToolBarWidget();
void clearErrorView();
+ virtual bool canRunRemotely() const;
+
private slots:
void settingsDestroyed(QObject *settings);
void maybeActiveRunConfigurationChanged();
- void engineStarting(const IAnalyzerEngine *engine);
+ void engineStarting(const Analyzer::IAnalyzerEngine *engine);
+ void finished();
+
void parserError(const Valgrind::XmlProtocol::Error &error);
void internalParserError(const QString &errorString);
void updateErrorFilter();
void suppressionActionTriggered();
- void finished();
- QMenu *filterMenu() const;
private:
- AnalyzerSettings *m_settings;
+ QMenu *filterMenu() const;
+
+ Analyzer::AnalyzerSettings *m_settings;
FrameFinder *m_frameFinder;
Valgrind::XmlProtocol::ErrorListModel *m_errorModel;
@@ -129,6 +139,6 @@ private:
};
} // namespace Internal
-} // namespace Analyzer
+} // namespace Memcheck
#endif // MEMCHECKTOOL_H
diff --git a/src/plugins/memcheck/suppressiondialog.cpp b/src/plugins/memcheck/suppressiondialog.cpp
index ba9faf3f7f..2830491fc0 100644
--- a/src/plugins/memcheck/suppressiondialog.cpp
+++ b/src/plugins/memcheck/suppressiondialog.cpp
@@ -34,8 +34,8 @@
#include "suppressiondialog.h"
-
#include "ui_suppressiondialog.h"
+
#include "memcheckerrorview.h"
#include "memchecksettings.h"
@@ -56,9 +56,11 @@
#include <valgrind/xmlprotocol/frame.h>
using namespace Analyzer;
-using namespace Analyzer::Internal;
+using namespace Memcheck;
using namespace Valgrind::XmlProtocol;
+using namespace Memcheck::Internal;
+
namespace {
QString suppressionText(const Error &error)
{
diff --git a/src/plugins/memcheck/suppressiondialog.h b/src/plugins/memcheck/suppressiondialog.h
index bb3653f916..379650b919 100644
--- a/src/plugins/memcheck/suppressiondialog.h
+++ b/src/plugins/memcheck/suppressiondialog.h
@@ -40,18 +40,18 @@
#include <valgrind/xmlprotocol/error.h>
-QT_BEGIN_NAMESPACE
-namespace Ui {
-class SuppressionDialog;
-}
-QT_END_NAMESPACE
-
-namespace Analyzer {
-
+namespace Analyzer
+{
class AnalyzerSettings;
+}
+namespace Memcheck {
namespace Internal {
+namespace Ui {
+class SuppressionDialog;
+}
+
class MemcheckErrorView;
class SuppressionDialog : public QDialog
@@ -72,7 +72,7 @@ private slots:
private:
MemcheckErrorView *m_view;
Ui::SuppressionDialog *m_ui;
- AnalyzerSettings *m_settings;
+ Analyzer::AnalyzerSettings *m_settings;
bool m_cleanupIfCanceled;
QList<Valgrind::XmlProtocol::Error> m_errors;
};
diff --git a/src/plugins/memcheck/suppressiondialog.ui b/src/plugins/memcheck/suppressiondialog.ui
index ad3e6df70c..30302034a0 100644
--- a/src/plugins/memcheck/suppressiondialog.ui
+++ b/src/plugins/memcheck/suppressiondialog.ui
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
- <class>SuppressionDialog</class>
- <widget class="QDialog" name="SuppressionDialog">
+ <class>Memcheck::Internal::SuppressionDialog</class>
+ <widget class="QDialog" name="Memcheck::Internal::SuppressionDialog">
<property name="geometry">
<rect>
<x>0</x>
@@ -74,7 +74,7 @@
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
- <receiver>SuppressionDialog</receiver>
+ <receiver>Memcheck::Internal::SuppressionDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
@@ -90,7 +90,7 @@
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
- <receiver>SuppressionDialog</receiver>
+ <receiver>Memcheck::Internal::SuppressionDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
diff --git a/src/plugins/mercurial/constants.h b/src/plugins/mercurial/constants.h
index d25eda9f93..f57cac6c2b 100644
--- a/src/plugins/mercurial/constants.h
+++ b/src/plugins/mercurial/constants.h
@@ -37,18 +37,9 @@ namespace Mercurial {
namespace Constants {
enum { debug = 0 };
-const char * const MERCURIAL = "mercurial";
const char * const MECURIALREPO = ".hg";
const char * const MERCURIALDEFAULT = "hg";
-//options page items
-const char * const MERCURIALPATH = "Mercurial_Path";
-const char * const MERCURIALUSERNAME = "Mercurial_Username";
-const char * const MERCURIALEMAIL = "Mercurial_Email";
-const char * const MERCURIALLOGCOUNT = "Mercurial_LogCount";
-const char * const MERCURIALTIMEOUT = "Mercurial_Timeout";
-const char * const MERCURIALPROMPTSUBMIT = "Mercurial_PromptOnSubmit";
-
//changeset identifiers
const char * const CHANGESETID12 = " ([a-f0-9]{12,12}) "; //match 12 hex chars and capture
const char * const CHANGESETID40 = " ([a-f0-9]{40,40}) ";
@@ -112,22 +103,7 @@ const char * const OUTGOING = "Mercurial.Action.Outgoing";
const char * const COMMIT = "Mercurial.Action.Commit";
const char * const CREATE_REPOSITORY = "Mercurial.Action.CreateRepository";
-//Repository Management
-const char * const MERGE = "Mercurial.Action.Merge";
-const char * const BRANCH = "Mercurial.Action.Branch";
-const char * const HEADS = "Mercurial.Action.Heads";
-const char * const PARENTS = "Mercurial.Action.Parents";
-const char * const TAGS = "Mercurial.Action.Tags";
-const char * const TIP = "Mercurial.Action.TIP";
-const char * const PATHS = "Mercurial.Action.Paths";
-
-//Less commonly used menu actions
-const char * const CLONE = "Mercurial.Action.Clone";
-const char * const INIT = "Mercurial.Action.Init";
-const char * const SERVE = "Mercurial.Action.Serve";
-
//submit editor actions
-const char * const COMMITEDITOR = "Mercurial.Action.Editor.Commit";
const char * const DIFFEDITOR = "Mercurial.Action.Editor.Diff";
} // namespace Constants
diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp
index f08552d4e4..f85cdc5bc9 100644
--- a/src/plugins/mercurial/mercurialclient.cpp
+++ b/src/plugins/mercurial/mercurialclient.cpp
@@ -35,14 +35,17 @@
#include <vcsbase/vcsbaseoutputwindow.h>
#include <vcsbase/vcsbaseplugin.h>
+#include <vcsbase/vcsbaseeditor.h>
+#include <vcsbase/vcsbaseeditorparameterwidget.h>
#include <vcsbase/vcsjobrunner.h>
#include <utils/synchronousprocess.h>
+#include <utils/qtcassert.h>
-#include <QDir>
-#include <QFileInfo>
-#include <QTextCodec>
-#include <QTextStream>
-#include <QVariant>
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QTextCodec>
+#include <QtCore/QTextStream>
+#include <QtCore/QVariant>
namespace Mercurial {
namespace Internal {
@@ -428,10 +431,24 @@ QStringList MercurialClient::annotateArguments(const QString &file,
return args << file;
}
-QStringList MercurialClient::diffArguments(const QStringList &files) const
+QStringList MercurialClient::diffArguments(const QStringList &files,
+ const ExtraCommandOptions &extraOptions) const
{
QStringList args;
args << QLatin1String("-g") << QLatin1String("-p") << QLatin1String("-U 8");
+ foreach (const QVariant &extraOption, extraOptions) {
+ switch (extraOption.type()) {
+ case QVariant::String:
+ args.append(extraOption.toString());
+ break;
+ case QVariant::StringList:
+ args.append(extraOption.toStringList());
+ break;
+ default:
+ QTC_ASSERT(false, continue; )
+ break;
+ }
+ }
if (!files.isEmpty())
args.append(files);
return args;
@@ -486,5 +503,72 @@ QPair<QString, QString> MercurialClient::parseStatusLine(const QString &line) co
return status;
}
+// Collect all parameters required for a diff to be able to associate them
+// with a diff editor and re-run the diff with parameters.
+struct MercurialDiffParameters
+{
+ QString workingDir;
+ QStringList files;
+ VCSBase::VCSBaseClient::ExtraCommandOptions extraOptions;
+};
+
+// Parameter widget controlling whitespace diff mode, associated with a parameter
+class MercurialDiffParameterWidget : public VCSBase::VCSBaseEditorParameterWidget
+{
+ Q_OBJECT
+public:
+ explicit MercurialDiffParameterWidget(const MercurialDiffParameters &p, QWidget *parent = 0);
+
+signals:
+ void reRunDiff(const Mercurial::Internal::MercurialDiffParameters &);
+
+private slots:
+ void triggerReRun();
+
+private:
+ const MercurialDiffParameters m_parameters;
+};
+
+MercurialDiffParameterWidget::MercurialDiffParameterWidget(const MercurialDiffParameters &p, QWidget *parent) :
+ VCSBase::VCSBaseEditorParameterWidget(parent), m_parameters(p)
+{
+ addIgnoreWhiteSpaceButton(QLatin1String("-w"));
+ addIgnoreBlankLinesButton(QLatin1String("-B"));
+ connect(this, SIGNAL(argumentsChanged()), this, SLOT(triggerReRun()));
+}
+
+void MercurialDiffParameterWidget::triggerReRun()
+{
+ MercurialDiffParameters effectiveParameters = m_parameters;
+ effectiveParameters.extraOptions.insert(42, QVariant(arguments()));
+ emit reRunDiff(effectiveParameters);
+}
+
+void MercurialClient::mercurialDiff(const Mercurial::Internal::MercurialDiffParameters &p)
+{
+ diff(p.workingDir, p.files, p.extraOptions);
+}
+
+void MercurialClient::initializeDiffEditor(const QString &workingDir, const QStringList &files,
+ const VCSBase::VCSBaseClient::ExtraCommandOptions &extra,
+ VCSBase::VCSBaseEditorWidget *diffEditorWidget)
+{
+ // Wire up the parameter widget to trigger a re-run on
+ // parameter change and 'revert' from inside the diff editor.
+ MercurialDiffParameters parameters;
+ parameters.workingDir = workingDir;
+ parameters.files = files;
+ parameters.extraOptions = extra;
+ diffEditorWidget->setRevertDiffChunkEnabled(true);
+ MercurialDiffParameterWidget *pw = new MercurialDiffParameterWidget(parameters);
+ connect(pw, SIGNAL(reRunDiff(Mercurial::Internal::MercurialDiffParameters)),
+ this, SLOT(mercurialDiff(Mercurial::Internal::MercurialDiffParameters)));
+ connect(diffEditorWidget, SIGNAL(diffChunkReverted(VCSBase::DiffChunk)),
+ pw, SLOT(triggerReRun()));
+ diffEditorWidget->setConfigurationWidget(pw);
+}
+
} // namespace Internal
} // namespace Mercurial
+
+#include "mercurialclient.moc"
diff --git a/src/plugins/mercurial/mercurialclient.h b/src/plugins/mercurial/mercurialclient.h
index 8421e4d9f5..6833a18fb3 100644
--- a/src/plugins/mercurial/mercurialclient.h
+++ b/src/plugins/mercurial/mercurialclient.h
@@ -37,6 +37,7 @@
namespace Mercurial {
namespace Internal {
+struct MercurialDiffParameters;
class MercurialClient : public VCSBase::VCSBaseClient
{
@@ -70,34 +71,41 @@ public:
void outgoing(const QString &repositoryRoot);
QString vcsGetRepositoryURL(const QString &directory);
+private slots:
+ void mercurialDiff(const Mercurial::Internal::MercurialDiffParameters &);
+
public:
- virtual QString findTopLevelForFile(const QFileInfo &file) const;
+ QString findTopLevelForFile(const QFileInfo &file) const;
protected:
- virtual QString vcsEditorKind(VCSCommand cmd) const;
+ QString vcsEditorKind(VCSCommand cmd) const;
- virtual QStringList cloneArguments(const QString &srcLocation,
- const QString &dstLocation,
- const ExtraCommandOptions &extraOptions) const;
- virtual QStringList pullArguments(const QString &srcLocation,
- const ExtraCommandOptions &extraOptions) const;
- virtual QStringList pushArguments(const QString &dstLocation,
- const ExtraCommandOptions &extraOptions) const;
- virtual QStringList commitArguments(const QStringList &files,
- const QString &commitMessageFile,
- const ExtraCommandOptions &extraOptions) const;
- virtual QStringList importArguments(const QStringList &files) const;
- virtual QStringList updateArguments(const QString &revision) const;
- virtual QStringList revertArguments(const QString &file, const QString &revision) const;
- virtual QStringList revertAllArguments(const QString &revision) const;
- virtual QStringList annotateArguments(const QString &file,
- const QString &revision, int lineNumber) const;
- virtual QStringList diffArguments(const QStringList &files) const;
- virtual QStringList logArguments(const QStringList &files) const;
- virtual QStringList statusArguments(const QString &file) const;
- virtual QStringList viewArguments(const QString &revision) const;
+ QStringList cloneArguments(const QString &srcLocation,
+ const QString &dstLocation,
+ const ExtraCommandOptions &extraOptions) const;
+ QStringList pullArguments(const QString &srcLocation,
+ const ExtraCommandOptions &extraOptions) const;
+ QStringList pushArguments(const QString &dstLocation,
+ const ExtraCommandOptions &extraOptions) const;
+ QStringList commitArguments(const QStringList &files,
+ const QString &commitMessageFile,
+ const ExtraCommandOptions &extraOptions) const;
+ QStringList importArguments(const QStringList &files) const;
+ QStringList updateArguments(const QString &revision) const;
+ QStringList revertArguments(const QString &file, const QString &revision) const;
+ QStringList revertAllArguments(const QString &revision) const;
+ QStringList annotateArguments(const QString &file,
+ const QString &revision, int lineNumber) const;
+ QStringList diffArguments(const QStringList &files,
+ const ExtraCommandOptions &extraOptions) const;
+ void initializeDiffEditor(const QString &workingDir, const QStringList &files,
+ const VCSBase::VCSBaseClient::ExtraCommandOptions &extra,
+ VCSBase::VCSBaseEditorWidget *ed);
+ QStringList logArguments(const QStringList &files) const;
+ QStringList statusArguments(const QString &file) const;
+ QStringList viewArguments(const QString &revision) const;
- virtual QPair<QString, QString> parseStatusLine(const QString &line) const;
+ QPair<QString, QString> parseStatusLine(const QString &line) const;
};
} //namespace Internal
diff --git a/src/plugins/mercurial/mercurialeditor.cpp b/src/plugins/mercurial/mercurialeditor.cpp
index 4be3559fb1..2cf351da7c 100644
--- a/src/plugins/mercurial/mercurialeditor.cpp
+++ b/src/plugins/mercurial/mercurialeditor.cpp
@@ -101,18 +101,18 @@ VCSBase::BaseAnnotationHighlighter *MercurialEditor::createAnnotationHighlighter
return new MercurialAnnotationHighlighter(changes);
}
-QString MercurialEditor::fileNameFromDiffSpecification(const QTextBlock &diffFileSpec) const
+QString MercurialEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
{
- const QString filechangeId(QLatin1String("+++ b/"));
- QTextBlock::iterator iterator;
- for (iterator = diffFileSpec.begin(); !(iterator.atEnd()); iterator++) {
- QTextFragment fragment = iterator.fragment();
- if(fragment.isValid()) {
- if (fragment.text().startsWith(filechangeId)) {
- const QString filename = fragment.text().remove(0, filechangeId.size());
- return findDiffFile(filename, MercurialPlugin::instance()->versionControl());
- }
+ // git-compatible format: check for "+++ b/src/plugins/git/giteditor.cpp" (blame and diff)
+ // Go back chunks.
+ const QString newFileIndicator = QLatin1String("+++ b/");
+ for (QTextBlock block = inBlock; block.isValid(); block = block.previous()) {
+ QString diffFileName = block.text();
+ if (diffFileName.startsWith(newFileIndicator)) {
+ diffFileName.remove(0, newFileIndicator.size());
+ return findDiffFile(diffFileName, MercurialPlugin::instance()->versionControl());
}
+
}
return QString();
}
diff --git a/src/plugins/perforce/perforceconstants.h b/src/plugins/perforce/perforceconstants.h
index 28c49479f5..360bae9c09 100644
--- a/src/plugins/perforce/perforceconstants.h
+++ b/src/plugins/perforce/perforceconstants.h
@@ -38,8 +38,6 @@
namespace Perforce {
namespace Constants {
-const char * const PERFORCEEDITOR_CONTEXT = "Perforce Editor";
-
const char * const PERFORCE_SUBMIT_EDITOR_ID = "Perforce.SubmitEditor";
const char * const PERFORCE_SUBMIT_EDITOR_DISPLAY_NAME = QT_TRANSLATE_NOOP("VCS", "Perforce.SubmitEditor");
const char * const PERFORCESUBMITEDITOR_CONTEXT = "Perforce Submit Editor";
diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp
index a891953eb7..d239dfa242 100644
--- a/src/plugins/perforce/perforceplugin.cpp
+++ b/src/plugins/perforce/perforceplugin.cpp
@@ -59,6 +59,7 @@
#include <vcsbase/basevcssubmiteditorfactory.h>
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/vcsbaseoutputwindow.h>
+#include <vcsbase/vcsbaseeditorparameterwidget.h>
#include <QtCore/QtPlugin>
#include <QtCore/QDebug>
@@ -1212,32 +1213,74 @@ void PerforcePlugin::slotSubmitDiff(const QStringList &files)
p4Diff(m_commitWorkingDirectory, files);
}
-void PerforcePlugin::p4Diff(const QString &workingDir, const QStringList &files)
+struct PerforceDiffParameters
{
- Core::IEditor *existingEditor = 0;
+ QString workingDir;
+ QStringList diffArguments;
+ QStringList files;
+};
- QTextCodec *codec = VCSBase::VCSBaseEditorWidget::getCodec(workingDir, files);
- const QString id = VCSBase::VCSBaseEditorWidget::getTitleId(workingDir, files);
- const QString source = VCSBase::VCSBaseEditorWidget::getSource(workingDir, files);
+// Parameter widget controlling whitespace diff mode, associated with a parameter
+class PerforceDiffParameterWidget : public VCSBase::VCSBaseEditorParameterWidget
+{
+ Q_OBJECT
+public:
+ explicit PerforceDiffParameterWidget(const PerforceDiffParameters &p, QWidget *parent = 0);
+
+signals:
+ void reRunDiff(const Perforce::Internal::PerforceDiffParameters &);
+
+private slots:
+ void triggerReRun();
+
+private:
+ const PerforceDiffParameters m_parameters;
+};
+
+PerforceDiffParameterWidget::PerforceDiffParameterWidget(const PerforceDiffParameters &p, QWidget *parent) :
+ VCSBase::VCSBaseEditorParameterWidget(parent), m_parameters(p)
+{
+ setBaseArguments(p.diffArguments);
+ addIgnoreWhiteSpaceButton(QString(QLatin1Char('w')));
+ connect(this, SIGNAL(argumentsChanged()), this, SLOT(triggerReRun()));
+}
+
+void PerforceDiffParameterWidget::triggerReRun()
+{
+ PerforceDiffParameters effectiveParameters = m_parameters;
+ effectiveParameters.diffArguments = arguments();
+ emit reRunDiff(effectiveParameters);
+}
+void PerforcePlugin::p4Diff(const QString &workingDir, const QStringList &files)
+{
+ PerforceDiffParameters p;
+ p.workingDir = workingDir;
+ p.files = files;
+ p.diffArguments.push_back(QString(QLatin1Char('u')));
+ p4Diff(p);
+}
+
+void PerforcePlugin::p4Diff(const PerforceDiffParameters &p)
+{
+ QTextCodec *codec = VCSBase::VCSBaseEditorWidget::getCodec(p.workingDir, p.files);
+ const QString id = VCSBase::VCSBaseEditorWidget::getTitleId(p.workingDir, p.files);
// Reuse existing editors for that id
- foreach (Core::IEditor *ed, Core::EditorManager::instance()->openedEditors()) {
- if (ed->file()->property("originalFileName").toString() == id) {
- existingEditor = ed;
- break;
- }
- }
+ const QString tag = VCSBase::VCSBaseEditorWidget::editorTag(VCSBase::DiffOutput, p.workingDir, p.files);
+ Core::IEditor *existingEditor = VCSBase::VCSBaseEditorWidget::locateEditorByTag(tag);
// Split arguments according to size
QStringList args;
- args << QLatin1String("diff") << QLatin1String("-du");
+ args << QLatin1String("diff");
+ if (!p.diffArguments.isEmpty()) // -duw..
+ args << (QLatin1String("-d") + p.diffArguments.join(QString()));
QStringList extraArgs;
- if (files.size() > 1) {
- extraArgs = files;
+ if (p.files.size() > 1) {
+ extraArgs = p.files;
} else {
- args.append(files);
+ args.append(p.files);
}
const unsigned flags = CommandToWindow|StdErrToWindow|ErrorToWindow|OverrideDiffEnvironment;
- const PerforceResponse result = runP4Cmd(workingDir, args, flags,
+ const PerforceResponse result = runP4Cmd(p.workingDir, args, flags,
extraArgs, QByteArray(), codec);
if (result.error)
return;
@@ -1245,12 +1288,23 @@ void PerforcePlugin::p4Diff(const QString &workingDir, const QStringList &files)
if (existingEditor) {
existingEditor->createNew(result.stdOut);
Core::EditorManager::instance()->activateEditor(existingEditor, Core::EditorManager::ModeSwitch);
- } else {
- Core::IEditor *editor = showOutputInEditor(tr("p4 diff %1").arg(id), result.stdOut, VCSBase::DiffOutput,
- VCSBase::VCSBaseEditorWidget::getSource(workingDir, files),
- codec);
- editor->file()->setProperty("originalFileName", id);
+ return;
}
+ // Create new editor
+ Core::IEditor *editor = showOutputInEditor(tr("p4 diff %1").arg(id), result.stdOut, VCSBase::DiffOutput,
+ VCSBase::VCSBaseEditorWidget::getSource(p.workingDir, p.files),
+ codec);
+ VCSBase::VCSBaseEditorWidget::tagEditor(editor, tag);
+ VCSBase::VCSBaseEditorWidget *diffEditorWidget = qobject_cast<VCSBase::VCSBaseEditorWidget *>(editor->widget());
+ // Wire up the parameter widget to trigger a re-run on
+ // parameter change and 'revert' from inside the diff editor.
+ diffEditorWidget->setRevertDiffChunkEnabled(true);
+ PerforceDiffParameterWidget *pw = new PerforceDiffParameterWidget(p);
+ connect(pw, SIGNAL(reRunDiff(Perforce::Internal::PerforceDiffParameters)),
+ this, SLOT(p4Diff(Perforce::Internal::PerforceDiffParameters)));
+ connect(diffEditorWidget, SIGNAL(diffChunkReverted(VCSBase::DiffChunk)),
+ pw, SLOT(triggerReRun()));
+ diffEditorWidget->setConfigurationWidget(pw);
}
void PerforcePlugin::describe(const QString & source, const QString &n)
@@ -1497,3 +1551,5 @@ void PerforcePlugin::getTopLevel()
}
Q_EXPORT_PLUGIN(Perforce::Internal::PerforcePlugin)
+
+#include "perforceplugin.moc"
diff --git a/src/plugins/perforce/perforceplugin.h b/src/plugins/perforce/perforceplugin.h
index e7721d9f08..0e1ba0dbda 100644
--- a/src/plugins/perforce/perforceplugin.h
+++ b/src/plugins/perforce/perforceplugin.h
@@ -62,7 +62,7 @@ namespace Locator {
namespace Perforce {
namespace Internal {
-
+struct PerforceDiffParameters;
class PerforceVersionControl;
struct PerforceResponse
@@ -110,6 +110,7 @@ public:
public slots:
void describe(const QString &source, const QString &n);
void vcsAnnotate(const QString &file, const QString &revision /* = QString() */, int lineNumber);
+ void p4Diff(const Perforce::Internal::PerforceDiffParameters &p);
private slots:
void openCurrentFile();
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 209562857c..6a7590626a 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -44,7 +44,8 @@ SUBDIRS = plugin_coreplugin \
!win32 {
SUBDIRS += plugin_valgrindtoolbase \
- plugin_memcheck
+ plugin_memcheck \
+ plugin_callgrind
}
linux-* {
@@ -63,6 +64,7 @@ contains(QT_CONFIG, declarative) {
minQtVersion(4, 7, 1) {
SUBDIRS += plugin_qmldesigner
+ !win32:SUBDIRS += plugin_qmlprofiler
} else {
warning()
warning("QmlDesigner plugin has been disabled.")
@@ -144,6 +146,7 @@ plugin_qt4projectmanager.depends += plugin_projectexplorer
plugin_qt4projectmanager.depends += plugin_cpptools
plugin_qt4projectmanager.depends += plugin_debugger
plugin_qt4projectmanager.depends += plugin_qmljseditor
+plugin_qt4projectmanager.depends += plugin_analyzerbase
plugin_locator.subdir = locator
plugin_locator.depends = plugin_coreplugin
@@ -261,6 +264,16 @@ plugin_analyzerbase.depends += plugin_projectexplorer
plugin_memcheck.depends = plugin_coreplugin
plugin_memcheck.depends += plugin_analyzerbase
plugin_memcheck.depends += plugin_valgrindtoolbase
+
+ plugin_callgrind.subdir = callgrind
+ plugin_callgrind.depends = plugin_coreplugin
+ plugin_callgrind.depends += plugin_analyzerbase
+ plugin_callgrind.depends += plugin_valgrindtoolbase
+
+ plugin_qmlprofiler.subdir = qmlprofiler
+ plugin_qmlprofiler.depends = plugin_coreplugin
+ plugin_qmlprofiler.depends += plugin_analyzerbase
+ plugin_qmlprofiler.depends += plugin_qmlprojectmanager
}
plugin_qmljstools.subdir = qmljstools
diff --git a/src/plugins/projectexplorer/abi.cpp b/src/plugins/projectexplorer/abi.cpp
index 33ccbdb3f9..50e89ba452 100644
--- a/src/plugins/projectexplorer/abi.cpp
+++ b/src/plugins/projectexplorer/abi.cpp
@@ -350,11 +350,20 @@ bool Abi::operator == (const Abi &other) const
bool Abi::isCompatibleWith(const Abi &other) const
{
- return (architecture() == other.architecture() || other.architecture() == Abi::UnknownArchitecture)
- && (os() == other.os() || other.os() == Abi::UnknownOS)
- && (osFlavor() == other.osFlavor() || other.osFlavor() == Abi::UnknownFlavor)
- && (binaryFormat() == other.binaryFormat() || other.binaryFormat() == Abi::UnknownFormat)
- && ((wordWidth() == other.wordWidth() && wordWidth() != 0) || other.wordWidth() == 0);
+ bool isCompat = (architecture() == other.architecture() || other.architecture() == Abi::UnknownArchitecture)
+ && (os() == other.os() || other.os() == Abi::UnknownOS)
+ && (osFlavor() == other.osFlavor() || other.osFlavor() == Abi::UnknownFlavor)
+ && (binaryFormat() == other.binaryFormat() || other.binaryFormat() == Abi::UnknownFormat)
+ && ((wordWidth() == other.wordWidth() && wordWidth() != 0) || other.wordWidth() == 0);
+ // *-linux-generic-* is compatible with *-linux-*:
+ if (!isCompat && architecture() == other.architecture()
+ && os() == other.os()
+ && osFlavor() == GenericLinuxFlavor
+ && other.os() == LinuxOS
+ && binaryFormat() == other.binaryFormat()
+ && wordWidth() == other.wordWidth())
+ isCompat = true;
+ return isCompat;
}
bool Abi::isValid() const
@@ -648,6 +657,10 @@ void ProjectExplorer::ProjectExplorerPlugin::testAbiOfBinary_data()
QTest::newRow("dynamic QtCore: arm linux 32bit")
<< QString::fromLatin1("%1/abi/dynamic/arm-linux.so").arg(prefix)
<< (QStringList() << QString::fromLatin1("arm-linux-generic-elf-32bit"));
+ QTest::newRow("dynamic QtCore: mips linux 32bit")
+ << QString::fromLatin1("%1/abi/dynamic/mips-linux.so").arg(prefix)
+ << (QStringList() << QString::fromLatin1("mips-linux-generic-elf-32bit"));
+
}
void ProjectExplorer::ProjectExplorerPlugin::testAbiOfBinary()
diff --git a/src/plugins/projectexplorer/abstractprocessstep.cpp b/src/plugins/projectexplorer/abstractprocessstep.cpp
index cdd1ead1ed..aeb4eb0221 100644
--- a/src/plugins/projectexplorer/abstractprocessstep.cpp
+++ b/src/plugins/projectexplorer/abstractprocessstep.cpp
@@ -174,7 +174,7 @@ void AbstractProcessStep::run(QFutureInterface<bool> &fi)
void AbstractProcessStep::processStarted()
{
- emit addOutput(tr("Starting: \"%1\" %2\n")
+ emit addOutput(tr("Starting: \"%1\" %2")
.arg(QDir::toNativeSeparators(m_param.effectiveCommand()),
m_param.prettyArguments()),
BuildStep::MessageOutput);
@@ -221,7 +221,7 @@ void AbstractProcessStep::stdOutput(const QString &line)
{
if (m_outputParserChain)
m_outputParserChain->stdOutput(line);
- emit addOutput(line, BuildStep::NormalOutput);
+ emit addOutput(line, BuildStep::NormalOutput, BuildStep::DontAppendNewline);
}
void AbstractProcessStep::processReadyReadStdError()
@@ -237,7 +237,7 @@ void AbstractProcessStep::stdError(const QString &line)
{
if (m_outputParserChain)
m_outputParserChain->stdError(line);
- emit addOutput(line, BuildStep::ErrorOutput);
+ emit addOutput(line, BuildStep::ErrorOutput, BuildStep::DontAppendNewline);
}
void AbstractProcessStep::checkForCancel()
@@ -300,7 +300,7 @@ void AbstractProcessStep::taskAdded(const ProjectExplorer::Task &task)
void AbstractProcessStep::outputAdded(const QString &string, ProjectExplorer::BuildStep::OutputFormat format)
{
- emit addOutput(string, format);
+ emit addOutput(string, format, BuildStep::DontAppendNewline);
}
void AbstractProcessStep::slotProcessFinished(int, QProcess::ExitStatus)
diff --git a/src/plugins/projectexplorer/buildmanager.cpp b/src/plugins/projectexplorer/buildmanager.cpp
index 65beea81fd..b5f82c8042 100644
--- a/src/plugins/projectexplorer/buildmanager.cpp
+++ b/src/plugins/projectexplorer/buildmanager.cpp
@@ -135,6 +135,7 @@ BuildManager::BuildManager(ProjectExplorerPlugin *parent)
pm->addObject(d->m_taskWindow);
qRegisterMetaType<ProjectExplorer::BuildStep::OutputFormat>();
+ qRegisterMetaType<ProjectExplorer::BuildStep::OutputNewlineSetting>();
connect(d->m_taskWindow, SIGNAL(tasksChanged()),
this, SLOT(updateTaskCount()));
@@ -197,10 +198,7 @@ void BuildManager::cancel()
// (And we want those to be before the cancel message.)
QTimer::singleShot(0, this, SLOT(emitCancelMessage()));
- disconnect(d->m_currentBuildStep, SIGNAL(addTask(ProjectExplorer::Task)),
- this, SLOT(addToTaskWindow(ProjectExplorer::Task)));
- disconnect(d->m_currentBuildStep, SIGNAL(addOutput(QString, ProjectExplorer::BuildStep::OutputFormat)),
- this, SLOT(addToOutputWindow(QString, ProjectExplorer::BuildStep::OutputFormat)));
+ disconnectOutput(d->m_currentBuildStep);
decrementActiveBuildSteps(d->m_currentBuildStep->buildConfiguration()->target()->project());
d->m_progressFutureInterface->setProgressValueAndText(d->m_progress*100, tr("Build canceled")); //TODO NBS fix in qtconcurrent
@@ -228,17 +226,14 @@ void BuildManager::finish()
void BuildManager::emitCancelMessage()
{
- emit addToOutputWindow(tr("Canceled build."), BuildStep::ErrorMessageOutput);
+ addToOutputWindow(tr("Canceled build."), BuildStep::ErrorMessageOutput);
}
void BuildManager::clearBuildQueue()
{
foreach (BuildStep *bs, d->m_buildQueue) {
decrementActiveBuildSteps(bs->buildConfiguration()->target()->project());
- disconnect(bs, SIGNAL(addTask(ProjectExplorer::Task)),
- this, SLOT(addToTaskWindow(ProjectExplorer::Task)));
- disconnect(bs, SIGNAL(addOutput(QString, ProjectExplorer::BuildStep::OutputFormat)),
- this, SLOT(addToOutputWindow(QString, ProjectExplorer::BuildStep::OutputFormat)));
+ disconnectOutput(bs);
}
d->m_buildQueue.clear();
@@ -328,9 +323,13 @@ void BuildManager::addToTaskWindow(const ProjectExplorer::Task &task)
d->m_taskHub->addTask(task);
}
-void BuildManager::addToOutputWindow(const QString &string, ProjectExplorer::BuildStep::OutputFormat format)
+void BuildManager::addToOutputWindow(const QString &string, BuildStep::OutputFormat format,
+ BuildStep::OutputNewlineSetting newLineSetting)
{
- d->m_outputWindow->appendText(string, format);
+ QString stringToWrite = string;
+ if (newLineSetting == BuildStep::DoAppendNewline)
+ stringToWrite += QLatin1Char('\n');
+ d->m_outputWindow->appendText(stringToWrite, format);
}
void BuildManager::nextBuildQueue()
@@ -338,11 +337,7 @@ void BuildManager::nextBuildQueue()
if (d->m_canceling)
return;
- disconnect(d->m_currentBuildStep, SIGNAL(addTask(ProjectExplorer::Task)),
- this, SLOT(addToTaskWindow(ProjectExplorer::Task)));
- disconnect(d->m_currentBuildStep, SIGNAL(addOutput(QString, ProjectExplorer::BuildStep::OutputFormat)),
- this, SLOT(addToOutputWindow(QString, ProjectExplorer::BuildStep::OutputFormat)));
-
+ disconnectOutput(d->m_currentBuildStep);
++d->m_progress;
d->m_progressFutureInterface->setProgressValueAndText(d->m_progress*100, msgProgress(d->m_progress, d->m_maxProgress));
decrementActiveBuildSteps(d->m_currentBuildStep->buildConfiguration()->target()->project());
@@ -419,8 +414,8 @@ bool BuildManager::buildQueueAppend(QList<BuildStep *> steps)
BuildStep *bs = steps.at(i);
connect(bs, SIGNAL(addTask(ProjectExplorer::Task)),
this, SLOT(addToTaskWindow(ProjectExplorer::Task)));
- connect(bs, SIGNAL(addOutput(QString, ProjectExplorer::BuildStep::OutputFormat)),
- this, SLOT(addToOutputWindow(QString, ProjectExplorer::BuildStep::OutputFormat)));
+ connect(bs, SIGNAL(addOutput(QString, ProjectExplorer::BuildStep::OutputFormat, ProjectExplorer::BuildStep::OutputNewlineSetting)),
+ this, SLOT(addToOutputWindow(QString, ProjectExplorer::BuildStep::OutputFormat, ProjectExplorer::BuildStep::OutputNewlineSetting)));
init = bs->init();
if (!init)
break;
@@ -436,13 +431,8 @@ bool BuildManager::buildQueueAppend(QList<BuildStep *> steps)
addToOutputWindow(tr("When executing build step '%1'").arg(bs->displayName()), BuildStep::ErrorOutput);
// disconnect the buildsteps again
- for (int j = 0; j <= i; ++j) {
- BuildStep *bs = steps.at(j);
- disconnect(bs, SIGNAL(addTask(ProjectExplorer::Task)),
- this, SLOT(addToTaskWindow(ProjectExplorer::Task)));
- disconnect(bs, SIGNAL(addOutput(QString, ProjectExplorer::BuildStep::OutputFormat)),
- this, SLOT(addToOutputWindow(QString, ProjectExplorer::BuildStep::OutputFormat)));
- }
+ for (int j = 0; j <= i; ++j)
+ disconnectOutput(steps.at(j));
return false;
}
@@ -534,4 +524,14 @@ void BuildManager::decrementActiveBuildSteps(Project *pro)
}
}
+void BuildManager::disconnectOutput(BuildStep *bs)
+{
+ disconnect(bs, SIGNAL(addTask(ProjectExplorer::Task)),
+ this, SLOT(addToTaskWindow(ProjectExplorer::Task)));
+ disconnect(bs, SIGNAL(addOutput(QString, ProjectExplorer::BuildStep::OutputFormat,
+ ProjectExplorer::BuildStep::OutputNewlineSetting)),
+ this, SLOT(addToOutputWindow(QString, ProjectExplorer::BuildStep::OutputFormat,
+ ProjectExplorer::BuildStep::OutputNewlineSetting)));
+}
+
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/buildmanager.h b/src/plugins/projectexplorer/buildmanager.h
index 28c5a803be..74fbe1b1f9 100644
--- a/src/plugins/projectexplorer/buildmanager.h
+++ b/src/plugins/projectexplorer/buildmanager.h
@@ -84,7 +84,8 @@ signals:
private slots:
void addToTaskWindow(const ProjectExplorer::Task &task);
- void addToOutputWindow(const QString &string, ProjectExplorer::BuildStep::OutputFormat);
+ void addToOutputWindow(const QString &string, ProjectExplorer::BuildStep::OutputFormat,
+ ProjectExplorer::BuildStep::OutputNewlineSetting = BuildStep::DoAppendNewline);
void nextBuildQueue();
void progressChanged();
@@ -101,6 +102,7 @@ private:
bool buildQueueAppend(QList<BuildStep *> steps);
void incrementActiveBuildSteps(Project *pro);
void decrementActiveBuildSteps(Project *pro);
+ void disconnectOutput(BuildStep *bs);
QScopedPointer<BuildManagerPrivate> d;
};
diff --git a/src/plugins/projectexplorer/buildstep.h b/src/plugins/projectexplorer/buildstep.h
index b2440c8cc7..d10439adfb 100644
--- a/src/plugins/projectexplorer/buildstep.h
+++ b/src/plugins/projectexplorer/buildstep.h
@@ -105,14 +105,17 @@ public:
Target *target() const;
enum OutputFormat { NormalOutput, ErrorOutput, MessageOutput, ErrorMessageOutput };
+ enum OutputNewlineSetting { DoAppendNewline, DontAppendNewline };
signals:
// Add a task.
void addTask(const ProjectExplorer::Task &task);
+
// The string is added to the generated output, usually in the output
// window.
// It should be in plain text, with the format in the parameter
- void addOutput(const QString &string, ProjectExplorer::BuildStep::OutputFormat format);
+ void addOutput(const QString &string, ProjectExplorer::BuildStep::OutputFormat format,
+ ProjectExplorer::BuildStep::OutputNewlineSetting newlineSetting = DoAppendNewline);
};
class PROJECTEXPLORER_EXPORT IBuildStepFactory :
@@ -174,5 +177,6 @@ signals:
} // namespace ProjectExplorer
Q_DECLARE_METATYPE(ProjectExplorer::BuildStep::OutputFormat)
+Q_DECLARE_METATYPE(ProjectExplorer::BuildStep::OutputNewlineSetting)
#endif // BUILDSTEP_H
diff --git a/src/plugins/projectexplorer/doubletabwidget.cpp b/src/plugins/projectexplorer/doubletabwidget.cpp
index 06edea4f3b..6548677fd3 100644
--- a/src/plugins/projectexplorer/doubletabwidget.cpp
+++ b/src/plugins/projectexplorer/doubletabwidget.cpp
@@ -40,6 +40,7 @@
#include <QtGui/QFont>
#include <QtGui/QMouseEvent>
#include <QtGui/QMenu>
+#include <QtGui/QToolTip>
#include <QtDebug>
@@ -136,22 +137,57 @@ QSize DoubleTabWidget::minimumSizeHint() const
return QSize(0, Utils::StyleHelper::navigationWidgetHeight() + OTHER_HEIGHT + 1);
}
-void DoubleTabWidget::addTab(const QString &name, const QStringList &subTabs)
+void DoubleTabWidget::updateNameIsUniqueAdd(Tab *tab)
+{
+ tab->nameIsUnique = true;
+ for (int i=0; i < m_tabs.size(); ++i) {
+ if (m_tabs.at(i).name == tab->name) {
+ m_tabs[i].nameIsUnique = false;
+ tab->nameIsUnique = false;
+ break;
+ }
+ }
+}
+
+void DoubleTabWidget::updateNameIsUniqueRemove(const Tab &tab)
+{
+ if (tab.nameIsUnique)
+ return;
+ int index;
+ int count = 0;
+ for (int i=0; i < m_tabs.size(); ++i) {
+ if (m_tabs.at(i).name == tab.name) {
+ ++count;
+ index = i;
+ }
+ }
+
+ if (count == 1)
+ m_tabs[index].nameIsUnique = true;
+}
+
+void DoubleTabWidget::addTab(const QString &name, const QString &fullName, const QStringList &subTabs)
{
Tab tab;
tab.name = name;
+ tab.fullName = fullName;
tab.subTabs = subTabs;
tab.currentSubTab = tab.subTabs.isEmpty() ? -1 : 0;
+ updateNameIsUniqueAdd(&tab);
+
m_tabs.append(tab);
update();
}
-void DoubleTabWidget::insertTab(int index, const QString &name, const QStringList &subTabs)
+void DoubleTabWidget::insertTab(int index, const QString &name, const QString &fullName, const QStringList &subTabs)
{
Tab tab;
tab.name = name;
+ tab.fullName = fullName;
tab.subTabs = subTabs;
tab.currentSubTab = tab.subTabs.isEmpty() ? -1 : 0;
+ updateNameIsUniqueAdd(&tab);
+
m_tabs.insert(index, tab);
if (m_currentIndex >= index) {
++m_currentIndex;
@@ -162,7 +198,8 @@ void DoubleTabWidget::insertTab(int index, const QString &name, const QStringLis
void DoubleTabWidget::removeTab(int index)
{
- m_tabs.removeAt(index);
+ Tab t = m_tabs.takeAt(index);
+ updateNameIsUniqueRemove(t);
if (index <= m_currentIndex) {
--m_currentIndex;
if (m_currentIndex < 0 && m_tabs.size() > 0)
@@ -181,66 +218,51 @@ int DoubleTabWidget::tabCount() const
return m_tabs.size();
}
-void DoubleTabWidget::mousePressEvent(QMouseEvent *event)
+/// Converts a position to the tab/subtab that is undeneath
+/// If HitArea is tab or subtab, then the second part of the pair
+/// is the tab or subtab number
+QPair<DoubleTabWidget::HitArea, int> DoubleTabWidget::convertPosToTab(QPoint pos)
{
- if (event->y() < Utils::StyleHelper::navigationWidgetHeight()) {
- int eventX = event->x();
- // clicked on the top level part of the bar
+ if (pos.y() < Utils::StyleHelper::navigationWidgetHeight()) {
+ // on the top level part of the bar
+ int eventX = pos.x();
QFontMetrics fm(font());
int x = m_title.isEmpty() ? 0 :
2 * MARGIN + qMax(fm.width(m_title), MIN_LEFT_MARGIN);
if (eventX <= x)
- return;
+ return qMakePair(HITNOTHING, -1);
int i;
for (i = 0; i <= m_lastVisibleIndex; ++i) {
int otherX = x + 2 * MARGIN + fm.width(m_tabs.at(
- m_currentTabIndices.at(i)).name);
+ m_currentTabIndices.at(i)).displayName());
if (eventX > x && eventX < otherX) {
break;
}
x = otherX;
}
if (i <= m_lastVisibleIndex) {
- if (m_currentIndex != m_currentTabIndices.at(i)) {
- m_currentIndex = m_currentTabIndices.at(i);
- update();
- emit currentIndexChanged(m_currentIndex, m_tabs.at(m_currentIndex).currentSubTab);
- }
- event->accept();
- return;
+ return qMakePair(HITTAB, i);
} else if (m_lastVisibleIndex < m_tabs.size() - 1) {
// handle overflow menu
if (eventX > x && eventX < x + OVERFLOW_DROPDOWN_WIDTH) {
- QMenu overflowMenu;
- QList<QAction *> actions;
- for (int i = m_lastVisibleIndex + 1; i < m_tabs.size(); ++i) {
- actions << overflowMenu.addAction(m_tabs.at(m_currentTabIndices.at(i)).name);
- }
- if (QAction *action = overflowMenu.exec(mapToGlobal(QPoint(x+1, 1)))) {
- int index = m_currentTabIndices.at(actions.indexOf(action) + m_lastVisibleIndex + 1);
- if (m_currentIndex != index) {
- m_currentIndex = index;
- update();
- emit currentIndexChanged(m_currentIndex, m_tabs.at(m_currentIndex).currentSubTab);
- }
- }
+ return qMakePair(HITOVERFLOW, -1);
}
}
- } else if (event->y() < Utils::StyleHelper::navigationWidgetHeight() + OTHER_HEIGHT) {
+ } else if (pos.y() < Utils::StyleHelper::navigationWidgetHeight() + OTHER_HEIGHT) {
int diff = (OTHER_HEIGHT - SELECTION_IMAGE_HEIGHT) / 2;
- if (event->y() < Utils::StyleHelper::navigationWidgetHeight() + diff
- || event->y() > Utils::StyleHelper::navigationWidgetHeight() + OTHER_HEIGHT - diff)
- return;
+ if (pos.y() < Utils::StyleHelper::navigationWidgetHeight() + diff
+ || pos.y() > Utils::StyleHelper::navigationWidgetHeight() + OTHER_HEIGHT - diff)
+ return qMakePair(HITNOTHING, -1);
+ // on the lower level part of the bar
if (m_currentIndex == -1)
- return;
+ return qMakePair(HITNOTHING, -1);
Tab currentTab = m_tabs.at(m_currentIndex);
QStringList subTabs = currentTab.subTabs;
if (subTabs.isEmpty())
- return;
- int eventX = event->x();
+ return qMakePair(HITNOTHING, -1);
+ int eventX = pos.x();
QFontMetrics fm(font());
- // clicked on the lower level part of the bar
int x = MARGIN;
int i;
for (i = 0; i < subTabs.size(); ++i) {
@@ -251,10 +273,50 @@ void DoubleTabWidget::mousePressEvent(QMouseEvent *event)
x = otherX + 2 * MARGIN;
}
if (i < subTabs.size()) {
- if (m_tabs[m_currentIndex].currentSubTab != i) {
- m_tabs[m_currentIndex].currentSubTab = i;
+ return qMakePair(HITSUBTAB, i);
+ }
+ }
+ return qMakePair(HITNOTHING, -1);
+}
+
+void DoubleTabWidget::mousePressEvent(QMouseEvent *event)
+{
+ // todo:
+ // the even wasn't accepted/ignored in a consistent way
+ // now the event is accepted everywhere were it hitted something interesting
+ // and otherwise ignored
+ // should not make any difference
+ QPair<HitArea, int> hit = convertPosToTab(event->pos());
+ if (hit.first == HITTAB) {
+ if (m_currentIndex != m_currentTabIndices.at(hit.second)) {
+ m_currentIndex = m_currentTabIndices.at(hit.second);
+ update();
+ event->accept();
+ emit currentIndexChanged(m_currentIndex, m_tabs.at(m_currentIndex).currentSubTab);
+ return;
+ }
+ } else if (hit.first == HITOVERFLOW) {
+ QMenu overflowMenu;
+ QList<QAction *> actions;
+ for (int i = m_lastVisibleIndex + 1; i < m_tabs.size(); ++i) {
+ actions << overflowMenu.addAction(m_tabs.at(m_currentTabIndices.at(i)).displayName());
+ }
+ if (QAction *action = overflowMenu.exec(event->globalPos())) { // todo used different position before
+ int index = m_currentTabIndices.at(actions.indexOf(action) + m_lastVisibleIndex + 1);
+ if (m_currentIndex != index) {
+ m_currentIndex = index;
update();
+ event->accept();
+ emit currentIndexChanged(m_currentIndex, m_tabs.at(m_currentIndex).currentSubTab);
+ return;
}
+ }
+ } else if (hit.first == HITSUBTAB) {
+ if (m_tabs[m_currentIndex].currentSubTab != hit.second) {
+ m_tabs[m_currentIndex].currentSubTab = hit.second;
+ update();
+ // todo next two lines were outside the if leading to
+ // unecessary (?) signal emissions?
event->accept();
emit currentIndexChanged(m_currentIndex, m_tabs.at(m_currentIndex).currentSubTab);
return;
@@ -316,7 +378,7 @@ void DoubleTabWidget::paintEvent(QPaintEvent *event)
int indexSmallerThanWidth = -1;
for (int i = 0; i < m_tabs.size(); ++i) {
const Tab &tab = m_tabs.at(i);
- int w = fm.width(tab.name);
+ int w = fm.width(tab.displayName());
nameWidth << w;
width += 2 * MARGIN + w;
if (width < r.width())
@@ -380,7 +442,7 @@ void DoubleTabWidget::paintEvent(QPaintEvent *event)
painter.setPen(Utils::StyleHelper::borderColor());
painter.drawLine(x - 1, 0, x - 1, r.height() - 1);
painter.fillRect(QRect(x, 0,
- 2 * MARGIN + fm.width(tab.name),
+ 2 * MARGIN + fm.width(tab.displayName()),
r.height() + 1),
grad);
@@ -390,7 +452,7 @@ void DoubleTabWidget::paintEvent(QPaintEvent *event)
}
x += MARGIN;
painter.setPen(Qt::black);
- painter.drawText(x, baseline, tab.name);
+ painter.drawText(x, baseline, tab.displayName());
x += nameWidth.at(actualIndex);
x += MARGIN;
painter.setPen(Utils::StyleHelper::borderColor());
@@ -404,7 +466,7 @@ void DoubleTabWidget::paintEvent(QPaintEvent *event)
drawFirstLevelSeparator(&painter, QPoint(x, 0), QPoint(x, r.height()-1));
x += MARGIN;
painter.setPen(Utils::StyleHelper::panelTextColor());
- painter.drawText(x + 1, baseline, tab.name);
+ painter.drawText(x + 1, baseline, tab.displayName());
x += nameWidth.at(actualIndex);
x += MARGIN;
drawFirstLevelSeparator(&painter, QPoint(x, 0), QPoint(x, r.height()-1));
@@ -461,3 +523,16 @@ void DoubleTabWidget::changeEvent(QEvent *e)
break;
}
}
+
+bool DoubleTabWidget::event(QEvent *event)
+{
+ if (event->type() == QEvent::ToolTip) {
+ QHelpEvent *helpevent = static_cast<QHelpEvent*>(event);
+ QPair<HitArea, int> hit = convertPosToTab(helpevent->pos());
+ if (hit.first == HITTAB && m_tabs.at(m_currentTabIndices.at(hit.second)).nameIsUnique)
+ QToolTip::showText(helpevent->globalPos(), m_tabs.at(m_currentTabIndices.at(hit.second)).fullName, this);
+ else
+ QToolTip::showText(helpevent->globalPos(), "", this);
+ }
+ return QWidget::event(event);
+}
diff --git a/src/plugins/projectexplorer/doubletabwidget.h b/src/plugins/projectexplorer/doubletabwidget.h
index 86bdd2fc75..e834828960 100644
--- a/src/plugins/projectexplorer/doubletabwidget.h
+++ b/src/plugins/projectexplorer/doubletabwidget.h
@@ -54,8 +54,8 @@ public:
void setTitle(const QString &title);
QString title() const { return m_title; }
- void addTab(const QString &name, const QStringList &subTabs);
- void insertTab(int index, const QString &name, const QStringList &subTabs);
+ void addTab(const QString &name, const QString &fullName, const QStringList &subTabs);
+ void insertTab(int index, const QString &name, const QString &fullName, const QStringList &subTabs);
void removeTab(int index);
int tabCount() const;
@@ -71,14 +71,25 @@ protected:
void paintEvent(QPaintEvent *event);
void mousePressEvent(QMouseEvent *event);
void changeEvent(QEvent *e);
+ bool event(QEvent *event);
QSize minimumSizeHint() const;
private:
struct Tab {
QString name;
+ QString fullName;
+ bool nameIsUnique;
QStringList subTabs;
int currentSubTab;
+ QString displayName() const {
+ return nameIsUnique ? name : fullName;
+ }
};
+ void updateNameIsUniqueAdd(Tab *tab);
+ void updateNameIsUniqueRemove(const Tab &tab);
+
+ enum HitArea { HITNOTHING, HITOVERFLOW, HITTAB, HITSUBTAB };
+ QPair<DoubleTabWidget::HitArea, int> convertPosToTab(QPoint pos);
const QPixmap m_left;
const QPixmap m_mid;
diff --git a/src/plugins/projectexplorer/environmentwidget.cpp b/src/plugins/projectexplorer/environmentwidget.cpp
index 7b18243942..67d8df0c8e 100644
--- a/src/plugins/projectexplorer/environmentwidget.cpp
+++ b/src/plugins/projectexplorer/environmentwidget.cpp
@@ -146,6 +146,9 @@ EnvironmentWidget::EnvironmentWidget(QWidget *parent, QWidget *additionalDetails
connect(d->m_environmentView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
this, SLOT(environmentCurrentIndexChanged(QModelIndex)));
+ connect(d->m_detailsContainer, SIGNAL(linkActivated(QString)),
+ this, SLOT(linkActivated(QString)));
+
connect(d->m_model, SIGNAL(userChangesChanged()), this, SLOT(updateSummaryText()));
}
@@ -198,9 +201,9 @@ void EnvironmentWidget::updateSummaryText()
if (item.name != Utils::EnvironmentModel::tr("<VARIABLE>")) {
text.append("<br>");
if (item.unset)
- text.append(tr("Unset <b>%1</b>").arg(Qt::escape(item.name)));
+ text.append(tr("Unset <a href=\"%1\"><b>%1</b></a>").arg(Qt::escape(item.name)));
else
- text.append(tr("Set <b>%1</b> to <b>%2</b>").arg(Qt::escape(item.name), Qt::escape(item.value)));
+ text.append(tr("Set <a href=\"%1\"><b>%1</b></a> to <b>%2</b>").arg(Qt::escape(item.name), Qt::escape(item.value)));
}
}
@@ -212,6 +215,13 @@ void EnvironmentWidget::updateSummaryText()
d->m_detailsContainer->setSummaryText(text);
}
+void EnvironmentWidget::linkActivated(const QString &link)
+{
+ d->m_detailsContainer->setState(Utils::DetailsWidget::Expanded);
+ QModelIndex idx = d->m_model->variableToIndex(link);
+ focusIndex(idx);
+}
+
void EnvironmentWidget::updateButtons()
{
environmentCurrentIndexChanged(d->m_environmentView->currentIndex());
diff --git a/src/plugins/projectexplorer/environmentwidget.h b/src/plugins/projectexplorer/environmentwidget.h
index 721dff9e81..cd56c46ef2 100644
--- a/src/plugins/projectexplorer/environmentwidget.h
+++ b/src/plugins/projectexplorer/environmentwidget.h
@@ -74,6 +74,7 @@ private slots:
void updateSummaryText();
void focusIndex(const QModelIndex &index);
void updateButtons();
+ void linkActivated(const QString &link);
private:
QScopedPointer<EnvironmentWidgetPrivate> d;
diff --git a/src/plugins/projectexplorer/gccparser.cpp b/src/plugins/projectexplorer/gccparser.cpp
index 7e014657c2..8b8da2bb38 100644
--- a/src/plugins/projectexplorer/gccparser.cpp
+++ b/src/plugins/projectexplorer/gccparser.cpp
@@ -622,6 +622,21 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
Constants::TASK_CATEGORY_COMPILE))
<< QString();
+ QTest::newRow("enumeration warning")
+ << QString::fromLatin1("../../../src/shared/proparser/profileevaluator.cpp: In member function ‘ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateConditionalFunction(const ProString&, const ProStringList&)’:\n"
+ "../../../src/shared/proparser/profileevaluator.cpp:2817:9: warning: case value ‘0’ not in enumerated type ‘ProFileEvaluator::Private::TestFunc’")
+ << OutputParserTester::STDERR
+ << QString() << QString()
+ << ( QList<ProjectExplorer::Task>()
+ << Task(Task::Unknown,
+ QLatin1String("In member function ‘ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateConditionalFunction(const ProString&, const ProStringList&)’:"),
+ QLatin1String("../../../src/shared/proparser/profileevaluator.cpp"), -1,
+ Constants::TASK_CATEGORY_COMPILE)
+ << Task(Task::Warning,
+ QLatin1String("case value ‘0’ not in enumerated type ‘ProFileEvaluator::Private::TestFunc’"),
+ QLatin1String("../../../src/shared/proparser/profileevaluator.cpp"), 2817,
+ Constants::TASK_CATEGORY_COMPILE))
+ << QString();
}
void ProjectExplorerPlugin::testGccOutputParsers()
diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp
index 1e755b15ab..84058b072a 100644
--- a/src/plugins/projectexplorer/gcctoolchain.cpp
+++ b/src/plugins/projectexplorer/gcctoolchain.cpp
@@ -181,7 +181,8 @@ static QList<ProjectExplorer::Abi> guessGccAbi(const QString &m)
foreach (const QString &p, parts) {
if (p == QLatin1String("unknown") || p == QLatin1String("pc") || p == QLatin1String("none")
- || p == QLatin1String("gnu") || p == QLatin1String("86_64")) {
+ || p == QLatin1String("gnu") || p == QLatin1String("uclibc")
+ || p == QLatin1String("86_64")) {
continue;
} else if (p == QLatin1String("i386") || p == QLatin1String("i486") || p == QLatin1String("i586")
|| p == QLatin1String("i686") || p == QLatin1String("x86")) {
@@ -190,6 +191,9 @@ static QList<ProjectExplorer::Abi> guessGccAbi(const QString &m)
} else if (p == QLatin1String("arm")) {
arch = ProjectExplorer::Abi::ArmArchitecture;
width = 32;
+ } else if (p == QLatin1String("mipsel")) {
+ arch = ProjectExplorer::Abi::MipsArcitecture;
+ width = 32;
} else if (p == QLatin1String("x86_64")) {
arch = ProjectExplorer::Abi::X86Architecture;
width = 64;
@@ -231,7 +235,7 @@ static QList<ProjectExplorer::Abi> guessGccAbi(const QString &m)
if (unknownCount == parts.count())
return abiList;
- if (os == Abi::MacOS) {
+ if (os == Abi::MacOS && arch != Abi::ArmArchitecture) {
// Apple does PPC and x86!
abiList << ProjectExplorer::Abi(arch, os, flavor, format, width);
abiList << ProjectExplorer::Abi(arch, os, flavor, format, width == 64 ? 32 : 64);
@@ -567,14 +571,14 @@ Internal::GccToolChainConfigWidget::GccToolChainConfigWidget(GccToolChain *tc) :
connect(m_compilerPath, SIGNAL(changed(QString)), this, SLOT(handlePathChange()));
layout->addRow(tr("&Compiler path:"), m_compilerPath);
+ addDebuggerCommandControls(layout, gnuVersionArgs);
+ addErrorLabel(layout);
+
populateAbiList(tc->supportedAbis());
layout->addRow(tr("&ABI:"), m_abiComboBox);
connect(m_abiComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(handleAbiChange()));
- addDebuggerCommandControls(layout, gnuVersionArgs);
- addErrorLabel(layout);
-
setFromToolchain();
}
@@ -632,6 +636,13 @@ bool Internal::GccToolChainConfigWidget::isDirty() const
|| m_abiList.at(m_abiComboBox->currentIndex()) != tc->targetAbi();
}
+void Internal::GccToolChainConfigWidget::makeReadOnly()
+{
+ m_compilerPath->setEnabled(false);
+ m_abiComboBox->setEnabled(false);
+ ToolChainConfigWidget::makeReadOnly();
+}
+
void Internal::GccToolChainConfigWidget::handlePathChange()
{
QString path = m_compilerPath->path();
@@ -837,6 +848,9 @@ void ProjectExplorerPlugin::testGccAbiGuessing_data()
<< QString::fromLatin1("x86_64-linux-gnu")
<< (QStringList() << QLatin1String("x86-linux-generic-elf-64bit")
<< QLatin1String("x86-linux-generic-elf-32bit"));
+ QTest::newRow("Linux 4")
+ << QString::fromLatin1("mipsel-linux-uclibc")
+ << (QStringList() << QLatin1String("mips-linux-generic-elf-32bit"));
QTest::newRow("Mingw 1")
<< QString::fromLatin1("i686-w64-mingw32")
<< (QStringList() << QLatin1String("x86-windows-msys-pe-64bit")
@@ -862,6 +876,9 @@ void ProjectExplorerPlugin::testGccAbiGuessing_data()
<< QLatin1String("x86-macos-generic-mach_o-64bit")
<< QLatin1String("ppc-macos-generic-mach_o-32bit")
<< QLatin1String("ppc-macos-generic-mach_o-64bit"));
+ QTest::newRow("Mac IOS")
+ << QString::fromLatin1("arm-apple-darwin9")
+ << (QStringList() << QLatin1String("arm-macos-generic-mach_o-32bit"));
QTest::newRow("Intel 1")
<< QString::fromLatin1("86_64 x86_64 GNU/Linux")
<< (QStringList() << QLatin1String("x86-linux-generic-elf-64bit")
diff --git a/src/plugins/projectexplorer/gcctoolchainfactories.h b/src/plugins/projectexplorer/gcctoolchainfactories.h
index 6cc3b84c8d..cf703fb96a 100644
--- a/src/plugins/projectexplorer/gcctoolchainfactories.h
+++ b/src/plugins/projectexplorer/gcctoolchainfactories.h
@@ -90,6 +90,7 @@ public:
void apply();
void discard() { setFromToolchain(); }
bool isDirty() const;
+ void makeReadOnly();
private slots:
void handlePathChange();
diff --git a/src/plugins/projectexplorer/iprojectmanager.h b/src/plugins/projectexplorer/iprojectmanager.h
index 76989f2893..fe461679ad 100644
--- a/src/plugins/projectexplorer/iprojectmanager.h
+++ b/src/plugins/projectexplorer/iprojectmanager.h
@@ -52,9 +52,6 @@ class PROJECTEXPLORER_EXPORT IProjectManager
public:
IProjectManager() {}
- virtual Core::Context projectContext() const = 0; //TODO move into project
- virtual Core::Context projectLanguage() const = 0; //TODO move into project
-
virtual QString mimeType() const = 0;
virtual Project *openProject(const QString &fileName) = 0;
};
diff --git a/src/plugins/projectexplorer/localapplicationruncontrol.cpp b/src/plugins/projectexplorer/localapplicationruncontrol.cpp
index 201b579d10..637070269c 100644
--- a/src/plugins/projectexplorer/localapplicationruncontrol.cpp
+++ b/src/plugins/projectexplorer/localapplicationruncontrol.cpp
@@ -106,7 +106,7 @@ void LocalApplicationRunControl::start()
m_applicationLauncher.start(m_runMode, m_executable, m_commandLineArguments);
emit started();
- QString msg = tr("Starting %1...").arg(QDir::toNativeSeparators(m_executable));
+ QString msg = tr("Starting %1...\n").arg(QDir::toNativeSeparators(m_executable));
appendMessage(msg, NormalMessageFormat);
}
@@ -121,6 +121,11 @@ bool LocalApplicationRunControl::isRunning() const
return m_applicationLauncher.isRunning();
}
+QIcon LocalApplicationRunControl::icon() const
+{
+ return QIcon(ProjectExplorer::Constants::ICON_RUN_SMALL);
+}
+
void LocalApplicationRunControl::slotAppendMessage(const QString &err,
OutputFormat format)
{
@@ -129,7 +134,7 @@ void LocalApplicationRunControl::slotAppendMessage(const QString &err,
void LocalApplicationRunControl::processExited(int exitCode)
{
- QString msg = tr("%1 exited with code %2")
+ QString msg = tr("%1 exited with code %2\n")
.arg(QDir::toNativeSeparators(m_executable)).arg(exitCode);
appendMessage(msg, NormalMessageFormat);
emit finished();
diff --git a/src/plugins/projectexplorer/localapplicationruncontrol.h b/src/plugins/projectexplorer/localapplicationruncontrol.h
index f505f158b4..26520957f3 100644
--- a/src/plugins/projectexplorer/localapplicationruncontrol.h
+++ b/src/plugins/projectexplorer/localapplicationruncontrol.h
@@ -62,6 +62,7 @@ public:
virtual void start();
virtual StopResult stop();
virtual bool isRunning() const;
+ virtual QIcon icon() const;
private slots:
void processExited(int exitCode);
void slotAppendMessage(const QString &err, ProjectExplorer::OutputFormat isError);
diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.cpp b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
index 05e107b4a2..3f07bec0c9 100644
--- a/src/plugins/projectexplorer/miniprojecttargetselector.cpp
+++ b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
@@ -39,6 +39,7 @@
#include <utils/styledbar.h>
#include <utils/stylehelper.h>
+#include <coreplugin/ifile.h>
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
@@ -397,7 +398,8 @@ MiniProjectTargetSelector::MiniProjectTargetSelector(QAction *targetSelectorActi
m_projectsBox->setFixedHeight(panelHeight);
m_projectsBox->setProperty("hideborder", true);
m_projectsBox->setObjectName(QString::fromUtf8("ProjectsBox"));
- m_projectsBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
+ m_projectsBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ m_projectsBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
toolLayout->addWidget(lbl);
toolLayout->addWidget(new Utils::StyledSeparator);
@@ -443,7 +445,12 @@ void MiniProjectTargetSelector::mousePressEvent(QMouseEvent *e)
QWidget::mousePressEvent(e);
}
-void MiniProjectTargetSelector::addProject(ProjectExplorer::Project* project)
+QString MiniProjectTargetSelector::fullName(ProjectExplorer::Project *project)
+{
+ return project->displayName() + " (" + project->file()->fileName() + ")";
+}
+
+void MiniProjectTargetSelector::addProject(ProjectExplorer::Project *project)
{
QTC_ASSERT(project, return);
ProjectListWidget *targetList = new ProjectListWidget(project);
@@ -452,14 +459,28 @@ void MiniProjectTargetSelector::addProject(ProjectExplorer::Project* project)
m_ignoreIndexChange = true;
+ QString sortName = fullName(project);
int pos = 0;
- for (int i=0; i < m_projectsBox->count(); ++i)
- if (m_projectsBox->itemText(i) > project->displayName())
+ for (int i=0; i < m_projectsBox->count(); ++i) {
+ Project *p = m_projectsBox->itemData(i).value<Project*>();
+ QString itemSortName = fullName(p);
+ if (itemSortName > sortName)
pos = i;
+ }
m_widgetStack->insertWidget(pos, targetList);
- m_projectsBox->insertItem(pos, project->displayName(), QVariant::fromValue(project));
+ bool useFullName = false;
+ for (int i = 0; i < m_projectsBox->count(); ++i) {
+ Project *p = m_projectsBox->itemData(i).value<Project*>();
+ if (p->displayName() == project->displayName()) {
+ useFullName = true;
+ m_projectsBox->setItemText(i, fullName(p));
+ }
+ }
+
+ QString displayName = useFullName ? fullName(project) : project->displayName();
+ m_projectsBox->insertItem(pos, displayName, QVariant::fromValue(project));
connect(project, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
SLOT(updateAction()));
@@ -482,6 +503,7 @@ void MiniProjectTargetSelector::addProject(ProjectExplorer::Project* project)
addTarget(t, t == project->activeTarget());
m_projectsBox->setEnabled(m_projectsBox->count() > 1);
+ m_projectsBox->parentWidget()->layout()->activate();
}
void MiniProjectTargetSelector::removeProject(ProjectExplorer::Project* project)
@@ -497,7 +519,25 @@ void MiniProjectTargetSelector::removeProject(ProjectExplorer::Project* project)
m_projectsBox->removeItem(index);
m_projectsBox->setEnabled(m_projectsBox->count() > 1);
delete plw;
+
+ // Update display names
+ QString name = project->displayName();
+ int count = 0;
+ int otherIndex;
+ for (int i = 0; i < m_projectsBox->count(); ++i) {
+ Project *p = m_projectsBox->itemData(i).value<Project*>();
+ if (p->displayName() == name) {
+ ++count;
+ otherIndex = i;
+ }
+ }
+ if (count == 1) {
+ Project *p = m_projectsBox->itemData(otherIndex).value<Project*>();
+ m_projectsBox->setItemText(otherIndex, p->displayName());
+ }
+
m_ignoreIndexChange = false;
+ m_projectsBox->parentWidget()->layout()->activate();
}
void MiniProjectTargetSelector::addTarget(ProjectExplorer::Target *target, bool activeTarget)
diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.h b/src/plugins/projectexplorer/miniprojecttargetselector.h
index 554761db91..c2b47a9739 100644
--- a/src/plugins/projectexplorer/miniprojecttargetselector.h
+++ b/src/plugins/projectexplorer/miniprojecttargetselector.h
@@ -135,6 +135,7 @@ private slots:
void mousePressEvent(QMouseEvent *);
private:
+ QString fullName(ProjectExplorer::Project *project);
int indexFor(ProjectExplorer::Project *project) const;
QAction *m_projectAction;
diff --git a/src/plugins/projectexplorer/outputwindow.cpp b/src/plugins/projectexplorer/outputwindow.cpp
index e24dd0ae73..24b6c6514c 100644
--- a/src/plugins/projectexplorer/outputwindow.cpp
+++ b/src/plugins/projectexplorer/outputwindow.cpp
@@ -87,11 +87,8 @@ OutputPane::OutputPane() :
m_reRunButton(new QToolButton),
m_stopButton(new QToolButton)
{
- m_runIcon.addFile(Constants::ICON_RUN);
- m_runIcon.addFile(Constants::ICON_RUN_SMALL);
-
// Rerun
- m_reRunButton->setIcon(m_runIcon);
+ m_reRunButton->setIcon(QIcon(ProjectExplorer::Constants::ICON_RUN_SMALL));
m_reRunButton->setToolTip(tr("Re-run this run-configuration"));
m_reRunButton->setAutoRaise(true);
m_reRunButton->setEnabled(false);
@@ -395,7 +392,7 @@ void OutputPane::tabChanged(int i)
RunControl *rc = m_runControlTabs.at(index).runControl;
m_stopAction->setEnabled(rc->isRunning());
m_reRunButton->setEnabled(!rc->isRunning());
- m_reRunButton->setIcon(m_runIcon);
+ m_reRunButton->setIcon(rc->icon());
}
}
@@ -405,7 +402,7 @@ void OutputPane::runControlStarted()
if (current && current == sender()) {
m_reRunButton->setEnabled(false);
m_stopAction->setEnabled(true);
- m_reRunButton->setIcon(m_runIcon);
+ m_reRunButton->setIcon(current->icon());
}
}
@@ -426,7 +423,7 @@ void OutputPane::runControlFinished()
if (current && current == sender()) {
m_reRunButton->setEnabled(true);
m_stopAction->setEnabled(false);
- m_reRunButton->setIcon(m_runIcon);
+ m_reRunButton->setIcon(current->icon());
}
// Check for asynchronous close. Close the tab.
if (m_runControlTabs.at(senderIndex).asyncClosing)
@@ -487,9 +484,12 @@ OutputWindow::OutputWindow(QWidget *parent)
setWordWrapMode(QTextOption::NoWrap);
static uint usedIds = 0;
- Core::ICore *core = Core::ICore::instance();
Core::Context context(Constants::C_APP_OUTPUT, usedIds++);
- m_outputWindowContext = new Core::BaseContext(this, context);
+ Core::ICore *core = Core::ICore::instance();
+
+ m_outputWindowContext = new Core::IContext;
+ m_outputWindowContext->setContext(context);
+ m_outputWindowContext->setWidget(this);
core->addContextObject(m_outputWindowContext);
QAction *undoAction = new QAction(this);
@@ -614,13 +614,15 @@ QString OutputWindow::doNewlineEnfocement(const QString &out)
{
m_scrollToBottom = true;
QString s = out;
- if (m_enforceNewline)
+ if (m_enforceNewline) {
s.prepend(QLatin1Char('\n'));
+ m_enforceNewline = false;
+ }
- m_enforceNewline = true; // make appendOutputInline put in a newline next time
-
- if (s.endsWith(QLatin1Char('\n')))
+ if (s.endsWith(QLatin1Char('\n'))) {
+ m_enforceNewline = true; // make appendOutputInline put in a newline next time
s.chop(1);
+ }
return s;
}
diff --git a/src/plugins/projectexplorer/outputwindow.h b/src/plugins/projectexplorer/outputwindow.h
index 4d5f5d936d..2a7845e2f2 100644
--- a/src/plugins/projectexplorer/outputwindow.h
+++ b/src/plugins/projectexplorer/outputwindow.h
@@ -46,7 +46,7 @@ class QAction;
QT_END_NAMESPACE
namespace Core {
- class BaseContext;
+ class IContext;
}
namespace ProjectExplorer {
@@ -145,7 +145,6 @@ private:
QAction *m_stopAction;
QToolButton *m_reRunButton;
QToolButton *m_stopButton;
- QIcon m_runIcon;
};
@@ -189,7 +188,7 @@ private:
void enableUndoRedo();
QString doNewlineEnfocement(const QString &out);
- Core::BaseContext *m_outputWindowContext;
+ Core::IContext *m_outputWindowContext;
OutputFormatter *m_formatter;
bool m_enforceNewline;
diff --git a/src/plugins/projectexplorer/persistentsettings.cpp b/src/plugins/projectexplorer/persistentsettings.cpp
index 2981ef28db..9516dfa2fc 100644
--- a/src/plugins/projectexplorer/persistentsettings.cpp
+++ b/src/plugins/projectexplorer/persistentsettings.cpp
@@ -32,184 +32,375 @@
#include "persistentsettings.h"
+#include <coreplugin/coreconstants.h>
+
#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QVariant>
-#include <QtXml/QDomDocument>
-#include <QtXml/QDomCDATASection>
-#include <QtXml/QDomElement>
+#include <QtCore/QStack>
+#include <QtCore/QXmlStreamAttributes>
+#include <QtCore/QXmlStreamReader>
+#include <QtCore/QXmlStreamWriter>
+#include <QtCore/QDateTime>
+
+#include <utils/qtcassert.h>
+
+/*!
+ \class ProjectExplorer::PersistentSettingsReader
+
+ \brief Reads a QVariantMap of arbitrary, nested data structures from a XML file.
+
+ Handles all string-serializable simple types and QVariantList and QVariantMap. Example:
+ \code
+<qtcreator>
+ <data>
+ <variable>ProjectExplorer.Project.ActiveTarget</variable>
+ <value type="int">0</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.EditorSettings</variable>
+ <valuemap type="QVariantMap">
+ <value type="bool" key="EditorConfiguration.AutoIndent">true</value>
+ </valuemap>
+ </data>
+ \endcode
+
+ When parsing the structure, a parse stack of ParseValueStackEntry is used for each
+ <data> element. ParseValueStackEntry is a variant/union of:
+ \list
+ \o simple value
+ \o map
+ \o list
+ \endlist
+
+ When entering a value element ( \c <value> / \c <valuelist> , \c <valuemap> ), entry is pushed
+ accordingly. When leaving the element, the QVariant-value of the entry is taken off the stack
+ and added to the stack entry below (added to list or inserted into map). The first element
+ of the stack is the value of the <data> element.
+
+ \sa ProjectExplorer::PersistentSettingsWriter
+*/
+
+namespace ProjectExplorer {
+
+struct Context // Basic context containing element name string constants.
+{
+ Context();
+
+ const QString qtCreatorElement;
+ const QString dataElement;
+ const QString variableElement;
+ const QString typeAttribute;
+ const QString valueElement;
+ const QString valueListElement;
+ const QString valueMapElement;
+ const QString keyAttribute;
+};
+
+Context::Context() :
+ qtCreatorElement(QLatin1String("qtcreator")),
+ dataElement(QLatin1String("data")),
+ variableElement(QLatin1String("variable")),
+ typeAttribute(QLatin1String("type")),
+ valueElement(QLatin1String("value")),
+ valueListElement(QLatin1String("valuelist")),
+ valueMapElement(QLatin1String("valuemap")),
+ keyAttribute(QLatin1String("key"))
+{
+}
+
+struct ParseValueStackEntry
+{
+ explicit ParseValueStackEntry(QVariant::Type t = QVariant::Invalid, const QString &k = QString()) : type(t), key(k) {}
+ explicit ParseValueStackEntry(const QVariant &aSimpleValue, const QString &k);
+ QVariant value() const;
+ void addChild(const QString &key, const QVariant &v);
-using namespace ProjectExplorer;
+ QVariant::Type type;
+ QString key;
+ QVariant simpleValue;
+ QVariantList listValue;
+ QVariantMap mapValue;
+};
-PersistentSettingsReader::PersistentSettingsReader()
+ParseValueStackEntry::ParseValueStackEntry(const QVariant &aSimpleValue, const QString &k) :
+ type(aSimpleValue.type()), key(k), simpleValue(aSimpleValue)
{
-
+ QTC_ASSERT(simpleValue.isValid(), return ; )
}
-QVariant PersistentSettingsReader::restoreValue(const QString & variable) const
+QVariant ParseValueStackEntry::value() const
{
- if (m_valueMap.contains(variable))
- return m_valueMap.value(variable);
- return QVariant();
+ switch (type) {
+ case QVariant::Invalid:
+ return QVariant();
+ case QVariant::Map:
+ return QVariant(mapValue);
+ case QVariant::List:
+ return QVariant(listValue);
+ default:
+ break;
+ }
+ return simpleValue;
}
-QVariantMap PersistentSettingsReader::restoreValues() const
+void ParseValueStackEntry::addChild(const QString &key, const QVariant &v)
{
- return m_valueMap;
+ switch (type) {
+ case QVariant::Map:
+ mapValue.insert(key, v);
+ break;
+ case QVariant::List:
+ listValue.push_back(v);
+ break;
+ default:
+ qWarning() << "ParseValueStackEntry::Internal error adding " << key << v << " to "
+ << QVariant::typeToName(type) << value();
+ break;
+ }
}
-bool PersistentSettingsReader::load(const QString & fileName)
+class ParseContext : public Context
{
- m_valueMap.clear();
+public:
+ QVariantMap parse(QFile &file);
- QFile file(fileName);
- if (!file.open(QIODevice::ReadOnly))
- return false;
+private:
+ enum Element { QtCreatorElement, DataElement, VariableElement,
+ SimpleValueElement, ListValueElement, MapValueElement, UnknownElement };
- QDomDocument doc;
- if (!doc.setContent(&file))
- return false;
+ Element element(const QStringRef &r) const;
+ static inline bool isValueElement(Element e)
+ { return e == SimpleValueElement || e == ListValueElement || e == MapValueElement; }
+ QVariant readSimpleValue(QXmlStreamReader &r, const QXmlStreamAttributes &attributes) const;
- QDomElement root = doc.documentElement();
- if (root.nodeName() != QLatin1String("qtcreator"))
- return false;
+ bool handleStartElement(QXmlStreamReader &r);
+ bool handleEndElement(const QStringRef &name);
- QDomElement child = root.firstChildElement();
- for (; !child.isNull(); child = child.nextSiblingElement()) {
- if (child.nodeName() == QLatin1String("data"))
- readValues(child);
- }
+ QStack<ParseValueStackEntry> m_valueStack;
+ QVariantMap m_result;
+ QString m_currentVariableName;
+};
- file.close();
- return true;
+QVariantMap ParseContext::parse(QFile &file)
+{
+ QXmlStreamReader r(&file);
+
+ m_result.clear();
+ m_currentVariableName.clear();
+
+ while (!r.atEnd()) {
+ switch (r.readNext()) {
+ case QXmlStreamReader::StartElement:
+ if (handleStartElement(r))
+ return m_result;
+ break;
+ case QXmlStreamReader::EndElement:
+ if (handleEndElement(r.name()))
+ return m_result;
+ break;
+ case QXmlStreamReader::Invalid:
+ qWarning("Error reading %s:%d: %s", qPrintable(file.fileName()),
+ int(r.lineNumber()), qPrintable(r.errorString()));
+ return QVariantMap();
+ break;
+ default:
+ break;
+ } // switch token
+ } // while (!r.atEnd())
+ return m_result;
}
-QVariant PersistentSettingsReader::readValue(const QDomElement &valElement) const
+bool ParseContext::handleStartElement(QXmlStreamReader &r)
{
- QString name = valElement.nodeName();
- QString type = valElement.attribute(QLatin1String("type"));
- QVariant v;
+ const QStringRef name = r.name();
+ const Element e = element(name);
+ if (e == VariableElement) {
+ m_currentVariableName = r.readElementText();
+ return false;
+ }
+ if (!ParseContext::isValueElement(e))
+ return false;
- if (name == QLatin1String("value")) {
- if(type == QLatin1String("QChar")) {
- //Workaround: QTBUG-12345
- v.setValue(QChar(valElement.text().at(0)));
- } else {
- v.setValue(valElement.text());
- v.convert(QVariant::nameToType(type.toLatin1().data()));
- }
- } else if (name == QLatin1String("valuelist")) {
- QDomElement child = valElement.firstChildElement();
- QList<QVariant> valList;
- for (; !child.isNull(); child = child.nextSiblingElement()) {
- valList << readValue(child);
- }
- v.setValue(valList);
- } else if (name == QLatin1String("valuemap")) {
- QDomElement child = valElement.firstChildElement();
- QMap<QString, QVariant> valMap;
- for (; !child.isNull(); child = child.nextSiblingElement()) {
- QString key = child.attribute(QLatin1String("key"));
- valMap.insert(key, readValue(child));
- }
- v.setValue(valMap);
+ const QXmlStreamAttributes attributes = r.attributes();
+ const QString key = attributes.hasAttribute(keyAttribute) ?
+ attributes.value(keyAttribute).toString() : QString();
+ switch (e) {
+ case SimpleValueElement:
+ // This reads away the end element, so, handle end element right here.
+ m_valueStack.push_back(ParseValueStackEntry(readSimpleValue(r, attributes), key));
+ return handleEndElement(name);
+ case ListValueElement:
+ m_valueStack.push_back(ParseValueStackEntry(QVariant::List, key));
+ break;
+ case MapValueElement:
+ m_valueStack.push_back(ParseValueStackEntry(QVariant::Map, key));
+ break;
+ default:
+ break;
}
+ return false;
+}
- return v;
+bool ParseContext::handleEndElement(const QStringRef &name)
+{
+ const Element e = element(name);
+ if (ParseContext::isValueElement(e)) {
+ QTC_ASSERT(!m_valueStack.isEmpty(), return true; )
+ const ParseValueStackEntry top = m_valueStack.pop();
+ if (m_valueStack.isEmpty()) { // Last element? -> Done with that variable.
+ QTC_ASSERT(!m_currentVariableName.isEmpty(), return true; )
+ m_result.insert(m_currentVariableName, top.value());
+ m_currentVariableName.clear();
+ return false;
+ }
+ m_valueStack.top().addChild(top.key, top.value());
+ }
+ return e == QtCreatorElement;
}
-void PersistentSettingsReader::readValues(const QDomElement &data)
+ParseContext::Element ParseContext::element(const QStringRef &r) const
{
- QString variable;
- QVariant v;
+ if (r == valueElement)
+ return SimpleValueElement;
+ if (r == valueListElement)
+ return ListValueElement;
+ if (r == valueMapElement)
+ return MapValueElement;
+ if (r == qtCreatorElement)
+ return QtCreatorElement;
+ if (r == dataElement)
+ return DataElement;
+ if (r == variableElement)
+ return VariableElement;
+ return UnknownElement;
+}
- QDomElement child = data.firstChildElement();
- for (; !child.isNull(); child = child.nextSiblingElement()) {
- if (child.nodeName() == QLatin1String("variable")) {
- variable = child.text();
- } else {
- v = readValue(child);
- }
+QVariant ParseContext::readSimpleValue(QXmlStreamReader &r, const QXmlStreamAttributes &attributes) const
+{
+ // Simple value
+ const QString type = attributes.value(typeAttribute).toString();
+ const QString text = r.readElementText();
+ if (type == QLatin1String("QChar")) { // Workaround: QTBUG-12345
+ QTC_ASSERT(text.size() == 1, return QVariant(); )
+ return QVariant(QChar(text.at(0)));
}
+ QVariant value;
+ value.setValue(text);
+ value.convert(QVariant::nameToType(type.toLatin1().data()));
+ return value;
+}
- m_valueMap.insert(variable, v);
+// =================================== PersistentSettingsReader
+
+PersistentSettingsReader::PersistentSettingsReader()
+{
}
-///
-/// PersistentSettingsWriter
-///
+QVariant PersistentSettingsReader::restoreValue(const QString & variable) const
+{
+ if (m_valueMap.contains(variable))
+ return m_valueMap.value(variable);
+ return QVariant();
+}
-PersistentSettingsWriter::PersistentSettingsWriter()
+QVariantMap PersistentSettingsReader::restoreValues() const
{
+ return m_valueMap;
+}
+bool PersistentSettingsReader::load(const QString & fileName)
+{
+ m_valueMap.clear();
+
+ QFile file(fileName);
+ if (!file.open(QIODevice::ReadOnly|QIODevice::Text))
+ return false;
+ ParseContext ctx;
+ m_valueMap = ctx.parse(file);
+ file.close();
+ return true;
}
-void PersistentSettingsWriter::writeValue(QDomElement &ps, const QVariant &variant)
+/*!
+ \class ProjectExplorer::PersistentSettingsWriter
+
+ \brief Serializes a QVariantMap of arbitrary, nested data structures to a XML file.
+ \sa ProjectExplorer::PersistentSettingsReader
+*/
+
+PersistentSettingsWriter::PersistentSettingsWriter()
{
- if (variant.type() == QVariant::StringList || variant.type() == QVariant::List) {
- QDomElement values = ps.ownerDocument().createElement("valuelist");
- values.setAttribute("type", QVariant::typeToName(QVariant::List));
- QList<QVariant> varList = variant.toList();
- foreach (const QVariant &var, varList) {
- writeValue(values, var);
- }
- ps.appendChild(values);
- } else if (variant.type() == QVariant::Map) {
- QDomElement values = ps.ownerDocument().createElement("valuemap");
- values.setAttribute("type", QVariant::typeToName(QVariant::Map));
-
- QMap<QString, QVariant> varMap = variant.toMap();
- QMap<QString, QVariant>::const_iterator i = varMap.constBegin();
- while (i != varMap.constEnd()) {
- writeValue(values, i.value());
- values.lastChild().toElement().
- setAttribute(QLatin1String("key"), i.key());
- ++i;
- }
+}
- ps.appendChild(values);
- } else {
- QDomElement value = ps.ownerDocument().createElement("value");
- ps.appendChild(value);
- QDomText valueText = ps.ownerDocument().createTextNode(variant.toString());
- value.appendChild(valueText);
- value.setAttribute("type", variant.typeName());
- ps.appendChild(value);
+static void writeVariantValue(QXmlStreamWriter &w, const Context &ctx,
+ const QVariant &variant, const QString &key = QString())
+{
+ switch (variant.type()) {
+ case QVariant::StringList:
+ case QVariant::List:
+ w.writeStartElement(ctx.valueListElement);
+ w.writeAttribute(ctx.typeAttribute, QVariant::typeToName(QVariant::List));
+ if (!key.isEmpty())
+ w.writeAttribute(ctx.keyAttribute, key);
+ foreach (const QVariant &var, variant.toList())
+ writeVariantValue(w, ctx, var);
+ w.writeEndElement();
+ break;
+ case QVariant::Map: {
+ w.writeStartElement(ctx.valueMapElement);
+ w.writeAttribute(ctx.typeAttribute, QVariant::typeToName(QVariant::Map));
+ if (!key.isEmpty())
+ w.writeAttribute(ctx.keyAttribute, key);
+ const QVariantMap varMap = variant.toMap();
+ const QVariantMap::const_iterator cend = varMap.constEnd();
+ for (QVariantMap::const_iterator i = varMap.constBegin(); i != cend; ++i)
+ writeVariantValue(w, ctx, i.value(), i.key());
+ w.writeEndElement();
+ }
+ break;
+ default:
+ w.writeStartElement(ctx.valueElement);
+ w.writeAttribute(ctx.typeAttribute, QLatin1String(variant.typeName()));
+ if (!key.isEmpty())
+ w.writeAttribute(ctx.keyAttribute, key);
+ w.writeCharacters(variant.toString());
+ w.writeEndElement();
+ break;
}
}
void PersistentSettingsWriter::saveValue(const QString & variable, const QVariant &value)
{
- m_valueMap[variable] = value;
+ m_valueMap.insert(variable, value);
}
-bool PersistentSettingsWriter::save(const QString & fileName, const QString & docType)
+bool PersistentSettingsWriter::save(const QString & fileName, const QString &docType) const
{
QFile file(fileName);
- if (!file.open(QIODevice::WriteOnly))
+ if (!file.open(QIODevice::WriteOnly|QIODevice::Text))
return false;
- QDomDocument doc(docType);
-
- QDomElement root = doc.createElement("qtcreator");
- doc.appendChild(root);
-
- QMap<QString, QVariant>::const_iterator i = m_valueMap.constBegin();
- while (i != m_valueMap.constEnd()) {
- QDomElement ps = doc.createElement("data");
- root.appendChild(ps);
-
- QDomElement variable = doc.createElement("variable");
- ps.appendChild(variable);
- QDomText variableText = doc.createTextNode(i.key());
- variable.appendChild(variableText);
-
- writeValue(ps, i.value());
- ++i;
+ const Context ctx;
+ QXmlStreamWriter w(&file);
+ w.setAutoFormatting(true);
+ w.setAutoFormattingIndent(1); // Historical, used to be QDom.
+ w.writeStartDocument();
+ w.writeDTD(QLatin1String("<!DOCTYPE ") + docType + QLatin1Char('>'));
+ w.writeComment(QString::fromAscii(" Written by Qt Creator %1, %2. ").
+ arg(QLatin1String(Core::Constants::IDE_VERSION_LONG),
+ QDateTime::currentDateTime().toString(Qt::ISODate)));
+ w.writeStartElement(ctx.qtCreatorElement);
+ const QVariantMap::const_iterator cend = m_valueMap.constEnd();
+ for (QVariantMap::const_iterator it = m_valueMap.constBegin(); it != cend; ++it) {
+ w.writeStartElement(ctx.dataElement);
+ w.writeTextElement(ctx.variableElement, it.key());
+ writeVariantValue(w, ctx, it.value());
+ w.writeEndElement();
}
-
- file.write(doc.toByteArray());
+ w.writeEndDocument();
file.close();
return true;
}
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/persistentsettings.h b/src/plugins/projectexplorer/persistentsettings.h
index 855d82f165..daf65e7ed4 100644
--- a/src/plugins/projectexplorer/persistentsettings.h
+++ b/src/plugins/projectexplorer/persistentsettings.h
@@ -38,10 +38,6 @@
#include <QtCore/QMap>
#include <QtCore/QVariant>
-QT_BEGIN_NAMESPACE
-class QDomElement;
-QT_END_NAMESPACE
-
namespace ProjectExplorer {
class PROJECTEXPLORER_EXPORT PersistentSettingsReader
@@ -53,8 +49,6 @@ public:
bool load(const QString & fileName);
private:
- QVariant readValue(const QDomElement &valElement) const;
- void readValues(const QDomElement &data);
QMap<QString, QVariant> m_valueMap;
};
@@ -63,10 +57,9 @@ class PROJECTEXPLORER_EXPORT PersistentSettingsWriter
public:
PersistentSettingsWriter();
void saveValue(const QString & variable, const QVariant &value);
- bool save(const QString & fileName, const QString & docType);
+ bool save(const QString & fileName, const QString & docType) const;
private:
- void writeValue(QDomElement &ps, const QVariant &value);
QMap<QString, QVariant> m_valueMap;
};
diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp
index 9ff6481b16..a9344b164d 100644
--- a/src/plugins/projectexplorer/project.cpp
+++ b/src/plugins/projectexplorer/project.cpp
@@ -41,6 +41,7 @@
#include "userfileaccessor.h"
#include <coreplugin/ifile.h>
+#include <coreplugin/icontext.h>
#include <extensionsystem/pluginmanager.h>
#include <limits>
#include <utils/qtcassert.h>
@@ -59,12 +60,15 @@ namespace ProjectExplorer {
// Project
// -------------------------------------------------------------------------
-class ProjectPrivate {
+class ProjectPrivate
+{
public:
ProjectPrivate();
QList<Target *> m_targets;
Target *m_activeTarget;
EditorConfiguration *m_editorConfiguration;
+ Core::Context m_projectContext;
+ Core::Context m_projectLanguage;
};
ProjectPrivate::ProjectPrivate() :
@@ -300,4 +304,24 @@ QString Project::generatedUiHeader(const QString & /* formFile */) const
return QString();
}
+void Project::setProjectContext(Core::Context context)
+{
+ d->m_projectContext = context;
+}
+
+void Project::setProjectLanguage(Core::Context language)
+{
+ d->m_projectLanguage = language;
+}
+
+Core::Context Project::projectContext() const
+{
+ return d->m_projectContext;
+}
+
+Core::Context Project::projectLanguage() const
+{
+ return d->m_projectLanguage;
+}
+
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h
index 28d6f5b6a1..8de8709e92 100644
--- a/src/plugins/projectexplorer/project.h
+++ b/src/plugins/projectexplorer/project.h
@@ -41,6 +41,7 @@
namespace Core {
class IFile;
+class Context;
}
namespace ProjectExplorer {
@@ -50,7 +51,6 @@ class IProjectManager;
class EditorConfiguration;
class ProjectNode;
class Target;
-class ITargetFactory;
class ProjectPrivate;
class PROJECTEXPLORER_EXPORT Project
@@ -118,6 +118,9 @@ public:
QString projectDirectory() const;
static QString projectDirectory(const QString &proFile);
+ virtual Core::Context projectContext() const;
+ virtual Core::Context projectLanguage() const;
+
signals:
void fileListChanged();
@@ -144,6 +147,9 @@ protected:
// Note: Do not forget to call your base class' fromMap method!
virtual bool fromMap(const QVariantMap &map);
+ virtual void setProjectContext(Core::Context context);
+ virtual void setProjectLanguage(Core::Context language);
+
private slots:
void changeEnvironment();
void changeBuildConfigurationEnabled();
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index cbc5dfc359..1bc69e2ea5 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -107,7 +107,6 @@
#include <coreplugin/vcsmanager.h>
#include <coreplugin/iversioncontrol.h>
#include <coreplugin/variablemanager.h>
-#include <welcome/welcomemode.h>
#include <extensionsystem/pluginmanager.h>
#include <find/searchresultwindow.h>
#include <utils/consoleprocess.h>
@@ -233,20 +232,17 @@ ProjectExplorerPluginPrivate::ProjectExplorerPluginPrivate() :
class ProjectsMode : public Core::IMode
{
public:
- ProjectsMode(QWidget *proWindow) : m_widget(proWindow) {}
-
- QString displayName() const { return QCoreApplication::translate("ProjectExplorer::ProjectsMode", "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;
+ ProjectsMode(QWidget *proWindow)
+ {
+ setWidget(proWindow);
+ setContext(Core::Context(Constants::C_PROJECTEXPLORER));
+ setDisplayName(QCoreApplication::translate("ProjectExplorer::ProjectsMode", "Projects"));
+ setIcon(QIcon(QLatin1String(":/fancyactionbar/images/mode_Project.png")));
+ setPriority(Constants::P_MODE_SESSION);
+ setId(QLatin1String(Constants::MODE_SESSION));
+ setType(QString());
+ setContextHelpId(QLatin1String("Managing Projects"));
+ }
};
} // namespace ProjectExplorer
@@ -628,8 +624,6 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+B")));
mbuild->addAction(cmd, Constants::G_BUILD_SESSION);
msessionContextMenu->addAction(cmd, Constants::G_SESSION_BUILD);
- // Add to mode bar
- modeManager->addAction(cmd->action(), Constants::P_ACTION_BUILDSESSION);
// rebuild session action
QIcon rebuildIcon(Constants::ICON_REBUILD);
@@ -656,12 +650,16 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
// build action
d->m_buildAction = new Utils::ParameterAction(tr("Build Project"), tr("Build Project \"%1\""),
Utils::ParameterAction::AlwaysEnabled, this);
+ d->m_buildAction->setIcon(buildIcon);
cmd = am->registerAction(d->m_buildAction, Constants::BUILD, globalcontext);
cmd->setAttribute(Core::Command::CA_UpdateText);
cmd->setDefaultText(d->m_buildAction->text());
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+B")));
mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
+ // Add to mode bar
+ modeManager->addAction(cmd->action(), Constants::P_ACTION_BUILDPROJECT);
+
// rebuild action
d->m_rebuildAction = new Utils::ParameterAction(tr("Rebuild Project"), tr("Rebuild Project \"%1\""),
Utils::ParameterAction::AlwaysEnabled, this);
@@ -844,7 +842,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
connect(d->m_session, SIGNAL(projectAdded(ProjectExplorer::Project*)),
d->m_targetSelector, SLOT(addProject(ProjectExplorer::Project*)));
- connect(d->m_session, SIGNAL(projectRemoved(ProjectExplorer::Project*)),
+ connect(d->m_session, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project*)),
d->m_targetSelector, SLOT(removeProject(ProjectExplorer::Project*)));
connect(d->m_targetSelector, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
this, SLOT(setStartupProject(ProjectExplorer::Project*)));
@@ -856,6 +854,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
addAutoReleasedObject(new ProjectTreeWidgetFactory);
addAutoReleasedObject(new FolderNavigationWidgetFactory);
+ addAutoReleasedObject(new DeployConfigurationFactory);
if (QSettings *s = core->settings()) {
const QStringList fileNames = s->value("ProjectExplorer/RecentProjects/FileNames").toStringList();
@@ -1182,6 +1181,7 @@ bool ProjectExplorerPlugin::openProject(const QString &fileName)
QList<Project *> list = openProjects(QStringList() << fileName);
if (!list.isEmpty()) {
addToRecentProjects(fileName, list.first()->displayName());
+ d->m_session->setStartupProject(list.first());
return true;
}
return false;
@@ -1497,12 +1497,12 @@ void ProjectExplorerPlugin::setCurrent(Project *project, QString filePath, Node
Core::Context newContext;
if (d->m_currentProject) {
- oldContext.add(d->m_currentProject->projectManager()->projectContext());
- oldContext.add(d->m_currentProject->projectManager()->projectLanguage());
+ oldContext.add(d->m_currentProject->projectContext());
+ oldContext.add(d->m_currentProject->projectLanguage());
}
if (project) {
- newContext.add(project->projectManager()->projectContext());
- newContext.add(project->projectManager()->projectLanguage());
+ newContext.add(project->projectContext());
+ newContext.add(project->projectLanguage());
}
core->updateAdditionalContexts(oldContext, newContext);
@@ -1657,10 +1657,10 @@ int ProjectExplorerPlugin::queue(QList<Project *> projects, QStringList stepIds)
return -1;
QList<BuildStepList *> stepLists;
- foreach (Project *pro, projects) {
- if (!pro || !pro->activeTarget())
- continue;
- foreach (const QString id, stepIds) {
+ foreach (const QString id, stepIds) {
+ foreach (Project *pro, projects) {
+ if (!pro || !pro->activeTarget())
+ continue;
BuildStepList *bsl = 0;
if (id == Core::Id(Constants::BUILDSTEPS_DEPLOY)
&& pro->activeTarget()->activeDeployConfiguration())
@@ -1686,6 +1686,12 @@ void ProjectExplorerPlugin::buildProjectOnly()
queue(QList<Project *>() << session()->startupProject(), QStringList() << Constants::BUILDSTEPS_BUILD);
}
+void ProjectExplorerPlugin::buildProject(ProjectExplorer::Project *p)
+{
+ queue(d->m_session->projectOrder(p),
+ QStringList() << Constants::BUILDSTEPS_BUILD);
+}
+
void ProjectExplorerPlugin::buildProject()
{
queue(d->m_session->projectOrder(session()->startupProject()),
diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h
index 89b91dbcef..45b90c0092 100644
--- a/src/plugins/projectexplorer/projectexplorer.h
+++ b/src/plugins/projectexplorer/projectexplorer.h
@@ -123,6 +123,8 @@ public:
void addExistingFiles(ProjectExplorer::ProjectNode *projectNode, const QStringList &filePaths);
void addExistingFiles(const QStringList &filePaths);
+ void buildProject(ProjectExplorer::Project *p);
+
signals:
void aboutToShowContextMenu(ProjectExplorer::Project *project,
ProjectExplorer::Node *node);
diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro
index e008145cb9..6adc7b80e8 100644
--- a/src/plugins/projectexplorer/projectexplorer.pro
+++ b/src/plugins/projectexplorer/projectexplorer.pro
@@ -1,7 +1,6 @@
TEMPLATE = lib
TARGET = ProjectExplorer
-QT += xml \
- script \
+QT += script \
network
include(../../qtcreatorplugin.pri)
include(projectexplorer_dependencies.pri)
diff --git a/src/plugins/projectexplorer/projectexplorerconstants.h b/src/plugins/projectexplorer/projectexplorerconstants.h
index 53657069ee..574f16a80d 100644
--- a/src/plugins/projectexplorer/projectexplorerconstants.h
+++ b/src/plugins/projectexplorer/projectexplorerconstants.h
@@ -65,16 +65,10 @@ const char * const CLEANPROJECTONLY = "ProjectExplorer.CleanProjectOnly";
const char * const CLEAN = "ProjectExplorer.Clean";
const char * const CLEANCM = "ProjectExplorer.CleanCM";
const char * const CLEANSESSION = "ProjectExplorer.CleanSession";
-const char * const BUILDPROJECTONLYMENU = "ProjectExplorer.BuildProjectOnlyMenu";
-const char * const BUILDCONFIGURATIONMENU = "ProjectExplorer.BuildConfigurationMenu";
const char * const CANCELBUILD = "ProjectExplorer.CancelBuild";
-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 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";
@@ -99,7 +93,7 @@ const char * const SELECTTARGET = "ProjectExplorer.SelectTarget";
// action priorities
const int P_ACTION_RUN = 100;
-const int P_ACTION_BUILDSESSION = 80;
+const int P_ACTION_BUILDPROJECT = 80;
// context
const char * const C_PROJECTEXPLORER = "Project Explorer";
@@ -116,9 +110,6 @@ const char * const M_DEBUG = "ProjectExplorer.Menu.Debug";
const char * const M_DEBUG_STARTDEBUGGING = "ProjectExplorer.Menu.Debug.StartDebugging";
const char * const M_SESSION = "ProjectExplorer.Menu.Session";
-// toolbars
-const char * const T_BUILDPROJECT = "ProjectExplorer.ToolBar.Build";
-
// menu groups
const char * const G_BUILD_SESSION = "ProjectExplorer.Group.BuildSession";
const char * const G_BUILD_PROJECT = "ProjectExplorer.Group.Build";
@@ -126,12 +117,6 @@ const char * const G_BUILD_OTHER = "ProjectExplorer.Group.Other";
const char * const G_BUILD_RUN = "ProjectExplorer.Group.Run";
const char * const G_BUILD_CANCEL = "ProjectExplorer.Group.BuildCancel";
-// toolbar groups
-const char * const G_TOOLBAR_CUSTOM = "ProjectExplorer.ToolBarGroup.Custom";
-const char * const G_TOOLBAR_BUILD = "ProjectExplorer.ToolBarGroup.Build";
-const char * const G_TOOLBAR_RUN = "ProjectExplorer.ToolBarGroup.Run";
-const char * const G_TOOLBAR_OTHER = "ProjectExplorer.ToolBarGroup.Other";
-
// context menus
const char * const M_SESSIONCONTEXT = "Project.Menu.Session";
const char * const M_PROJECTCONTEXT = "Project.Menu.Project";
@@ -166,9 +151,6 @@ const char * const RUNMENUCONTEXTMENU = "Project.RunMenu";
// file id
const char * const FILE_FACTORY_ID = "ProjectExplorer.FileFactoryId";
-// wizard kind
-const char * const WIZARD_TYPE_PROJECT = "ProjectExplorer.WizardType.Project";
-
// icons
const char * const ICON_BUILD = ":/projectexplorer/images/build.png";
const char * const ICON_BUILD_SMALL = ":/projectexplorer/images/build_small.png";
@@ -178,22 +160,12 @@ const char * const ICON_REBUILD = ":/projectexplorer/images/rebuild.png"
const char * const ICON_REBUILD_SMALL = ":/projectexplorer/images/rebuild_small.png";
const char * const ICON_RUN = ":/projectexplorer/images/run.png";
const char * const ICON_RUN_SMALL = ":/projectexplorer/images/run_small.png";
-const char * const ICON_SESSION = ":/projectexplorer/images/session.png";
-const char * const ICON_DEBUG = ":/projectexplorer/images/debugger_start.png";
const char * const ICON_DEBUG_SMALL = ":/projectexplorer/images/debugger_start_small.png";
-const char * const ICON_CLOSETAB = ":/projectexplorer/images/closetab.png";
const char * const ICON_STOP = ":/projectexplorer/images/stop.png";
const char * const ICON_TOOLCHAIN_SETTINGS_CATEGORY = ":projectexplorer/images/build.png"; // FIXME: Need an icon!
-// find filters
-const char * const FIND_CUR_PROJECT = "ProjectExplorer.FindFilter.CurrentProject";
-const char * const FIND_ALL_PROJECTS = "ProjectExplorer.FindFilter.AllProjects";
-
const char * const TASK_BUILD = "ProjectExplorer.Task.Build";
-const char * const SESSIONFILE_MIMETYPE = "application/vnd.nokia.xml.qt.creator.session";
-
-const char * const PROFILE_MIMETYPE = "application/vnd.nokia.qt.qmakeprofile";
const char * const C_SOURCE_MIMETYPE = "text/x-csrc";
const char * const C_HEADER_MIMETYPE = "text/x-chdr";
const char * const CPP_SOURCE_MIMETYPE = "text/x-c++src";
diff --git a/src/plugins/projectexplorer/projecttreewidget.cpp b/src/plugins/projectexplorer/projecttreewidget.cpp
index 399ae4d568..722fd98e00 100644
--- a/src/plugins/projectexplorer/projecttreewidget.cpp
+++ b/src/plugins/projectexplorer/projecttreewidget.cpp
@@ -74,8 +74,8 @@ public:
setEditTriggers(QAbstractItemView::EditKeyPressed);
setContextMenuPolicy(Qt::CustomContextMenu);
// setExpandsOnDoubleClick(false);
- Core::Context context(Constants::C_PROJECT_TREE);
- m_context = new Core::BaseContext(this, context);
+ m_context = new Core::IContext(this);
+ m_context->setContext(Core::Context(Constants::C_PROJECT_TREE));
Core::ICore::instance()->addContextObject(m_context);
}
~ProjectTreeView()
@@ -85,7 +85,7 @@ public:
}
private:
- Core::BaseContext *m_context;
+ Core::IContext *m_context;
};
/*!
@@ -100,6 +100,7 @@ ProjectTreeWidget::ProjectTreeWidget(QWidget *parent)
m_model(0),
m_filterProjectsAction(0),
m_autoSync(false),
+ m_autoExpand(true),
m_currentItemLocked(0)
{
m_model = new FlatModel(m_explorer->session()->sessionNode(), this);
@@ -148,6 +149,13 @@ ProjectTreeWidget::ProjectTreeWidget(QWidget *parent)
connect(m_explorer->session(), SIGNAL(startupProjectChanged(ProjectExplorer::Project *)),
this, SLOT(startupProjectChanged(ProjectExplorer::Project *)));
+ connect(m_explorer->session(), SIGNAL(aboutToLoadSession()),
+ this, SLOT(disableAutoExpand()));
+ connect(m_explorer->session(), SIGNAL(sessionLoaded()),
+ this, SLOT(loadExpandData()));
+ connect(m_explorer->session(), SIGNAL(aboutToSaveSession()),
+ this, SLOT(saveExpandData()));
+
m_toggleSync = new QToolButton;
m_toggleSync->setIcon(QIcon(QLatin1String(Core::Constants::ICON_LINK)));
m_toggleSync->setCheckable(true);
@@ -158,6 +166,47 @@ ProjectTreeWidget::ProjectTreeWidget(QWidget *parent)
setAutoSynchronization(true);
}
+void ProjectTreeWidget::disableAutoExpand()
+{
+ m_autoExpand = false;
+}
+
+void ProjectTreeWidget::loadExpandData()
+{
+ m_autoExpand = true;
+ QStringList data = m_explorer->session()->value("ProjectTree.ExpandData").toStringList();
+ recursiveLoadExpandData(m_view->rootIndex(), data.toSet());
+}
+
+void ProjectTreeWidget::recursiveLoadExpandData(const QModelIndex &index, const QSet<QString> &data)
+{
+ if (data.contains(m_model->nodeForIndex(index)->path())) {
+ m_view->expand(index);
+ int count = m_model->rowCount(index);
+ for (int i = 0; i < count; ++i)
+ recursiveLoadExpandData(index.child(i, 0), data);
+ }
+}
+
+void ProjectTreeWidget::saveExpandData()
+{
+ QStringList data;
+ recursiveSaveExpandData(m_view->rootIndex(), &data);
+ // TODO if there are multiple ProjectTreeWidgets, the last one saves the data
+ m_explorer->session()->setValue("ProjectTree.ExpandData", data);
+}
+
+void ProjectTreeWidget::recursiveSaveExpandData(const QModelIndex &index, QStringList *data)
+{
+ Q_ASSERT(data);
+ if (m_view->isExpanded(index)) {
+ data->append(m_model->nodeForIndex(index)->path());
+ int count = m_model->rowCount(index);
+ for (int i = 0; i < count; ++i)
+ recursiveSaveExpandData(index.child(i, 0), data);
+ }
+}
+
void ProjectTreeWidget::foldersAboutToBeRemoved(FolderNode *, const QList<FolderNode*> &list)
{
Node *n = m_explorer->currentNode();
@@ -282,7 +331,8 @@ void ProjectTreeWidget::handleProjectAdded(ProjectExplorer::Project *project)
Node *node = project->rootProjectNode();
QModelIndex idx = m_model->indexForNode(node);
- m_view->setExpanded(idx, true);
+ if (m_autoExpand) // disabled while session restoring
+ m_view->setExpanded(idx, true);
m_view->setCurrentIndex(idx);
}
diff --git a/src/plugins/projectexplorer/projecttreewidget.h b/src/plugins/projectexplorer/projecttreewidget.h
index c28dac327b..23b97869b4 100644
--- a/src/plugins/projectexplorer/projecttreewidget.h
+++ b/src/plugins/projectexplorer/projecttreewidget.h
@@ -83,7 +83,13 @@ private slots:
void foldersAboutToBeRemoved(FolderNode *, const QList<FolderNode*> &);
void filesAboutToBeRemoved(FolderNode *, const QList<FileNode*> &);
+ void loadExpandData();
+ void saveExpandData();
+ void disableAutoExpand();
+
private:
+ void recursiveLoadExpandData(const QModelIndex &index, const QSet<QString> &data);
+ void recursiveSaveExpandData(const QModelIndex &index, QStringList *data);
ProjectExplorerPlugin *m_explorer;
QTreeView *m_view;
FlatModel *m_model;
@@ -94,6 +100,7 @@ private:
QModelIndex m_subIndex;
QString m_modelId;
bool m_autoSync;
+ bool m_autoExpand;
Node *m_currentItemLocked;
friend class ProjectTreeWidgetFactory;
};
diff --git a/src/plugins/projectexplorer/projectwindow.cpp b/src/plugins/projectexplorer/projectwindow.cpp
index 759a62a6ee..c9f81ea138 100644
--- a/src/plugins/projectexplorer/projectwindow.cpp
+++ b/src/plugins/projectexplorer/projectwindow.cpp
@@ -348,7 +348,7 @@ void ProjectWindow::registerProject(ProjectExplorer::Project *project)
}
m_tabIndexToProject.insert(index, project);
- m_tabWidget->insertTab(index, project->displayName(), subtabs);
+ m_tabWidget->insertTab(index, project->displayName(), project->file()->fileName(), subtabs);
}
void ProjectWindow::deregisterProject(ProjectExplorer::Project *project)
diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h
index 648c25d02c..505966592c 100644
--- a/src/plugins/projectexplorer/runconfiguration.h
+++ b/src/plugins/projectexplorer/runconfiguration.h
@@ -41,6 +41,7 @@
#include <QtCore/QMetaType>
#include <QtCore/QWeakPointer>
#include <QtGui/QWidget>
+#include <QtGui/QIcon>
namespace ProjectExplorer {
@@ -251,6 +252,10 @@ public:
virtual StopResult stop() = 0;
virtual bool isRunning() const = 0;
virtual QString displayName() const;
+ /// \returns the icon to be shown in the outputwindow
+ // TODO the icon differs currently only per "mode"
+ // so this is more flexibel then it needs to be
+ virtual QIcon icon() const = 0;
bool sameRunConfiguration(const RunControl *other) const;
diff --git a/src/plugins/projectexplorer/runsettingspropertiespage.cpp b/src/plugins/projectexplorer/runsettingspropertiespage.cpp
index bf07fb486b..d036a8870c 100644
--- a/src/plugins/projectexplorer/runsettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/runsettingspropertiespage.cpp
@@ -318,10 +318,9 @@ void RunSettingsWidget::currentDeployConfigurationChanged(int index)
void RunSettingsWidget::aboutToShowDeployMenu()
{
m_addDeployMenu->clear();
- DeployConfigurationFactory *factory = m_target->deployConfigurationFactory();
- QStringList ids = factory->availableCreationIds(m_target);
+ QStringList ids = m_target->availableDeployConfigurationIds();
foreach (const QString &id, ids) {
- QAction *action = m_addDeployMenu->addAction(factory->displayNameForId(id));;
+ QAction *action = m_addDeployMenu->addAction(m_target->displayNameForDeployConfigurationId(id));
action->setData(QVariant(id));
connect(action, SIGNAL(triggered()),
this, SLOT(addDeployConfiguration()));
@@ -334,7 +333,7 @@ void RunSettingsWidget::addDeployConfiguration()
if (!act)
return;
QString id = act->data().toString();
- DeployConfiguration *newDc = m_target->deployConfigurationFactory()->create(m_target, id);
+ DeployConfiguration *newDc = m_target->createDeployConfiguration(id);
if (!newDc)
return;
m_target->addDeployConfiguration(newDc);
diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp
index 0764936ede..c235a2116f 100644
--- a/src/plugins/projectexplorer/session.cpp
+++ b/src/plugins/projectexplorer/session.cpp
@@ -555,9 +555,6 @@ bool SessionManager::createImpl(const QString &fileName)
if (debug)
qDebug() << "SessionManager - creating new session returns " << success;
- if (success)
- emit sessionLoaded();
-
return success;
}
@@ -966,8 +963,10 @@ QString SessionManager::sessionNameToFileName(const QString &session) const
void SessionManager::createAndLoadNewDefaultSession()
{
+ emit aboutToLoadSession();
updateName("default");
createImpl(sessionNameToFileName(m_sessionName));
+ emit sessionLoaded();
}
bool SessionManager::createSession(const QString &session)
@@ -1024,6 +1023,7 @@ bool SessionManager::loadSession(const QString &session)
if (!sessions().contains(session))
return false;
+ emit aboutToLoadSession();
QString fileName = sessionNameToFileName(session);
if (QFileInfo(fileName).exists()) {
if (loadImpl(fileName)) {
diff --git a/src/plugins/projectexplorer/session.h b/src/plugins/projectexplorer/session.h
index c66892b039..84b8d12d1d 100644
--- a/src/plugins/projectexplorer/session.h
+++ b/src/plugins/projectexplorer/session.h
@@ -149,6 +149,7 @@ signals:
void startupProjectChanged(ProjectExplorer::Project *project);
+ void aboutToLoadSession();
void sessionLoaded();
void aboutToUnloadSession();
void aboutToSaveSession();
diff --git a/src/plugins/projectexplorer/target.cpp b/src/plugins/projectexplorer/target.cpp
index 613863e49d..522b725904 100644
--- a/src/plugins/projectexplorer/target.cpp
+++ b/src/plugins/projectexplorer/target.cpp
@@ -40,6 +40,7 @@
#include "toolchainmanager.h"
#include <limits>
+#include <extensionsystem/pluginmanager.h>
#include <utils/qtcassert.h>
#include <QtGui/QIcon>
@@ -68,6 +69,9 @@ namespace ProjectExplorer {
class TargetPrivate {
public:
TargetPrivate();
+
+ QList<DeployConfigurationFactory *> deployFactories() const;
+
bool m_isEnabled;
QIcon m_icon;
QIcon m_overlayIcon;
@@ -89,6 +93,11 @@ TargetPrivate::TargetPrivate() :
{
}
+QList<DeployConfigurationFactory *> TargetPrivate::deployFactories() const
+{
+ return ExtensionSystem::PluginManager::instance()->getObjects<DeployConfigurationFactory>();
+}
+
Target::Target(Project *project, const QString &id) :
ProjectConfiguration(project, id), d(new TargetPrivate)
@@ -198,7 +207,7 @@ void Target::addDeployConfiguration(DeployConfiguration *dc)
QTC_ASSERT(dc && !d->m_deployConfigurations.contains(dc), return);
Q_ASSERT(dc->target() == this);
- if (!deployConfigurationFactory())
+ if (d->deployFactories().isEmpty())
return;
// Check that we don't have a configuration with the same displayName
@@ -259,6 +268,32 @@ void Target::setActiveDeployConfiguration(DeployConfiguration *dc)
}
}
+QStringList Target::availableDeployConfigurationIds()
+{
+ QStringList ids;
+ foreach (const DeployConfigurationFactory * const factory, d->deployFactories())
+ ids << factory->availableCreationIds(this);
+ return ids;
+}
+
+QString Target::displayNameForDeployConfigurationId(const QString &id)
+{
+ foreach (const DeployConfigurationFactory * const factory, d->deployFactories()) {
+ if (factory->availableCreationIds(this).contains(id))
+ return factory->displayNameForId(id);
+ }
+ return QString();
+}
+
+DeployConfiguration *Target::createDeployConfiguration(const QString &id)
+{
+ foreach (DeployConfigurationFactory * const factory, d->deployFactories()) {
+ if (factory->canCreate(this, id))
+ return factory->create(this, id);
+ }
+ return 0;
+}
+
QList<RunConfiguration *> Target::runConfigurations() const
{
return d->m_runConfigurations;
@@ -451,15 +486,20 @@ bool Target::fromMap(const QVariantMap &map)
if (!map.contains(key))
return false;
DeployConfiguration *dc = 0;
- if (deployConfigurationFactory())
- dc = deployConfigurationFactory()->restore(this, map.value(key).toMap());
+ foreach (DeployConfigurationFactory * const factory, d->deployFactories()) {
+ QVariantMap valueMap = map.value(key).toMap();
+ if (factory->canRestore(this, valueMap)) {
+ dc = factory->restore(this, valueMap);
+ break;
+ }
+ }
if (!dc)
continue;
addDeployConfiguration(dc);
if (i == activeConfiguration)
setActiveDeployConfiguration(dc);
}
- if (deployConfigurations().isEmpty() && deployConfigurationFactory())
+ if (deployConfigurations().isEmpty() && d->deployFactories().isEmpty())
return false;
int rcCount(map.value(QLatin1String(RC_COUNT_KEY), 0).toInt(&ok));
diff --git a/src/plugins/projectexplorer/target.h b/src/plugins/projectexplorer/target.h
index afcf08d5cf..82be0313c0 100644
--- a/src/plugins/projectexplorer/target.h
+++ b/src/plugins/projectexplorer/target.h
@@ -84,7 +84,9 @@ public:
virtual DeployConfiguration *activeDeployConfiguration() const;
void setActiveDeployConfiguration(DeployConfiguration *configuration);
- virtual DeployConfigurationFactory *deployConfigurationFactory() const = 0;
+ QStringList availableDeployConfigurationIds();
+ QString displayNameForDeployConfigurationId(const QString &id);
+ DeployConfiguration *createDeployConfiguration(const QString &id);
// Running
QList<RunConfiguration *> runConfigurations() const;
diff --git a/src/plugins/projectexplorer/taskwindow.cpp b/src/plugins/projectexplorer/taskwindow.cpp
index 5814e589a3..f56bf33d2a 100644
--- a/src/plugins/projectexplorer/taskwindow.cpp
+++ b/src/plugins/projectexplorer/taskwindow.cpp
@@ -77,11 +77,6 @@ class TaskWindowContext : public Core::IContext
{
public:
TaskWindowContext(QWidget *widget);
- virtual Core::Context context() const;
- virtual QWidget *widget();
-private:
- QWidget *m_taskList;
- const Core::Context m_context;
};
class TaskModel : public QAbstractItemModel
@@ -1144,24 +1139,13 @@ void TaskDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
}
TaskWindowContext::TaskWindowContext(QWidget *widget)
- : Core::IContext(widget),
- m_taskList(widget),
- m_context(Core::Constants::C_PROBLEM_PANE)
-{
-}
-
-Core::Context TaskWindowContext::context() const
+ : Core::IContext(widget)
{
- return m_context;
-}
-
-QWidget *TaskWindowContext::widget()
-{
- return m_taskList;
+ setWidget(widget);
+ setContext(Core::Context(Core::Constants::C_PROBLEM_PANE));
}
} // namespace Internal
-
} // namespace ProjectExplorer
#include "taskwindow.moc"
diff --git a/src/plugins/projectexplorer/toolchainconfigwidget.cpp b/src/plugins/projectexplorer/toolchainconfigwidget.cpp
index 43bf46ddf7..a6a493e9ee 100644
--- a/src/plugins/projectexplorer/toolchainconfigwidget.cpp
+++ b/src/plugins/projectexplorer/toolchainconfigwidget.cpp
@@ -82,6 +82,12 @@ ToolChain *ToolChainConfigWidget::toolChain() const
return m_d->m_toolChain;
}
+void ToolChainConfigWidget::makeReadOnly()
+{
+ if (m_d->m_debuggerPathChooser)
+ m_d->m_debuggerPathChooser->setEnabled(false);
+}
+
void ToolChainConfigWidget::emitDirty()
{
emit dirty(toolChain());
diff --git a/src/plugins/projectexplorer/toolchainconfigwidget.h b/src/plugins/projectexplorer/toolchainconfigwidget.h
index e9b92326ba..aaef06b14c 100644
--- a/src/plugins/projectexplorer/toolchainconfigwidget.h
+++ b/src/plugins/projectexplorer/toolchainconfigwidget.h
@@ -67,6 +67,8 @@ public:
virtual bool isDirty() const = 0;
+ virtual void makeReadOnly();
+
signals:
void dirty(ProjectExplorer::ToolChain *);
diff --git a/src/plugins/projectexplorer/toolchainmanager.cpp b/src/plugins/projectexplorer/toolchainmanager.cpp
index 55b60c12c8..ada08f87e6 100644
--- a/src/plugins/projectexplorer/toolchainmanager.cpp
+++ b/src/plugins/projectexplorer/toolchainmanager.cpp
@@ -95,6 +95,12 @@ ToolChainManager::ToolChainManager(QObject *parent) :
m_instance = this;
connect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()),
this, SLOT(saveToolChains()));
+ connect(this, SIGNAL(toolChainAdded(ProjectExplorer::ToolChain*)),
+ this, SIGNAL(toolChainsChanged()));
+ connect(this, SIGNAL(toolChainRemoved(ProjectExplorer::ToolChain*)),
+ this, SIGNAL(toolChainsChanged()));
+ connect(this, SIGNAL(toolChainUpdated(ProjectExplorer::ToolChain*)),
+ this, SIGNAL(toolChainsChanged()));
}
void ToolChainManager::restoreToolChains()
@@ -240,17 +246,18 @@ void ToolChainManager::notifyAboutUpdate(ProjectExplorer::ToolChain *tc)
emit toolChainUpdated(tc);
}
-void ToolChainManager::registerToolChain(ToolChain *tc)
+bool ToolChainManager::registerToolChain(ToolChain *tc)
{
if (!tc || m_d->m_toolChains.contains(tc))
- return;
+ return true;
foreach (ToolChain *current, m_d->m_toolChains) {
if (*tc == *current)
- return;
+ return false;
}
m_d->m_toolChains.append(tc);
emit toolChainAdded(tc);
+ return true;
}
void ToolChainManager::deregisterToolChain(ToolChain *tc)
diff --git a/src/plugins/projectexplorer/toolchainmanager.h b/src/plugins/projectexplorer/toolchainmanager.h
index c2e278473e..dacf577fc2 100644
--- a/src/plugins/projectexplorer/toolchainmanager.h
+++ b/src/plugins/projectexplorer/toolchainmanager.h
@@ -70,7 +70,7 @@ public:
QString defaultDebugger(const Abi &abi) const;
public slots:
- void registerToolChain(ProjectExplorer::ToolChain *tc);
+ bool registerToolChain(ProjectExplorer::ToolChain *tc);
void deregisterToolChain(ProjectExplorer::ToolChain *tc);
void saveToolChains();
@@ -81,6 +81,8 @@ signals:
void toolChainRemoved(ProjectExplorer::ToolChain *);
// Tool chain was updated.
void toolChainUpdated(ProjectExplorer::ToolChain *);
+ // Something changed:
+ void toolChainsChanged();
private:
explicit ToolChainManager(QObject *parent = 0);
diff --git a/src/plugins/projectexplorer/toolchainoptionspage.cpp b/src/plugins/projectexplorer/toolchainoptionspage.cpp
index fc8c7d852b..9aa73766d3 100644
--- a/src/plugins/projectexplorer/toolchainoptionspage.cpp
+++ b/src/plugins/projectexplorer/toolchainoptionspage.cpp
@@ -62,7 +62,8 @@ public:
p->childNodes.append(this);
widget = tc ? tc->configurationWidget() : 0;
if (widget) {
- widget->setEnabled(tc ? !tc->isAutoDetected() : false);
+ if (tc && tc->isAutoDetected())
+ widget->makeReadOnly();
widget->setVisible(false);
}
}
@@ -305,15 +306,34 @@ void ToolChainModel::apply()
}
// Add new (and already updated) tool chains
+ QStringList removedTcs;
nodes = m_toAddList;
foreach (ToolChainNode *n, nodes) {
- ToolChainManager::instance()->registerToolChain(n->toolChain);
+ if (!ToolChainManager::instance()->registerToolChain(n->toolChain))
+ removedTcs << n->toolChain->displayName();
}
//
foreach (ToolChainNode *n, m_toAddList) {
markForRemoval(n->toolChain);
}
qDeleteAll(m_toAddList);
+
+ if (removedTcs.count() == 1) {
+ QMessageBox::warning(0,
+ tr("Duplicate Tool Chain detected"),
+ tr("The following tool chain was already configured:<br>"
+ "&nbsp;%1<br>"
+ "It was not configured again.")
+ .arg(removedTcs.at(0)));
+
+ } else if (!removedTcs.isEmpty()) {
+ QMessageBox::warning(0,
+ tr("Duplicate Tool Chains detected"),
+ tr("The following tool chains were already configured:<br>"
+ "&nbsp;%1<br>"
+ "They were not configured again.")
+ .arg(removedTcs.join(QLatin1String(",<br>&nbsp;"))));
+ }
}
void ToolChainModel::markForRemoval(ToolChain *tc)
diff --git a/src/plugins/projectexplorer/userfileaccessor.cpp b/src/plugins/projectexplorer/userfileaccessor.cpp
index 248462d4df..0dd784503b 100644
--- a/src/plugins/projectexplorer/userfileaccessor.cpp
+++ b/src/plugins/projectexplorer/userfileaccessor.cpp
@@ -244,6 +244,24 @@ public:
QVariantMap update(Project *project, const QVariantMap &map);
};
+// Version 9 reflects the refactoring of the Maemo deploy step.
+class Version9Handler : public UserFileVersionHandler
+{
+public:
+ int userFileVersion() const
+ {
+ return 9;
+ }
+
+ QString displayUserFileVersion() const
+ {
+ return QLatin1String("2.3pre1");
+ }
+
+ QVariantMap update(Project *project, const QVariantMap &map);
+};
+
+
} // namespace
//
@@ -371,6 +389,7 @@ UserFileAccessor::UserFileAccessor() :
addVersionHandler(new Version6Handler);
addVersionHandler(new Version7Handler);
addVersionHandler(new Version8Handler);
+ addVersionHandler(new Version9Handler);
}
UserFileAccessor::~UserFileAccessor()
@@ -1865,3 +1884,52 @@ QVariantMap Version8Handler::update(Project *, const QVariantMap &map)
const char * const *p4 = varExpandedKeys;
return processHandlerNodes(buildHandlerNodes(&p4), rmap3, version8VarNodeHandler);
}
+
+QVariantMap Version9Handler::update(Project *project, const QVariantMap &map)
+{
+ Q_UNUSED(project);
+
+ QVariantMap result;
+ QMapIterator<QString, QVariant> globalIt(map);
+ while (globalIt.hasNext()) {
+ globalIt.next();
+ const QString &globalKey = globalIt.key();
+ // check for target info
+ if (!globalKey.startsWith(QLatin1String("ProjectExplorer.Project.Target."))) {
+ result.insert(globalKey, globalIt.value());
+ continue;
+ }
+
+ const QVariantMap &origTargetMap = globalIt.value().toMap();
+ const QString targetIdKey
+ = QLatin1String("ProjectExplorer.ProjectConfiguration.Id");
+ // check for maemo device target
+ if (origTargetMap.value(targetIdKey)
+ != QLatin1String("Qt4ProjectManager.Target.MaemoDeviceTarget")
+ && origTargetMap.value(targetIdKey)
+ != QLatin1String("Qt4ProjectManager.Target.HarmattanDeviceTarget")
+ && origTargetMap.value(targetIdKey)
+ != QLatin1String("Qt4ProjectManager.Target.MeegoDeviceTarget"))
+ {
+ result.insert(globalKey, origTargetMap);
+ continue;
+ }
+
+ QVariantMap newTargetMap;
+ QMapIterator<QString, QVariant> targetIt(origTargetMap);
+ while (targetIt.hasNext()) {
+ targetIt.next();
+ if (!targetIt.key().startsWith(QLatin1String("ProjectExplorer.Target.DeployConfiguration."))) {
+ newTargetMap.insert(targetIt.key(), targetIt.value());
+ continue;
+ }
+
+ QVariantMap deployConfMap = targetIt.value().toMap();
+ deployConfMap.insert(QLatin1String("ProjectExplorer.ProjectConfiguration.Id"),
+ QLatin1String("2.2MaemoDeployConfig"));
+ newTargetMap.insert(targetIt.key(), deployConfMap);
+ }
+ result.insert(globalKey, newTargetMap);
+ }
+ return result;
+}
diff --git a/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp b/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp
index 8b04ce7b50..27b4ab956d 100644
--- a/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp
+++ b/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp
@@ -235,6 +235,7 @@ void RewriteActionCompressor::compressPropertyActions(QList<RewriteAction *> &ac
if (RemovePropertyRewriteAction *removeAction = action->asRemovePropertyRewriteAction()) {
const AbstractProperty property = removeAction->property();
if (AddPropertyRewriteAction *addAction = addedProperties.value(property, 0)) {
+ Q_UNUSED(addAction);
} else {
removedProperties.insert(property, action);
}
diff --git a/src/plugins/qmldesigner/designmodecontext.cpp b/src/plugins/qmldesigner/designmodecontext.cpp
index 36ce50ad5f..4a558fe420 100644
--- a/src/plugins/qmldesigner/designmodecontext.cpp
+++ b/src/plugins/qmldesigner/designmodecontext.cpp
@@ -35,62 +35,32 @@
#include "designmodewidget.h"
#include "formeditorwidget.h"
-#include <QWidget>
-
namespace QmlDesigner {
namespace Internal {
-DesignModeContext::DesignModeContext(DesignModeWidget *widget)
- : IContext(widget),
- m_widget(widget),
- m_context(Constants::C_QMLDESIGNER, Constants::C_QT_QUICK_TOOLS_MENU)
-{
-}
-
-DesignModeContext::~DesignModeContext()
-{
-}
-
-Core::Context DesignModeContext::context() const
-{
- return m_context;
-}
-
-QWidget *DesignModeContext::widget()
+DesignModeContext::DesignModeContext(QWidget *widget)
+ : IContext(widget)
{
- return m_widget;
+ setWidget(widget);
+ setContext(Core::Context(Constants::C_QMLDESIGNER, Constants::C_QT_QUICK_TOOLS_MENU));
}
QString DesignModeContext::contextHelpId() const
{
- return m_widget->contextHelpId();
+ return qobject_cast<DesignModeWidget *>(m_widget)->contextHelpId();
}
-FormEditorContext::FormEditorContext(FormEditorWidget *widget)
- : IContext(widget),
- m_widget(widget),
- m_context(Constants::C_QMLFORMEDITOR, Constants::C_QT_QUICK_TOOLS_MENU)
-{
-}
-
-FormEditorContext::~FormEditorContext()
-{
-}
-
-Core::Context FormEditorContext::context() const
-{
- return m_context;
-}
-
-QWidget *FormEditorContext::widget()
+FormEditorContext::FormEditorContext(QWidget *widget)
+ : IContext(widget)
{
- return m_widget;
+ setWidget(widget);
+ setContext(Core::Context(Constants::C_QMLFORMEDITOR, Constants::C_QT_QUICK_TOOLS_MENU));
}
QString FormEditorContext::contextHelpId() const
{
- return m_widget->contextHelpId();
+ return qobject_cast<FormEditorWidget *>(m_widget)->contextHelpId();
}
}
diff --git a/src/plugins/qmldesigner/designmodecontext.h b/src/plugins/qmldesigner/designmodecontext.h
index 3c91312f58..8683f06674 100644
--- a/src/plugins/qmldesigner/designmodecontext.h
+++ b/src/plugins/qmldesigner/designmodecontext.h
@@ -34,53 +34,25 @@
#define DESIGNMODECONTEXT_H
#include <coreplugin/icontext.h>
-#include <QList>
-
-QT_BEGIN_NAMESPACE
-class QWidget;
-QT_END_NAMESPACE
namespace QmlDesigner {
-
-class FormEditorWidget;
-
namespace Internal {
-class DesignModeWidget;
-
/**
* Bauhaus Design mode context object
*/
class DesignModeContext : public Core::IContext
{
public:
- DesignModeContext(DesignModeWidget *widget);
- ~DesignModeContext();
-
- Core::Context context() const;
- QWidget *widget();
-
+ DesignModeContext(QWidget *widget);
QString contextHelpId() const;
-
-private:
- DesignModeWidget *m_widget;
- const Core::Context m_context;
};
class FormEditorContext : public Core::IContext
{
public:
- FormEditorContext(FormEditorWidget *widget);
- ~FormEditorContext();
-
- Core::Context context() const;
- QWidget *widget();
-
+ FormEditorContext(QWidget *widget);
QString contextHelpId() const;
-
-private:
- FormEditorWidget *m_widget;
- const Core::Context m_context;
};
}
diff --git a/src/plugins/qmldesigner/qmldesignerconstants.h b/src/plugins/qmldesigner/qmldesignerconstants.h
index d782bf41c4..ece8225524 100644
--- a/src/plugins/qmldesigner/qmldesignerconstants.h
+++ b/src/plugins/qmldesigner/qmldesignerconstants.h
@@ -39,7 +39,6 @@ namespace Constants {
const char * const DELETE = "QmlDesigner.Delete";
// context
-const char * const C_DESIGN_MODE = "QmlDesigner::DesignMode";
const char * const C_QMLDESIGNER = "QmlDesigner::QmlDesignerMain";
const char * const C_QMLFORMEDITOR = "QmlDesigner::FormEditor";
@@ -52,13 +51,6 @@ const char * const RESTORE_DEFAULT_VIEW = "QmlDesigner.RestoreDefaultView";
const char * const TOGGLE_LEFT_SIDEBAR = "QmlDesigner.ToggleLeftSideBar";
const char * const TOGGLE_RIGHT_SIDEBAR = "QmlDesigner.ToggleRightSideBar";
-// mode
-const char * const DESIGN_MODE_NAME = "Design";
-
-// Wizard type
-const char * const FORM_MIMETYPE = "application/x-qmldesigner";
-
-
// This setting is also accessed by the QMlJsEditor.
const char * const QML_SETTINGS_GROUP = "QML";
const char * const QML_DESIGNER_SETTINGS_GROUP = "Designer";
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.h b/src/plugins/qmldesigner/qmldesignerplugin.h
index e57c82ebc1..24eaca6e7f 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.h
+++ b/src/plugins/qmldesigner/qmldesignerplugin.h
@@ -47,11 +47,7 @@ QT_END_NAMESPACE
namespace Core {
class Context;
class IContext;
- class IWizard;
- class ICore;
- class IEditorFactory;
class IEditor;
- class IMode;
class DesignMode;
class EditorManager;
}
diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp
index 4261431953..4fac404e69 100644
--- a/src/plugins/qmljseditor/qmljseditor.cpp
+++ b/src/plugins/qmljseditor/qmljseditor.cpp
@@ -747,11 +747,6 @@ bool QmlJSEditorEditable::open(const QString &fileName)
return b;
}
-Core::Context QmlJSEditorEditable::context() const
-{
- return m_context;
-}
-
void QmlJSTextEditorWidget::updateDocument()
{
m_updateDocumentTimer->start(UPDATE_DOCUMENT_DEFAULT_INTERVAL);
diff --git a/src/plugins/qmljseditor/qmljseditorconstants.h b/src/plugins/qmljseditor/qmljseditorconstants.h
index 0b15e02875..69942ccb5c 100644
--- a/src/plugins/qmljseditor/qmljseditorconstants.h
+++ b/src/plugins/qmljseditor/qmljseditorconstants.h
@@ -46,7 +46,6 @@ const char * const SEPARATOR1 = "QmlJSEditor.Separator1";
const char * const SEPARATOR2 = "QmlJSEditor.Separator2";
const char * const M_REFACTORING_MENU_INSERTION_POINT = "QmlJSEditor.RefactorGroup";
-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_SEARCH = "QmlJSEditor.TaskSearch";
diff --git a/src/plugins/qmljseditor/qmljseditoreditable.h b/src/plugins/qmljseditor/qmljseditoreditable.h
index 631937bf7c..a94772597c 100644
--- a/src/plugins/qmljseditor/qmljseditoreditable.h
+++ b/src/plugins/qmljseditor/qmljseditoreditable.h
@@ -45,7 +45,6 @@ class QMLJSEDITOR_EXPORT QmlJSEditorEditable : public TextEditor::BaseTextEditor
public:
explicit QmlJSEditorEditable(QmlJSTextEditorWidget *);
- Core::Context context() const;
bool duplicateSupported() const { return true; }
Core::IEditor *duplicate(QWidget *parent);
@@ -54,10 +53,6 @@ public:
virtual bool open(const QString & fileName);
virtual QString preferredModeType() const;
void setTextCodec(QTextCodec *codec, TextCodecReason = TextCodecOtherReason);
-
-
-private:
- Core::Context m_context;
};
} // namespace QmlJSEditor
diff --git a/src/plugins/qmljsinspector/qmljsinspectorconstants.h b/src/plugins/qmljsinspector/qmljsinspectorconstants.h
index 29b4d405e3..c613cae15f 100644
--- a/src/plugins/qmljsinspector/qmljsinspectorconstants.h
+++ b/src/plugins/qmljsinspector/qmljsinspectorconstants.h
@@ -35,30 +35,20 @@
namespace QmlJSInspector {
namespace Constants {
-const char * const RUN = "QmlInspector.Run";
-const char * const STOP = "QmlInspector.Stop";
-
-const char * const COMPLETE_THIS = "QmlInspector.CompleteThis";
-
-const char * const M_DEBUG_SIMULTANEOUSLY = "QmlInspector.Menu.SimultaneousDebug";
-
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 PLAY_ACTION = "QmlInspector.Play";
const char * const SELECT_ACTION = "QmlInspector.Select";
-const char * const SELECT_MARQUEE_ACTION = "QmlInspector.SelectMarquee";
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";
const char * const S_LIVE_PREVIEW_WARNING_KEY = "ShowLivePreview";
-const char * const ARG_DESIGNMODE = "-designmode";
enum DesignTool {
NoTool = 0,
diff --git a/src/plugins/qmlprofiler/QmlProfiler.pluginspec.in b/src/plugins/qmlprofiler/QmlProfiler.pluginspec.in
new file mode 100644
index 0000000000..6bdcd694e7
--- /dev/null
+++ b/src/plugins/qmlprofiler/QmlProfiler.pluginspec.in
@@ -0,0 +1,20 @@
+<plugin name=\"QmlProfiler\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2011 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>Qml Profiler Plugin</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"AnalyzerBase\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/qmlprofiler/canvas/canvas.pri b/src/plugins/qmlprofiler/canvas/canvas.pri
new file mode 100644
index 0000000000..2b37e8ee5d
--- /dev/null
+++ b/src/plugins/qmlprofiler/canvas/canvas.pri
@@ -0,0 +1,11 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += $$PWD/qdeclarativecontext2d_p.h \
+ $$PWD/qdeclarativecanvas_p.h \
+ $$PWD/qdeclarativetiledcanvas_p.h \
+ $$PWD/qdeclarativecanvastimer_p.h
+
+SOURCES += $$PWD/qdeclarativecontext2d.cpp \
+ $$PWD/qdeclarativecanvas.cpp \
+ $$PWD/qdeclarativetiledcanvas.cpp \
+ $$PWD/qdeclarativecanvastimer.cpp
diff --git a/src/plugins/qmlprofiler/canvas/qdeclarativecanvas.cpp b/src/plugins/qmlprofiler/canvas/qdeclarativecanvas.cpp
new file mode 100644
index 0000000000..0f7c7ae501
--- /dev/null
+++ b/src/plugins/qmlprofiler/canvas/qdeclarativecanvas.cpp
@@ -0,0 +1,257 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#include "qdeclarativecanvas_p.h"
+#include "qdeclarativecanvastimer_p.h"
+#include "qdeclarativecontext2d_p.h"
+
+#include <QtGui/qpainter.h>
+
+QT_BEGIN_NAMESPACE
+
+Canvas::Canvas(QDeclarativeItem *parent)
+ : QDeclarativeItem(parent),
+ m_context(new Context2D(this)),
+ m_canvasWidth(0),
+ m_canvasHeight(0),
+ m_fillMode(Canvas::Stretch),
+ m_color(Qt::white)
+{
+ setFlag(QGraphicsItem::ItemHasNoContents, false);
+ setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+}
+
+
+void Canvas::componentComplete()
+{
+ if (m_canvasWidth == 0 && m_canvasHeight == 0)
+ m_context->setSize(width(), height());
+ else
+ m_context->setSize(m_canvasWidth, m_canvasHeight);
+
+ connect(m_context, SIGNAL(changed()), this, SLOT(requestPaint()));
+ emit init();
+ QDeclarativeItem::componentComplete();
+}
+
+void Canvas::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ m_context->setInPaint(true);
+ emit paint();
+
+ bool oldAA = painter->testRenderHint(QPainter::Antialiasing);
+ bool oldSmooth = painter->testRenderHint(QPainter::SmoothPixmapTransform);
+ if (smooth())
+ painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, smooth());
+
+ if (m_context->pixmap().isNull()) {
+ painter->fillRect(0, 0, width(), height(), m_color);
+ } else if (width() != m_context->pixmap().width() || height() != m_context->pixmap().height()) {
+ if (m_fillMode>= Tile) {
+ if (m_fillMode== Tile) {
+ painter->drawTiledPixmap(QRectF(0,0,width(),height()), m_context->pixmap());
+ } else {
+ qreal widthScale = width() / qreal(m_context->pixmap().width());
+ qreal heightScale = height() / qreal(m_context->pixmap().height());
+
+ QTransform scale;
+ if (m_fillMode== TileVertically) {
+ scale.scale(widthScale, 1.0);
+ QTransform old = painter->transform();
+ painter->setWorldTransform(scale * old);
+ painter->drawTiledPixmap(QRectF(0,0,m_context->pixmap().width(),height()), m_context->pixmap());
+ painter->setWorldTransform(old);
+ } else {
+ scale.scale(1.0, heightScale);
+ QTransform old = painter->transform();
+ painter->setWorldTransform(scale * old);
+ painter->drawTiledPixmap(QRectF(0,0,width(),m_context->pixmap().height()), m_context->pixmap());
+ painter->setWorldTransform(old);
+ }
+ }
+ } else {
+ qreal widthScale = width() / qreal(m_context->pixmap().width());
+ qreal heightScale = height() / qreal(m_context->pixmap().height());
+
+ QTransform scale;
+
+ if (m_fillMode== PreserveAspectFit) {
+ if (widthScale <= heightScale) {
+ heightScale = widthScale;
+ scale.translate(0, (height() - heightScale * m_context->pixmap().height()) / 2);
+ } else if (heightScale < widthScale) {
+ widthScale = heightScale;
+ scale.translate((width() - widthScale * m_context->pixmap().width()) / 2, 0);
+ }
+ } else if (m_fillMode== PreserveAspectCrop) {
+ if (widthScale < heightScale) {
+ widthScale = heightScale;
+ scale.translate((width() - widthScale * m_context->pixmap().width()) / 2, 0);
+ } else if (heightScale < widthScale) {
+ heightScale = widthScale;
+ scale.translate(0, (height() - heightScale * m_context->pixmap().height()) / 2);
+ }
+ }
+ if (clip()) {
+ painter->save();
+ painter->setClipRect(boundingRect(), Qt::IntersectClip);
+ }
+ scale.scale(widthScale, heightScale);
+ QTransform old = painter->transform();
+ painter->setWorldTransform(scale * old);
+ painter->drawPixmap(0, 0, m_context->pixmap());
+ painter->setWorldTransform(old);
+ if (clip()) {
+ painter->restore();
+ }
+ }
+ } else {
+ painter->drawPixmap(0, 0, m_context->pixmap());
+ }
+
+ if (smooth()) {
+ painter->setRenderHint(QPainter::Antialiasing, oldAA);
+ painter->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth);
+ }
+ m_context->setInPaint(false);
+}
+
+Context2D *Canvas::getContext(const QString &contextId)
+{
+ if (contextId == QLatin1String("2d"))
+ return m_context;
+ qDebug("Canvas:requesting unsupported context");
+ return 0;
+}
+
+void Canvas::requestPaint()
+{
+ update();
+}
+
+void Canvas::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ if (m_canvasWidth == 0 && m_canvasHeight == 0
+ && newGeometry.width() > 0 && newGeometry.height() > 0) {
+ m_context->setSize(width(), height());
+ }
+ QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+void Canvas::setCanvasWidth(int newWidth)
+{
+ if (m_canvasWidth != newWidth) {
+ m_canvasWidth = newWidth;
+ m_context->setSize(m_canvasWidth, m_canvasHeight);
+ emit canvasWidthChanged();
+ }
+}
+
+void Canvas::setCanvasHeight(int newHeight)
+{
+ if (m_canvasHeight != newHeight) {
+ m_canvasHeight = newHeight;
+ m_context->setSize(m_canvasWidth, m_canvasHeight);
+ emit canvasHeightChanged();
+ }
+}
+
+void Canvas::setFillMode(FillMode mode)
+{
+ if (m_fillMode == mode)
+ return;
+
+ m_fillMode = mode;
+ update();
+ emit fillModeChanged();
+}
+
+QColor Canvas::color()
+{
+ return m_color;
+}
+
+void Canvas::setColor(const QColor &color)
+{
+ if (m_color !=color) {
+ m_color = color;
+ colorChanged();
+ }
+}
+
+Canvas::FillMode Canvas::fillMode() const
+{
+ return m_fillMode;
+}
+
+bool Canvas::save(const QString &filename) const
+{
+ return m_context->pixmap().save(filename);
+}
+
+CanvasImage *Canvas::toImage() const
+{
+ return new CanvasImage(m_context->pixmap());
+}
+
+void Canvas::setTimeout(const QScriptValue &handler, long timeout)
+{
+ if (handler.isFunction())
+ CanvasTimer::createTimer(this, handler, timeout, true);
+}
+
+void Canvas::setInterval(const QScriptValue &handler, long interval)
+{
+ if (handler.isFunction())
+ CanvasTimer::createTimer(this, handler, interval, false);
+}
+
+void Canvas::clearTimeout(const QScriptValue &handler)
+{
+ CanvasTimer::removeTimer(handler);
+}
+
+void Canvas::clearInterval(const QScriptValue &handler)
+{
+ CanvasTimer::removeTimer(handler);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmlprofiler/canvas/qdeclarativecanvas_p.h b/src/plugins/qmlprofiler/canvas/qdeclarativecanvas_p.h
new file mode 100644
index 0000000000..72512258e5
--- /dev/null
+++ b/src/plugins/qmlprofiler/canvas/qdeclarativecanvas_p.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVECANVAS_P_H
+#define QDECLARATIVECANVAS_P_H
+
+#include <QtDeclarative/qdeclarativeitem.h>
+
+#include "qdeclarativecontext2d_p.h"
+#include "qdeclarativecanvastimer_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class Canvas : public QDeclarativeItem
+{
+ Q_OBJECT
+
+ Q_ENUMS(FillMode)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged);
+ Q_PROPERTY(int canvasWidth READ canvasWidth WRITE setCanvasWidth NOTIFY canvasWidthChanged);
+ Q_PROPERTY(int canvasHeight READ canvasHeight WRITE setCanvasHeight NOTIFY canvasHeightChanged);
+ Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged)
+
+public:
+ Canvas(QDeclarativeItem *parent = 0);
+ enum FillMode { Stretch, PreserveAspectFit, PreserveAspectCrop, Tile, TileVertically, TileHorizontally };
+
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
+ void setCanvasWidth(int newWidth);
+ int canvasWidth() {return m_canvasWidth;}
+
+ void setCanvasHeight(int canvasHeight);
+ int canvasHeight() {return m_canvasHeight;}
+
+ void componentComplete();
+
+
+public Q_SLOTS:
+ Context2D *getContext(const QString & = QString("2d"));
+ void requestPaint();
+
+ FillMode fillMode() const;
+ void setFillMode(FillMode);
+
+ QColor color();
+ void setColor(const QColor &);
+
+ // Save current canvas to disk
+ bool save(const QString& filename) const;
+
+ // Timers
+ void setInterval(const QScriptValue &handler, long timeout);
+ void setTimeout(const QScriptValue &handler, long timeout);
+ void clearInterval(const QScriptValue &handler);
+ void clearTimeout(const QScriptValue &handler);
+
+Q_SIGNALS:
+ void fillModeChanged();
+ void canvasWidthChanged();
+ void canvasHeightChanged();
+ void colorChanged();
+ void init();
+ void paint();
+
+private:
+ // Return canvas contents as a drawable image
+ CanvasImage *toImage() const;
+ Context2D *m_context;
+ int m_canvasWidth;
+ int m_canvasHeight;
+ FillMode m_fillMode;
+ QColor m_color;
+
+ friend class Context2D;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QDECLARATIVECANVAS_P_H
diff --git a/src/plugins/qmlprofiler/canvas/qdeclarativecanvastimer.cpp b/src/plugins/qmlprofiler/canvas/qdeclarativecanvastimer.cpp
new file mode 100644
index 0000000000..64e6be08d5
--- /dev/null
+++ b/src/plugins/qmlprofiler/canvas/qdeclarativecanvastimer.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#include <QtScript/qscriptengine.h>
+#include <QtScript/qscriptvalue.h>
+#include <QtCore/qtimer.h>
+
+#include "qdeclarativecanvastimer_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QList<CanvasTimer*> , activeTimers);
+
+CanvasTimer::CanvasTimer(QObject *parent, const QScriptValue &data)
+ : QTimer(parent), m_value(data)
+{
+}
+
+void CanvasTimer::handleTimeout()
+{
+ Q_ASSERT(m_value.isFunction());
+ m_value.call();
+ if (isSingleShot()) {
+ removeTimer(this);
+ }
+}
+
+void CanvasTimer::createTimer(QObject *parent, const QScriptValue &val, long timeout, bool singleshot)
+{
+
+ CanvasTimer *timer = new CanvasTimer(parent, val);
+ timer->setInterval(timeout);
+ timer->setSingleShot(singleshot);
+ connect(timer, SIGNAL(timeout()), timer, SLOT(handleTimeout()));
+ activeTimers()->append(timer);
+ timer->start();
+}
+
+void CanvasTimer::removeTimer(CanvasTimer *timer)
+{
+ activeTimers()->removeAll(timer);
+ timer->deleteLater();
+}
+
+void CanvasTimer::removeTimer(const QScriptValue &val)
+{
+ if (!val.isFunction())
+ return;
+
+ for (int i = 0 ; i < activeTimers()->count() ; ++i) {
+ CanvasTimer *timer = activeTimers()->at(i);
+ if (timer->equals(val)) {
+ removeTimer(timer);
+ return;
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/qmlprofiler/canvas/qdeclarativecanvastimer_p.h b/src/plugins/qmlprofiler/canvas/qdeclarativecanvastimer_p.h
new file mode 100644
index 0000000000..3e55d0260a
--- /dev/null
+++ b/src/plugins/qmlprofiler/canvas/qdeclarativecanvastimer_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVECANVASTIMER_P_H
+#define QDECLARATIVECANVASTIMER_P_H
+
+#include <QtScript/qscriptvalue.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class CanvasTimer : public QTimer
+{
+ Q_OBJECT
+
+public:
+ CanvasTimer(QObject *parent, const QScriptValue &data);
+
+public Q_SLOTS:
+ void handleTimeout();
+ bool equals(const QScriptValue &value){return m_value.equals(value);}
+
+public:
+ static void createTimer(QObject *parent, const QScriptValue &val, long timeout, bool singleshot);
+ static void removeTimer(CanvasTimer *timer);
+ static void removeTimer(const QScriptValue &);
+
+private:
+ QScriptValue m_value;
+
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVECANVASTIMER_P_H
diff --git a/src/plugins/qmlprofiler/canvas/qdeclarativecontext2d.cpp b/src/plugins/qmlprofiler/canvas/qdeclarativecontext2d.cpp
new file mode 100644
index 0000000000..dfabe1f46c
--- /dev/null
+++ b/src/plugins/qmlprofiler/canvas/qdeclarativecontext2d.cpp
@@ -0,0 +1,1139 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#include "qdeclarativecontext2d_p.h"
+
+#include "qdeclarativecanvas_p.h"
+
+#include <QtCore/qdebug.h>
+#include <math.h>
+
+#include <QtGui/qgraphicsitem.h>
+#include <QtGui/qapplication.h>
+#include <QtGui/qgraphicseffect.h>
+
+#include <QtGui/QImage>
+
+QT_BEGIN_NAMESPACE
+
+static const double Q_PI = 3.14159265358979323846; // pi
+
+class CustomDropShadowEffect : public QGraphicsDropShadowEffect
+{
+public:
+ void draw(QPainter *painter) { QGraphicsDropShadowEffect::draw(painter);}
+ void drawSource(QPainter *painter) { QGraphicsDropShadowEffect::drawSource(painter);}
+};
+
+// Note, this is exported but in a private header as qtopengl depends on it.
+// But it really should be considered private API
+void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0);
+void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0);
+
+#define DEGREES(t) ((t) * 180.0 / Q_PI)
+
+#define qClamp(val, min, max) qMin(qMax(val, min), max)
+static QList<qreal> parseNumbersList(QString::const_iterator &itr)
+{
+ QList<qreal> points;
+ QString temp;
+ while ((*itr).isSpace())
+ ++itr;
+ while ((*itr).isNumber() ||
+ (*itr) == '-' || (*itr) == '+' || (*itr) == '.') {
+ temp = QString();
+
+ if ((*itr) == '-')
+ temp += *itr++;
+ else if ((*itr) == '+')
+ temp += *itr++;
+ while ((*itr).isDigit())
+ temp += *itr++;
+ if ((*itr) == '.')
+ temp += *itr++;
+ while ((*itr).isDigit())
+ temp += *itr++;
+ while ((*itr).isSpace())
+ ++itr;
+ if ((*itr) == ',')
+ ++itr;
+ points.append(temp.toDouble());
+ //eat spaces
+ while ((*itr).isSpace())
+ ++itr;
+ }
+
+ return points;
+}
+
+QColor colorFromString(const QString &name)
+{
+ QString::const_iterator itr = name.constBegin();
+ QList<qreal> compo;
+ if (name.startsWith("rgba(")) {
+ ++itr; ++itr; ++itr; ++itr; ++itr;
+ compo = parseNumbersList(itr);
+ if (compo.size() != 4) {
+ return QColor();
+ }
+ //alpha seems to be always between 0-1
+ compo[3] *= 255;
+ return QColor((int)compo[0], (int)compo[1],
+ (int)compo[2], (int)compo[3]);
+ } else if (name.startsWith("rgb(")) {
+ ++itr; ++itr; ++itr; ++itr;
+ compo = parseNumbersList(itr);
+ if (compo.size() != 3) {
+ return QColor();
+ }
+ return QColor((int)qClamp(compo[0], qreal(0), qreal(255)),
+ (int)qClamp(compo[1], qreal(0), qreal(255)),
+ (int)qClamp(compo[2], qreal(0), qreal(255)));
+ } else if (name.startsWith("hsla(")){
+ ++itr; ++itr; ++itr; ++itr; ++itr;
+ compo = parseNumbersList(itr);
+ if (compo.size() != 4) {
+ return QColor();
+ }
+ return QColor::fromHslF(compo[0], compo[1],
+ compo[2], compo[3]);
+ } else if (name.startsWith("hsl(")){
+ ++itr; ++itr; ++itr; ++itr; ++itr;
+ compo = parseNumbersList(itr);
+ if (compo.size() != 3) {
+ return QColor();
+ }
+ return QColor::fromHslF(compo[0], compo[1],
+ compo[2]);
+ } else {
+ //QRgb color;
+ //CSSParser::parseColor(name, color);
+ return QColor(name);
+ }
+}
+
+
+static QPainter::CompositionMode compositeOperatorFromString(const QString &compositeOperator)
+{
+ if (compositeOperator == QLatin1String("source-over")) {
+ return QPainter::CompositionMode_SourceOver;
+ } else if (compositeOperator == QLatin1String("source-out")) {
+ return QPainter::CompositionMode_SourceOut;
+ } else if (compositeOperator == QLatin1String("source-in")) {
+ return QPainter::CompositionMode_SourceIn;
+ } else if (compositeOperator == QLatin1String("source-atop")) {
+ return QPainter::CompositionMode_SourceAtop;
+ } else if (compositeOperator == QLatin1String("destination-atop")) {
+ return QPainter::CompositionMode_DestinationAtop;
+ } else if (compositeOperator == QLatin1String("destination-in")) {
+ return QPainter::CompositionMode_DestinationIn;
+ } else if (compositeOperator == QLatin1String("destination-out")) {
+ return QPainter::CompositionMode_DestinationOut;
+ } else if (compositeOperator == QLatin1String("destination-over")) {
+ return QPainter::CompositionMode_DestinationOver;
+ } else if (compositeOperator == QLatin1String("darker")) {
+ return QPainter::CompositionMode_SourceOver;
+ } else if (compositeOperator == QLatin1String("lighter")) {
+ return QPainter::CompositionMode_SourceOver;
+ } else if (compositeOperator == QLatin1String("copy")) {
+ return QPainter::CompositionMode_Source;
+ } else if (compositeOperator == QLatin1String("xor")) {
+ return QPainter::CompositionMode_Xor;
+ }
+
+ return QPainter::CompositionMode_SourceOver;
+}
+
+static QString compositeOperatorToString(QPainter::CompositionMode op)
+{
+ switch (op) {
+ case QPainter::CompositionMode_SourceOver:
+ return "source-over";
+ case QPainter::CompositionMode_DestinationOver:
+ return "destination-over";
+ case QPainter::CompositionMode_Clear:
+ return "clear";
+ case QPainter::CompositionMode_Source:
+ return "source";
+ case QPainter::CompositionMode_Destination:
+ return "destination";
+ case QPainter::CompositionMode_SourceIn:
+ return "source-in";
+ case QPainter::CompositionMode_DestinationIn:
+ return "destination-in";
+ case QPainter::CompositionMode_SourceOut:
+ return "source-out";
+ case QPainter::CompositionMode_DestinationOut:
+ return "destination-out";
+ case QPainter::CompositionMode_SourceAtop:
+ return "source-atop";
+ case QPainter::CompositionMode_DestinationAtop:
+ return "destination-atop";
+ case QPainter::CompositionMode_Xor:
+ return "xor";
+ case QPainter::CompositionMode_Plus:
+ return "plus";
+ case QPainter::CompositionMode_Multiply:
+ return "multiply";
+ case QPainter::CompositionMode_Screen:
+ return "screen";
+ case QPainter::CompositionMode_Overlay:
+ return "overlay";
+ case QPainter::CompositionMode_Darken:
+ return "darken";
+ case QPainter::CompositionMode_Lighten:
+ return "lighten";
+ case QPainter::CompositionMode_ColorDodge:
+ return "color-dodge";
+ case QPainter::CompositionMode_ColorBurn:
+ return "color-burn";
+ case QPainter::CompositionMode_HardLight:
+ return "hard-light";
+ case QPainter::CompositionMode_SoftLight:
+ return "soft-light";
+ case QPainter::CompositionMode_Difference:
+ return "difference";
+ case QPainter::CompositionMode_Exclusion:
+ return "exclusion";
+ default:
+ break;
+ }
+ return QString();
+}
+
+void Context2D::save()
+{
+ m_stateStack.push(m_state);
+}
+
+
+void Context2D::restore()
+{
+ if (!m_stateStack.isEmpty()) {
+ m_state = m_stateStack.pop();
+ m_state.flags = AllIsFullOfDirt;
+ }
+}
+
+
+void Context2D::scale(qreal x, qreal y)
+{
+ m_state.matrix.scale(x, y);
+ m_state.flags |= DirtyTransformationMatrix;
+}
+
+
+void Context2D::rotate(qreal angle)
+{
+ m_state.matrix.rotate(DEGREES(angle));
+ m_state.flags |= DirtyTransformationMatrix;
+}
+
+
+void Context2D::translate(qreal x, qreal y)
+{
+ m_state.matrix.translate(x, y);
+ m_state.flags |= DirtyTransformationMatrix;
+}
+
+
+void Context2D::transform(qreal m11, qreal m12, qreal m21, qreal m22,
+ qreal dx, qreal dy)
+{
+ QMatrix mat(m11, m12,
+ m21, m22,
+ dx, dy);
+ m_state.matrix *= mat;
+ m_state.flags |= DirtyTransformationMatrix;
+}
+
+
+void Context2D::setTransform(qreal m11, qreal m12, qreal m21, qreal m22,
+ qreal dx, qreal dy)
+{
+ QMatrix mat(m11, m12,
+ m21, m22,
+ dx, dy);
+ m_state.matrix = mat;
+ m_state.flags |= DirtyTransformationMatrix;
+}
+
+
+QString Context2D::globalCompositeOperation() const
+{
+ return compositeOperatorToString(m_state.globalCompositeOperation);
+}
+
+void Context2D::setGlobalCompositeOperation(const QString &op)
+{
+ QPainter::CompositionMode mode =
+ compositeOperatorFromString(op);
+ m_state.globalCompositeOperation = mode;
+ m_state.flags |= DirtyGlobalCompositeOperation;
+}
+
+QVariant Context2D::strokeStyle() const
+{
+ return m_state.strokeStyle;
+}
+
+void Context2D::setStrokeStyle(const QVariant &style)
+{
+ CanvasGradient * gradient= qobject_cast<CanvasGradient*>(style.value<QObject*>());
+ if (gradient) {
+ m_state.strokeStyle = gradient->value();
+ } else {
+ QColor color = colorFromString(style.toString());
+ m_state.strokeStyle = color;
+ }
+ m_state.flags |= DirtyStrokeStyle;
+}
+
+QVariant Context2D::fillStyle() const
+{
+ return m_state.fillStyle;
+}
+
+void Context2D::setFillStyle(const QVariant &style)
+{
+ CanvasGradient * gradient= qobject_cast<CanvasGradient*>(style.value<QObject*>());
+ if (gradient) {
+ m_state.fillStyle = gradient->value();
+ } else {
+ QColor color = colorFromString(style.toString());
+ m_state.fillStyle = color;
+ }
+ m_state.flags |= DirtyFillStyle;
+}
+
+qreal Context2D::globalAlpha() const
+{
+ return m_state.globalAlpha;
+}
+
+void Context2D::setGlobalAlpha(qreal alpha)
+{
+ m_state.globalAlpha = alpha;
+ m_state.flags |= DirtyGlobalAlpha;
+}
+
+CanvasImage *Context2D::createImage(const QString &url)
+{
+ return new CanvasImage(url);
+}
+
+CanvasGradient *Context2D::createLinearGradient(qreal x0, qreal y0,
+ qreal x1, qreal y1)
+{
+ QLinearGradient g(x0, y0, x1, y1);
+ return new CanvasGradient(g);
+}
+
+
+CanvasGradient *Context2D::createRadialGradient(qreal x0, qreal y0,
+ qreal r0, qreal x1,
+ qreal y1, qreal r1)
+{
+ QRadialGradient g(QPointF(x1, y1), r0+r1, QPointF(x0, y0));
+ return new CanvasGradient(g);
+}
+
+qreal Context2D::lineWidth() const
+{
+ return m_state.lineWidth;
+}
+
+void Context2D::setLineWidth(qreal w)
+{
+ m_state.lineWidth = w;
+ m_state.flags |= DirtyLineWidth;
+}
+
+QString Context2D::lineCap() const
+{
+ switch (m_state.lineCap) {
+ case Qt::FlatCap:
+ return "butt";
+ case Qt::SquareCap:
+ return "square";
+ case Qt::RoundCap:
+ return "round";
+ default: ;
+ }
+ return QString();
+}
+
+void Context2D::setLineCap(const QString &capString)
+{
+ Qt::PenCapStyle style;
+ if (capString == QLatin1String("round"))
+ style = Qt::RoundCap;
+ else if (capString == QLatin1String("square"))
+ style = Qt::SquareCap;
+ else //if (capString == "butt")
+ style = Qt::FlatCap;
+ m_state.lineCap = style;
+ m_state.flags |= DirtyLineCap;
+}
+
+QString Context2D::lineJoin() const
+{
+ switch (m_state.lineJoin) {
+ case Qt::RoundJoin:
+ return QLatin1String("round");
+ case Qt::BevelJoin:
+ return QLatin1String("bevel");
+ case Qt::MiterJoin:
+ return QLatin1String("miter");
+ default: ;
+ }
+ return QString();
+}
+
+void Context2D::setLineJoin(const QString &joinString)
+{
+ Qt::PenJoinStyle style;
+ if (joinString == QLatin1String("round"))
+ style = Qt::RoundJoin;
+ else if (joinString == QLatin1String("bevel"))
+ style = Qt::BevelJoin;
+ else //if (joinString == "miter")
+ style = Qt::MiterJoin;
+ m_state.lineJoin = style;
+ m_state.flags |= DirtyLineJoin;
+}
+
+qreal Context2D::miterLimit() const
+{
+ return m_state.miterLimit;
+}
+
+void Context2D::setMiterLimit(qreal m)
+{
+ m_state.miterLimit = m;
+ m_state.flags |= DirtyMiterLimit;
+}
+
+void Context2D::setShadowOffsetX(qreal x)
+{
+ if (m_state.shadowOffsetX == x)
+ return;
+ m_state.shadowOffsetX = x;
+ updateShadowBuffer();
+ if (m_painter.device() == &m_shadowbuffer && m_state.shadowBlur>0)
+ endPainting();
+ m_state.flags |= DirtyShadowOffsetX;
+}
+
+const QList<Context2D::MouseArea> &Context2D::mouseAreas() const
+{
+ return m_mouseAreas;
+}
+
+void Context2D::updateShadowBuffer() {
+ if (m_shadowbuffer.isNull() || m_shadowbuffer.width() != m_width+m_state.shadowOffsetX ||
+ m_shadowbuffer.height() != m_height+m_state.shadowOffsetY) {
+ m_shadowbuffer = QImage(m_width+m_state.shadowOffsetX, m_height+m_state.shadowOffsetY, QImage::Format_ARGB32);
+ m_shadowbuffer.fill(Qt::transparent);
+ }
+}
+
+void Context2D::setShadowOffsetY(qreal y)
+{
+ if (m_state.shadowOffsetY == y)
+ return;
+ m_state.shadowOffsetY = y;
+ updateShadowBuffer();
+ if (m_painter.device() == &m_shadowbuffer && m_state.shadowBlur>0)
+ endPainting();
+
+ m_state.flags |= DirtyShadowOffsetY;
+}
+
+void Context2D::setShadowBlur(qreal b)
+{
+ if (m_state.shadowBlur == b)
+ return;
+ m_state.shadowBlur = b;
+ updateShadowBuffer();
+ if (m_painter.device() == &m_shadowbuffer && m_state.shadowBlur>0)
+ endPainting();
+ m_state.flags |= DirtyShadowBlur;
+}
+
+void Context2D::setShadowColor(const QString &str)
+{
+ m_state.shadowColor = colorFromString(str);
+ if (m_painter.device() == &m_shadowbuffer && m_state.shadowBlur>0)
+ endPainting();
+ m_state.flags |= DirtyShadowColor;
+}
+
+QString Context2D::textBaseline()
+{
+ switch (m_state.textBaseline) {
+ case Context2D::Alphabetic:
+ return QLatin1String("alphabetic");
+ case Context2D::Hanging:
+ return QLatin1String("hanging");
+ case Context2D::Bottom:
+ return QLatin1String("bottom");
+ case Context2D::Top:
+ return QLatin1String("top");
+ case Context2D::Middle:
+ return QLatin1String("middle");
+ default:
+ Q_ASSERT("invalid value");
+ return QLatin1String("start");
+ }
+}
+
+void Context2D::setTextBaseline(const QString &baseline)
+{
+ if (baseline==QLatin1String("alphabetic"))
+ m_state.textBaseline = Context2D::Alphabetic;
+ else if (baseline == QLatin1String("hanging"))
+ m_state.textBaseline = Context2D::Hanging;
+ else if (baseline == QLatin1String("top"))
+ m_state.textBaseline = Context2D::Top;
+ else if (baseline == QLatin1String("bottom"))
+ m_state.textBaseline = Context2D::Bottom;
+ else if (baseline == QLatin1String("middle"))
+ m_state.textBaseline = Context2D::Middle;
+ else {
+ m_state.textBaseline = Context2D::Alphabetic;
+ qWarning() << ("Context2D: invalid baseline:" + baseline);
+ }
+ m_state.flags |= DirtyTextBaseline;
+}
+
+QString Context2D::textAlign()
+{
+ switch (m_state.textAlign) {
+ case Context2D::Left:
+ return QLatin1String("left");
+ case Context2D::Right:
+ return QLatin1String("right");
+ case Context2D::Center:
+ return QLatin1String("center");
+ case Context2D::Start:
+ return QLatin1String("start");
+ case Context2D::End:
+ return QLatin1String("end");
+ default:
+ Q_ASSERT("invalid value");
+ qWarning() << ("Context2D::invalid textAlign");
+ return QLatin1String("start");
+ }
+}
+
+void Context2D::setTextAlign(const QString &baseline)
+{
+ if (baseline==QLatin1String("start"))
+ m_state.textAlign = Context2D::Start;
+ else if (baseline == QLatin1String("end"))
+ m_state.textAlign = Context2D::End;
+ else if (baseline == QLatin1String("left"))
+ m_state.textAlign = Context2D::Left;
+ else if (baseline == QLatin1String("right"))
+ m_state.textAlign = Context2D::Right;
+ else if (baseline == QLatin1String("center"))
+ m_state.textAlign = Context2D::Center;
+ else {
+ m_state.textAlign= Context2D::Start;
+ qWarning("Context2D: invalid text align");
+ }
+ // ### alphabetic, ideographic, hanging
+ m_state.flags |= DirtyTextBaseline;
+}
+
+void Context2D::setFont(const QString &fontString)
+{
+ QFont font;
+ // ### this is simplified and incomplete
+ QStringList tokens = fontString.split(" ");
+ foreach (const QString &token, tokens) {
+ if (token == QLatin1String("italic"))
+ font.setItalic(true);
+ else if (token == QLatin1String("bold"))
+ font.setBold(true);
+ else if (token.endsWith(QLatin1String("px"))) {
+ QString number = token;
+ number.remove("px");
+ font.setPointSizeF(number.trimmed().toFloat());
+ } else
+ font.setFamily(token);
+ }
+ m_state.font = font;
+ m_state.flags |= DirtyFont;
+}
+
+QString Context2D::font()
+{
+ return m_state.font.toString();
+}
+
+qreal Context2D::shadowOffsetX() const
+{
+ return m_state.shadowOffsetX;
+}
+
+qreal Context2D::shadowOffsetY() const
+{
+ return m_state.shadowOffsetY;
+}
+
+
+qreal Context2D::shadowBlur() const
+{
+ return m_state.shadowBlur;
+}
+
+
+QString Context2D::shadowColor() const
+{
+ return m_state.shadowColor.name();
+}
+
+
+void Context2D::clearRect(qreal x, qreal y, qreal w, qreal h)
+{
+ beginPainting();
+ m_painter.save();
+ m_painter.setMatrix(worldMatrix(), false);
+ m_painter.setCompositionMode(QPainter::CompositionMode_Source);
+ QColor fillColor = parent()->property("color").value<QColor>();
+
+ m_painter.fillRect(QRectF(x, y, w, h), fillColor);
+ m_painter.restore();
+ scheduleChange();
+}
+
+void Context2D::fillRect(qreal x, qreal y, qreal w, qreal h)
+{
+ beginPainting();
+ m_painter.save();
+ m_painter.setMatrix(worldMatrix(), false);
+ m_painter.fillRect(QRectF(x, y, w, h), m_painter.brush());
+ m_painter.restore();
+ scheduleChange();
+}
+
+int Context2D::baseLineOffset(Context2D::TextBaseLine value, const QFontMetrics &metrics)
+{
+ int offset = 0;
+ switch (value) {
+ case Context2D::Top:
+ break;
+ case Context2D::Alphabetic:
+ case Context2D::Middle:
+ case Context2D::Hanging:
+ offset = metrics.ascent();
+ break;
+ case Context2D::Bottom:
+ offset = metrics.height();
+ break;
+ }
+ return offset;
+}
+
+int Context2D::textAlignOffset(Context2D::TextAlign value, const QFontMetrics &metrics, const QString &text)
+{
+ int offset = 0;
+ if (value == Context2D::Start)
+ value = qApp->layoutDirection() == Qt::LeftToRight ? Context2D::Left : Context2D::Right;
+ else if (value == Context2D::End)
+ value = qApp->layoutDirection() == Qt::LeftToRight ? Context2D::Right: Context2D::Left;
+ switch (value) {
+ case Context2D::Center:
+ offset = metrics.width(text)/2;
+ break;
+ case Context2D::Right:
+ offset = metrics.width(text);
+ case Context2D::Left:
+ default:
+ break;
+ }
+ return offset;
+}
+
+void Context2D::fillText(const QString &text, qreal x, qreal y)
+{
+ beginPainting();
+ m_painter.save();
+ m_painter.setPen(QPen(m_state.fillStyle, m_state.lineWidth));
+ m_painter.setMatrix(worldMatrix(), false);
+ QFont font;
+ font.setBold(true);
+ m_painter.setFont(m_state.font);
+ int yoffset = baseLineOffset(m_state.textBaseline, m_painter.fontMetrics());
+ int xoffset = textAlignOffset(m_state.textAlign, m_painter.fontMetrics(), text);
+ QTextOption opt; // Adjust baseLine etc
+ m_painter.drawText(QRectF(x-xoffset, y-yoffset, QWIDGETSIZE_MAX, m_painter.fontMetrics().height()), text, opt);
+ m_painter.restore();
+ endPainting();
+ scheduleChange();
+}
+
+void Context2D::strokeText(const QString &text, qreal x, qreal y)
+{
+ beginPainting();
+ m_painter.save();
+ m_painter.setPen(QPen(m_state.fillStyle,0));
+ m_painter.setMatrix(worldMatrix(), false);
+
+ QPainterPath textPath;
+ QFont font = m_state.font;
+ font.setStyleStrategy(QFont::ForceOutline);
+ m_painter.setFont(font);
+ const QFontMetrics &metrics = m_painter.fontMetrics();
+ int yoffset = baseLineOffset(m_state.textBaseline, metrics);
+ int xoffset = textAlignOffset(m_state.textAlign, metrics, text);
+ textPath.addText(x-xoffset, y-yoffset+metrics.ascent(), font, text);
+ m_painter.strokePath(textPath, QPen(m_state.fillStyle, m_state.lineWidth));
+ m_painter.restore();
+ endPainting();
+ scheduleChange();
+}
+
+void Context2D::strokeRect(qreal x, qreal y, qreal w, qreal h)
+{
+ QPainterPath path;
+ path.addRect(x, y, w, h);
+ beginPainting();
+ m_painter.save();
+ m_painter.setMatrix(worldMatrix(), false);
+ m_painter.strokePath(path, m_painter.pen());
+ m_painter.restore();
+ scheduleChange();
+}
+
+void Context2D::mouseArea(qreal x, qreal y, qreal w, qreal h, const QScriptValue &callback,
+ const QScriptValue &data)
+{
+ MouseArea a = { callback, data, QRectF(x, y, w, h), m_state.matrix };
+ m_mouseAreas << a;
+}
+
+void Context2D::beginPath()
+{
+ m_path = QPainterPath();
+}
+
+
+void Context2D::closePath()
+{
+ m_path.closeSubpath();
+}
+
+
+void Context2D::moveTo(qreal x, qreal y)
+{
+ QPointF pt = worldMatrix().map(QPointF(x, y));
+ m_path.moveTo(pt);
+}
+
+
+void Context2D::lineTo(qreal x, qreal y)
+{
+ QPointF pt = worldMatrix().map(QPointF(x, y));
+ m_path.lineTo(pt);
+}
+
+
+void Context2D::quadraticCurveTo(qreal cpx, qreal cpy, qreal x, qreal y)
+{
+ QPointF cp = worldMatrix().map(QPointF(cpx, cpy));
+ QPointF xy = worldMatrix().map(QPointF(x, y));
+ m_path.quadTo(cp, xy);
+}
+
+
+void Context2D::bezierCurveTo(qreal cp1x, qreal cp1y,
+ qreal cp2x, qreal cp2y, qreal x, qreal y)
+{
+ QPointF cp1 = worldMatrix().map(QPointF(cp1x, cp1y));
+ QPointF cp2 = worldMatrix().map(QPointF(cp2x, cp2y));
+ QPointF end = worldMatrix().map(QPointF(x, y));
+ m_path.cubicTo(cp1, cp2, end);
+}
+
+
+void Context2D::arcTo(qreal x1, qreal y1, qreal x2, qreal y2, qreal radius)
+{
+ //FIXME: this is surely busted
+ QPointF st = worldMatrix().map(QPointF(x1, y1));
+ QPointF end = worldMatrix().map(QPointF(x2, y2));
+ m_path.arcTo(st.x(), st.y(),
+ end.x()-st.x(), end.y()-st.y(),
+ radius, 90);
+}
+
+
+void Context2D::rect(qreal x, qreal y, qreal w, qreal h)
+{
+ QPainterPath path; path.addRect(x, y, w, h);
+ path = worldMatrix().map(path);
+ m_path.addPath(path);
+}
+
+void Context2D::arc(qreal xc, qreal yc, qreal radius,
+ qreal sar, qreal ear,
+ bool anticlockwise)
+{
+ //### HACK
+ // In Qt we don't switch the coordinate system for degrees
+ // and still use the 0,0 as bottom left for degrees so we need
+ // to switch
+ sar = -sar;
+ ear = -ear;
+ anticlockwise = !anticlockwise;
+ //end hack
+
+ float sa = DEGREES(sar);
+ float ea = DEGREES(ear);
+
+ double span = 0;
+
+ double xs = xc - radius;
+ double ys = yc - radius;
+ double width = radius*2;
+ double height = radius*2;
+
+ if (!anticlockwise && (ea < sa)) {
+ span += 360;
+ } else if (anticlockwise && (sa < ea)) {
+ span -= 360;
+ }
+
+ //### this is also due to switched coordinate system
+ // we would end up with a 0 span instead of 360
+ if (!(qFuzzyCompare(span + (ea - sa) + 1, 1) &&
+ qFuzzyCompare(qAbs(span), 360))) {
+ span += ea - sa;
+ }
+
+ QPainterPath path;
+ path.moveTo(QPointF(xc + radius * cos(sar),
+ yc - radius * sin(sar)));
+
+ path.arcTo(xs, ys, width, height, sa, span);
+ path = worldMatrix().map(path);
+ m_path.addPath(path);
+}
+
+
+void Context2D::fill()
+{
+ beginPainting();
+ m_painter.fillPath(m_path, m_painter.brush());
+ scheduleChange();
+}
+
+
+void Context2D::stroke()
+{
+ beginPainting();
+ m_painter.save();
+ m_painter.setMatrix(worldMatrix(), false);
+ QPainterPath tmp = worldMatrix().inverted().map(m_path);
+ m_painter.strokePath(tmp, m_painter.pen());
+ m_painter.restore();
+ scheduleChange();
+}
+
+
+void Context2D::clip()
+{
+ m_state.clipPath = m_path;
+ m_state.flags |= DirtyClippingRegion;
+}
+
+
+bool Context2D::isPointInPath(qreal x, qreal y) const
+{
+ return m_path.contains(QPointF(x, y));
+}
+
+
+ImageData Context2D::getImageData(qreal sx, qreal sy, qreal sw, qreal sh)
+{
+ Q_UNUSED(sx);
+ Q_UNUSED(sy);
+ Q_UNUSED(sw);
+ Q_UNUSED(sh);
+ return ImageData();
+}
+
+
+void Context2D::putImageData(ImageData image, qreal dx, qreal dy)
+{
+ Q_UNUSED(image);
+ Q_UNUSED(dx);
+ Q_UNUSED(dy);
+}
+
+Context2D::Context2D(QObject *parent)
+ : QObject(parent), m_changeTimerId(-1), m_width(0), m_height(0), m_inPaint(false)
+{
+ reset();
+}
+
+void Context2D::setupPainter()
+{
+ m_painter.setRenderHint(QPainter::Antialiasing, true);
+ if ((m_state.flags & DirtyClippingRegion) && !m_state.clipPath.isEmpty())
+ m_painter.setClipPath(m_state.clipPath);
+ if (m_state.flags & DirtyFillStyle)
+ m_painter.setBrush(m_state.fillStyle);
+ if (m_state.flags & DirtyGlobalAlpha)
+ m_painter.setOpacity(m_state.globalAlpha);
+ if (m_state.flags & DirtyGlobalCompositeOperation)
+ m_painter.setCompositionMode(m_state.globalCompositeOperation);
+ if (m_state.flags & MDirtyPen) {
+ QPen pen = m_painter.pen();
+ if (m_state.flags & DirtyStrokeStyle)
+ pen.setBrush(m_state.strokeStyle);
+ if (m_state.flags & DirtyLineWidth)
+ pen.setWidthF(m_state.lineWidth);
+ if (m_state.flags & DirtyLineCap)
+ pen.setCapStyle(m_state.lineCap);
+ if (m_state.flags & DirtyLineJoin)
+ pen.setJoinStyle(m_state.lineJoin);
+ if (m_state.flags & DirtyMiterLimit)
+ pen.setMiterLimit(m_state.miterLimit);
+ m_painter.setPen(pen);
+ }
+}
+
+void Context2D::beginPainting()
+{
+ if (m_width <= 0 || m_height <=0)
+ return;
+
+ if (m_pixmap.width() != m_width || m_pixmap.height() != m_height) {
+ m_pixmap = QPixmap(m_width, m_height);
+ m_pixmap.fill(parent()->property("color").value<QColor>());
+ }
+
+ if (m_state.shadowBlur > 0 && m_painter.device() != &m_shadowbuffer) {
+ if (m_painter.isActive())
+ m_painter.end();
+ updateShadowBuffer();
+ m_painter.begin(&m_shadowbuffer);
+ m_painter.setViewport(m_state.shadowOffsetX,
+ m_state.shadowOffsetY,
+ m_shadowbuffer.width(),
+ m_shadowbuffer.height());
+ m_shadowbuffer.fill(Qt::transparent);
+ }
+
+ if (!m_painter.isActive()) {
+ m_painter.begin(&m_pixmap);
+ m_painter.setRenderHint(QPainter::Antialiasing);
+ if (!m_state.clipPath.isEmpty())
+ m_painter.setClipPath(m_state.clipPath);
+ m_painter.setBrush(m_state.fillStyle);
+ m_painter.setOpacity(m_state.globalAlpha);
+ QPen pen;
+ pen.setBrush(m_state.strokeStyle);
+ if (pen.style() == Qt::NoPen)
+ pen.setStyle(Qt::SolidLine);
+ pen.setCapStyle(m_state.lineCap);
+ pen.setJoinStyle(m_state.lineJoin);
+ pen.setWidthF(m_state.lineWidth);
+ pen.setMiterLimit(m_state.miterLimit);
+ m_painter.setPen(pen);
+ } else {
+ setupPainter();
+ m_state.flags = 0;
+ }
+}
+
+void Context2D::endPainting()
+{
+ if (m_state.shadowBlur > 0) {
+ QImage alphaChannel = m_shadowbuffer.alphaChannel();
+
+ qt_blurImage(alphaChannel, m_state.shadowBlur, false, 1);
+
+ QRect imageRect = m_shadowbuffer.rect();
+
+ if (m_shadowColorIndexBuffer.isEmpty() || m_shadowColorBuffer != m_state.shadowColor) {
+ m_shadowColorIndexBuffer.clear();
+ m_shadowColorBuffer = m_state.shadowColor;
+
+ for (int i = 0; i < 256; ++i) {
+ m_shadowColorIndexBuffer << qRgba(qRound(255 * m_state.shadowColor.redF()),
+ qRound(255 * m_state.shadowColor.greenF()),
+ qRound(255 * m_state.shadowColor.blueF()),
+ i);
+ }
+ }
+ alphaChannel.setColorTable(m_shadowColorIndexBuffer);
+
+ if (m_painter.isActive())
+ m_painter.end();
+
+ m_painter.begin(&m_pixmap);
+
+ // draw the blurred drop shadow...
+ m_painter.save();
+ QTransform tf = m_painter.transform();
+ m_painter.translate(0, imageRect.height());
+ m_painter.rotate(-90);
+ m_painter.drawImage(0, 0, alphaChannel);
+ m_painter.setTransform(tf);
+ m_painter.restore();
+
+ // draw source
+ m_painter.drawImage(-m_state.shadowOffsetX, -m_state.shadowOffsetY, m_shadowbuffer.copy());
+ m_painter.end();
+ }
+}
+
+void Context2D::clear()
+{
+ m_painter.fillRect(QRect(QPoint(0,0), size()), Qt::white);
+}
+
+void Context2D::reset()
+{
+ m_stateStack.clear();
+ m_state.matrix = QMatrix();
+ m_state.clipPath = QPainterPath();
+ m_state.strokeStyle = Qt::black;
+ m_state.fillStyle = Qt::black;
+ m_state.globalAlpha = 1.0;
+ m_state.lineWidth = 1;
+ m_state.lineCap = Qt::FlatCap;
+ m_state.lineJoin = Qt::MiterJoin;
+ m_state.miterLimit = 10;
+ m_state.shadowOffsetX = 0;
+ m_state.shadowOffsetY = 0;
+ m_state.shadowBlur = 0;
+ m_state.shadowColor = qRgba(0, 0, 0, 0);
+ m_state.globalCompositeOperation = QPainter::CompositionMode_SourceOver;
+ m_state.font = QFont();
+ m_state.textAlign = Start;
+ m_state.textBaseline = Alphabetic;
+ m_state.flags = AllIsFullOfDirt;
+ m_mouseAreas.clear();
+ clear();
+}
+
+void Context2D::drawImage(const QVariant &var, qreal sx, qreal sy,
+ qreal sw = 0, qreal sh = 0)
+{
+ CanvasImage *image = qobject_cast<CanvasImage*>(var.value<QObject*>());
+ if (!image) {
+ Canvas *canvas = qobject_cast<Canvas*>(var.value<QObject*>());
+ if (canvas)
+ image = canvas->toImage();
+ }
+ if (image) {
+ beginPainting();
+ if (sw == sh && sh == 0)
+ m_painter.drawPixmap(QPointF(sx, sy), image->value());
+ else
+ m_painter.drawPixmap(QRect(sx, sy, sw, sh), image->value());
+
+ scheduleChange();
+ }
+}
+
+void Context2D::setSize(int width, int height)
+{
+ endPainting();
+ m_width = width;
+ m_height = height;
+
+ scheduleChange();
+}
+
+void Context2D::setSize(const QSize &size)
+{
+ setSize(size.width(), size.height());
+}
+
+QSize Context2D::size() const
+{
+ return m_pixmap.size();
+}
+
+QPoint Context2D::painterTranslate() const
+{
+ return m_painterTranslate;
+}
+
+void Context2D::setPainterTranslate(const QPoint &translate)
+{
+ m_painterTranslate = translate;
+ m_state.flags |= DirtyTransformationMatrix;
+}
+
+void Context2D::scheduleChange()
+{
+ if (m_changeTimerId == -1 && !m_inPaint)
+ m_changeTimerId = startTimer(0);
+}
+
+void Context2D::timerEvent(QTimerEvent *e)
+{
+ if (e->timerId() == m_changeTimerId) {
+ killTimer(m_changeTimerId);
+ m_changeTimerId = -1;
+ endPainting();
+ emit changed();
+ } else {
+ QObject::timerEvent(e);
+ }
+}
+
+QMatrix Context2D::worldMatrix() const
+{
+ QMatrix mat;
+ mat.translate(m_painterTranslate.x(), m_painterTranslate.y());
+ mat *= m_state.matrix;
+ return mat;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmlprofiler/canvas/qdeclarativecontext2d_p.h b/src/plugins/qmlprofiler/canvas/qdeclarativecontext2d_p.h
new file mode 100644
index 0000000000..6b7d605f6f
--- /dev/null
+++ b/src/plugins/qmlprofiler/canvas/qdeclarativecontext2d_p.h
@@ -0,0 +1,336 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVECONTEXT2D_P_H
+#define QDECLARATIVECONTEXT2D_P_H
+
+#include <QtGui/qpainter.h>
+#include <QtGui/qpainterpath.h>
+#include <QtGui/qpixmap.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qstack.h>
+#include <QtCore/qmetatype.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qvariant.h>
+#include <QtScript/qscriptvalue.h>
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+QColor colorFromString(const QString &name);
+
+class CanvasGradient : public QObject
+{
+ Q_OBJECT
+public:
+ CanvasGradient(const QGradient &gradient) : m_gradient(gradient) {}
+
+public slots:
+ QGradient value() { return m_gradient; }
+ void addColorStop(float pos, const QString &color) { m_gradient.setColorAt(pos, colorFromString(color));}
+
+public:
+ QGradient m_gradient;
+};
+
+class CanvasImage: public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString src READ src WRITE setSrc NOTIFY sourceChanged)
+ Q_PROPERTY(int width READ width)
+ Q_PROPERTY(int height READ height)
+
+public:
+ CanvasImage() {}
+ CanvasImage(const QString &url) : m_image(url), m_src(url) {}
+ CanvasImage(const QPixmap &pixmap) {m_image = pixmap;}
+
+public slots:
+ int width() { return m_image.width(); }
+ int height() { return m_image.height(); }
+ QPixmap &value() { return m_image; }
+ QString src() { return m_src; }
+ void setSrc(const QString &src) { m_src = src; m_image.load(src); emit sourceChanged();}
+signals:
+ void sourceChanged();
+
+private:
+ QPixmap m_image;
+ QString m_src;
+};
+
+
+class ImageData {
+};
+
+class Context2D : public QObject
+{
+ Q_OBJECT
+ // compositing
+ Q_PROPERTY(qreal globalAlpha READ globalAlpha WRITE setGlobalAlpha)
+ Q_PROPERTY(QString globalCompositeOperation READ globalCompositeOperation WRITE setGlobalCompositeOperation)
+ Q_PROPERTY(QVariant strokeStyle READ strokeStyle WRITE setStrokeStyle)
+ Q_PROPERTY(QVariant fillStyle READ fillStyle WRITE setFillStyle)
+ // line caps/joins
+ Q_PROPERTY(qreal lineWidth READ lineWidth WRITE setLineWidth)
+ Q_PROPERTY(QString lineCap READ lineCap WRITE setLineCap)
+ Q_PROPERTY(QString lineJoin READ lineJoin WRITE setLineJoin)
+ Q_PROPERTY(qreal miterLimit READ miterLimit WRITE setMiterLimit)
+ // shadows
+ Q_PROPERTY(qreal shadowOffsetX READ shadowOffsetX WRITE setShadowOffsetX)
+ Q_PROPERTY(qreal shadowOffsetY READ shadowOffsetY WRITE setShadowOffsetY)
+ Q_PROPERTY(qreal shadowBlur READ shadowBlur WRITE setShadowBlur)
+ Q_PROPERTY(QString shadowColor READ shadowColor WRITE setShadowColor)
+ // fonts
+ Q_PROPERTY(QString font READ font WRITE setFont)
+ Q_PROPERTY(QString textBaseline READ textBaseline WRITE setTextBaseline)
+ Q_PROPERTY(QString textAlign READ textAlign WRITE setTextAlign)
+
+ enum TextBaseLine { Alphabetic=0, Top, Middle, Bottom, Hanging};
+ enum TextAlign { Start=0, End, Left, Right, Center};
+
+public:
+ Context2D(QObject *parent = 0);
+ void setSize(int width, int height);
+ void setSize(const QSize &size);
+ QSize size() const;
+
+ QPoint painterTranslate() const;
+ void setPainterTranslate(const QPoint &);
+
+ void scheduleChange();
+ void timerEvent(QTimerEvent *e);
+
+ void clear();
+ void reset();
+
+ QPixmap pixmap() { return m_pixmap; }
+
+ // compositing
+ qreal globalAlpha() const; // (default 1.0)
+ QString globalCompositeOperation() const; // (default over)
+ QVariant strokeStyle() const; // (default black)
+ QVariant fillStyle() const; // (default black)
+
+ void setGlobalAlpha(qreal alpha);
+ void setGlobalCompositeOperation(const QString &op);
+ void setStrokeStyle(const QVariant &style);
+ void setFillStyle(const QVariant &style);
+
+ // line caps/joins
+ qreal lineWidth() const; // (default 1)
+ QString lineCap() const; // "butt", "round", "square" (default "butt")
+ QString lineJoin() const; // "round", "bevel", "miter" (default "miter")
+ qreal miterLimit() const; // (default 10)
+
+ void setLineWidth(qreal w);
+ void setLineCap(const QString &s);
+ void setLineJoin(const QString &s);
+ void setMiterLimit(qreal m);
+
+ void setFont(const QString &font);
+ QString font();
+ void setTextBaseline(const QString &font);
+ QString textBaseline();
+ void setTextAlign(const QString &font);
+ QString textAlign();
+
+ // shadows
+ qreal shadowOffsetX() const; // (default 0)
+ qreal shadowOffsetY() const; // (default 0)
+ qreal shadowBlur() const; // (default 0)
+ QString shadowColor() const; // (default black)
+
+ void setShadowOffsetX(qreal x);
+ void setShadowOffsetY(qreal y);
+ void setShadowBlur(qreal b);
+ void setShadowColor(const QString &str);
+
+ struct MouseArea {
+ QScriptValue callback;
+ QScriptValue data;
+ QRectF rect;
+ QMatrix matrix;
+ };
+ const QList<MouseArea> &mouseAreas() const;
+
+public slots:
+ void save(); // push state on state stack
+ void restore(); // pop state stack and restore state
+
+ void fillText(const QString &text, qreal x, qreal y);
+ void strokeText(const QString &text, qreal x, qreal y);
+
+ void setInPaint(bool val){m_inPaint = val;}
+ void scale(qreal x, qreal y);
+ void rotate(qreal angle);
+ void translate(qreal x, qreal y);
+ void transform(qreal m11, qreal m12, qreal m21, qreal m22,
+ qreal dx, qreal dy);
+ void setTransform(qreal m11, qreal m12, qreal m21, qreal m22,
+ qreal dx, qreal dy);
+
+ CanvasGradient *createLinearGradient(qreal x0, qreal y0,
+ qreal x1, qreal y1);
+ CanvasGradient *createRadialGradient(qreal x0, qreal y0,
+ qreal r0, qreal x1,
+ qreal y1, qreal r1);
+
+ // rects
+ void clearRect(qreal x, qreal y, qreal w, qreal h);
+ void fillRect(qreal x, qreal y, qreal w, qreal h);
+ void strokeRect(qreal x, qreal y, qreal w, qreal h);
+
+ // mouse
+ void mouseArea(qreal x, qreal y, qreal w, qreal h, const QScriptValue &, const QScriptValue & = QScriptValue());
+
+ // path API
+ void beginPath();
+ void closePath();
+ void moveTo(qreal x, qreal y);
+ void lineTo(qreal x, qreal y);
+ void quadraticCurveTo(qreal cpx, qreal cpy, qreal x, qreal y);
+ void bezierCurveTo(qreal cp1x, qreal cp1y,
+ qreal cp2x, qreal cp2y, qreal x, qreal y);
+ void arcTo(qreal x1, qreal y1, qreal x2, qreal y2, qreal radius);
+ void rect(qreal x, qreal y, qreal w, qreal h);
+ void arc(qreal x, qreal y, qreal radius,
+ qreal startAngle, qreal endAngle,
+ bool anticlockwise);
+ void fill();
+ void stroke();
+ void clip();
+ bool isPointInPath(qreal x, qreal y) const;
+
+ CanvasImage *createImage(const QString &url);
+
+ // drawing images (no overloads due to QTBUG-11604)
+ void drawImage(const QVariant &var, qreal dx, qreal dy, qreal dw, qreal dh);
+
+ // pixel manipulation
+ ImageData getImageData(qreal sx, qreal sy, qreal sw, qreal sh);
+ void putImageData(ImageData image, qreal dx, qreal dy);
+ void endPainting();
+
+signals:
+ void changed();
+
+private:
+ void setupPainter();
+ void beginPainting();
+ void updateShadowBuffer();
+
+ int m_changeTimerId;
+ QPainterPath m_path;
+
+ enum DirtyFlag {
+ DirtyTransformationMatrix = 0x00001,
+ DirtyClippingRegion = 0x00002,
+ DirtyStrokeStyle = 0x00004,
+ DirtyFillStyle = 0x00008,
+ DirtyGlobalAlpha = 0x00010,
+ DirtyLineWidth = 0x00020,
+ DirtyLineCap = 0x00040,
+ DirtyLineJoin = 0x00080,
+ DirtyMiterLimit = 0x00100,
+ MDirtyPen = DirtyStrokeStyle
+ | DirtyLineWidth
+ | DirtyLineCap
+ | DirtyLineJoin
+ | DirtyMiterLimit,
+ DirtyShadowOffsetX = 0x00200,
+ DirtyShadowOffsetY = 0x00400,
+ DirtyShadowBlur = 0x00800,
+ DirtyShadowColor = 0x01000,
+ DirtyGlobalCompositeOperation = 0x2000,
+ DirtyFont = 0x04000,
+ DirtyTextAlign = 0x08000,
+ DirtyTextBaseline = 0x10000,
+ AllIsFullOfDirt = 0xfffff
+ };
+
+ struct State {
+ State() : flags(0) {}
+ QMatrix matrix;
+ QPainterPath clipPath;
+ QBrush strokeStyle;
+ QBrush fillStyle;
+ qreal globalAlpha;
+ qreal lineWidth;
+ Qt::PenCapStyle lineCap;
+ Qt::PenJoinStyle lineJoin;
+ qreal miterLimit;
+ qreal shadowOffsetX;
+ qreal shadowOffsetY;
+ qreal shadowBlur;
+ QColor shadowColor;
+ QPainter::CompositionMode globalCompositeOperation;
+ QFont font;
+ Context2D::TextAlign textAlign;
+ Context2D::TextBaseLine textBaseline;
+ int flags;
+ };
+
+ int baseLineOffset(Context2D::TextBaseLine value, const QFontMetrics &metrics);
+ int textAlignOffset(Context2D::TextAlign value, const QFontMetrics &metrics, const QString &string);
+
+ QMatrix worldMatrix() const;
+
+ QPoint m_painterTranslate;
+ State m_state;
+ QStack<State> m_stateStack;
+ QPixmap m_pixmap;
+ QList<MouseArea> m_mouseAreas;
+ QImage m_shadowbuffer;
+ QVector<QRgb> m_shadowColorIndexBuffer;
+ QColor m_shadowColorBuffer;
+ QPainter m_painter;
+ int m_width, m_height;
+ bool m_inPaint;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(CanvasImage*)
+Q_DECLARE_METATYPE(CanvasGradient*)
+
+#endif // QDECLARATIVECONTEXT2D_P_H
diff --git a/src/plugins/qmlprofiler/canvas/qdeclarativetiledcanvas.cpp b/src/plugins/qmlprofiler/canvas/qdeclarativetiledcanvas.cpp
new file mode 100644
index 0000000000..9e086e141a
--- /dev/null
+++ b/src/plugins/qmlprofiler/canvas/qdeclarativetiledcanvas.cpp
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Toolkit.
+**
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativetiledcanvas_p.h"
+
+#include "qdeclarativecontext2d_p.h"
+
+#include <QtGui/qpixmap.h>
+#include <QtGui/qpainter.h>
+
+TiledCanvas::TiledCanvas()
+: m_context2d(new Context2D(this)), m_canvasSize(-1, -1), m_tileSize(100, 100)
+{
+ setFlag(QGraphicsItem::ItemHasNoContents, false);
+ setAcceptedMouseButtons(Qt::LeftButton);
+ setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+}
+
+QSizeF TiledCanvas::canvasSize() const
+{
+ return m_canvasSize;
+}
+
+void TiledCanvas::setCanvasSize(const QSizeF &v)
+{
+ if (m_canvasSize != v) {
+ m_canvasSize = v;
+ emit canvasSizeChanged();
+ update();
+ }
+}
+
+QSize TiledCanvas::tileSize() const
+{
+ return m_tileSize;
+}
+
+void TiledCanvas::setTileSize(const QSize &v)
+{
+ if (v != m_tileSize) {
+ m_tileSize = v;
+ emit tileSizeChanged();
+ update();
+ }
+}
+
+QRectF TiledCanvas::canvasWindow() const
+{
+ return m_canvasWindow;
+}
+
+void TiledCanvas::setCanvasWindow(const QRectF &v)
+{
+ if (m_canvasWindow != v) {
+ m_canvasWindow = v;
+ emit canvasWindowChanged();
+ update();
+ }
+}
+
+void TiledCanvas::requestPaint()
+{
+ update();
+}
+
+void TiledCanvas::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ if (m_context2d->size() != m_tileSize)
+ m_context2d->setSize(m_tileSize);
+
+ const int tw = m_tileSize.width();
+ const int th = m_tileSize.height();
+
+ int h1 = m_canvasWindow.left() / tw;
+ int htiles = ((m_canvasWindow.right() - h1 * tw) + tw - 1) / tw;
+
+ int v1 = m_canvasWindow.top() / th;
+ int vtiles = ((m_canvasWindow.bottom() - v1 * th) + th - 1) / th;
+
+ for (int yy = 0; yy < vtiles; ++yy) {
+ for (int xx = 0; xx < htiles; ++xx) {
+ int ht = xx + h1;
+ int vt = yy + v1;
+
+ m_context2d->reset();
+ m_context2d->setPainterTranslate(QPoint(-ht * tw, -vt * th));
+
+ emit drawRegion(m_context2d, QRect(ht * tw, vt * th, tw, th));
+
+ p->drawPixmap(-m_canvasWindow.x() + ht * tw, -m_canvasWindow.y() + vt * th, m_context2d->pixmap());
+ }
+ }
+}
+
+void TiledCanvas::componentComplete()
+{
+ const QMetaObject *metaObject = this->metaObject();
+ int propertyCount = metaObject->propertyCount();
+ int requestPaintMethod = metaObject->indexOfMethod("requestPaint()");
+ for (int ii = TiledCanvas::staticMetaObject.propertyCount(); ii < propertyCount; ++ii) {
+ QMetaProperty p = metaObject->property(ii);
+ if (p.hasNotifySignal())
+ QMetaObject::connect(this, p.notifySignalIndex(), this, requestPaintMethod, 0, 0);
+ }
+ QDeclarativeItem::componentComplete();
+}
+
+
+void TiledCanvas::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_UNUSED(event);
+ qWarning("MPE");
+}
+
+QPixmap TiledCanvas::getTile(int xx, int yy)
+{
+ QPixmap pix(m_tileSize);
+
+ pix.fill(Qt::green);
+
+ QString text = QString::number(xx) + " " + QString::number(yy);
+
+ QPainter p(&pix);
+ p.drawText(pix.rect(), Qt::AlignHCenter | Qt::AlignVCenter, text);
+
+ return pix;
+}
+
diff --git a/src/plugins/qmlprofiler/canvas/qdeclarativetiledcanvas_p.h b/src/plugins/qmlprofiler/canvas/qdeclarativetiledcanvas_p.h
new file mode 100644
index 0000000000..e3f45a700e
--- /dev/null
+++ b/src/plugins/qmlprofiler/canvas/qdeclarativetiledcanvas_p.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 QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file 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 QDECLARATIVETILEDCANVAS_P_H
+#define QDECLARATIVETILEDCANVAS_P_H
+
+#include <QtDeclarative/qdeclarativeitem.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class Context2D;
+class TiledCanvas : public QDeclarativeItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QSizeF canvasSize READ canvasSize WRITE setCanvasSize NOTIFY canvasSizeChanged)
+ Q_PROPERTY(QSize tileSize READ tileSize WRITE setTileSize NOTIFY tileSizeChanged)
+ Q_PROPERTY(QRectF canvasWindow READ canvasWindow WRITE setCanvasWindow NOTIFY canvasWindowChanged)
+
+public:
+ TiledCanvas();
+
+ QSizeF canvasSize() const;
+ void setCanvasSize(const QSizeF &);
+
+ QSize tileSize() const;
+ void setTileSize(const QSize &);
+
+ QRectF canvasWindow() const;
+ void setCanvasWindow(const QRectF &);
+
+Q_SIGNALS:
+ void canvasSizeChanged();
+ void tileSizeChanged();
+ void canvasWindowChanged();
+
+ void drawRegion(Context2D *ctxt, const QRect &region);
+
+public Q_SLOTS:
+ void requestPaint();
+
+protected:
+ virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+ virtual void componentComplete();
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
+
+private:
+ QPixmap getTile(int, int);
+
+ Context2D *m_context2d;
+
+ QSizeF m_canvasSize;
+ QSize m_tileSize;
+ QRectF m_canvasWindow;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVETILEDCANVAS_P_H
diff --git a/src/plugins/qmlprofiler/qml/Detail.qml b/src/plugins/qmlprofiler/qml/Detail.qml
new file mode 100644
index 0000000000..89f4be509b
--- /dev/null
+++ b/src/plugins/qmlprofiler/qml/Detail.qml
@@ -0,0 +1,67 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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.
+**
+**************************************************************************/
+
+import QtQuick 1.0
+import Monitor 1.0
+import "MainView.js" as Plotter
+
+Item {
+ id: detail
+ property string label
+ property string content
+ property int maxLines: 4
+ signal linkActivated(string url)
+
+ height: childrenRect.height
+ width: childrenRect.width
+ Item {
+ id: guideline
+ x: 70
+ width: 5
+ }
+ Text {
+ id: lbl
+ text: label + ":"
+ font.pixelSize: 12
+ font.bold: true
+ anchors.right: guideline.left
+ }
+ Text {
+ text: content
+ font.pixelSize: 12
+ anchors.baseline: lbl.baseline
+ anchors.left: guideline.right
+ // maximumLineCount: maxLines
+ onLinkActivated: detail.linkActivated(link)
+ }
+}
diff --git a/src/plugins/qmlprofiler/qml/Label.qml b/src/plugins/qmlprofiler/qml/Label.qml
new file mode 100644
index 0000000000..b3b6fd9183
--- /dev/null
+++ b/src/plugins/qmlprofiler/qml/Label.qml
@@ -0,0 +1,56 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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.
+**
+**************************************************************************/
+
+import QtQuick 1.0
+
+Item {
+ property alias text: txt.text
+
+ height: 50
+ width: 150 //### required, or ignored by positioner
+
+ Text {
+ id: txt;
+ x: 5
+ font.pixelSize: 12
+ color: "#232323"
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ Rectangle {
+ height: 1
+ width: parent.width
+ color: "#cccccc"
+ anchors.bottom: parent.bottom
+ }
+}
diff --git a/src/plugins/qmlprofiler/qml/MainView.js b/src/plugins/qmlprofiler/qml/MainView.js
new file mode 100644
index 0000000000..036fdc02a4
--- /dev/null
+++ b/src/plugins/qmlprofiler/qml/MainView.js
@@ -0,0 +1,149 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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.
+**
+**************************************************************************/
+
+.pragma library
+
+var values = [ ]; //events
+var ranges = [ ];
+var frameFps = [ ];
+var valuesdone = false;
+var xmargin = 0;
+var ymargin = 0;
+
+var names = [ "Painting", "Compiling", "Creating", "Binding", "Handling Signal"]
+//### need better way to manipulate color from QML. In the meantime, these need to be kept in sync.
+var colors = [ "#99CCB3", "#99CCCC", "#99B3CC", "#9999CC", "#CC99B3", "#CC99CC", "#CCCC99", "#CCB399" ];
+var origColors = [ "#99CCB3", "#99CCCC", "#99B3CC", "#9999CC", "#CC99B3", "#CC99CC", "#CCCC99", "#CCB399" ];
+var xRayColors = [ "#6699CCB3", "#6699CCCC", "#6699B3CC", "#669999CC", "#66CC99B3", "#66CC99CC", "#66CCCC99", "#66CCB399" ];
+
+function reset()
+{
+ values = [];
+ ranges = [];
+ frameFps = [];
+ xmargin = 0;
+ ymargin = 0;
+ valuesdone = false;
+}
+
+function calcFps()
+{
+ if (values.length)
+ frameFps = new Array(values.length - 1);
+ for (var i = 0; i < values.length - 1; ++i) {
+ var frameTime = (values[i + 1] - values[i]) / 1000000;
+ frameFps[i] = 1000 / frameTime;
+ }
+}
+
+//draw background of the graph
+function drawGraph(canvas, ctxt, region)
+{
+ var grad = ctxt.createLinearGradient(0, 0, 0, canvas.canvasSize.height);
+ grad.addColorStop(0, '#fff');
+ grad.addColorStop(1, '#ccc');
+ ctxt.fillStyle = grad;
+
+ ctxt.fillRect(0, 0, canvas.canvasSize.width + xmargin, canvas.canvasSize.height - ymargin);
+}
+
+//draw the actual data to be graphed
+function drawData(canvas, ctxt, region)
+{
+ if (values.length == 0 && ranges.length == 0)
+ return;
+
+ var width = canvas.canvasSize.width - xmargin;
+ var height = canvas.height - ymargin;
+
+ var sumValue = ranges[ranges.length - 1].start + ranges[ranges.length - 1].duration - ranges[0].start;
+ var spacing = width / sumValue;
+
+ ctxt.fillStyle = "rgba(0,0,0,1)";
+ var highest = [0,0,0,0,0];
+
+ //### only draw those in range
+ for (var ii = 0; ii < ranges.length; ++ii) {
+
+ var xx = (ranges[ii].start - ranges[0].start) * spacing + xmargin;
+ if (xx > region.x + region.width)
+ continue;
+
+ var size = ranges[ii].duration * spacing;
+ if (xx + size < region.x)
+ continue;
+
+ if (size < 0.5)
+ size = 0.5;
+
+ xx = Math.round(xx);
+ if (xx + size > highest[ranges[ii].type]) {
+ ctxt.fillRect(xx, ranges[ii].type*10, size, 10);
+ highest[ranges[ii].type] = xx+size;
+ }
+ }
+
+ //draw fps overlay
+ var heightScale = height / 60;
+ ctxt.beginPath();
+ ctxt.moveTo(0,0);
+ for (var i = 1; i < values.length; ++i) {
+ var xx = (values[i] - ranges[0].start) * spacing + xmargin;
+ ctxt.lineTo(xx, height - frameFps[i-1]*heightScale)
+ }
+ ctxt.lineTo(width, 0);
+ ctxt.closePath();
+ var grad = ctxt.createLinearGradient(0, 0, 0, canvas.canvasSize.height);
+ grad.addColorStop(0, "rgba(255,128,128,.5)");
+ grad.addColorStop(1, "rgba(255,0,0,.5)");
+ ctxt.fillStyle = grad;
+ ctxt.fill();
+}
+
+function plot(canvas, ctxt, region)
+{
+ drawGraph(canvas, ctxt, region);
+ drawData(canvas, ctxt, region);
+}
+
+function xScale(canvas)
+{
+ if (values.length === 0 && ranges.length === 0)
+ return;
+
+ var width = canvas.canvasSize.width - xmargin;
+
+ var sumValue = ranges[ranges.length - 1].start + ranges[ranges.length - 1].duration - ranges[0].start;
+ var spacing = sumValue / width;
+ return spacing;
+}
diff --git a/src/plugins/qmlprofiler/qml/MainView.qml b/src/plugins/qmlprofiler/qml/MainView.qml
new file mode 100644
index 0000000000..a747c6c8fb
--- /dev/null
+++ b/src/plugins/qmlprofiler/qml/MainView.qml
@@ -0,0 +1,321 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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.
+**
+**************************************************************************/
+
+import QtQuick 1.0
+import Monitor 1.0
+import "MainView.js" as Plotter
+
+Rectangle {
+ id: root
+
+ property variant colors: Plotter.colors //the colors used for the timeline data
+ property bool xRay: false //useful for seeing "nested" ranges (but redraw is buggy -- QGV problem?)
+ property Item currentItem //currently selected item in the view
+
+ property bool zooming:false
+
+ // move the cursor in the editor
+ signal updateCursorPosition
+ property string fileName: ""
+ property int lineNumber: -1
+ function gotoSourceLocation(file,line) {
+ root.fileName = file;
+ root.lineNumber = line;
+ root.updateCursorPosition();
+ }
+
+ function clearAll() {
+ Plotter.reset();
+ view.clearData();
+ rangeMover.x = 2
+ rangeMover.opacity = 0
+ }
+
+ //handle debug data coming from C++
+ Connections {
+ target: connection
+ onEvent: {
+ if (Plotter.valuesdone) {
+ root.clearAll();
+ }
+
+ if (!Plotter.valuesdone && event === 0) //### only handle paint event
+ Plotter.values.push(time);
+ }
+
+ onRange: {
+ if (Plotter.valuesdone) {
+ root.clearAll();
+ }
+
+ if (!Plotter.valuesdone)
+ Plotter.ranges.push( { type: type, start: startTime, duration: length, label: data, fileName: fileName, line: line } );
+ }
+
+ onComplete: {
+ Plotter.valuesdone = true;
+ Plotter.calcFps();
+ view.visible = true;
+ view.setRanges(Plotter.ranges);
+ view.updateTimeline();
+ canvas.requestPaint();
+ rangeMover.x = 1 //### hack to get view to display things immediately
+ rangeMover.opacity = 1
+ }
+
+ onClear: {
+ root.clearAll();
+ Plotter.valuesdone = false;
+ canvas.requestPaint();
+ view.visible = false;
+ root.elapsedTime = 0;
+ root.updateTimer();
+ }
+
+ }
+
+ // Elapsed
+ property real elapsedTime;
+ signal updateTimer;
+ Timer {
+ property date startDate
+ property bool reset: true
+ running: connection.recording
+ repeat: true
+ onRunningChanged: if (running) reset = true
+ interval: 100
+ triggeredOnStart: true
+ onTriggered: {
+ if (reset) {
+ startDate = new Date()
+ reset = false
+ }
+ var time = (new Date() - startDate)/1000
+ //elapsed.text = time.toFixed(1) + "s"
+ root.elapsedTime = time.toFixed(1);
+ root.updateTimer();
+ }
+ }
+
+ //timeline background
+ Item {
+ anchors.fill: flick
+ Column {
+ anchors.fill: parent
+
+ Repeater {
+ model: 5 //### values.length?
+ delegate: Rectangle {
+ width: parent.width
+ height: 50 //###
+ color: index % 2 ? "#fafafa" : "white"
+ }
+ }
+ }
+ }
+
+ //our main interaction view
+ Flickable {
+ id: flick
+ anchors.top: parent.top
+ anchors.right: parent.right
+ anchors.left: labels.right
+ anchors.bottom: canvas.top
+ contentWidth: view.totalWidth
+ contentHeight: view.height
+
+ TimelineView {
+ id: view
+
+ width: flick.width; height: flick.height
+
+ startX: flick.contentX
+ onStartXChanged: {
+ var newX = startTime / Plotter.xScale(canvas) - canvas.canvasWindow.x;
+ if (Math.abs(rangeMover.x - newX) > .01)
+ rangeMover.x = newX
+ if (Math.abs(startX - flick.contentX) > .01)
+ flick.contentX = startX
+ }
+ startTime: rangeMover.value
+
+ property real prevXStep: -1
+ property real possibleEndTime: startTime + (rangeMover.width*Plotter.xScale(canvas))
+ onPossibleEndTimeChanged: {
+ var set = ((zooming && prevXStep != canvas.canvasWindow.x) || !zooming);
+ prevXStep = canvas.canvasWindow.x;
+ if (set)
+ endTime = possibleEndTime
+ }
+ onEndTimeChanged: updateTimeline()
+
+ delegate: Rectangle {
+ id: obj
+
+ property color baseColor: colors[type]
+ property color myColor: baseColor
+
+ function conditionalHide() {
+ if (!mouseArea.containsMouse)
+ mouseArea.exited()
+ }
+
+ height: 50
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: myColor }
+ GradientStop { position: 0.5; color: Qt.darker(myColor, 1.1) }
+ GradientStop { position: 1.0; color: myColor }
+ }
+ smooth: true
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onEntered: {
+ currentItem = obj
+ myColor = Qt.darker(baseColor, 1.2)
+ rangeDetails.duration = duration
+ rangeDetails.label = label
+ rangeDetails.file = fileName
+ rangeDetails.line = line
+ rangeDetails.type = Plotter.names[type]
+
+ var pos = mapToItem(rangeDetails.parent, mouseX, y+height)
+ var preferredX = Math.max(10, pos.x - rangeDetails.width/2)
+ if (preferredX + rangeDetails.width > rangeDetails.parent.width)
+ preferredX = rangeDetails.parent.width - rangeDetails.width
+ rangeDetails.x = preferredX
+
+ var preferredY = pos.y - rangeDetails.height/2;
+ if (preferredY + rangeDetails.height > root.height - 10)
+ preferredY = root.height - 10 - rangeDetails.height;
+ if (preferredY < 10)
+ preferredY=10;
+ rangeDetails.y = preferredY;
+ rangeDetails.visible = true
+ }
+ onExited: {
+ myColor = baseColor
+ rangeDetails.visible = false
+ rangeDetails.duration = ""
+ rangeDetails.label = ""
+ rangeDetails.type = ""
+ rangeDetails.file = ""
+ rangeDetails.line = -1
+ }
+ onClicked: root.gotoSourceLocation(rangeDetails.file, rangeDetails.line);
+ }
+ }
+ }
+ }
+
+ //popup showing the details for the hovered range
+ RangeDetails {
+ id: rangeDetails
+ }
+
+ Rectangle {
+ id: labels
+ width: 150
+ color: "#dcdcdc"
+ anchors.top: root.top
+ anchors.bottom: canvas.top
+
+ Column {
+ //### change to use Repeater + Plotter.names?
+ Label { text: "Painting" }
+ Label { text: "Compiling" }
+ Label { text: "Creating" }
+ Label { text: "Binding" }
+ Label { text: "Signal Handler" }
+ }
+
+ //right border divider
+ Rectangle {
+ width: 1
+ height: parent.height
+ anchors.right: parent.right
+ color: "#cccccc"
+ }
+ }
+
+ //bottom border divider
+ Rectangle {
+ height: 1
+ width: parent.width
+ anchors.bottom: canvas.top
+ color: "#cccccc"
+ }
+
+ //"overview" graph at the bottom
+ TiledCanvas {
+ id: canvas
+
+ anchors.bottom: parent.bottom
+ width: parent.width; height: 50
+
+ property int canvasWidth: width
+
+ canvasSize {
+ width: canvasWidth
+ height: canvas.height
+ }
+
+ tileSize.width: width
+ tileSize.height: height
+
+ canvasWindow.width: width
+ canvasWindow.height: 50
+
+ onDrawRegion: {
+ if (Plotter.valuesdone)
+ Plotter.plot(canvas, ctxt, region);
+ else
+ Plotter.drawGraph(canvas, ctxt, region) //just draw the background
+ }
+ }
+
+ //moves the range mover to the position of a click
+ MouseArea {
+ anchors.fill: canvas
+ //### ideally we could press to position then immediately drag
+ onPressed: rangeMover.x = mouse.x - rangeMover.width/2
+ }
+
+ RangeMover {
+ id: rangeMover
+ opacity: 0
+ anchors.top: canvas.top
+ }
+
+}
diff --git a/src/plugins/qmlprofiler/qml/RangeDetails.qml b/src/plugins/qmlprofiler/qml/RangeDetails.qml
new file mode 100644
index 0000000000..3b76eae38a
--- /dev/null
+++ b/src/plugins/qmlprofiler/qml/RangeDetails.qml
@@ -0,0 +1,94 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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.
+**
+**************************************************************************/
+
+import QtQuick 1.0
+import Monitor 1.0
+import "MainView.js" as Plotter
+
+BorderImage {
+ id: rangeDetails
+
+ property string duration //###int?
+ property string label
+ property string type
+ property string file
+ property int line
+
+ source: "popup.png"
+ border {
+ left: 10; top: 10
+ right: 20; bottom: 20
+ }
+
+ width: col.width + 45
+ height: childrenRect.height + 30
+ z: 1
+ visible: false
+
+ //title
+ Text {
+ id: typeTitle
+ text: rangeDetails.type
+ font.bold: true
+ y: 10
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.horizontalCenterOffset: -5
+ }
+
+ //details
+ Column {
+ id: col
+ anchors.top: typeTitle.bottom
+ Detail {
+ label: "Duration"
+ content: rangeDetails.duration + "μs"
+ }
+ Detail {
+ opacity: content.length !== 0 ? 1 : 0
+ label: "Details"
+ content: rangeDetails.label
+ }
+ Detail {
+ opacity: content.length !== 0 ? 1 : 0
+ label: "Location"
+ content: {
+ var file = rangeDetails.file
+ var pos = file.lastIndexOf("/")
+ if (pos != -1)
+ file = file.substr(pos+1)
+ return (file.length !== 0) ? (file + ":" + rangeDetails.line) : "";
+ }
+ onLinkActivated: Qt.openUrlExternally(url)
+ }
+ }
+}
diff --git a/src/plugins/qmlprofiler/qml/RangeMover.qml b/src/plugins/qmlprofiler/qml/RangeMover.qml
new file mode 100644
index 0000000000..9b6df07506
--- /dev/null
+++ b/src/plugins/qmlprofiler/qml/RangeMover.qml
@@ -0,0 +1,95 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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.
+**
+**************************************************************************/
+
+import "MainView.js" as Plotter
+import QtQuick 1.0
+import Monitor 1.0
+
+Item {
+ id: rangeMover
+ width: rect.width; height: 50
+
+ property real prevXStep: -1
+ property real possibleValue: (canvas.canvasWindow.x + x) * Plotter.xScale(canvas)
+ onPossibleValueChanged: {
+ var set = (!zooming || (zooming && prevXStep != canvas.canvasWindow.x))
+ prevXStep = canvas.canvasWindow.x;
+ if (set)
+ value = possibleValue
+ }
+
+ property real value
+ //onValueChanged: console.log("*************** " + value)
+
+ /*Image {
+ id: leftRange
+ source: "range.png"
+ anchors.horizontalCenter: parent.left
+ anchors.bottom: parent.bottom
+ }*/
+
+ Rectangle {
+ id: rect
+
+ color: "#cc80b2f6"
+ width: 20
+ //anchors.left: parent.left
+ //anchors.right: rightRange.horizontalCenter
+
+ height: parent.height
+ }
+
+ /*Image {
+ id: rightRange
+ source: "range.png"
+ x: 13
+ anchors.bottom: parent.bottom
+
+ MouseArea {
+ width: parent.width
+ height: 15
+ drag.target: rightRange
+ drag.axis: "XAxis"
+ drag.minimumX: -7 //###
+ drag.maximumX: canvas.width - rangeMover.width //###
+ }
+ }*/
+
+ MouseArea {
+ anchors.fill: parent
+ drag.target: rangeMover
+ drag.axis: "XAxis"
+ drag.minimumX: 0
+ drag.maximumX: canvas.width - rangeMover.width //###
+ }
+}
diff --git a/src/plugins/qmlprofiler/qml/RecordButton.qml b/src/plugins/qmlprofiler/qml/RecordButton.qml
new file mode 100644
index 0000000000..17b556838f
--- /dev/null
+++ b/src/plugins/qmlprofiler/qml/RecordButton.qml
@@ -0,0 +1,86 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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.
+**
+**************************************************************************/
+
+import QtQuick 1.0
+
+Rectangle {
+ id: button
+
+ property alias text: textItem.text
+ property bool recording: false
+
+ signal clicked
+
+ width: 80; height: textItem.height + 8
+ border.width: 1
+ border.color: Qt.darker(button.color, 1.4)
+ radius: height/2
+ smooth: true
+
+ color: "#049e0e"
+
+ Text {
+ id: textItem
+ anchors.centerIn: parent
+ font.pixelSize: 14
+ color: "white"
+ text: "Recording"
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ onClicked: {
+ recording = !recording;
+ button.clicked()
+ }
+ }
+
+ StateGroup {
+ id: recordState
+ states: State {
+ name: "recording"
+ when: recording
+ PropertyChanges { target: button; color: "#ff120c"; }
+ PropertyChanges { target: textItem; text: "Stop" }
+ }
+ }
+
+ StateGroup {
+ states: State {
+ name: "pressed"; when: mouseArea.pressed && mouseArea.containsMouse
+ PropertyChanges { target: button; color: Qt.darker(color, 1.1); explicit: true }
+ PropertyChanges { target: textItem; x: textItem.x + 1; y: textItem.y + 1; explicit: true }
+ }
+ }
+}
diff --git a/src/plugins/qmlprofiler/qml/ToolButton.qml b/src/plugins/qmlprofiler/qml/ToolButton.qml
new file mode 100644
index 0000000000..512a6d0319
--- /dev/null
+++ b/src/plugins/qmlprofiler/qml/ToolButton.qml
@@ -0,0 +1,60 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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.
+**
+**************************************************************************/
+
+import QtQuick 1.0
+import Monitor 1.0
+import "MainView.js" as Plotter
+
+Rectangle {
+ property string label
+ signal clicked
+
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.verticalCenterOffset: -1
+ width: 30; height: 22
+
+ border.color: "#cc80b2f6"
+ color: "transparent"
+
+ Text {
+ anchors.centerIn: parent
+ text: label
+ color: "white"
+ font.pixelSize: 14
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: parent.clicked()
+ }
+}
diff --git a/src/plugins/qmlprofiler/qml/analyzer_category_small.png b/src/plugins/qmlprofiler/qml/analyzer_category_small.png
new file mode 100644
index 0000000000..5bc90fbf91
--- /dev/null
+++ b/src/plugins/qmlprofiler/qml/analyzer_category_small.png
Binary files differ
diff --git a/src/plugins/qmlprofiler/qml/lock.png b/src/plugins/qmlprofiler/qml/lock.png
new file mode 100644
index 0000000000..4942a5ce58
--- /dev/null
+++ b/src/plugins/qmlprofiler/qml/lock.png
Binary files differ
diff --git a/src/plugins/qmlprofiler/qml/popup.png b/src/plugins/qmlprofiler/qml/popup.png
new file mode 100644
index 0000000000..38028e9432
--- /dev/null
+++ b/src/plugins/qmlprofiler/qml/popup.png
Binary files differ
diff --git a/src/plugins/qmlprofiler/qml/qml.qrc b/src/plugins/qmlprofiler/qml/qml.qrc
new file mode 100644
index 0000000000..84e33bfc89
--- /dev/null
+++ b/src/plugins/qmlprofiler/qml/qml.qrc
@@ -0,0 +1,16 @@
+<RCC>
+ <qresource prefix="/qmlprofiler">
+ <file>Detail.qml</file>
+ <file>Label.qml</file>
+ <file>lock.png</file>
+ <file>MainView.js</file>
+ <file>MainView.qml</file>
+ <file>popup.png</file>
+ <file>range.png</file>
+ <file>RangeDetails.qml</file>
+ <file>RangeMover.qml</file>
+ <file>RecordButton.qml</file>
+ <file>ToolButton.qml</file>
+ <file>analyzer_category_small.png</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/qmlprofiler/qml/range.png b/src/plugins/qmlprofiler/qml/range.png
new file mode 100644
index 0000000000..2ac200fe18
--- /dev/null
+++ b/src/plugins/qmlprofiler/qml/range.png
Binary files differ
diff --git a/src/plugins/qmlprofiler/qmlprofiler.pro b/src/plugins/qmlprofiler/qmlprofiler.pro
new file mode 100644
index 0000000000..ff399c9896
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofiler.pro
@@ -0,0 +1,54 @@
+TEMPLATE = lib
+TARGET = QmlProfiler
+
+DEFINES += PROFILER_LIBRARY
+
+include(../../qtcreatorplugin.pri)
+include(../../plugins/coreplugin/coreplugin.pri)
+include(../../plugins/analyzerbase/analyzerbase.pri)
+include(../../plugins/qmlprojectmanager/qmlprojectmanager.pri)
+
+
+QT += network script declarative
+
+include(canvas/canvas.pri)
+#include($$QMLJSDEBUGGER_PATH/qmljsdebugger-lib.pri)
+
+SOURCES += \
+ qmlprofilerplugin.cpp \
+ qmlprofilertool.cpp \
+ qmlprofilerengine.cpp \
+ tracewindow.cpp \
+ timelineview.cpp \
+ qmlprofilerattachdialog.cpp \
+ qmlprofilersummaryview.cpp \
+ qmlprojectanalyzerruncontrolfactory.cpp
+
+HEADERS += \
+ qmlprofilerconstants.h \
+ qmlprofiler_global.h \
+ qmlprofilerplugin.h \
+ qmlprofilertool.h \
+ qmlprofilerengine.h \
+ tracewindow.h \
+ timelineview.h \
+ qmlprofilerattachdialog.h \
+ qmlprofilersummaryview.h \
+ qmlprojectanalyzerruncontrolfactory.h
+
+RESOURCES += \
+ qml/qml.qrc
+
+OTHER_FILES += \
+ qml/Detail.qml \
+ qml/Elapsed.qml \
+ qml/Label.qml \
+ qml/MainView.qml \
+ qml/RangeDetails.qml \
+ qml/RangeMover.qml \
+ qml/RecordButton.qml \
+ qml/ToolButton.qml \
+ qml/MainView.js
+
+FORMS += \
+ qmlprofilerattachdialog.ui
diff --git a/src/plugins/qmlprofiler/qmlprofiler_global.h b/src/plugins/qmlprofiler/qmlprofiler_global.h
new file mode 100644
index 0000000000..2713e6a897
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofiler_global.h
@@ -0,0 +1,46 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 QMLPROFILER_GLOBAL_H
+#define QMLPROFILER_GLOBAL_H
+
+#include <QtCore/QtGlobal>
+
+#if defined(QMLPROFILERPLUGIN_LIBRARY)
+# define QMLPROFILERPLUGINSHARED_EXPORT Q_DECL_EXPORT
+#else
+# define QMLPROFILERPLUGINSHARED_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // QMLPROFILER_GLOBAL_H
+
diff --git a/src/plugins/qmlprofiler/qmlprofilerattachdialog.cpp b/src/plugins/qmlprofiler/qmlprofilerattachdialog.cpp
new file mode 100644
index 0000000000..d4d08180b7
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilerattachdialog.cpp
@@ -0,0 +1,40 @@
+#include "qmlprofilerattachdialog.h"
+#include "ui_qmlprofilerattachdialog.h"
+
+namespace QmlProfiler {
+namespace Internal {
+
+QmlProfilerAttachDialog::QmlProfilerAttachDialog(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::QmlProfilerAttachDialog)
+{
+ ui->setupUi(this);
+}
+
+QmlProfilerAttachDialog::~QmlProfilerAttachDialog()
+{
+ delete ui;
+}
+
+QString QmlProfilerAttachDialog::address() const
+{
+ return ui->addressLineEdit->text();
+}
+
+uint QmlProfilerAttachDialog::port() const
+{
+ return ui->portSpinBox->value();
+}
+
+void QmlProfilerAttachDialog::setAddress(const QString &address)
+{
+ ui->addressLineEdit->setText(address);
+}
+
+void QmlProfilerAttachDialog::setPort(uint port)
+{
+ ui->portSpinBox->setValue(port);
+}
+
+} // namespace Internal
+} // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/qmlprofilerattachdialog.h b/src/plugins/qmlprofiler/qmlprofilerattachdialog.h
new file mode 100644
index 0000000000..ac85df7918
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilerattachdialog.h
@@ -0,0 +1,34 @@
+#ifndef QMLPROFILERATTACHDIALOG_H
+#define QMLPROFILERATTACHDIALOG_H
+
+#include <QDialog>
+
+namespace QmlProfiler {
+namespace Internal {
+
+namespace Ui {
+ class QmlProfilerAttachDialog;
+}
+
+class QmlProfilerAttachDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit QmlProfilerAttachDialog(QWidget *parent = 0);
+ ~QmlProfilerAttachDialog();
+
+ QString address() const;
+ uint port() const;
+
+ void setAddress(const QString &address);
+ void setPort(uint port);
+
+private:
+ Ui::QmlProfilerAttachDialog *ui;
+};
+
+} // namespace Internal
+} // namespace QmlProfiler
+
+#endif // QMLPROFILERATTACHDIALOG_H
diff --git a/src/plugins/qmlprofiler/qmlprofilerattachdialog.ui b/src/plugins/qmlprofiler/qmlprofilerattachdialog.ui
new file mode 100644
index 0000000000..5bae9fee4c
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilerattachdialog.ui
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>QmlProfiler::Internal::QmlProfilerAttachDialog</class>
+ <widget class="QDialog" name="QmlProfiler::Internal::QmlProfilerAttachDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>164</width>
+ <height>96</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="addressLabel">
+ <property name="text">
+ <string>Address:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="addressLineEdit">
+ <property name="text">
+ <string>127.0.0.1</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="portLabel">
+ <property name="text">
+ <string>Port:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="portSpinBox">
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>65535</number>
+ </property>
+ <property name="value">
+ <number>3768</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </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>QmlProfiler::Internal::QmlProfilerAttachDialog</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>QmlProfiler::Internal::QmlProfilerAttachDialog</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/qmlprofiler/qmlprofilerconstants.h b/src/plugins/qmlprofiler/qmlprofilerconstants.h
new file mode 100644
index 0000000000..dbb2b0c9ee
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilerconstants.h
@@ -0,0 +1,45 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 QMLPROFILERCONSTANTS_H
+#define QMLPROFILERCONSTANTS_H
+
+namespace QmlProfiler {
+namespace Constants {
+
+const char * const ATTACH = "Menu.Analyzer.Attach";
+
+} // namespace Constants
+} // namespace QmlProfiler
+
+#endif // QMLPROFILERCONSTANTS_H
diff --git a/src/plugins/qmlprofiler/qmlprofilerengine.cpp b/src/plugins/qmlprofiler/qmlprofilerengine.cpp
new file mode 100644
index 0000000000..5314867488
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilerengine.cpp
@@ -0,0 +1,198 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "qmlprofilerengine.h"
+
+#include "qmlprofilerplugin.h"
+#include "qmlprofilertool.h"
+
+#include <analyzerbase/analyzermanager.h>
+#include <analyzerbase/analyzerconstants.h>
+
+#include <private/qdeclarativedebugclient_p.h>
+
+#include "timelineview.h"
+#include "tracewindow.h"
+
+#include <QDebug>
+
+#include "canvas/qdeclarativecanvas_p.h"
+#include "canvas/qdeclarativecontext2d_p.h"
+#include "canvas/qdeclarativetiledcanvas_p.h"
+
+#include <QProcess>
+
+#ifdef Q_OS_UNIX
+#include <unistd.h> // sleep
+#endif
+
+using namespace QmlProfiler::Internal;
+
+class QmlProfilerEngine::QmlProfilerEnginePrivate
+{
+public:
+ QmlProfilerEnginePrivate(QmlProfilerEngine *qq) : q(qq) {}
+ ~QmlProfilerEnginePrivate() {}
+
+ bool launchperfmonitor();
+ bool attach(const QString &address, uint port);
+
+ QmlProfilerEngine *q;
+
+ Analyzer::AnalyzerStartParameters m_params;
+ QProcess *m_process;
+ bool m_running;
+ bool m_fetchingData;
+};
+
+QmlProfilerEngine::QmlProfilerEngine(const Analyzer::AnalyzerStartParameters &sp, ProjectExplorer::RunConfiguration *runConfiguration)
+ : IAnalyzerEngine(sp, runConfiguration)
+ , d(new QmlProfilerEnginePrivate(this))
+{
+ d->m_params = sp;
+ d->m_process = 0;
+ d->m_running = false;
+ d->m_fetchingData = false;
+}
+
+QmlProfilerEngine::~QmlProfilerEngine()
+{
+ if (d->m_running)
+ stop();
+ delete d;
+}
+
+void QmlProfilerEngine::start()
+{
+ d->launchperfmonitor();
+ d->m_running = true;
+
+ emit processRunning();
+}
+
+void QmlProfilerEngine::stop()
+{
+ d->m_running = false;
+ if (d->m_fetchingData)
+ emit stopRecording();
+ else
+ finishProcess();
+}
+
+void QmlProfilerEngine::spontaneousStop()
+{
+ d->m_running = false;
+ Analyzer::AnalyzerManager::instance()->stopTool();
+ emit finished();
+}
+
+void QmlProfilerEngine::setFetchingData(bool b) {
+ d->m_fetchingData = b;
+ }
+
+void QmlProfilerEngine::finishProcess()
+{
+ // user stop?
+ if (!d->m_running) {
+ if (d->m_process) {
+ disconnect(d->m_process,SIGNAL(finished(int)),this,SLOT(spontaneousStop()));
+ if (d->m_process->state() == QProcess::Running) {
+ d->m_process->terminate();
+ if (!d->m_process->waitForFinished(1000)) {
+ d->m_process->kill();
+ d->m_process->waitForFinished();
+ }
+ }
+ delete d->m_process;
+ d->m_process = 0;
+ }
+
+ emit finished();
+ }
+}
+
+bool QmlProfilerEngine::QmlProfilerEnginePrivate::launchperfmonitor()
+{
+ bool qtquick1 = false;
+
+ m_process = new QProcess();
+
+ QStringList arguments("-qmljsdebugger=port:" + QString::number(QmlProfilerTool::port) + ",block");
+ arguments.append(m_params.debuggeeArgs.split(" "));
+
+ if (QmlProfilerPlugin::debugOutput)
+ qWarning("QmlProfiler: Launching %s", qPrintable(m_params.displayName));
+
+ if (qtquick1) {
+ QProcessEnvironment env;
+ env.insert("QMLSCENE_IMPORT_NAME", "quick1");
+ m_process->setProcessEnvironment(env);
+ }
+
+ m_process->setProcessChannelMode(QProcess::ForwardedChannels);
+ m_process->setWorkingDirectory(m_params.workingDirectory);
+ connect(m_process,SIGNAL(finished(int)),q,SLOT(spontaneousStop()));
+ m_process->start(m_params.debuggee, arguments);
+
+ // give the process time to start
+ sleep(1);
+
+ if (!m_process->waitForStarted()) {
+ if (QmlProfilerPlugin::debugOutput)
+ qWarning("QmlProfiler: %s failed to start", qPrintable(m_params.displayName));
+ return false;
+ }
+
+ if (QmlProfilerPlugin::debugOutput)
+ qWarning("QmlProfiler: Connecting to %s:%d", qPrintable(QmlProfilerTool::host), QmlProfilerTool::port);
+
+ return true;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/plugins/qmlprofiler/qmlprofilerengine.h b/src/plugins/qmlprofiler/qmlprofilerengine.h
new file mode 100644
index 0000000000..5fc49aa7cc
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilerengine.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 QMLPROFILERENGINE_H
+#define QMLPROFILERENGINE_H
+
+#include <analyzerbase/ianalyzerengine.h>
+
+namespace QmlProfiler {
+namespace Internal {
+
+class QmlProfilerEngine : public Analyzer::IAnalyzerEngine
+{
+ Q_OBJECT
+public:
+ explicit QmlProfilerEngine(const Analyzer::AnalyzerStartParameters &sp,
+ ProjectExplorer::RunConfiguration *runConfiguration);
+ ~QmlProfilerEngine();
+
+signals:
+ void processRunning();
+ //void finished();
+ void stopRecording();
+
+public slots:
+ void start();
+ void stop();
+ void spontaneousStop();
+
+ void setFetchingData(bool);
+ void finishProcess();
+
+private:
+ class QmlProfilerEnginePrivate;
+ QmlProfilerEnginePrivate *d;
+};
+
+} // namespace Internal
+} // namespace QmlProfiler
+
+#endif // QMLPROFILERENGINE_H
diff --git a/src/plugins/qmlprofiler/qmlprofilerplugin.cpp b/src/plugins/qmlprofiler/qmlprofilerplugin.cpp
new file mode 100644
index 0000000000..6b3b5d6e02
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilerplugin.cpp
@@ -0,0 +1,129 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "qmlprofilerplugin.h"
+#include "qmlprofilerconstants.h"
+#include "qmlprojectanalyzerruncontrolfactory.h"
+
+#include <coreplugin/icore.h>
+#include <coreplugin/icontext.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/coreconstants.h>
+
+#include <analyzerbase/analyzermanager.h>
+
+#include <QtGui/QAction>
+#include <QtGui/QMessageBox>
+#include <QtGui/QMainWindow>
+#include <QtGui/QMenu>
+
+#include <QtCore/QtPlugin>
+
+#include "qmlprofilertool.h"
+
+using namespace Analyzer;
+using namespace QmlProfiler::Internal;
+
+QmlProfilerPlugin *QmlProfilerPlugin::m_instance = 0;
+bool QmlProfilerPlugin::debugOutput = false;
+
+
+class QmlProfilerPlugin::QmlProfilerPluginPrivate
+{
+public:
+ QmlProfilerPluginPrivate(QmlProfilerPlugin *qq):
+ q(qq)
+ {}
+
+ void initialize(const QStringList &arguments, QString *errorString);
+
+ QmlProjectAnalyzerRunControlFactory *m_runControlFactory;
+ QmlProfilerPlugin *q;
+};
+
+void QmlProfilerPlugin::QmlProfilerPluginPrivate::initialize(const QStringList &arguments, QString *errorString)
+{
+ Q_UNUSED(arguments)
+ Q_UNUSED(errorString)
+
+ m_runControlFactory = new QmlProjectAnalyzerRunControlFactory();
+ Analyzer::AnalyzerManager::instance()->registerRunControlFactory(m_runControlFactory);
+}
+
+
+
+QmlProfilerPlugin::QmlProfilerPlugin()
+ : d(new QmlProfilerPluginPrivate(this))
+{
+ m_instance = this;
+}
+
+QmlProfilerPlugin::~QmlProfilerPlugin()
+{
+ delete d;
+ m_instance = 0;
+}
+
+bool QmlProfilerPlugin::initialize(const QStringList &arguments, QString *errorString)
+{
+ d->initialize(arguments, errorString);
+
+ AnalyzerManager::instance()->addTool(new QmlProfilerTool(this));
+
+ return true;
+}
+
+void QmlProfilerPlugin::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 QmlProfilerPlugin::aboutToShutdown()
+{
+ // Save settings
+ // Disconnect from signals that are not needed during shutdown
+ // Hide UI (if you add UI that is not in the main window directly)
+ return SynchronousShutdown;
+}
+
+QmlProfilerPlugin *QmlProfilerPlugin::instance()
+{
+ return m_instance;
+}
+
+Q_EXPORT_PLUGIN(QmlProfilerPlugin)
+
diff --git a/src/plugins/qmlprofiler/qmlprofilerplugin.h b/src/plugins/qmlprofiler/qmlprofilerplugin.h
new file mode 100644
index 0000000000..4a2dcb997e
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilerplugin.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 QMLPROFILERPLUGIN_H
+#define QMLPROFILERPLUGIN_H
+
+#include "qmlprofiler_global.h"
+
+#include <extensionsystem/iplugin.h>
+
+namespace QmlProfiler {
+namespace Internal {
+
+class QmlProfilerPlugin : public ExtensionSystem::IPlugin
+{
+ Q_OBJECT
+
+public:
+ static QmlProfilerPlugin *instance();
+
+ QmlProfilerPlugin();
+ ~QmlProfilerPlugin();
+
+ bool initialize(const QStringList &arguments, QString *errorString);
+ void extensionsInitialized();
+ ShutdownFlag aboutToShutdown();
+
+ static bool debugOutput;
+
+private:
+ class QmlProfilerPluginPrivate;
+ QmlProfilerPluginPrivate *d;
+
+ static QmlProfilerPlugin *m_instance;
+};
+
+} // namespace Internal
+} // namespace QmlProfiler
+
+#endif // QMLPROFILERPLUGIN_H
+
diff --git a/src/plugins/qmlprofiler/qmlprofilersummaryview.cpp b/src/plugins/qmlprofiler/qmlprofilersummaryview.cpp
new file mode 100644
index 0000000000..723f063566
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilersummaryview.cpp
@@ -0,0 +1,277 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "qmlprofilersummaryview.h"
+
+#include <QtCore/QUrl>
+#include <QtCore/QHash>
+
+#include <QtGui/QHeaderView>
+#include <QtGui/QStandardItemModel>
+
+using namespace QmlProfiler::Internal;
+
+struct BindingData {
+ QString displayname;
+ QString filename;
+ int line;
+ qint64 duration;
+ qint64 calls;
+ qint64 minTime;
+ qint64 maxTime;
+ double tpc;
+ double percent;
+};
+
+class QmlProfilerSummaryView::QmlProfilerSummaryViewPrivate
+{
+public:
+ QmlProfilerSummaryViewPrivate(QmlProfilerSummaryView *qq):q(qq) {}
+ ~QmlProfilerSummaryViewPrivate() {}
+
+ QmlProfilerSummaryView *q;
+
+ QStandardItemModel *m_model;
+ QHash<QString, BindingData *> m_bindingHash;
+
+ enum RangeType {
+ Painting,
+ Compiling,
+ Creating,
+ Binding,
+ HandlingSignal,
+
+ MaximumRangeType
+ };
+};
+
+class ProfilerItem : public QStandardItem
+{
+public:
+ ProfilerItem(const QString &text):QStandardItem ( text ) {}
+
+ virtual bool operator< ( const QStandardItem & other ) const
+ {
+ if (data().type() == QVariant::String) {
+ // first column
+ return data(Qt::UserRole+2).toString() == other.data(Qt::UserRole+2).toString() ?
+ data(Qt::UserRole+3).toInt() < other.data(Qt::UserRole+3).toInt() :
+ data(Qt::UserRole+2).toString() < other.data(Qt::UserRole+2).toString();
+ }
+
+ return data().toDouble() < other.data().toDouble();
+ }
+};
+
+QmlProfilerSummaryView::QmlProfilerSummaryView(QWidget *parent) :
+ QTreeView(parent), d(new QmlProfilerSummaryViewPrivate(this))
+{
+ setRootIsDecorated(false);
+ header()->setResizeMode(QHeaderView::Interactive);
+ header()->setMinimumSectionSize(100);
+ setSortingEnabled(false);
+
+ d->m_model = new QStandardItemModel(this);
+
+ setModel(d->m_model);
+
+ d->m_model->setColumnCount(7);
+ setHeaderLabels();
+
+ connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex)));
+}
+
+QmlProfilerSummaryView::~QmlProfilerSummaryView()
+{
+ delete d->m_model;
+}
+
+void QmlProfilerSummaryView::clean()
+{
+ d->m_model->clear();
+ d->m_model->setColumnCount(7);
+
+ // clean the hash
+ QHashIterator<QString, BindingData *>it(d->m_bindingHash);
+ while (it.hasNext()) {
+ it.next();
+ delete it.value();
+ }
+ d->m_bindingHash.clear();
+
+ setHeaderLabels();
+ setSortingEnabled(false);
+}
+
+void QmlProfilerSummaryView::addRangedEvent(int type, qint64 startTime, qint64 length, const QStringList &data, const QString &fileName, int line)
+{
+ Q_UNUSED(startTime);
+ Q_UNUSED(data);
+
+ if (type != QmlProfilerSummaryViewPrivate::Binding && type != QmlProfilerSummaryViewPrivate::HandlingSignal)
+ return;
+
+ if (fileName.isEmpty())
+ return;
+ QString localName = QUrl(fileName).toLocalFile();
+ QString displayName = localName.mid(localName.lastIndexOf(QChar('/'))+1)+QLatin1String(":")+QString::number(line);
+ QString location = fileName+":"+QString::number(line);
+
+ QHash<QString, BindingData *>::iterator it = d->m_bindingHash.find(location);
+ if (it != d->m_bindingHash.end()) {
+ BindingData *bindingInfo = it.value();
+ bindingInfo->duration += length;
+ bindingInfo->calls++;
+ if (bindingInfo->maxTime < length)
+ bindingInfo->maxTime = length;
+ if (bindingInfo->minTime > length)
+ bindingInfo->minTime = length;
+ } else {
+ BindingData *newBinding = new BindingData;
+ newBinding->calls = 1;
+ newBinding->duration = length;
+ newBinding->displayname = displayName;
+ newBinding->filename = fileName;
+ newBinding->line = line;
+ newBinding->minTime = length;
+ newBinding->maxTime = length;
+
+ d->m_bindingHash.insert(location, newBinding);
+ }
+}
+
+void QmlProfilerSummaryView::complete()
+{
+ // compute percentages
+ double totalTime = 0;
+
+ QHashIterator<QString, BindingData *> it(d->m_bindingHash);
+
+ while (it.hasNext()) {
+ it.next();
+ totalTime += it.value()->duration;
+ }
+
+ it.toFront();
+
+ while (it.hasNext()) {
+ it.next();
+ BindingData *binding = it.value();
+ binding->percent = binding->duration * 100.0 / totalTime;
+ binding->tpc = binding->calls>0? (double)binding->duration / binding->calls : 0;
+
+ appendRow(binding->displayname,
+ binding->filename,
+ binding->line,
+ binding->percent,
+ binding->duration,
+ binding->calls,
+ binding->tpc,
+ binding->maxTime,
+ binding->minTime);
+
+ }
+ setSortingEnabled(true);
+ sortByColumn(1,Qt::DescendingOrder);
+ resizeColumnToContents(0);
+}
+
+void QmlProfilerSummaryView::jumpToItem(const QModelIndex &index)
+{
+ int line = d->m_model->item(index.row(),0)->data(Qt::UserRole+3).toInt();
+ if (line == -1)
+ return;
+ QString fileName = d->m_model->item(index.row(),0)->data(Qt::UserRole+2).toString();
+ emit gotoSourceLocation(fileName, line);
+}
+
+void QmlProfilerSummaryView::appendRow(const QString &displayName,
+ const QString &fileName,
+ int line,
+ double percentTime,
+ double totalTime,
+ int nCalls,
+ double timePerCall,
+ double maxTime,
+ double minTime)
+{
+ QString location =fileName+":"+QString::number(line);
+ ProfilerItem *locationColumn = new ProfilerItem(displayName);
+ locationColumn->setData(QVariant(location),Qt::UserRole+1);
+ locationColumn->setData(QVariant(fileName),Qt::UserRole+2);
+ locationColumn->setData(QVariant(line),Qt::UserRole+3);
+ locationColumn->setEditable(false);
+ ProfilerItem *percentColumn = new ProfilerItem(QString::number(percentTime,'f',2)+QLatin1String(" %"));
+ percentColumn->setData(QVariant(percentTime));
+ percentColumn->setEditable(false);
+ ProfilerItem *timeColumn = new ProfilerItem(displayTime(totalTime));
+ timeColumn->setData(QVariant(totalTime));
+ timeColumn->setEditable(false);
+ ProfilerItem *callsColumn = new ProfilerItem(QString::number(nCalls));
+ callsColumn->setData(QVariant(nCalls));
+ callsColumn->setEditable(false);
+ ProfilerItem *tpcColumn = new ProfilerItem(displayTime(timePerCall));
+ tpcColumn->setData(QVariant(timePerCall));
+ tpcColumn->setEditable(false);
+ ProfilerItem *maxTimeColumn = new ProfilerItem(displayTime(maxTime));
+ maxTimeColumn->setData(QVariant(maxTime));
+ maxTimeColumn->setEditable(false);
+ ProfilerItem *minTimeColumn = new ProfilerItem(displayTime(minTime));
+ minTimeColumn->setData(QVariant(minTime));
+ minTimeColumn->setEditable(false);
+
+ QList<QStandardItem *> newRow;
+ newRow << locationColumn << percentColumn << timeColumn << callsColumn << tpcColumn << maxTimeColumn << minTimeColumn;
+ d->m_model->appendRow(newRow);
+}
+
+QString QmlProfilerSummaryView::displayTime(double time) const
+{
+ if (time<1e6)
+ return QString::number(time/1e3,'f',3) + QString::fromUtf8(" \u03BCs");//(" \u03BCs");
+ if (time<1e9)
+ return QString::number(time/1e6,'f',3) + QLatin1String(" ms");
+
+ return QString::number(time/1e9,'f',3) + QLatin1String(" s");
+}
+
+void QmlProfilerSummaryView::setHeaderLabels()
+{
+ d->m_model->setHeaderData(0,Qt::Horizontal,QVariant(tr("location")));
+ d->m_model->setHeaderData(1,Qt::Horizontal,QVariant(tr("% time")));
+ d->m_model->setHeaderData(2,Qt::Horizontal,QVariant(tr("total time")));
+ d->m_model->setHeaderData(3,Qt::Horizontal,QVariant(tr("calls")));
+ d->m_model->setHeaderData(4,Qt::Horizontal,QVariant(tr("time per call")));
+ d->m_model->setHeaderData(5,Qt::Horizontal,QVariant(tr("longest time")));
+ d->m_model->setHeaderData(6,Qt::Horizontal,QVariant(tr("shortest time")));
+}
diff --git a/src/plugins/qmlprofiler/qmlprofilersummaryview.h b/src/plugins/qmlprofiler/qmlprofilersummaryview.h
new file mode 100644
index 0000000000..e8d462044d
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilersummaryview.h
@@ -0,0 +1,79 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 QMLPROFILERSUMMARYVIEW_H
+#define QMLPROFILERSUMMARYVIEW_H
+
+#include <QTreeView>
+
+namespace QmlProfiler {
+namespace Internal {
+
+class QmlProfilerSummaryView : public QTreeView
+{
+ Q_OBJECT
+public:
+ explicit QmlProfilerSummaryView(QWidget *parent = 0);
+ ~QmlProfilerSummaryView();
+
+signals:
+ void gotoSourceLocation(const QString &fileName, int lineNumber);
+
+public slots:
+ void clean();
+ void addRangedEvent(int type, qint64 startTime, qint64 length, const QStringList &data, const QString &fileName, int line);
+ void complete();
+ void jumpToItem(const QModelIndex &index);
+
+private:
+ class QmlProfilerSummaryViewPrivate;
+ QmlProfilerSummaryViewPrivate *d;
+
+ void appendRow(const QString &displayname,
+ const QString &filename,
+ int line,
+ double percentTime,
+ double totalTime,
+ int ncalls,
+ double timepercall,
+ double maxtime,
+ double mintime);
+ void setHeaderLabels();
+ QString displayTime(double time) const;
+
+};
+
+}
+}
+
+#endif // QMLPROFILERSUMMARYVIEW_H
diff --git a/src/plugins/qmlprofiler/qmlprofilertool.cpp b/src/plugins/qmlprofiler/qmlprofilertool.cpp
new file mode 100644
index 0000000000..60f53c31ca
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilertool.cpp
@@ -0,0 +1,416 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "qmlprofilertool.h"
+#include "qmlprofilerengine.h"
+#include "qmlprofilerplugin.h"
+#include "qmlprofilerconstants.h"
+#include "qmlprofilerattachdialog.h"
+
+#include "tracewindow.h"
+#include <private/qdeclarativedebugclient_p.h>
+
+#include <analyzerbase/analyzermanager.h>
+#include <analyzerbase/analyzerconstants.h>
+#include <analyzerbase/ianalyzeroutputpaneadapter.h>
+
+#include "timelineview.h"
+
+#include "canvas/qdeclarativecanvas_p.h"
+#include "canvas/qdeclarativecontext2d_p.h"
+#include "canvas/qdeclarativetiledcanvas_p.h"
+
+#include <qmlprojectmanager/qmlprojectrunconfiguration.h>
+#include <utils/fileinprojectfinder.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/target.h>
+
+#include <texteditor/itexteditor.h>
+#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/icore.h>
+
+#include <QtCore/QFile>
+
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QToolButton>
+
+#include <QtGui/QTabWidget>
+#include "qmlprofilersummaryview.h"
+
+using namespace Analyzer;
+using namespace QmlProfiler::Internal;
+
+QString QmlProfilerTool::host = QLatin1String("localhost");
+quint16 QmlProfilerTool::port = 33456;
+
+
+// Adapter for output pane.
+class QmlProfilerOutputPaneAdapter : public Analyzer::IAnalyzerOutputPaneAdapter
+{
+public:
+ explicit QmlProfilerOutputPaneAdapter(QmlProfilerTool *mct) :
+ IAnalyzerOutputPaneAdapter(mct), m_tool(mct) {}
+
+ virtual QWidget *toolBarWidget() { return m_tool->createToolBarWidget(); }
+ virtual QWidget *paneWidget() { return m_tool->createTimeLineWidget(); }
+ virtual void clearContents() { m_tool->clearDisplay(); }
+ virtual void setFocus() { /*TODO*/ }
+ virtual bool hasFocus() const { return false; /*TODO*/ }
+ virtual bool canFocus() const { return false; /*TODO*/ }
+ virtual bool canNavigate() const { return false; /*TODO*/ }
+ virtual bool canNext() const { return false; /*TODO*/ }
+ virtual bool canPrevious() const { return false; /*TODO*/ }
+ virtual void goToNext() { /*TODO*/ }
+ virtual void goToPrev() { /*TODO*/ }
+
+
+private:
+ QmlProfilerTool *m_tool;
+};
+
+class QmlProfilerTool::QmlProfilerToolPrivate
+{
+public:
+ QmlProfilerToolPrivate(QmlProfilerTool *qq) : q(qq) {}
+ ~QmlProfilerToolPrivate() {}
+
+ QmlProfilerTool *q;
+
+ QDeclarativeDebugConnection *m_client;
+ TraceWindow *m_traceWindow;
+ QTabWidget *m_tabbed;
+ QmlProfilerSummaryView *m_summary;
+ QmlProfilerOutputPaneAdapter *m_outputPaneAdapter;
+ ProjectExplorer::Project *m_project;
+ Utils::FileInProjectFinder m_projectFinder;
+ ProjectExplorer::RunConfiguration *m_runConfiguration;
+ bool m_isAttached;
+ QAction *m_attachAction;
+ QToolButton *m_recordButton;
+};
+
+QmlProfilerTool::QmlProfilerTool(QObject *parent)
+ : IAnalyzerTool(parent), d(new QmlProfilerToolPrivate(this))
+{
+ d->m_client = 0;
+ d->m_traceWindow = 0;
+ d->m_outputPaneAdapter = 0;
+ d->m_project = 0;
+ d->m_runConfiguration = 0;
+ d->m_isAttached = false;
+ d->m_attachAction = 0;
+}
+
+QmlProfilerTool::~QmlProfilerTool()
+{
+ if (d->m_client->isConnected())
+ d->m_client->disconnectFromHost();
+ delete d->m_tabbed;
+
+ delete d->m_outputPaneAdapter;
+ delete d;
+}
+
+QString QmlProfilerTool::id() const
+{
+ return "QmlProfiler";
+}
+
+QString QmlProfilerTool::displayName() const
+{
+ return tr("Qml Performance Monitor");
+}
+
+IAnalyzerTool::ToolMode QmlProfilerTool::mode() const
+{
+ return DebugMode;
+}
+
+
+IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp,
+ ProjectExplorer::RunConfiguration *runConfiguration)
+{
+ QmlProfilerEngine *engine = new QmlProfilerEngine(sp, runConfiguration);
+
+ d->m_runConfiguration = runConfiguration;
+ d->m_project = runConfiguration->target()->project();
+ if (d->m_project) {
+ d->m_projectFinder.setProjectDirectory(d->m_project->projectDirectory());
+ updateProjectFileList();
+ connect(d->m_project, SIGNAL(fileListChanged()), this, SLOT(updateProjectFileList()));
+ }
+
+ connect(engine, SIGNAL(processRunning()), this, SLOT(connectClient()));
+ connect(engine, SIGNAL(finished()), this, SLOT(disconnectClient()));
+ connect(engine, SIGNAL(stopRecording()), this, SLOT(stopRecording()));
+ connect(d->m_traceWindow, SIGNAL(viewUpdated()), engine, SLOT(finishProcess()));
+ connect(this, SIGNAL(fetchingData(bool)), engine, SLOT(setFetchingData(bool)));
+ emit fetchingData(d->m_recordButton->isChecked());
+
+ return engine;
+}
+
+void QmlProfilerTool::initialize(ExtensionSystem::IPlugin */*plugin*/)
+{
+ qmlRegisterType<Canvas>("Monitor", 1, 0, "Canvas");
+ qmlRegisterType<TiledCanvas>("Monitor", 1, 0, "TiledCanvas");
+ qmlRegisterType<Context2D>();
+ qmlRegisterType<CanvasImage>();
+ qmlRegisterType<CanvasGradient>();
+
+ qmlRegisterType<TimelineView>("Monitor", 1, 0,"TimelineView");
+
+ d->m_client = new QDeclarativeDebugConnection;
+
+ d->m_tabbed = new QTabWidget();
+
+ d->m_traceWindow = new TraceWindow(d->m_tabbed);
+ d->m_traceWindow->reset(d->m_client);
+
+ connect(d->m_traceWindow, SIGNAL(gotoSourceLocation(QString,int)), this, SLOT(gotoSourceLocation(QString,int)));
+ connect(d->m_traceWindow, SIGNAL(timeChanged(qreal)), this, SLOT(updateTimer(qreal)));
+
+ d->m_summary = new QmlProfilerSummaryView(d->m_tabbed);
+ d->m_tabbed->addTab(d->m_traceWindow, "timeline");
+ d->m_tabbed->addTab(d->m_summary, "summary");
+
+ connect(d->m_traceWindow,SIGNAL(range(int,qint64,qint64,QStringList,QString,int)),
+ d->m_summary,SLOT(addRangedEvent(int,qint64,qint64,QStringList,QString,int)));
+ connect(d->m_traceWindow,SIGNAL(viewUpdated()), d->m_summary, SLOT(complete()));
+ connect(d->m_summary,SIGNAL(gotoSourceLocation(QString,int)), this, SLOT(gotoSourceLocation(QString,int)));
+
+ Core::ICore *core = Core::ICore::instance();
+ Core::ActionManager *am = core->actionManager();
+ Core::ActionContainer *manalyzer = am->actionContainer(Analyzer::Constants::M_DEBUG_ANALYZER);
+ const Core::Context globalcontext(Core::Constants::C_GLOBAL);
+
+ d->m_attachAction = new QAction(tr("Attach ..."), manalyzer);
+ Core::Command *command = am->registerAction(d->m_attachAction,
+ Constants::ATTACH, globalcontext);
+ command->setAttribute(Core::Command::CA_UpdateText);
+ manalyzer->addAction(command, Analyzer::Constants::G_ANALYZER_STARTSTOP);
+ connect(d->m_attachAction, SIGNAL(triggered()), this, SLOT(attach()));
+
+ Analyzer::AnalyzerManager *analyzerMgr = Analyzer::AnalyzerManager::instance();
+ connect(analyzerMgr, SIGNAL(currentToolChanged(Analyzer::IAnalyzerTool*)),
+ this, SLOT(updateAttachAction()));
+
+ updateAttachAction();
+}
+
+void QmlProfilerTool::extensionsInitialized()
+{
+}
+
+IAnalyzerOutputPaneAdapter *QmlProfilerTool::outputPaneAdapter()
+{
+ if (!d->m_outputPaneAdapter)
+ d->m_outputPaneAdapter = new QmlProfilerOutputPaneAdapter(this);
+ return d->m_outputPaneAdapter;
+}
+
+QWidget *QmlProfilerTool::createToolBarWidget()
+{
+ // custom toolbar (TODO)
+ QWidget *toolbarWidget = new QWidget;
+ toolbarWidget->setObjectName(QLatin1String("QmlProfilerToolBarWidget"));
+
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->setMargin(0);
+ layout->setSpacing(0);
+
+ d->m_recordButton = new QToolButton(toolbarWidget);
+
+ d->m_recordButton->setIcon(QIcon(QLatin1String(":/qmlprofiler/analyzer_category_small.png")));
+ d->m_recordButton->setCheckable(true);
+
+ connect(d->m_recordButton,SIGNAL(toggled(bool)), this, SLOT(setRecording(bool)));
+ d->m_recordButton->setChecked(true);
+ layout->addWidget(d->m_recordButton);
+
+ QLabel *timeLabel = new QLabel(tr("elapsed: 0 s"));
+ QPalette palette = timeLabel->palette();
+ palette.setColor(QPalette::WindowText, Qt::white);
+ timeLabel->setPalette(palette);
+
+ connect(this,SIGNAL(setTimeLabel(QString)),timeLabel,SLOT(setText(QString)));
+ layout->addWidget(timeLabel);
+ toolbarWidget->setLayout(layout);
+
+ return toolbarWidget;
+}
+
+QWidget *QmlProfilerTool::createTimeLineWidget()
+{
+ return d->m_tabbed;
+}
+
+void QmlProfilerTool::connectClient()
+{
+ QDeclarativeDebugConnection *newClient = new QDeclarativeDebugConnection;
+ d->m_traceWindow->reset(newClient);
+ delete d->m_client;
+ d->m_client = newClient;
+
+ d->m_client->connectToHost(host, port);
+ d->m_client->waitForConnected();
+
+ if (d->m_client->isConnected()) {
+ if (QmlProfilerPlugin::debugOutput)
+ qWarning("QmlProfiler: connected and running");
+ } else {
+ if (QmlProfilerPlugin::debugOutput)
+ qWarning("QmlProfiler: Failed to connect: %s", qPrintable(d->m_client->errorString()));
+ }
+
+ if (d->m_traceWindow->isRecording())
+ clearDisplay();
+}
+
+void QmlProfilerTool::disconnectClient()
+{
+ d->m_client->disconnectFromHost();
+}
+
+
+void QmlProfilerTool::startRecording()
+{
+ d->m_traceWindow->setRecordAtStart(true);
+ if (d->m_client->isConnected()) {
+ clearDisplay();
+ d->m_traceWindow->setRecording(true);
+ }
+ emit fetchingData(true);
+}
+
+void QmlProfilerTool::stopRecording()
+{
+ d->m_traceWindow->setRecordAtStart(d->m_recordButton->isChecked());
+ if (d->m_client->isConnected())
+ d->m_traceWindow->setRecording(false);
+ emit fetchingData(false);
+}
+
+void QmlProfilerTool::setRecording(bool recording)
+{
+ if (recording)
+ startRecording();
+ else
+ stopRecording();
+}
+
+void QmlProfilerTool::gotoSourceLocation(const QString &fileUrl, int lineNumber)
+{
+ if (lineNumber < 0 || fileUrl.isEmpty())
+ return;
+
+ const QString fileName = QUrl(fileUrl).toLocalFile();
+ const QString projectFileName = d->m_projectFinder.findFile(fileName);
+
+ Core::EditorManager *editorManager = Core::EditorManager::instance();
+ Core::IEditor *editor = editorManager->openEditor(projectFileName);
+ TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor*>(editor);
+
+ if (textEditor) {
+ editorManager->addCurrentPositionToNavigationHistory();
+ textEditor->gotoLine(lineNumber);
+ textEditor->widget()->setFocus();
+ }
+}
+
+void QmlProfilerTool::updateTimer(qreal elapsedSeconds)
+{
+ QString timeString = QString::number(elapsedSeconds,'f',1);
+ timeString = QString(" ").left(6-timeString.length()) + timeString;
+ emit setTimeLabel(tr("elapsed: ")+timeString+QLatin1String(" s"));
+}
+
+void QmlProfilerTool::updateProjectFileList()
+{
+ d->m_projectFinder.setProjectFiles(
+ d->m_project->files(ProjectExplorer::Project::ExcludeGeneratedFiles));
+}
+
+bool QmlProfilerTool::canRunRemotely() const
+{
+ // TODO: Is this correct?
+ return true;
+}
+
+void QmlProfilerTool::clearDisplay()
+{
+ d->m_traceWindow->clearDisplay();
+ d->m_summary->clean();
+}
+
+void QmlProfilerTool::attach()
+{
+ if (!d->m_isAttached) {
+ QmlProfilerAttachDialog dialog;
+ int result = dialog.exec();
+
+ if (result == QDialog::Rejected)
+ return;
+
+ port = dialog.port();
+ host = dialog.address();
+
+ connectClient();
+ AnalyzerManager::instance()->showMode();
+ } else {
+ stopRecording();
+ }
+
+ d->m_isAttached = !d->m_isAttached;
+ updateAttachAction();
+}
+
+void QmlProfilerTool::updateAttachAction()
+{
+ if (d->m_attachAction) {
+ if (d->m_isAttached) {
+ d->m_attachAction->setText(tr("Detach"));
+ } else {
+ d->m_attachAction->setText(tr("Attach..."));
+ }
+ }
+
+ d->m_attachAction->setEnabled(Analyzer::AnalyzerManager::instance()->currentTool() == this);
+}
+
diff --git a/src/plugins/qmlprofiler/qmlprofilertool.h b/src/plugins/qmlprofiler/qmlprofilertool.h
new file mode 100644
index 0000000000..f7d12972d7
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilertool.h
@@ -0,0 +1,101 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 QMLPROFILERTOOL_H
+#define QMLPROFILERTOOL_H
+
+#include <analyzerbase/ianalyzertool.h>
+#include <analyzerbase/ianalyzerengine.h>
+
+namespace QmlProfiler {
+namespace Internal {
+
+class QmlProfilerTool : public Analyzer::IAnalyzerTool
+{
+ Q_OBJECT
+public:
+ explicit QmlProfilerTool(QObject *parent = 0);
+ ~QmlProfilerTool();
+
+ QString id() const;
+ QString displayName() const;
+ ToolMode mode() const;
+
+ void initialize(ExtensionSystem::IPlugin *plugin);
+ void extensionsInitialized();
+
+ Analyzer::IAnalyzerEngine *createEngine(const Analyzer::AnalyzerStartParameters &sp,
+ ProjectExplorer::RunConfiguration *runConfiguration = 0);
+
+ Analyzer::IAnalyzerOutputPaneAdapter *outputPaneAdapter();
+ QWidget *createToolBarWidget();
+ QWidget *createTimeLineWidget();
+
+ bool canRunRemotely() const;
+
+ void clearDisplay();
+
+public slots:
+ void connectClient();
+ void disconnectClient();
+
+ void startRecording();
+ void stopRecording();
+ void setRecording(bool recording);
+
+ void gotoSourceLocation(const QString &fileUrl, int lineNumber);
+ void updateTimer(qreal elapsedSeconds);
+
+signals:
+ void setTimeLabel(const QString &);
+ void fetchingData(bool);
+
+public:
+ // Todo: configurable parameters
+ static QString host;
+ static quint16 port;
+
+private slots:
+ void updateProjectFileList();
+ void attach();
+ void updateAttachAction();
+
+private:
+ class QmlProfilerToolPrivate;
+ QmlProfilerToolPrivate *d;
+};
+
+} // namespace Internal
+} // namespace QmlProfiler
+
+#endif // QMLPROFILERTOOL_H
diff --git a/src/plugins/qmlprofiler/qmlprojectanalyzerruncontrolfactory.cpp b/src/plugins/qmlprofiler/qmlprojectanalyzerruncontrolfactory.cpp
new file mode 100644
index 0000000000..e310335ed5
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprojectanalyzerruncontrolfactory.cpp
@@ -0,0 +1,123 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "qmlprojectanalyzerruncontrolfactory.h"
+#include "qmlprojectmanager/qmlprojectrunconfiguration.h"
+#include <analyzerbase/analyzerstartparameters.h>
+#include <analyzerbase/analyzersettings.h>
+#include <analyzerbase/analyzerrunconfigwidget.h>
+
+#include <utils/qtcassert.h>
+
+using namespace Analyzer;
+using namespace ProjectExplorer;
+using namespace QmlProfiler::Internal;
+
+AnalyzerStartParameters localStartParameters(ProjectExplorer::RunConfiguration *runConfiguration)
+{
+ AnalyzerStartParameters sp;
+ QTC_ASSERT(runConfiguration, return sp);
+ QmlProjectManager::QmlProjectRunConfiguration *rc =
+ qobject_cast<QmlProjectManager::QmlProjectRunConfiguration *>(runConfiguration);
+ QTC_ASSERT(rc, return sp);
+
+ sp.startMode = StartLocal;
+ sp.environment = rc->environment();
+ sp.workingDirectory = rc->workingDirectory();
+ sp.debuggee = rc->observerPath();
+ sp.debuggeeArgs = rc->viewerArguments();
+ sp.displayName = rc->displayName();
+ return sp;
+}
+
+QmlProjectAnalyzerRunControlFactory::QmlProjectAnalyzerRunControlFactory(QObject *parent)
+ : IRunControlFactory(parent)
+{
+
+}
+
+QmlProjectAnalyzerRunControlFactory::~QmlProjectAnalyzerRunControlFactory()
+{
+
+}
+
+bool QmlProjectAnalyzerRunControlFactory::canRun(RunConfiguration *runConfiguration, const QString &mode) const
+{
+ if (!qobject_cast<QmlProjectManager::QmlProjectRunConfiguration *>(runConfiguration))
+ return false;
+ return mode == Constants::MODE_ANALYZE;
+}
+
+RunControl *QmlProjectAnalyzerRunControlFactory::create(RunConfiguration *runConfiguration, const QString &mode)
+{
+ if (!qobject_cast<QmlProjectManager::QmlProjectRunConfiguration *>(runConfiguration) ||
+ mode != Constants::MODE_ANALYZE) {
+ return 0;
+ }
+ const AnalyzerStartParameters sp = localStartParameters(runConfiguration);
+ return create(sp, runConfiguration);
+}
+
+AnalyzerRunControl *QmlProjectAnalyzerRunControlFactory::create(const Analyzer::AnalyzerStartParameters &sp, RunConfiguration *runConfiguration)
+{
+ AnalyzerRunControl *rc = new AnalyzerRunControl(sp, runConfiguration);
+ emit runControlCreated(rc);
+ return rc;
+}
+
+QString QmlProjectAnalyzerRunControlFactory::displayName() const
+{
+ return tr("QmlAnalyzer");
+}
+
+IRunConfigurationAspect *QmlProjectAnalyzerRunControlFactory::createRunConfigurationAspect()
+{
+ return new AnalyzerProjectSettings;
+}
+
+RunConfigWidget *QmlProjectAnalyzerRunControlFactory::createConfigurationWidget(RunConfiguration *runConfiguration)
+{
+ QmlProjectManager::QmlProjectRunConfiguration *localRc =
+ qobject_cast<QmlProjectManager::QmlProjectRunConfiguration *>(runConfiguration);
+ if (!localRc)
+ return 0;
+
+ AnalyzerProjectSettings *settings = runConfiguration->extraAspect<AnalyzerProjectSettings>();
+ if (!settings)
+ return 0;
+
+ Analyzer::AnalyzerRunConfigWidget *ret = new Analyzer::AnalyzerRunConfigWidget;
+ ret->setRunConfiguration(runConfiguration);
+ return ret;
+// return 0;
+}
diff --git a/src/plugins/qmlprofiler/qmlprojectanalyzerruncontrolfactory.h b/src/plugins/qmlprofiler/qmlprojectanalyzerruncontrolfactory.h
new file mode 100644
index 0000000000..1d2de80d0c
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprojectanalyzerruncontrolfactory.h
@@ -0,0 +1,69 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 QMLPROJECTANALYZERRUNCONTROLFACTORY_H
+#define QMLPROJECTANALYZERRUNCONTROLFACTORY_H
+
+#include <analyzerbase/analyzerruncontrol.h>
+//#include <analyzerbase/analyzerruncontrolfactory.h>
+#include <projectexplorer/runconfiguration.h>
+
+namespace QmlProfiler {
+namespace Internal {
+
+class QmlProjectAnalyzerRunControlFactory : public ProjectExplorer::IRunControlFactory
+{
+ Q_OBJECT
+public:
+ typedef ProjectExplorer::RunConfiguration RunConfiguration;
+
+ QmlProjectAnalyzerRunControlFactory(QObject *parent = 0);
+ ~QmlProjectAnalyzerRunControlFactory();
+
+ // virtuals from IRunControlFactory
+ bool canRun(RunConfiguration *runConfiguration, const QString &mode) const;
+ ProjectExplorer::RunControl *create(RunConfiguration *runConfiguration, const QString &mode);
+ Analyzer::AnalyzerRunControl *create(const Analyzer::AnalyzerStartParameters &sp, RunConfiguration *runConfiguration = 0);
+ QString displayName() const;
+
+ ProjectExplorer::IRunConfigurationAspect *createRunConfigurationAspect();
+ ProjectExplorer::RunConfigWidget *createConfigurationWidget(RunConfiguration *runConfiguration);
+
+signals:
+ void runControlCreated(Analyzer::AnalyzerRunControl *);
+};
+
+}
+}
+
+#endif // QMLPROJECTANALYZERRUNCONTROLFACTORY_H
diff --git a/src/plugins/qmlprofiler/timelineview.cpp b/src/plugins/qmlprofiler/timelineview.cpp
new file mode 100644
index 0000000000..26a09fd1c1
--- /dev/null
+++ b/src/plugins/qmlprofiler/timelineview.cpp
@@ -0,0 +1,238 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "timelineview.h"
+
+#include <qdeclarativecontext.h>
+#include <qdeclarativeproperty.h>
+
+using namespace QmlProfiler::Internal;
+
+TimelineView::TimelineView(QDeclarativeItem *parent) :
+ QDeclarativeItem(parent), m_delegate(0), m_startTime(0), m_endTime(0), m_startX(0),
+ prevMin(0), prevMax(0), m_totalWidth(0)
+{
+}
+
+void TimelineView::componentComplete()
+{
+ QDeclarativeItem::componentComplete();
+}
+
+void TimelineView::clearData()
+{
+ m_rangeList.clear();
+ m_items.clear();
+ m_startTime = 0;
+ m_endTime = 0;
+ m_startX = 0;
+ prevMin = 0;
+ prevMax = 0;
+ m_prevLimits.clear();
+ m_totalWidth = 0;
+
+}
+
+void TimelineView::setRanges(const QScriptValue &value)
+{
+ //TODO clear old values (always?)
+ m_ranges = value;
+
+ //### below code not yet used anywhere
+ int length = m_ranges.property("length").toInt32();
+
+ for (int i = 0; i < length; ++i) {
+ int type = m_ranges.property(i).property("type").toNumber();
+ Q_ASSERT(type >= 0);
+ while (m_rangeList.count() <= type)
+ m_rangeList.append(ValueList());
+ m_rangeList[type] << m_ranges.property(i);
+ }
+
+ for (int i = 0; i < m_rangeList.count(); ++i)
+ m_prevLimits << PrevLimits(0, 0);
+
+ qreal startValue = m_ranges.property(0).property("start").toNumber();
+ m_starts.clear();
+ m_starts.reserve(length);
+ m_ends.clear();
+ m_ends.reserve(length);
+ for (int i = 0; i < length; ++i) {
+ m_starts.append(m_ranges.property(i).property("start").toNumber() - startValue);
+ m_ends.append(m_ranges.property(i).property("start").toNumber() + m_ranges.property(i).property("duration").toNumber() - startValue);
+ }
+}
+
+void TimelineView::setStartX(qreal arg)
+{
+ if (arg == m_startX)
+ return;
+
+ if (!m_ranges.isArray())
+ return;
+
+ qreal window = m_endTime - m_startTime;
+ if (window == 0) //###
+ return;
+ qreal spacing = width() / window;
+ qreal oldStart = m_startTime;
+ m_startTime = arg / spacing;
+ m_endTime += m_startTime - oldStart;
+
+ updateTimeline(false);
+ m_startX = arg;
+ emit startXChanged(m_startX);
+}
+
+void TimelineView::updateTimeline(bool updateStartX)
+{
+ if (!m_delegate)
+ return;
+
+ if (!m_ranges.isArray())
+ return;
+
+ int length = m_ranges.property("length").toInt32();
+
+ qreal startValue = m_ranges.property(0).property("start").toNumber();
+ qreal endValue = m_ranges.property(length-1).property("start").toNumber() + m_ranges.property(length-1).property("duration").toNumber();
+
+ qreal totalRange = endValue - startValue;
+ qreal window = m_endTime - m_startTime;
+
+ if (window == 0) //###
+ return;
+
+ qreal spacing = width() / window;
+ qreal oldtw = m_totalWidth;
+ m_totalWidth = totalRange * spacing;
+
+ // Find region samples
+ int minsample = 0;
+ int maxsample = 0;
+
+ for (int i = 0; i < length; ++i) {
+ if (m_ends.at(i) >= m_startTime)
+ break;
+ minsample = i;
+ }
+
+ for (int i = minsample + 1; i < length; ++i) {
+ maxsample = i;
+ if (m_starts.at(i) > m_endTime)
+ break;
+ }
+
+ //### overkill (if we can expose whether or not data is nested)
+ for (int i = maxsample + 1; i < length; ++i) {
+ if (m_starts.at(i) < m_endTime)
+ maxsample = i;
+ }
+
+ //qDebug() << maxsample - minsample;
+
+ if (updateStartX) {
+ qreal oldStartX = m_startX;
+ m_startX = qRound(m_startTime * spacing);
+ if (m_startX != oldStartX) {
+ emit startXChanged(m_startX);
+ }
+ }
+
+ //### emitting this before startXChanged was causing issues
+ if (m_totalWidth != oldtw)
+ emit totalWidthChanged(m_totalWidth);
+
+ //clear items no longer in view
+ while (prevMin < minsample) {
+ delete m_items.take(prevMin);
+ ++prevMin;
+ }
+ while (prevMax > maxsample) {
+ delete m_items.take(prevMax);
+ --prevMax;
+ }
+
+ // Show items
+ int z = 0;
+ for (int i = maxsample-1; i >= minsample; --i) {
+ QDeclarativeItem *item = 0;
+ item = m_items.value(i);
+ bool creating = false;
+ if (!item) {
+ QDeclarativeContext *ctxt = new QDeclarativeContext(qmlContext(this));
+ item = qobject_cast<QDeclarativeItem*>(m_delegate->beginCreate(ctxt));
+ m_items.insert(i, item);
+ creating = true;
+
+ int type = m_ranges.property(i).property("type").toNumber();
+
+ ctxt->setParent(item); //### QDeclarative_setParent_noEvent(ctxt, item); instead?
+ ctxt->setContextProperty("duration", qMax(qRound(m_ranges.property(i).property("duration").toNumber()/qreal(1000)),1));
+ ctxt->setContextProperty("fileName", m_ranges.property(i).property("fileName").toString());
+ ctxt->setContextProperty("line", m_ranges.property(i).property("line").toNumber());
+ QString label;
+ QVariantList list = m_ranges.property(i).property("label").toVariant().value<QVariantList>();
+ for (int i = 0; i < list.size(); ++i) {
+ if (i > 0)
+ label += "\n";
+ QString sub = list.at(i).toString();
+
+ //### only do rewrite for bindings...
+ if (type == 3) {
+ //### don't construct in loop
+ QRegExp rewrite("\\(function \\$(\\w+)\\(\\) \\{ return (.+) \\}\\)");
+ bool match = rewrite.exactMatch(sub);
+ if (match)
+ sub = rewrite.cap(1) + ": " + rewrite.cap(2);
+ }
+
+ label += sub;
+ }
+ ctxt->setContextProperty("label", label);
+ ctxt->setContextProperty("type", type);
+ item->setY(type*50);
+ item->setParentItem(this);
+ }
+ if (item) {
+ item->setX(m_starts.at(i)*spacing);
+ item->setWidth((m_ends.at(i)-m_starts.at(i)) * spacing);
+ item->setZValue(++z);
+ }
+ if (creating)
+ m_delegate->completeCreate();
+ }
+
+ prevMin = minsample;
+ prevMax = maxsample;
+}
diff --git a/src/plugins/qmlprofiler/timelineview.h b/src/plugins/qmlprofiler/timelineview.h
new file mode 100644
index 0000000000..d52e5a8806
--- /dev/null
+++ b/src/plugins/qmlprofiler/timelineview.h
@@ -0,0 +1,150 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 TIMELINEVIEW_H
+#define TIMELINEVIEW_H
+
+#include <QtDeclarative/QDeclarativeItem>
+#include <QtScript/QScriptValue>
+
+namespace QmlProfiler {
+namespace Internal {
+
+class TimelineView : public QDeclarativeItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+ Q_PROPERTY(qint64 startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
+ Q_PROPERTY(qint64 endTime READ endTime WRITE setEndTime NOTIFY endTimeChanged)
+ Q_PROPERTY(qreal startX READ startX WRITE setStartX NOTIFY startXChanged)
+ Q_PROPERTY(qreal totalWidth READ totalWidth NOTIFY totalWidthChanged)
+
+public:
+ explicit TimelineView(QDeclarativeItem *parent = 0);
+
+ QDeclarativeComponent * delegate() const
+ {
+ return m_delegate;
+ }
+
+ qint64 startTime() const
+ {
+ return m_startTime;
+ }
+
+ qint64 endTime() const
+ {
+ return m_endTime;
+ }
+
+ qreal startX() const
+ {
+ return m_startX;
+ }
+
+ qreal totalWidth() const
+ {
+ return m_totalWidth;
+ }
+
+signals:
+ void delegateChanged(QDeclarativeComponent * arg);
+ void startTimeChanged(qint64 arg);
+ void endTimeChanged(qint64 arg);
+ void startXChanged(qreal arg);
+ void totalWidthChanged(qreal arg);
+
+public slots:
+ void clearData();
+ void setRanges(const QScriptValue &value);
+ void updateTimeline(bool updateStartX = true);
+
+ void setDelegate(QDeclarativeComponent * arg)
+ {
+ if (m_delegate != arg) {
+ m_delegate = arg;
+ emit delegateChanged(arg);
+ }
+ }
+
+ void setStartTime(qint64 arg)
+ {
+ if (m_startTime != arg) {
+ m_startTime = arg;
+ emit startTimeChanged(arg);
+ }
+ }
+
+ void setEndTime(qint64 arg)
+ {
+ if (m_endTime != arg) {
+ m_endTime = arg;
+ emit endTimeChanged(arg);
+ }
+ }
+
+ void setStartX(qreal arg);
+
+protected:
+ void componentComplete();
+
+private:
+ QDeclarativeComponent * m_delegate;
+ QScriptValue m_ranges;
+ typedef QList<QScriptValue> ValueList;
+ QList<ValueList> m_rangeList;
+ QHash<int,QDeclarativeItem*> m_items;
+ qint64 m_startTime;
+ qint64 m_endTime;
+ qreal m_startX;
+ int prevMin;
+ int prevMax;
+ QList<qreal> m_starts;
+ QList<qreal> m_ends;
+
+ struct PrevLimits {
+ PrevLimits(int _min, int _max) : min(_min), max(_max) {}
+ int min;
+ int max;
+ };
+
+ QList<PrevLimits> m_prevLimits;
+ qreal m_totalWidth;
+};
+
+} // namespace Internal
+} // namespace QmlProfiler
+
+QML_DECLARE_TYPE(QmlProfiler::Internal::TimelineView)
+
+#endif // TIMELINEVIEW_H
diff --git a/src/plugins/qmlprofiler/tracewindow.cpp b/src/plugins/qmlprofiler/tracewindow.cpp
new file mode 100644
index 0000000000..8c3f3dbb26
--- /dev/null
+++ b/src/plugins/qmlprofiler/tracewindow.cpp
@@ -0,0 +1,345 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "tracewindow.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qmargins.h>
+
+#include <QtGui/qapplication.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qboxlayout.h>
+#include <QtGui/qevent.h>
+#include <QtCore/qstack.h>
+
+#include <QGraphicsObject>
+
+#include <QtDeclarative/qdeclarativeview.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarative.h>
+
+#include "qmlprofilerplugin.h"
+//#include <jsdebuggeragent.h>
+//#include <qdeclarativeviewobserver.h>
+
+#define GAP_TIME 150
+
+namespace QmlProfiler {
+namespace Internal {
+
+struct Location
+{
+ Location() : line(-1) {}
+ Location(const QString &file, int lineNumber) : fileName(file), line(lineNumber) {}
+ QString fileName;
+ int line;
+};
+
+class TracePlugin : public QDeclarativeDebugClient
+{
+ Q_OBJECT
+ Q_PROPERTY(bool recording READ recording WRITE setRecording NOTIFY recordingChanged)
+public:
+ TracePlugin(QDeclarativeDebugConnection *client);
+
+ enum EventType {
+ FramePaint,
+ Mouse,
+ Key,
+
+ MaximumEventType
+ };
+
+ enum Message {
+ Event,
+ RangeStart,
+ RangeData,
+ RangeLocation,
+ RangeEnd,
+ Complete,
+
+ MaximumMessage
+ };
+
+ enum RangeType {
+ Painting,
+ Compiling,
+ Creating,
+ Binding,
+ HandlingSignal,
+
+ MaximumRangeType
+ };
+
+ bool recording() const
+ {
+ return m_recording;
+ }
+
+public slots:
+ void setRecording(bool);
+ void clearView();
+
+signals:
+ void complete();
+ void gap(qint64);
+ void event(int event, qint64 time);
+ void range(int type, qint64 startTime, qint64 length, const QStringList &data, const QString &fileName, int line);
+
+ void sample(int, int, int, bool);
+
+ void recordingChanged(bool arg);
+
+ void enabled();
+ void clear();
+
+protected:
+ virtual void statusChanged(Status);
+ virtual void messageReceived(const QByteArray &);
+
+private:
+
+ qint64 m_inProgressRanges;
+ QStack<qint64> m_rangeStartTimes[MaximumRangeType];
+ QStack<QStringList> m_rangeDatas[MaximumRangeType];
+ QStack<Location> m_rangeLocations[MaximumRangeType];
+ int m_rangeCount[MaximumRangeType];
+ qint64 m_maximumTime;
+ bool m_recording;
+};
+
+} // namespace Internal
+} // namespace QmlProfiler
+
+using namespace QmlProfiler::Internal;
+
+TracePlugin::TracePlugin(QDeclarativeDebugConnection *client)
+ : QDeclarativeDebugClient(QLatin1String("CanvasFrameRate"), client), m_inProgressRanges(0), m_maximumTime(0), m_recording(false)
+{
+ ::memset(m_rangeCount, 0, MaximumRangeType * sizeof(int));
+}
+
+void TracePlugin::clearView()
+{
+ ::memset(m_rangeCount, 0, MaximumRangeType * sizeof(int));
+ emit clear();
+}
+
+void TracePlugin::setRecording(bool v)
+{
+ if (v == m_recording)
+ return;
+ QByteArray ba;
+ QDataStream stream(&ba, QIODevice::WriteOnly);
+ stream << v;
+ sendMessage(ba);
+ m_recording = v;
+ emit recordingChanged(v);
+}
+
+void TracePlugin::statusChanged(Status status)
+{
+ if (status == Enabled) {
+ m_recording = !m_recording;
+ setRecording(!m_recording);
+ emit enabled();
+ }
+}
+
+void TracePlugin::messageReceived(const QByteArray &data)
+{
+ QByteArray rwData = data;
+ QDataStream stream(&rwData, QIODevice::ReadOnly);
+
+ qint64 time;
+ int messageType;
+
+ stream >> time >> messageType;
+
+// qDebug() << __FUNCTION__ << messageType;
+
+ if (messageType >= MaximumMessage)
+ return;
+
+ if (time > (m_maximumTime + GAP_TIME) && 0 == m_inProgressRanges)
+ emit gap(time);
+
+ if (messageType == Event) {
+ int event;
+ stream >> event;
+
+ if (event < MaximumEventType) {
+ emit this->event((EventType)event, time);
+ m_maximumTime = qMax(time, m_maximumTime);
+ }
+ } else if (messageType == Complete) {
+ emit complete();
+ } else {
+ int range;
+ stream >> range;
+
+ if (range >= MaximumRangeType)
+ return;
+
+ if (messageType == RangeStart) {
+ m_rangeStartTimes[range].push(time);
+ m_inProgressRanges |= (1 << range);
+ ++m_rangeCount[range];
+ } else if (messageType == RangeData) {
+ QString data;
+ stream >> data;
+
+ int count = m_rangeCount[range];
+ if (count > 0) {
+ while (m_rangeDatas[range].count() < count)
+ m_rangeDatas[range].push(QStringList());
+ m_rangeDatas[range][count-1] << data;
+ }
+
+ } else if (messageType == RangeLocation) {
+ QString fileName;
+ int line;
+ stream >> fileName >> line;
+
+ if (m_rangeCount[range] > 0) {
+ m_rangeLocations[range].push(Location(fileName, line));
+ }
+ } else {
+ if (m_rangeCount[range] > 0) {
+ --m_rangeCount[range];
+ if (m_inProgressRanges & (1 << range))
+ m_inProgressRanges &= ~(1 << range);
+
+ m_maximumTime = qMax(time, m_maximumTime);
+ QStringList data = m_rangeDatas[range].count() ? m_rangeDatas[range].pop() : QStringList();
+ Location location = m_rangeLocations[range].count() ? m_rangeLocations[range].pop() : Location();
+
+ qint64 startTime = m_rangeStartTimes[range].pop();
+ emit this->range((RangeType)range, startTime, time - startTime, data, location.fileName, location.line);
+ if (m_rangeCount[range] == 0) {
+ int count = m_rangeDatas[range].count() +
+ m_rangeStartTimes[range].count() +
+ m_rangeLocations[range].count();
+ if (count != 0)
+ qWarning() << "incorrectly nested data";
+ }
+ }
+ }
+ }
+}
+
+TraceWindow::TraceWindow(QWidget *parent)
+: QWidget(parent),
+ m_plugin(0), m_recordAtStart(false)
+{
+ setObjectName(tr("Qml Performance Monitor"));
+
+ QVBoxLayout *groupLayout = new QVBoxLayout;
+ groupLayout->setContentsMargins(0, 0, 0, 0);
+ groupLayout->setSpacing(0);
+
+ m_view = new QDeclarativeView(this);
+
+ if (QmlProfilerPlugin::debugOutput) {
+ //new QmlJSDebugger::JSDebuggerAgent(m_view->engine());
+ //new QmlJSDebugger::QDeclarativeViewObserver(m_view, m_view);
+ }
+
+ m_view->setResizeMode(QDeclarativeView::SizeRootObjectToView);
+ m_view->setFocus();
+ groupLayout->addWidget(m_view);
+
+ setLayout(groupLayout);
+
+ // Maximum height: 5 rows of 50 pixels + scrollbar of 50 pixels
+ setFixedHeight(300);
+}
+
+TraceWindow::~TraceWindow()
+{
+ delete m_plugin;
+}
+
+void TraceWindow::reset(QDeclarativeDebugConnection *conn)
+{
+ if (m_plugin)
+ disconnect(m_plugin,SIGNAL(complete()), this, SIGNAL(viewUpdated()));
+ delete m_plugin;
+ m_plugin = new TracePlugin(conn);
+ connect(m_plugin,SIGNAL(complete()), this, SIGNAL(viewUpdated()));
+ connect(m_plugin,SIGNAL(range(int,qint64,qint64,QStringList,QString,int)),this,SIGNAL(range(int,qint64,qint64,QStringList,QString,int)));
+ if (m_recordAtStart)
+ m_plugin->setRecording(true);
+
+ m_view->rootContext()->setContextProperty("connection", m_plugin);
+ m_view->setSource(QUrl("qrc:/qmlprofiler/MainView.qml"));
+
+ connect(m_view->rootObject(), SIGNAL(updateCursorPosition()), this, SLOT(updateCursorPosition()));
+ connect(m_view->rootObject(), SIGNAL(updateTimer()), this, SLOT(updateTimer()));
+}
+
+void TraceWindow::updateCursorPosition()
+{
+ emit gotoSourceLocation(m_view->rootObject()->property("fileName").toString(),
+ m_view->rootObject()->property("lineNumber").toInt());
+}
+
+void TraceWindow::updateTimer()
+{
+ emit timeChanged(m_view->rootObject()->property("elapsedTime").toDouble());
+}
+
+void TraceWindow::clearDisplay()
+{
+ if (m_plugin)
+ m_plugin->clearView();
+}
+
+void TraceWindow::setRecordAtStart(bool record)
+{
+ m_recordAtStart = record;
+}
+
+void TraceWindow::setRecording(bool recording)
+{
+ m_plugin->setRecording(recording);
+}
+
+bool TraceWindow::isRecording() const
+{
+ return (m_plugin->recording());
+}
+
+#include "tracewindow.moc"
diff --git a/src/plugins/qmlprofiler/tracewindow.h b/src/plugins/qmlprofiler/tracewindow.h
new file mode 100644
index 0000000000..4f0fb72e8d
--- /dev/null
+++ b/src/plugins/qmlprofiler/tracewindow.h
@@ -0,0 +1,94 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 TRACEWINDOW_H
+#define TRACEWINDOW_H
+
+#include <QtCore/qpointer.h>
+#include <QtGui/qwidget.h>
+
+#include <QtDeclarative/private/qdeclarativedebugclient_p.h>
+
+
+QT_BEGIN_NAMESPACE
+class QTabWidget;
+class QSlider;
+class QGroupBox;
+class QLabel;
+class QSpinBox;
+class QPushButton;
+class QDeclarativeView;
+QT_END_NAMESPACE
+
+namespace QmlProfiler {
+namespace Internal {
+
+class TracePlugin;
+
+class TraceWindow : public QWidget
+{
+ Q_OBJECT
+public:
+ TraceWindow(QWidget *parent = 0);
+ ~TraceWindow();
+
+ void reset(QDeclarativeDebugConnection *conn);
+ void setRecordAtStart(bool record);
+
+ void setRecording(bool recording);
+ bool isRecording() const;
+
+public slots:
+ void updateCursorPosition();
+ void updateTimer();
+ void clearDisplay();
+
+signals:
+ void viewUpdated();
+ void gotoSourceLocation(const QString &fileUrl, int lineNumber);
+ void timeChanged(qreal newTime);
+ void range(int type, qint64 startTime, qint64 length, const QStringList &data, const QString &fileName, int line);
+
+private:
+ TracePlugin *m_plugin;
+ QSize m_sizeHint;
+ bool m_recordAtStart;
+
+ QDeclarativeView *m_view;
+};
+
+} // namespace Internal
+} // namespace QmlProfiler
+
+#endif // TRACEWINDOW_H
+
diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp
index 2bd565c14a..5a1907b9e6 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.cpp
+++ b/src/plugins/qmlprojectmanager/qmlproject.cpp
@@ -36,6 +36,7 @@
#include "fileformat/qmlprojectitem.h"
#include "qmlprojectrunconfiguration.h"
#include "qmlprojecttarget.h"
+#include "qmlprojectconstants.h"
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
@@ -57,6 +58,9 @@ QmlProject::QmlProject(Internal::Manager *manager, const QString &fileName)
m_modelManager(ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>()),
m_fileWatcher(new ProjectExplorer::FileWatcher(this))
{
+ setProjectContext(Core::Context(QmlProjectManager::Constants::PROJECTCONTEXT));
+ setProjectLanguage(Core::Context(QmlProjectManager::Constants::LANG_QML));
+
QFileInfo fileInfo(m_fileName);
m_projectName = fileInfo.completeBaseName();
diff --git a/src/plugins/qmlprojectmanager/qmlprojectconstants.h b/src/plugins/qmlprojectmanager/qmlprojectconstants.h
index f5bb9f6675..83d7f7633f 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectconstants.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectconstants.h
@@ -40,16 +40,6 @@ const char *const PROJECTCONTEXT = "QmlProject.ProjectContext";
const char *const LANG_QML = "QML";
const char *const QMLMIMETYPE = "application/x-qmlproject";
-// contexts
-const char *const C_FILESEDITOR = ".files Editor";
-
-// kinds
-const char *const PROJECT_KIND = "QML";
-
-const char *const FILES_EDITOR_ID = "Qt4.QmlProjectEditor";
-const char *const FILES_EDITOR_DISPLAY_NAME = QT_TRANSLATE_NOOP("OpenWith::Editors", ".qmlproject Editor");
-const char *const FILES_MIMETYPE = QMLMIMETYPE;
-
} // namespace Constants
} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlprojectmanager.cpp b/src/plugins/qmlprojectmanager/qmlprojectmanager.cpp
index 7143d35cb0..d1dd1a1516 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectmanager.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectmanager.cpp
@@ -48,19 +48,8 @@ namespace Internal {
Manager::Manager()
{
- m_projectContext = Core::Context(QmlProjectManager::Constants::PROJECTCONTEXT);
- m_projectLanguage = Core::Context(QmlProjectManager::Constants::LANG_QML);
}
-Manager::~Manager()
-{ }
-
-Core::Context Manager::projectContext() const
-{ return m_projectContext; }
-
-Core::Context Manager::projectLanguage() const
-{ return m_projectLanguage; }
-
QString Manager::mimeType() const
{ return QLatin1String(Constants::QMLMIMETYPE); }
diff --git a/src/plugins/qmlprojectmanager/qmlprojectmanager.h b/src/plugins/qmlprojectmanager/qmlprojectmanager.h
index ca933cfe11..634601a51d 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectmanager.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectmanager.h
@@ -48,10 +48,6 @@ class Manager: public ProjectExplorer::IProjectManager
public:
Manager();
- virtual ~Manager();
-
- virtual Core::Context projectContext() const;
- virtual Core::Context projectLanguage() const;
virtual QString mimeType() const;
virtual ProjectExplorer::Project *openProject(const QString &fileName);
@@ -62,8 +58,6 @@ public:
void unregisterProject(QmlProject *project);
private:
- Core::Context m_projectContext;
- Core::Context m_projectLanguage;
QList<QmlProject *> m_projects;
};
diff --git a/src/plugins/qmlprojectmanager/qmlprojectmanagerconstants.h b/src/plugins/qmlprojectmanager/qmlprojectmanagerconstants.h
index e1e0c6c92c..c5cb5800d7 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectmanagerconstants.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectmanagerconstants.h
@@ -36,7 +36,6 @@ namespace QmlProjectManager {
namespace Constants {
const char * const QML_RC_ID = "QmlProjectManager.QmlRunConfiguration";
-const char * const QML_RC_DISPLAY_NAME = QT_TRANSLATE_NOOP("QmlProjectManager::Internal::QmlRunConfiguration", "QML Viewer");
const char * const QML_VIEWER_QT_KEY = "QmlProjectManager.QmlRunConfiguration.QtVersion";
const char * const QML_VIEWER_ARGUMENTS_KEY = "QmlProjectManager.QmlRunConfiguration.QDeclarativeViewerArguments";
const char * const QML_VIEWER_TARGET_ID = "QmlProjectManager.QmlTarget";
diff --git a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp
index 096bd6ac0c..189bccd4a2 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp
@@ -96,7 +96,7 @@ void QmlRunControl::start()
m_commandLineArguments);
emit started();
- QString msg = tr("Starting %1 %2")
+ QString msg = tr("Starting %1 %2\n")
.arg(QDir::toNativeSeparators(m_executable), m_commandLineArguments);
appendMessage(msg, NormalMessageFormat);
}
@@ -112,6 +112,11 @@ bool QmlRunControl::isRunning() const
return m_applicationLauncher.isRunning();
}
+QIcon QmlRunControl::icon() const
+{
+ return QIcon(ProjectExplorer::Constants::ICON_RUN_SMALL);
+}
+
void QmlRunControl::slotBringApplicationToForeground(qint64 pid)
{
bringApplicationToForeground(pid);
@@ -124,7 +129,7 @@ void QmlRunControl::slotAppendMessage(const QString &line, OutputFormat format)
void QmlRunControl::processExited(int exitCode)
{
- QString msg = tr("%1 exited with code %2")
+ QString msg = tr("%1 exited with code %2\n")
.arg(QDir::toNativeSeparators(m_executable)).arg(exitCode);
appendMessage(msg, exitCode ? ErrorMessageFormat : NormalMessageFormat);
emit finished();
@@ -146,6 +151,8 @@ bool QmlRunControlFactory::canRun(RunConfiguration *runConfiguration,
qobject_cast<QmlProjectRunConfiguration*>(runConfiguration);
if (mode == ProjectExplorer::Constants::RUNMODE)
return config != 0 && !config->viewerPath().isEmpty();
+ else if (mode != Debugger::Constants::DEBUGMODE)
+ return false;
bool qmlDebugSupportInstalled =
Debugger::DebuggerPlugin::isActiveDebugLanguage(Debugger::QmlLanguage);
diff --git a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h
index 4b89f6ac84..6fdea20241 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h
@@ -53,6 +53,7 @@ public:
virtual void start();
virtual StopResult stop();
virtual bool isRunning() const;
+ virtual QIcon icon() const;
private slots:
void processExited(int exitCode);
diff --git a/src/plugins/qmlprojectmanager/qmlprojecttarget.cpp b/src/plugins/qmlprojectmanager/qmlprojecttarget.cpp
index 4f7bc72b75..e1791e9213 100644
--- a/src/plugins/qmlprojectmanager/qmlprojecttarget.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojecttarget.cpp
@@ -71,11 +71,6 @@ ProjectExplorer::IBuildConfigurationFactory *QmlProjectTarget::buildConfiguratio
return 0;
}
-ProjectExplorer::DeployConfigurationFactory *QmlProjectTarget::deployConfigurationFactory() const
-{
- return 0;
-}
-
bool QmlProjectTarget::fromMap(const QVariantMap &map)
{
if (!Target::fromMap(map))
diff --git a/src/plugins/qmlprojectmanager/qmlprojecttarget.h b/src/plugins/qmlprojectmanager/qmlprojecttarget.h
index ac8fb64737..810077ae95 100644
--- a/src/plugins/qmlprojectmanager/qmlprojecttarget.h
+++ b/src/plugins/qmlprojectmanager/qmlprojecttarget.h
@@ -60,7 +60,6 @@ public:
QmlProject *qmlProject() const;
ProjectExplorer::IBuildConfigurationFactory *buildConfigurationFactory() const;
- ProjectExplorer::DeployConfigurationFactory *deployConfigurationFactory() const;
protected:
bool fromMap(const QVariantMap &map);
diff --git a/src/plugins/qt4projectmanager/profileeditor.cpp b/src/plugins/qt4projectmanager/profileeditor.cpp
index adfa26744d..4a39831f9c 100644
--- a/src/plugins/qt4projectmanager/profileeditor.cpp
+++ b/src/plugins/qt4projectmanager/profileeditor.cpp
@@ -36,7 +36,6 @@
#include "qt4projectmanager.h"
#include "qt4projectmanagerconstants.h"
#include "profileeditorfactory.h"
-#include "addlibrarywizard.h"
#include <coreplugin/icore.h>
#include <coreplugin/actionmanager/actionmanager.h>
@@ -59,18 +58,13 @@ using namespace Qt4ProjectManager::Internal;
//
ProFileEditor::ProFileEditor(ProFileEditorWidget *editor)
- : BaseTextEditor(editor),
- m_context(Qt4ProjectManager::Constants::C_PROFILEEDITOR,
- TextEditor::Constants::C_TEXTEDITOR)
+ : BaseTextEditor(editor)
{
+ setContext(Core::Context(Qt4ProjectManager::Constants::C_PROFILEEDITOR,
+ TextEditor::Constants::C_TEXTEDITOR));
// m_contexts << uidm->uniqueIdentifier(Qt4ProjectManager::Constants::PROJECT_KIND);
}
-Core::Context ProFileEditor::context() const
-{
- return m_context;
-}
-
Core::IEditor *ProFileEditor::duplicate(QWidget *parent)
{
ProFileEditorWidget *ret = new ProFileEditorWidget(parent, qobject_cast<ProFileEditorWidget*>(editorWidget())->factory(),
@@ -103,10 +97,6 @@ ProFileEditorWidget::ProFileEditorWidget(QWidget *parent, ProFileEditorFactory *
m_commentDefinition.setSingleLine(QString(QLatin1Char('#')));
}
-ProFileEditorWidget::~ProFileEditorWidget()
-{
-}
-
void ProFileEditorWidget::unCommentSelection()
{
Utils::unCommentSelection(this, m_commentDefinition);
@@ -243,26 +233,6 @@ void ProFileEditorWidget::setFontSettings(const TextEditor::FontSettings &fs)
highlighter->rehighlight();
}
-void ProFileEditorWidget::addLibrary()
-{
- AddLibraryWizard wizard(file()->fileName(), this);
- if (wizard.exec() != QDialog::Accepted)
- return;
-
- TextEditor::BaseTextEditor *editable = editor();
- const int endOfDoc = editable->position(TextEditor::ITextEditor::EndOfDoc);
- editable->setCursorPosition(endOfDoc);
- QString snippet = wizard.snippet();
-
- // add extra \n in case the last line is not empty
- int line, column;
- editable->convertPosition(endOfDoc, &line, &column);
- if (!editable->textAt(endOfDoc - column, column).simplified().isEmpty())
- snippet = QLatin1Char('\n') + snippet;
-
- editable->insert(snippet);
-}
-
void ProFileEditorWidget::jumpToFile()
{
openLink(findLinkAt(textCursor()));
diff --git a/src/plugins/qt4projectmanager/profileeditor.h b/src/plugins/qt4projectmanager/profileeditor.h
index 12afd2619d..89662020d9 100644
--- a/src/plugins/qt4projectmanager/profileeditor.h
+++ b/src/plugins/qt4projectmanager/profileeditor.h
@@ -60,14 +60,11 @@ class ProFileEditor : public TextEditor::BaseTextEditor
public:
ProFileEditor(ProFileEditorWidget *);
- Core::Context context() const;
bool duplicateSupported() const { return true; }
Core::IEditor *duplicate(QWidget *parent);
QString id() const;
bool isTemporary() const { return false; }
-private:
- const Core::Context m_context;
};
class ProFileEditorWidget : public TextEditor::BaseTextEditorWidget
@@ -77,11 +74,9 @@ class ProFileEditorWidget : public TextEditor::BaseTextEditorWidget
public:
ProFileEditorWidget(QWidget *parent, ProFileEditorFactory *factory,
TextEditor::TextEditorActionHandler *ah);
- ~ProFileEditorWidget();
bool save(const QString &fileName = QString());
-
ProFileEditorFactory *factory() { return m_factory; }
TextEditor::TextEditorActionHandler *actionHandler() const { return m_ah; }
@@ -93,7 +88,6 @@ protected:
public slots:
virtual void setFontSettings(const TextEditor::FontSettings &);
- void addLibrary();
void jumpToFile();
private:
diff --git a/src/plugins/qt4projectmanager/qmakestep.cpp b/src/plugins/qt4projectmanager/qmakestep.cpp
index 66549d7ed3..ae6d139999 100644
--- a/src/plugins/qt4projectmanager/qmakestep.cpp
+++ b/src/plugins/qt4projectmanager/qmakestep.cpp
@@ -160,6 +160,17 @@ QStringList QMakeStep::moreArguments()
|| tc->targetAbi().osFlavor() == ProjectExplorer::Abi::MaemoLinuxFlavor))
arguments << QLatin1String("-unix");
#endif
+
+ if (m_linkQmlDebuggingLibrary
+ && !bc->qtVersion()->qmlDebuggingHelperLibrary(true).isEmpty()) {
+ // Do not turn debugger path into native path separators: Qmake does not like that!
+ const QString debuggingHelperPath
+ = QFileInfo(bc->qtVersion()->qmlDebuggingHelperLibrary(true)).dir().path();
+
+ arguments << QLatin1String(Constants::QMAKEVAR_QMLJSDEBUGGER_PATH)
+ + QLatin1Char('=') + debuggingHelperPath;
+ }
+
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
@@ -172,16 +183,6 @@ QStringList QMakeStep::moreArguments()
<< QLatin1String("UI_DIR=ui")
<< QLatin1String("RCC_DIR=rcc");
}
-
- if (m_linkQmlDebuggingLibrary
- && !bc->qtVersion()->qmlDebuggingHelperLibrary(true).isEmpty()) {
- // Do not turn debugger path into native path separators: Qmake does not like that!
- const QString debuggingHelperPath
- = QFileInfo(bc->qtVersion()->qmlDebuggingHelperLibrary(true)).dir().path();
-
- arguments << QLatin1String(Constants::QMAKEVAR_QMLJSDEBUGGER_PATH)
- + QLatin1Char('=') + debuggingHelperPath;
- }
return arguments;
}
diff --git a/src/plugins/qt4projectmanager/qt-desktop/qt4desktoptarget.cpp b/src/plugins/qt4projectmanager/qt-desktop/qt4desktoptarget.cpp
index c09cc0bddf..12a0c3764c 100644
--- a/src/plugins/qt4projectmanager/qt-desktop/qt4desktoptarget.cpp
+++ b/src/plugins/qt4projectmanager/qt-desktop/qt4desktoptarget.cpp
@@ -43,8 +43,7 @@ using namespace Qt4ProjectManager::Internal;
Qt4DesktopTarget::Qt4DesktopTarget(Qt4Project *parent, const QString &id) :
Qt4BaseTarget(parent, id),
- m_buildConfigurationFactory(new Qt4BuildConfigurationFactory(this)),
- m_deployConfigurationFactory(new ProjectExplorer::DeployConfigurationFactory(this))
+ m_buildConfigurationFactory(new Qt4BuildConfigurationFactory(this))
{
setDisplayName(defaultDisplayName());
setIcon(qApp->style()->standardIcon(QStyle::SP_ComputerIcon));
@@ -64,11 +63,6 @@ Qt4BuildConfigurationFactory *Qt4DesktopTarget::buildConfigurationFactory() cons
return m_buildConfigurationFactory;
}
-ProjectExplorer::DeployConfigurationFactory *Qt4DesktopTarget::deployConfigurationFactory() const
-{
- return m_deployConfigurationFactory;
-}
-
void Qt4DesktopTarget::createApplicationProFiles()
{
removeUnconfiguredCustomExectutableRunConfigurations();
diff --git a/src/plugins/qt4projectmanager/qt-desktop/qt4desktoptarget.h b/src/plugins/qt4projectmanager/qt-desktop/qt4desktoptarget.h
index 1262a73e29..3895ad76be 100644
--- a/src/plugins/qt4projectmanager/qt-desktop/qt4desktoptarget.h
+++ b/src/plugins/qt4projectmanager/qt-desktop/qt4desktoptarget.h
@@ -50,7 +50,6 @@ public:
virtual ~Qt4DesktopTarget();
Internal::Qt4BuildConfigurationFactory *buildConfigurationFactory() const;
- ProjectExplorer::DeployConfigurationFactory *deployConfigurationFactory() const;
void createApplicationProFiles();
QList<ProjectExplorer::RunConfiguration *> runConfigurationsForNode(ProjectExplorer::Node *n);
@@ -59,7 +58,6 @@ public:
private:
Internal::Qt4BuildConfigurationFactory *m_buildConfigurationFactory;
- ProjectExplorer::DeployConfigurationFactory *m_deployConfigurationFactory;
};
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-desktop/qt4desktoptargetfactory.cpp b/src/plugins/qt4projectmanager/qt-desktop/qt4desktoptargetfactory.cpp
index e64be07182..984b46bb4c 100644
--- a/src/plugins/qt4projectmanager/qt-desktop/qt4desktoptargetfactory.cpp
+++ b/src/plugins/qt4projectmanager/qt-desktop/qt4desktoptargetfactory.cpp
@@ -83,6 +83,13 @@ QString Qt4DesktopTargetFactory::displayNameForId(const QString &id) const
return QString();
}
+QString Qt4DesktopTargetFactory::buildNameForId(const QString &id) const
+{
+ if (id == QLatin1String(Constants::DESKTOP_TARGET_ID))
+ return QLatin1String("desktop");
+ return QString();
+}
+
QIcon Qt4DesktopTargetFactory::iconForId(const QString &id) const
{
if (id == QLatin1String(Constants::DESKTOP_TARGET_ID))
@@ -116,45 +123,17 @@ ProjectExplorer::Target *Qt4DesktopTargetFactory::restore(ProjectExplorer::Proj
return 0;
}
-QString Qt4DesktopTargetFactory::defaultShadowBuildDirectory(const QString &projectLocation, const QString &id)
-{
- if (id != QLatin1String(Constants::DESKTOP_TARGET_ID))
- return QString();
-
- // currently we can't have the build directory to be deeper than the source directory
- // since that is broken in qmake
- // Once qmake is fixed we can change that to have a top directory and
- // subdirectories per build. (Replacing "QChar('-')" with "QChar('/') )
- return projectLocation + QLatin1String("-desktop");
-}
-
-QList<BuildConfigurationInfo> Qt4DesktopTargetFactory::availableBuildConfigurations(const QString &id, const QString &proFilePath, const QtVersionNumber &minimumQtVersion)
-{
- Q_ASSERT(id == Constants::DESKTOP_TARGET_ID);
- QList<BuildConfigurationInfo> infoList;
- QList<QtVersion *> knownVersions = QtVersionManager::instance()->versionsForTargetId(id, minimumQtVersion);
-
- foreach (QtVersion *version, knownVersions) {
- if (!version->isValid() || !version->toolChainAvailable(id))
- continue;
- QtVersion::QmakeBuildConfigs config = version->defaultBuildConfig();
-
- QString dir = defaultShadowBuildDirectory(Qt4Project::defaultTopLevelBuildDirectory(proFilePath), id);
- infoList.append(BuildConfigurationInfo(version, config, QString(), dir));
- infoList.append(BuildConfigurationInfo(version, config ^ QtVersion::DebugBuild, QString(), dir));
- }
- return infoList;
-}
-
- Qt4TargetSetupWidget *Qt4DesktopTargetFactory::createTargetSetupWidget(const QString &id, const QString &proFilePath, const QtVersionNumber &number, bool importEnabled, QList<BuildConfigurationInfo> importInfos)
+Qt4TargetSetupWidget *Qt4DesktopTargetFactory::createTargetSetupWidget(const QString &id, const QString &proFilePath, const QtVersionNumber &number, bool importEnabled, QList<BuildConfigurationInfo> importInfos)
{
Qt4DefaultTargetSetupWidget *widget
= static_cast<Qt4DefaultTargetSetupWidget *>(
Qt4BaseTargetFactory::createTargetSetupWidget(id, proFilePath,
number, importEnabled,
importInfos));
- if (widget)
+ if (widget) {
widget->setShadowBuildCheckBoxVisible(true);
+ widget->setBuildConfiguraionComboBoxVisible(true);
+ }
return widget;
}
@@ -202,7 +181,7 @@ ProjectExplorer::Target *Qt4DesktopTargetFactory::create(ProjectExplorer::Projec
info.version, info.buildConfig,
info.additionalArguments, info.directory);
- t->addDeployConfiguration(t->deployConfigurationFactory()->create(t, ProjectExplorer::Constants::DEFAULT_DEPLOYCONFIGURATION_ID));
+ t->addDeployConfiguration(t->createDeployConfiguration(ProjectExplorer::Constants::DEFAULT_DEPLOYCONFIGURATION_ID));
t->createApplicationProFiles();
diff --git a/src/plugins/qt4projectmanager/qt-desktop/qt4desktoptargetfactory.h b/src/plugins/qt4projectmanager/qt-desktop/qt4desktoptargetfactory.h
index 32364be2a2..9b1b6ea9b3 100644
--- a/src/plugins/qt4projectmanager/qt-desktop/qt4desktoptargetfactory.h
+++ b/src/plugins/qt4projectmanager/qt-desktop/qt4desktoptargetfactory.h
@@ -51,14 +51,13 @@ public:
bool canCreate(ProjectExplorer::Project *parent, const QString &id) const;
bool canRestore(ProjectExplorer::Project *parent, const QVariantMap &map) const;
ProjectExplorer::Target *restore(ProjectExplorer::Project *parent, const QVariantMap &map);
- QString defaultShadowBuildDirectory(const QString &projectLocation, const QString &id);
virtual bool supportsTargetId(const QString &id) const;
Qt4TargetSetupWidget *createTargetSetupWidget(const QString &id, const QString &proFilePath, const QtVersionNumber &minimumQtVersion, bool importEnabled, QList<BuildConfigurationInfo> importInfos);
+ QString buildNameForId(const QString &id) const;
bool isMobileTarget(const QString &id);
bool supportsShadowBuilds(const QString &id);
- QList<BuildConfigurationInfo> availableBuildConfigurations(const QString &id, const QString &proFilePath, const QtVersionNumber &minimumQtVersion);
ProjectExplorer::Target *create(ProjectExplorer::Project *parent, const QString &id);
ProjectExplorer::Target *create(ProjectExplorer::Project *parent, const QString &id, const QList<BuildConfigurationInfo> &infos);
diff --git a/src/plugins/qt4projectmanager/qt-desktop/qt4simulatortarget.cpp b/src/plugins/qt4projectmanager/qt-desktop/qt4simulatortarget.cpp
index e4b8f642cc..bcfce81e29 100644
--- a/src/plugins/qt4projectmanager/qt-desktop/qt4simulatortarget.cpp
+++ b/src/plugins/qt4projectmanager/qt-desktop/qt4simulatortarget.cpp
@@ -48,8 +48,7 @@ using namespace Qt4ProjectManager::Internal;
Qt4SimulatorTarget::Qt4SimulatorTarget(Qt4Project *parent, const QString &id) :
Qt4BaseTarget(parent, id),
- m_buildConfigurationFactory(new Qt4BuildConfigurationFactory(this)),
- m_deployConfigurationFactory(new ProjectExplorer::DeployConfigurationFactory(this))
+ m_buildConfigurationFactory(new Qt4BuildConfigurationFactory(this))
{
setDisplayName(defaultDisplayName());
setIcon(QIcon(":/projectexplorer/images/SymbianEmulator.png"));
@@ -69,11 +68,6 @@ Qt4BuildConfigurationFactory *Qt4SimulatorTarget::buildConfigurationFactory() co
return m_buildConfigurationFactory;
}
-ProjectExplorer::DeployConfigurationFactory *Qt4SimulatorTarget::deployConfigurationFactory() const
-{
- return m_deployConfigurationFactory;
-}
-
void Qt4SimulatorTarget::createApplicationProFiles()
{
removeUnconfiguredCustomExectutableRunConfigurations();
diff --git a/src/plugins/qt4projectmanager/qt-desktop/qt4simulatortarget.h b/src/plugins/qt4projectmanager/qt-desktop/qt4simulatortarget.h
index dce18f4ccb..c3fe9c7d8e 100644
--- a/src/plugins/qt4projectmanager/qt-desktop/qt4simulatortarget.h
+++ b/src/plugins/qt4projectmanager/qt-desktop/qt4simulatortarget.h
@@ -50,7 +50,6 @@ public:
virtual ~Qt4SimulatorTarget();
Internal::Qt4BuildConfigurationFactory *buildConfigurationFactory() const;
- ProjectExplorer::DeployConfigurationFactory *deployConfigurationFactory() const;
void createApplicationProFiles();
QList<ProjectExplorer::RunConfiguration *> runConfigurationsForNode(ProjectExplorer::Node *n);
@@ -59,7 +58,6 @@ public:
private:
Internal::Qt4BuildConfigurationFactory *m_buildConfigurationFactory;
- ProjectExplorer::DeployConfigurationFactory *m_deployConfigurationFactory;
};
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-desktop/qt4simulatortargetfactory.cpp b/src/plugins/qt4projectmanager/qt-desktop/qt4simulatortargetfactory.cpp
index 8138666247..359a93a40c 100644
--- a/src/plugins/qt4projectmanager/qt-desktop/qt4simulatortargetfactory.cpp
+++ b/src/plugins/qt4projectmanager/qt-desktop/qt4simulatortargetfactory.cpp
@@ -91,6 +91,13 @@ QIcon Qt4SimulatorTargetFactory::iconForId(const QString &id) const
return QIcon();
}
+QString Qt4SimulatorTargetFactory::buildNameForId(const QString &id) const
+{
+ if (id == QLatin1String(Constants::QT_SIMULATOR_TARGET_ID))
+ return QLatin1String("simulator");
+ return QString();
+}
+
bool Qt4SimulatorTargetFactory::canCreate(ProjectExplorer::Project *parent, const QString &id) const
{
if (!qobject_cast<Qt4Project *>(parent))
@@ -116,35 +123,6 @@ ProjectExplorer::Target *Qt4SimulatorTargetFactory::restore(ProjectExplorer::Pro
return 0;
}
-QString Qt4SimulatorTargetFactory::defaultShadowBuildDirectory(const QString &projectLocation, const QString &id)
-{
- if (id != QLatin1String(Constants::QT_SIMULATOR_TARGET_ID))
- return QString();
-
- // currently we can't have the build directory to be deeper than the source directory
- // since that is broken in qmake
- // Once qmake is fixed we can change that to have a top directory and
- // subdirectories per build. (Replacing "QChar('-')" with "QChar('/') )
- return projectLocation + QLatin1String("-simulator");
-}
-
-QList<BuildConfigurationInfo> Qt4SimulatorTargetFactory::availableBuildConfigurations(const QString &id, const QString &proFilePath, const QtVersionNumber &minimumQtVersion)
-{
- Q_ASSERT(id == Constants::QT_SIMULATOR_TARGET_ID);
- QList<BuildConfigurationInfo> infos;
- QList<QtVersion *> knownVersions = QtVersionManager::instance()->versionsForTargetId(id, minimumQtVersion);
-
- foreach (QtVersion *version, knownVersions) {
- if (!version->isValid() || !version->toolChainAvailable(id))
- continue;
- QtVersion::QmakeBuildConfigs config = version->defaultBuildConfig();
- QString dir = defaultShadowBuildDirectory(Qt4Project::defaultTopLevelBuildDirectory(proFilePath), id);
- infos.append(BuildConfigurationInfo(version, config, QString(), dir));
- infos.append(BuildConfigurationInfo(version, config ^ QtVersion::DebugBuild, QString(), dir));
- }
- return infos;
-}
-
bool Qt4SimulatorTargetFactory::isMobileTarget(const QString &id)
{
Q_UNUSED(id)
@@ -187,7 +165,7 @@ ProjectExplorer::Target *Qt4SimulatorTargetFactory::create(ProjectExplorer::Proj
t->addQt4BuildConfiguration(msgBuildConfigurationName(info), info.version, info.buildConfig,
info.additionalArguments, info.directory);
- t->addDeployConfiguration(t->deployConfigurationFactory()->create(t, ProjectExplorer::Constants::DEFAULT_DEPLOYCONFIGURATION_ID));
+ t->addDeployConfiguration(t->createDeployConfiguration(ProjectExplorer::Constants::DEFAULT_DEPLOYCONFIGURATION_ID));
t->createApplicationProFiles();
diff --git a/src/plugins/qt4projectmanager/qt-desktop/qt4simulatortargetfactory.h b/src/plugins/qt4projectmanager/qt-desktop/qt4simulatortargetfactory.h
index b5cf62a0e7..b616fc738b 100644
--- a/src/plugins/qt4projectmanager/qt-desktop/qt4simulatortargetfactory.h
+++ b/src/plugins/qt4projectmanager/qt-desktop/qt4simulatortargetfactory.h
@@ -54,12 +54,11 @@ public:
bool canCreate(ProjectExplorer::Project *parent, const QString &id) const;
bool canRestore(ProjectExplorer::Project *parent, const QVariantMap &map) const;
ProjectExplorer::Target *restore(ProjectExplorer::Project *parent, const QVariantMap &map);
- QString defaultShadowBuildDirectory(const QString &projectLocation, const QString &id);
bool supportsTargetId(const QString &id) const;
- QList<BuildConfigurationInfo> availableBuildConfigurations(const QString &id, const QString &proFilePath, const QtVersionNumber &minimumQtVersion);
bool isMobileTarget(const QString &id);
+ QString buildNameForId(const QString &id) const;
bool supportsShadowBuilds(const QString &id);
ProjectExplorer::Target *create(ProjectExplorer::Project *parent, const QString &id);
ProjectExplorer::Target *create(ProjectExplorer::Project *parent, const QString &id, const QList<BuildConfigurationInfo> &infos);
diff --git a/src/plugins/qt4projectmanager/qt-maemo/abstractmaemodeploystep.cpp b/src/plugins/qt4projectmanager/qt-maemo/abstractmaemodeploystep.cpp
new file mode 100644
index 0000000000..b6d5773070
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/abstractmaemodeploystep.cpp
@@ -0,0 +1,458 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "abstractmaemodeploystep.h"
+
+#include "maemoconstants.h"
+#include "maemodeploystepwidget.h"
+#include "maemoglobal.h"
+#include "maemopackagecreationstep.h"
+#include "maemopertargetdeviceconfigurationlistmodel.h"
+#include "maemoqemumanager.h"
+#include "qt4maemodeployconfiguration.h"
+
+#include <utils/ssh/sshconnection.h>
+
+#include <projectexplorer/projectexplorerconstants.h>
+
+#include <qt4projectmanager/qt4buildconfiguration.h>
+#include <qt4projectmanager/qt4projectmanagerconstants.h>
+
+#include <utils/ssh/sshconnectionmanager.h>
+
+#include <QtCore/QEventLoop>
+#include <QtCore/QFileInfo>
+#include <QtCore/QTimer>
+
+#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(BaseState, state, m_baseState)
+
+using namespace Core;
+using namespace Utils;
+using namespace ProjectExplorer;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+namespace {
+
+class MaemoDeployEventHandler : public QObject
+{
+ Q_OBJECT
+public:
+ MaemoDeployEventHandler(AbstractMaemoDeployStep *deployStep,
+ QFutureInterface<bool> &future);
+
+private slots:
+ void handleDeployingDone();
+ void handleDeployingFailed();
+ void checkForCanceled();
+
+private:
+ AbstractMaemoDeployStep * const m_deployStep;
+ const QFutureInterface<bool> m_future;
+ QEventLoop * const m_eventLoop;
+ bool m_error;
+};
+
+} // anonymous namespace
+
+
+AbstractMaemoDeployStep::AbstractMaemoDeployStep(BuildStepList *parent,
+ const QString &id) : BuildStep(parent, id)
+{
+ baseCtor();
+}
+
+AbstractMaemoDeployStep::AbstractMaemoDeployStep(BuildStepList *parent,
+ AbstractMaemoDeployStep *other)
+ : BuildStep(parent, other), m_lastDeployed(other->m_lastDeployed)
+{
+ baseCtor();
+}
+
+AbstractMaemoDeployStep::~AbstractMaemoDeployStep() { }
+
+void AbstractMaemoDeployStep::baseCtor()
+{
+ m_baseState = BaseInactive;
+ m_deviceConfig = maemoDeployConfig()->deviceConfigModel()->defaultDeviceConfig();
+ connect(maemoDeployConfig()->deviceConfigModel(), SIGNAL(updated()),
+ SLOT(handleDeviceConfigurationsUpdated()));
+}
+
+void AbstractMaemoDeployStep::run(QFutureInterface<bool> &fi)
+{
+ // Move to GUI thread.
+ QTimer::singleShot(0, this, SLOT(start()));
+
+ MaemoDeployEventHandler eventHandler(this, fi);
+}
+
+BuildStepConfigWidget *AbstractMaemoDeployStep::createConfigWidget()
+{
+ return new MaemoDeployStepWidget(this);
+}
+
+QVariantMap AbstractMaemoDeployStep::toMap() const
+{
+ QVariantMap map(BuildStep::toMap());
+ addDeployTimesToMap(map);
+ map.insert(DeviceIdKey,
+ MaemoDeviceConfigurations::instance()->internalId(m_deviceConfig));
+ return map;
+}
+
+void AbstractMaemoDeployStep::addDeployTimesToMap(QVariantMap &map) const
+{
+ QVariantList hostList;
+ QVariantList fileList;
+ QVariantList remotePathList;
+ QVariantList timeList;
+ typedef QHash<DeployablePerHost, QDateTime>::ConstIterator DepIt;
+ for (DepIt it = m_lastDeployed.begin(); it != m_lastDeployed.end(); ++it) {
+ fileList << it.key().first.localFilePath;
+ remotePathList << it.key().first.remoteDir;
+ hostList << it.key().second;
+ timeList << it.value();
+ }
+ map.insert(LastDeployedHostsKey, hostList);
+ map.insert(LastDeployedFilesKey, fileList);
+ map.insert(LastDeployedRemotePathsKey, remotePathList);
+ map.insert(LastDeployedTimesKey, timeList);
+}
+
+bool AbstractMaemoDeployStep::fromMap(const QVariantMap &map)
+{
+ if (!BuildStep::fromMap(map))
+ return false;
+ getDeployTimesFromMap(map);
+ setDeviceConfig(map.value(DeviceIdKey, MaemoDeviceConfig::InvalidId).toULongLong());
+ return true;
+}
+
+void AbstractMaemoDeployStep::getDeployTimesFromMap(const QVariantMap &map)
+{
+ const QVariantList &hostList = map.value(LastDeployedHostsKey).toList();
+ const QVariantList &fileList = map.value(LastDeployedFilesKey).toList();
+ const QVariantList &remotePathList
+ = map.value(LastDeployedRemotePathsKey).toList();
+ const QVariantList &timeList = map.value(LastDeployedTimesKey).toList();
+ const int elemCount
+ = qMin(qMin(hostList.size(), fileList.size()),
+ qMin(remotePathList.size(), timeList.size()));
+ for (int i = 0; i < elemCount; ++i) {
+ const MaemoDeployable d(fileList.at(i).toString(),
+ remotePathList.at(i).toString());
+ m_lastDeployed.insert(DeployablePerHost(d, hostList.at(i).toString()),
+ timeList.at(i).toDateTime());
+ }
+}
+
+void AbstractMaemoDeployStep::raiseError(const QString &errorString)
+{
+ emit addTask(Task(Task::Error, errorString, QString(), -1,
+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ m_hasError = true;
+ emit error();
+}
+
+void AbstractMaemoDeployStep::writeOutput(const QString &text, OutputFormat format,
+ OutputNewlineSetting newlineSetting)
+{
+ emit addOutput(text, format, newlineSetting);
+}
+
+void AbstractMaemoDeployStep::stop()
+{
+ if (m_baseState == StopRequested || m_baseState == BaseInactive)
+ return;
+
+ writeOutput(tr("Operation canceled by user, cleaning up..."));
+ const BaseState oldState = m_baseState;
+ setBaseState(StopRequested);
+ switch (oldState) {
+ case Connecting:
+ m_connection->disconnectFromHost();
+ setDeploymentFinished();
+ break;
+ case Deploying:
+ stopInternal();
+ break;
+ default:
+ qFatal("Missing switch case in %s.", Q_FUNC_INFO);
+ }
+}
+
+bool AbstractMaemoDeployStep::currentlyNeedsDeployment(const QString &host,
+ const MaemoDeployable &deployable) const
+{
+ const QDateTime &lastDeployed
+ = m_lastDeployed.value(DeployablePerHost(deployable, host));
+ return !lastDeployed.isValid()
+ || QFileInfo(deployable.localFilePath).lastModified() > lastDeployed;
+}
+
+void AbstractMaemoDeployStep::setDeployed(const QString &host,
+ const MaemoDeployable &deployable)
+{
+ m_lastDeployed.insert(DeployablePerHost(deployable, host),
+ QDateTime::currentDateTime());
+}
+
+void AbstractMaemoDeployStep::handleDeviceConfigurationsUpdated()
+{
+ setDeviceConfig(MaemoDeviceConfigurations::instance()->internalId(m_deviceConfig));
+}
+
+void AbstractMaemoDeployStep::setDeviceConfig(MaemoDeviceConfig::Id internalId)
+{
+ m_deviceConfig = maemoDeployConfig()->deviceConfigModel()->find(internalId);
+ emit deviceConfigChanged();
+}
+
+void AbstractMaemoDeployStep::setDeviceConfig(int i)
+{
+ m_deviceConfig = maemoDeployConfig()->deviceConfigModel()->deviceAt(i);
+ emit deviceConfigChanged();
+}
+
+bool AbstractMaemoDeployStep::isDeploymentPossible(QString &whyNot) const
+{
+ if (!m_deviceConfig) {
+ whyNot = tr("No valid device set.");
+ return false;
+ }
+ return isDeploymentPossibleInternal(whyNot);
+}
+
+void AbstractMaemoDeployStep::start()
+{
+ if (m_baseState != BaseInactive) {
+ raiseError(tr("Cannot deploy: Still cleaning up from last time."));
+ emit done();
+ return;
+ }
+
+ m_cachedDeviceConfig = m_deviceConfig;
+
+ QString message;
+ if (!isDeploymentPossible(message)) {
+ raiseError(tr("Cannot deploy: %1").arg(message));
+ emit done();
+ return;
+ }
+
+ m_hasError = false;
+ if (isDeploymentNeeded(m_cachedDeviceConfig->sshParameters().host)) {
+ if (m_cachedDeviceConfig->type() == MaemoDeviceConfig::Emulator
+ && !MaemoQemuManager::instance().qemuIsRunning()) {
+ MaemoQemuManager::instance().startRuntime();
+ raiseError(tr("Cannot deploy: Qemu was not running. "
+ "It has now been started up for you, but it will take "
+ "a bit of time until it is ready."));
+ emit done();
+ return;
+ }
+
+ connectToDevice();
+ } else {
+ writeOutput(tr("All files up to date, no installation necessary."));
+ emit done();
+ }
+}
+
+void AbstractMaemoDeployStep::handleConnectionFailure()
+{
+ if (m_baseState == BaseInactive)
+ return;
+
+ const QString errorMsg = m_baseState == Connecting
+ ? MaemoGlobal::failedToConnectToServerMessage(m_connection, m_cachedDeviceConfig)
+ : tr("Connection error: %1").arg(m_connection->errorString());
+ raiseError(errorMsg);
+ setDeploymentFinished();
+}
+
+void AbstractMaemoDeployStep::connectToDevice()
+{
+ ASSERT_STATE(QList<BaseState>() << BaseInactive);
+ setBaseState(Connecting);
+
+ m_connection = SshConnectionManager::instance().acquireConnection(m_cachedDeviceConfig->sshParameters());
+ connect(m_connection.data(), SIGNAL(error(Utils::SshError)), this,
+ SLOT(handleConnectionFailure()));
+ if (m_connection->state() == SshConnection::Connected) {
+ handleConnected();
+ } else {
+ connect(m_connection.data(), SIGNAL(connected()), this,
+ SLOT(handleConnected()));
+ writeOutput(tr("Connecting to device..."));
+ m_connection->connectToHost();
+ }
+}
+
+void AbstractMaemoDeployStep::handleConnected()
+{
+ ASSERT_STATE(QList<BaseState>() << Connecting << StopRequested);
+
+ if (m_baseState == Connecting) {
+ setBaseState(Deploying);
+ startInternal();
+ }
+}
+
+void AbstractMaemoDeployStep::handleProgressReport(const QString &progressMsg)
+{
+ ASSERT_STATE(QList<BaseState>() << Deploying << StopRequested << BaseInactive);
+
+ switch (m_baseState) {
+ case Deploying:
+ case StopRequested:
+ writeOutput(progressMsg);
+ break;
+ case BaseInactive:
+ default:
+ break;
+ }
+}
+
+void AbstractMaemoDeployStep::setDeploymentFinished()
+{
+ if (m_hasError)
+ writeOutput(tr("Deployment failed."), ErrorMessageOutput);
+ else
+ writeOutput(tr("Deployment finished."));
+ setBaseState(BaseInactive);
+}
+
+void AbstractMaemoDeployStep::setBaseState(BaseState newState)
+{
+ if (newState == m_baseState)
+ return;
+ m_baseState = newState;
+ if (m_baseState == BaseInactive) {
+ disconnect(m_connection.data(), 0, this, 0);
+ SshConnectionManager::instance().releaseConnection(m_connection);
+ emit done();
+ }
+}
+
+void AbstractMaemoDeployStep::handleRemoteStdout(const QString &output)
+{
+ ASSERT_STATE(QList<BaseState>() << Deploying << StopRequested);
+
+ switch (m_baseState) {
+ case Deploying:
+ case StopRequested:
+ writeOutput(output, NormalOutput, DontAppendNewline);
+ break;
+ default:
+ break;
+ }
+}
+
+void AbstractMaemoDeployStep::handleRemoteStderr(const QString &output)
+{
+ ASSERT_STATE(QList<BaseState>() << Deploying << StopRequested);
+
+ switch (m_baseState) {
+ case Deploying:
+ case StopRequested:
+ writeOutput(output, ErrorOutput, DontAppendNewline);
+ break;
+ default:
+ break;
+ }
+}
+
+MaemoPortList AbstractMaemoDeployStep::freePorts() const
+{
+ const Qt4BuildConfiguration * const qt4bc = qt4BuildConfiguration();
+ const MaemoDeviceConfig::ConstPtr &devConf
+ = m_cachedDeviceConfig ? m_cachedDeviceConfig : m_deviceConfig;
+ if (!devConf)
+ return MaemoPortList();
+ if (devConf->type() == MaemoDeviceConfig::Emulator && qt4bc) {
+ MaemoQemuRuntime rt;
+ const int id = qt4bc->qtVersion()->uniqueId();
+ if (MaemoQemuManager::instance().runtimeForQtVersion(id, &rt))
+ return rt.m_freePorts;
+ }
+ return devConf->freePorts();
+}
+
+const Qt4BuildConfiguration *AbstractMaemoDeployStep::qt4BuildConfiguration() const
+{
+ return static_cast<Qt4BuildConfiguration *>(buildConfiguration());
+}
+
+Qt4MaemoDeployConfiguration *AbstractMaemoDeployStep::maemoDeployConfig() const
+{
+ return qobject_cast<Qt4MaemoDeployConfiguration *>(deployConfiguration());
+}
+
+MaemoDeployEventHandler::MaemoDeployEventHandler(AbstractMaemoDeployStep *deployStep,
+ QFutureInterface<bool> &future)
+ : 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()));
+ QTimer cancelChecker;
+ connect(&cancelChecker, SIGNAL(timeout()), this, SLOT(checkForCanceled()));
+ cancelChecker.start(500);
+ future.reportResult(m_eventLoop->exec() == 0);
+}
+
+void MaemoDeployEventHandler::handleDeployingDone()
+{
+ m_eventLoop->exit(m_error ? 1 : 0);
+}
+
+void MaemoDeployEventHandler::handleDeployingFailed()
+{
+ m_error = true;
+}
+
+void MaemoDeployEventHandler::checkForCanceled()
+{
+ if (!m_error && m_future.isCanceled()) {
+ QMetaObject::invokeMethod(m_deployStep, "stop");
+ m_error = true;
+ handleDeployingDone();
+ }
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#include "abstractmaemodeploystep.moc"
diff --git a/src/plugins/qt4projectmanager/qt-maemo/abstractmaemodeploystep.h b/src/plugins/qt4projectmanager/qt-maemo/abstractmaemodeploystep.h
new file mode 100644
index 0000000000..9e200a4a8d
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/abstractmaemodeploystep.h
@@ -0,0 +1,142 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 ABSTRACTMAEMODEPLOYSTEP_H
+#define ABSTRACTMAEMODEPLOYSTEP_H
+
+#include "maemodeployable.h"
+#include "maemodeployables.h"
+#include "maemodeviceconfigurations.h"
+
+#include <projectexplorer/buildstep.h>
+
+#include <QtCore/QHash>
+#include <QtCore/QList>
+#include <QtCore/QPair>
+#include <QtCore/QSharedPointer>
+
+QT_BEGIN_NAMESPACE
+class QEventLoop;
+QT_END_NAMESPACE
+
+namespace Utils { class SshConnection; }
+
+namespace Qt4ProjectManager {
+class Qt4BuildConfiguration;
+namespace Internal {
+class AbstractMaemoPackageCreationStep;
+class MaemoDeviceConfig;
+class Qt4MaemoDeployConfiguration;
+
+class AbstractMaemoDeployStep : public ProjectExplorer::BuildStep
+{
+ Q_OBJECT
+public:
+ virtual ~AbstractMaemoDeployStep();
+ QSharedPointer<const MaemoDeviceConfig> deviceConfig() const { return m_deviceConfig; }
+ void setDeviceConfig(int i);
+ bool currentlyNeedsDeployment(const QString &host,
+ const MaemoDeployable &deployable) const;
+ void setDeployed(const QString &host, const MaemoDeployable &deployable);
+ MaemoPortList freePorts() const;
+ Qt4MaemoDeployConfiguration *maemoDeployConfig() const;
+ bool isDeploymentPossible(QString &whyNot) const;
+
+ Q_INVOKABLE void stop();
+
+signals:
+ void done();
+ void error();
+ void deviceConfigChanged();
+
+protected:
+ AbstractMaemoDeployStep(ProjectExplorer::BuildStepList *bc,
+ const QString &id);
+ AbstractMaemoDeployStep(ProjectExplorer::BuildStepList *bc,
+ AbstractMaemoDeployStep *other);
+
+ enum BaseState { BaseInactive, StopRequested, Connecting, Deploying };
+ BaseState baseState() const { return m_baseState; }
+
+ void raiseError(const QString &error);
+ void writeOutput(const QString &text, OutputFormat format = MessageOutput,
+ OutputNewlineSetting newlineSetting = DoAppendNewline);
+ void setDeploymentFinished();
+
+ virtual const AbstractMaemoPackageCreationStep *packagingStep() const=0;
+
+ QString deployMountPoint() const;
+ const Qt4BuildConfiguration *qt4BuildConfiguration() const;
+ QSharedPointer<Utils::SshConnection> connection() const { return m_connection; }
+
+private slots:
+ void start();
+ void handleConnected();
+ void handleConnectionFailure();
+ void handleProgressReport(const QString &progressMsg);
+ void handleRemoteStdout(const QString &output);
+ void handleRemoteStderr(const QString &output);
+ void handleDeviceConfigurationsUpdated();
+
+private:
+ virtual bool init() { return true; }
+ virtual void run(QFutureInterface<bool> &fi);
+ virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
+ virtual QVariantMap toMap() const;
+ virtual bool fromMap(const QVariantMap &map);
+
+ virtual bool isDeploymentPossibleInternal(QString &whynot) const=0;
+ virtual bool isDeploymentNeeded(const QString &hostName) const=0;
+ virtual void startInternal()=0;
+ virtual void stopInternal()=0;
+
+ void baseCtor();
+ void addDeployTimesToMap(QVariantMap &map) const;
+ void getDeployTimesFromMap(const QVariantMap &map);
+ void connectToDevice();
+ void setBaseState(BaseState newState);
+ void setDeviceConfig(MaemoDeviceConfig::Id internalId);
+
+ QSharedPointer<Utils::SshConnection> m_connection;
+ typedef QPair<MaemoDeployable, QString> DeployablePerHost;
+ QHash<DeployablePerHost, QDateTime> m_lastDeployed;
+ QSharedPointer<const MaemoDeviceConfig> m_deviceConfig;
+ QSharedPointer<const MaemoDeviceConfig> m_cachedDeviceConfig;
+ BaseState m_baseState;
+ bool m_hasError;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // ABSTRACTMAEMODEPLOYSTEP_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoanalyzersupport.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoanalyzersupport.cpp
new file mode 100644
index 0000000000..2136168f4d
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoanalyzersupport.cpp
@@ -0,0 +1,76 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "maemoanalyzersupport.h"
+
+#include <analyzerbase/analyzermanager.h>
+#include <analyzerbase/analyzerstartparameters.h>
+#include <analyzerbase/analyzerconstants.h>
+#include <analyzerbase/analyzerruncontrol.h>
+
+#include <QtCore/QDir>
+
+using namespace Utils;
+using namespace Analyzer;
+using namespace ProjectExplorer;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+RunControl *MaemoAnalyzerSupport::createAnalyzerRunControl(MaemoRunConfiguration *runConfig)
+{
+ AnalyzerStartParameters params;
+
+ const MaemoDeviceConfig::ConstPtr &devConf = runConfig->deviceConfig();
+ params.debuggee = runConfig->remoteExecutableFilePath();
+ params.debuggeeArgs = runConfig->arguments();
+ params.analyzerCmdPrefix = MaemoGlobal::remoteCommandPrefix(devConf->osVersion(),
+ devConf->sshParameters().userName, runConfig->remoteExecutableFilePath())
+ + MaemoGlobal::remoteEnvironment(runConfig->userEnvironmentChanges());
+ params.startMode = StartRemote;
+ params.connParams = devConf->sshParameters();
+ params.localMountDir = runConfig->localDirToMountForRemoteGdb();
+ params.remoteMountPoint = runConfig->remoteProjectSourcesMountPoint();
+ const QString execDirAbs
+ = QDir::fromNativeSeparators(QFileInfo(runConfig->localExecutableFilePath()).path());
+ const QString execDirRel
+ = QDir(params.localMountDir).relativeFilePath(execDirAbs);
+ params.remoteSourcesDir = QString(params.remoteMountPoint
+ + QLatin1Char('/') + execDirRel).toUtf8();
+ params.displayName = runConfig->displayName();
+
+ return AnalyzerManager::instance()->createAnalyzer(params, runConfig);
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoanalyzersupport.h b/src/plugins/qt4projectmanager/qt-maemo/maemoanalyzersupport.h
new file mode 100644
index 0000000000..fb106f9b56
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoanalyzersupport.h
@@ -0,0 +1,51 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 MAEMOANALYZERSUPPORT_H
+#define MAEMOANALYZERSUPPORT_H
+
+#include "maemorunconfiguration.h"
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+namespace MaemoAnalyzerSupport {
+
+ProjectExplorer::RunControl *createAnalyzerRunControl(MaemoRunConfiguration *runConfig);
+
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOANALYZERSUPPORT_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.cpp
index 28c1db6f81..fe85029068 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.cpp
@@ -83,7 +83,12 @@ void MaemoConfigTestDialog::startConfigTest()
: tr("Testing configuration...");
m_ui->testResultEdit->setPlainText(testingText);
m_closeButton->setText(tr("Stop Test"));
- m_testProcessRunner = SshRemoteProcessRunner::create(m_config->sshParameters());
+
+ // We need to explicitly create the connection here, because the other
+ // constructor uses a managed connection, i.e. it might re-use an
+ // existing one, which we explicitly don't want here.
+ m_testProcessRunner = SshRemoteProcessRunner::create(SshConnection::create(m_config->sshParameters()));
+
connect(m_testProcessRunner.data(), SIGNAL(connectionError(Utils::SshError)),
this, SLOT(handleConnectionError()));
connect(m_testProcessRunner.data(), SIGNAL(processClosed(int)), this,
@@ -92,12 +97,15 @@ void MaemoConfigTestDialog::startConfigTest()
SIGNAL(processOutputAvailable(QByteArray)), this,
SLOT(processSshOutput(QByteArray)));
const QLatin1String sysInfoCmd("uname -rsm");
- const bool osUsesRpm = MaemoGlobal::packagingSystem(m_config->osVersion()) == MaemoGlobal::Rpm;
- const QLatin1String qtInfoCmd(osUsesRpm
- ? "rpm -qa 'libqt*' --queryformat '%{NAME} %{VERSION}\\n'"
- : "dpkg-query -W -f '${Package} ${Version} ${Status}\n' 'libqt*' "
- "|grep ' installed$'");
- QString command(sysInfoCmd + " && " + qtInfoCmd);
+ QString command = sysInfoCmd;
+ if (m_config->osVersion() != MaemoGlobal::GenericLinux) {
+ const bool osUsesRpm = MaemoGlobal::packagingSystem(m_config->osVersion()) == MaemoGlobal::Rpm;
+ const QLatin1String qtInfoCmd(osUsesRpm
+ ? "rpm -qa 'libqt*' --queryformat '%{NAME} %{VERSION}\\n'"
+ : "dpkg-query -W -f '${Package} ${Version} ${Status}\n' 'libqt*' "
+ "|grep ' installed$'");
+ command += QLatin1String(" && ") + qtInfoCmd;
+ }
m_testProcessRunner->run(command.toUtf8());
}
@@ -134,7 +142,7 @@ void MaemoConfigTestDialog::handleGeneralTestResult(int exitStatus)
|| m_testProcessRunner->process()->exitCode() != 0) {
m_ui->testResultEdit->setPlainText(tr("Remote process failed: %1")
.arg(m_testProcessRunner->process()->errorString()));
- } else {
+ } else {
const QString &output = parseTestOutput();
if (!m_qtVersionOk) {
m_ui->errorLabel->setText(tr("Qt version mismatch! "
@@ -143,11 +151,16 @@ void MaemoConfigTestDialog::handleGeneralTestResult(int exitStatus)
m_ui->testResultEdit->setPlainText(output);
}
+ if (m_config->osVersion() == MaemoGlobal::GenericLinux) {
+ testPorts();
+ return;
+ }
+
m_currentTest = MadDeveloperTest;
disconnect(m_testProcessRunner.data(),
SIGNAL(processOutputAvailable(QByteArray)), this,
SLOT(processSshOutput(QByteArray)));
- const QByteArray command = "test -x " + MaemoGlobal::remoteSudo().toUtf8();
+ const QByteArray command = "test -x " + MaemoGlobal::devrootshPath().toUtf8();
m_testProcessRunner->run(command);
}
@@ -167,11 +180,7 @@ void MaemoConfigTestDialog::handleMadDeveloperTestResult(int exitStatus)
}
m_ui->errorLabel->setText(errorMsg);
}
- if (m_config->freePorts().hasMore())
- m_portsGatherer->start(m_testProcessRunner->connection(),
- m_config->freePorts());
- else
- finish();
+ testPorts();
}
void MaemoConfigTestDialog::handlePortListFailure(const QString &errMsg)
@@ -196,6 +205,15 @@ void MaemoConfigTestDialog::handlePortListReady()
finish();
}
+void MaemoConfigTestDialog::testPorts()
+{
+ if (m_config->freePorts().hasMore())
+ m_portsGatherer->start(m_testProcessRunner->connection(),
+ m_config->freePorts());
+ else
+ finish();
+}
+
void MaemoConfigTestDialog::finish()
{
if (m_ui->errorLabel->text().isEmpty()) {
@@ -238,6 +256,11 @@ QString MaemoConfigTestDialog::parseTestOutput()
output = tr("Hardware architecture: %1\n").arg(unamePattern.cap(2));
output.append(tr("Kernel version: %1\n").arg(unamePattern.cap(1)));
+ if (m_config->osVersion() == MaemoGlobal::GenericLinux) {
+ m_qtVersionOk = true;
+ return output;
+ }
+
const bool osUsesRpm = MaemoGlobal::packagingSystem(m_config->osVersion()) == MaemoGlobal::Rpm;
const QRegExp packagePattern(QLatin1String(osUsesRpm
? "(libqt\\S+) ((\\d+)\\.(\\d+)\\.(\\d+))"
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.h b/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.h
index 0795a0153c..e5a22b8776 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoconfigtestdialog.h
@@ -74,6 +74,7 @@ private:
QString parseTestOutput();
void handleGeneralTestResult(int exitStatus);
void handleMadDeveloperTestResult(int exitStatus);
+ void testPorts();
void finish();
Ui_MaemoConfigTestDialog *m_ui;
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoconstants.h b/src/plugins/qt4projectmanager/qt-maemo/maemoconstants.h
index b671010a8a..af6ab1d3df 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoconstants.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoconstants.h
@@ -49,13 +49,11 @@ static const QLatin1String MAEMO_RC_ID(PREFIX);
static const QLatin1String MAEMO_RC_ID_PREFIX(PREFIX ".");
static const QLatin1String ArgumentsKey(PREFIX ".Arguments");
-static const QLatin1String SimulatorPathKey(PREFIX ".Simulator");
static const QLatin1String DeviceIdKey(PREFIX ".DeviceId");
static const QLatin1String LastDeployedHostsKey(PREFIX ".LastDeployedHosts");
static const QLatin1String LastDeployedFilesKey(PREFIX ".LastDeployedFiles");
static const QLatin1String LastDeployedRemotePathsKey(PREFIX ".LastDeployedRemotePaths");
static const QLatin1String LastDeployedTimesKey(PREFIX ".LastDeployedTimes");
-static const QLatin1String DeployToSysrootKey(PREFIX ".DeployToSysroot");
static const QLatin1String ProFileKey(PREFIX ".ProFile");
static const QLatin1String ExportedLocalDirsKey(PREFIX ".ExportedLocalDirs");
static const QLatin1String RemoteMountPointsKey(PREFIX ".RemoteMountPoints");
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.cpp
index ee755edb60..aaed62f71b 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.cpp
@@ -31,8 +31,8 @@
#include "maemodebugsupport.h"
+#include "abstractmaemodeploystep.h"
#include "maemodeployables.h"
-#include "maemodeploystep.h"
#include "maemoglobal.h"
#include "maemosshrunner.h"
#include "maemousedportsgatherer.h"
@@ -79,6 +79,7 @@ RunControl *MaemoDebugSupport::createDebugRunControl(MaemoRunConfiguration *runC
params.startMode = StartRemoteGdb;
params.executable = runConfig->remoteExecutableFilePath();
params.debuggerCommand = MaemoGlobal::remoteCommandPrefix(runConfig->deviceConfig()->osVersion(),
+ runConfig->deviceConfig()->sshParameters().userName,
runConfig->remoteExecutableFilePath())
+ MaemoGlobal::remoteEnvironment(runConfig->userEnvironmentChanges())
+ QLatin1String(" /usr/bin/gdb");
@@ -287,7 +288,7 @@ void MaemoDebugSupport::startDebugging()
}
const QString &remoteExe = m_runner->remoteExecutable();
const QString cmdPrefix = MaemoGlobal::remoteCommandPrefix(m_deviceConfig->osVersion(),
- remoteExe);
+ m_deviceConfig->sshParameters().userName, remoteExe);
const QString env = MaemoGlobal::remoteEnvironment(m_userEnvChanges);
QString args = m_runner->arguments();
if (m_debuggingType != MaemoRunConfiguration::DebugCppOnly) {
@@ -336,7 +337,7 @@ void MaemoDebugSupport::handleRemoteErrorOutput(const QByteArray &output)
void MaemoDebugSupport::handleProgressReport(const QString &progressOutput)
{
- showMessage(progressOutput, AppStuff);
+ showMessage(progressOutput + QLatin1Char('\n'), AppStuff);
}
void MaemoDebugSupport::handleAdapterSetupFailed(const QString &error)
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeployable.h b/src/plugins/qt4projectmanager/qt-maemo/maemodeployable.h
index d66de56166..52b08038ed 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeployable.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeployable.h
@@ -41,6 +41,8 @@ namespace Internal {
struct MaemoDeployable
{
+ MaemoDeployable() {}
+
MaemoDeployable(const QString &localFilePath, const QString &remoteDir)
: localFilePath(localFilePath), remoteDir(remoteDir) {}
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeployables.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeployables.cpp
index ec1b50c9ff..fa25b83ba6 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeployables.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeployables.cpp
@@ -32,20 +32,20 @@
#include "maemodeployables.h"
#include "maemoprofilesupdatedialog.h"
-#include "qt4maemotarget.h"
#include <profileevaluator.h>
#include <projectexplorer/buildstep.h>
#include <qt4projectmanager/qt4projectmanagerconstants.h>
#include <qt4projectmanager/qt4buildconfiguration.h>
#include <qt4projectmanager/qt4project.h>
+#include <qt4projectmanager/qt4target.h>
#include <QtCore/QTimer>
namespace Qt4ProjectManager {
namespace Internal {
-MaemoDeployables::MaemoDeployables(const AbstractQt4MaemoTarget *target)
+MaemoDeployables::MaemoDeployables(const Qt4BaseTarget *target)
: m_target(target), m_updateTimer(new QTimer(this))
{
QTimer::singleShot(0, this, SLOT(init()));
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeployables.h b/src/plugins/qt4projectmanager/qt-maemo/maemodeployables.h
index 6f19a08b02..568be25430 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeployables.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeployables.h
@@ -43,16 +43,16 @@ QT_FORWARD_DECLARE_CLASS(QTimer)
namespace Qt4ProjectManager {
class Qt4BuildConfiguration;
+class Qt4BaseTarget;
namespace Internal {
class Qt4ProFileNode;
-class AbstractQt4MaemoTarget;
class MaemoDeployables : public QAbstractListModel
{
Q_OBJECT
public:
- MaemoDeployables(const AbstractQt4MaemoTarget *target);
+ MaemoDeployables(const Qt4BaseTarget *target);
~MaemoDeployables();
void setUnmodified();
bool isModified() const;
@@ -74,7 +74,7 @@ private:
QList<MaemoDeployableListModel *> m_listModels;
UpdateSettingsMap m_updateSettings;
- const AbstractQt4MaemoTarget * const m_target;
+ const Qt4BaseTarget * const m_target;
QTimer *const m_updateTimer;
};
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeploybymountstep.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeploybymountstep.cpp
new file mode 100644
index 0000000000..4d63bc90e9
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeploybymountstep.cpp
@@ -0,0 +1,389 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "maemodeploybymountstep.h"
+
+#include "maemodeploymentmounter.h"
+#include "maemoglobal.h"
+#include "maemopackagecreationstep.h"
+#include "maemopackageinstaller.h"
+#include "maemoremotecopyfacility.h"
+#include "qt4maemodeployconfiguration.h"
+#include "qt4maemotarget.h"
+
+#include <utils/ssh/sshconnection.h>
+
+#include <QtCore/QFileInfo>
+
+#define ASSERT_BASE_STATE(state) ASSERT_STATE_GENERIC(BaseState, state, baseState())
+#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(ExtendedState, state, m_extendedState)
+
+using namespace ProjectExplorer;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+AbstractMaemoDeployByMountStep::AbstractMaemoDeployByMountStep(BuildStepList *parent,
+ const QString &id)
+ : AbstractMaemoDeployStep(parent, id)
+{
+ ctor();
+}
+
+AbstractMaemoDeployByMountStep::AbstractMaemoDeployByMountStep(BuildStepList *parent,
+ AbstractMaemoDeployByMountStep *other)
+ : AbstractMaemoDeployStep(parent, other)
+{
+ ctor();
+}
+
+void AbstractMaemoDeployByMountStep::ctor()
+{
+ m_extendedState= Inactive;
+
+ m_mounter = new MaemoDeploymentMounter(this);
+ connect(m_mounter, SIGNAL(setupDone()), this, SLOT(handleMounted()));
+ connect(m_mounter, SIGNAL(tearDownDone()), this, SLOT(handleUnmounted()));
+ connect(m_mounter, SIGNAL(error(QString)), this,
+ SLOT(handleMountError(QString)));
+ connect(m_mounter, SIGNAL(reportProgress(QString)), this,
+ SLOT(handleProgressReport(QString)));
+ connect(m_mounter, SIGNAL(debugOutput(QString)), this,
+ SLOT(handleMountDebugOutput(QString)));
+}
+
+void AbstractMaemoDeployByMountStep::stopInternal()
+{
+ ASSERT_STATE(QList<ExtendedState>() << Mounting << Installing
+ << Unmounting);
+
+ switch (m_extendedState) {
+ case Installing:
+ cancelInstallation();
+ unmount();
+ break;
+ case Mounting:
+ case Unmounting:
+ break; // Nothing to do here.
+ case Inactive:
+ setDeploymentFinished();
+ break;
+ default:
+ qFatal("Missing switch case in %s.", Q_FUNC_INFO);
+ }
+}
+
+void AbstractMaemoDeployByMountStep::startInternal()
+{
+ Q_ASSERT(m_extendedState == Inactive);
+
+ mount();
+}
+
+void AbstractMaemoDeployByMountStep::handleMounted()
+{
+ ASSERT_BASE_STATE(QList<BaseState>() << Deploying << StopRequested);
+ ASSERT_STATE(Mounting);
+
+ if (baseState() == StopRequested) {
+ unmount();
+ return;
+ }
+
+ writeOutput(tr("Installing package to device..."));
+ m_extendedState = Installing;
+ deploy();
+}
+
+void AbstractMaemoDeployByMountStep::handleUnmounted()
+{
+ ASSERT_BASE_STATE(QList<BaseState>() << Deploying << StopRequested);
+ ASSERT_STATE(Unmounting);
+
+ setFinished();
+}
+
+void AbstractMaemoDeployByMountStep::handleMountError(const QString &errorMsg)
+{
+ ASSERT_BASE_STATE(QList<BaseState>() << Deploying << StopRequested);
+ ASSERT_STATE(QList<ExtendedState>() << Mounting << Unmounting);
+
+ raiseError(errorMsg);
+ setFinished();
+}
+
+void AbstractMaemoDeployByMountStep::handleMountDebugOutput(const QString &output)
+{
+ ASSERT_BASE_STATE(QList<BaseState>() << Deploying << StopRequested);
+
+ if (m_extendedState != Inactive)
+ writeOutput(output, ErrorOutput, DontAppendNewline);
+}
+
+void AbstractMaemoDeployByMountStep::mount()
+{
+ m_extendedState = Mounting;
+ m_mounter->setupMounts(connection(), mountSpecifications(), freePorts(),
+ qt4BuildConfiguration());
+}
+
+QString AbstractMaemoDeployByMountStep::deployMountPoint() const
+{
+ return MaemoGlobal::homeDirOnDevice(connection()->connectionParameters().userName)
+ + QLatin1String("/deployMountPoint_") + target()->project()->displayName();
+}
+
+void AbstractMaemoDeployByMountStep::handleInstallationFinished(const QString &errorMsg)
+{
+ ASSERT_BASE_STATE(QList<BaseState>() << Deploying << StopRequested);
+
+ if (baseState() == StopRequested) {
+ unmount();
+ return;
+ }
+
+ if (m_extendedState != Installing)
+ return;
+
+ if (errorMsg.isEmpty())
+ handleInstallationSuccess();
+ else
+ raiseError(errorMsg);
+ unmount();
+}
+
+void AbstractMaemoDeployByMountStep::unmount()
+{
+ m_extendedState = Unmounting;
+ m_mounter->tearDownMounts();
+}
+
+void AbstractMaemoDeployByMountStep::setFinished()
+{
+ m_extendedState = Inactive;
+ setDeploymentFinished();
+}
+
+
+MaemoMountAndInstallDeployStep::MaemoMountAndInstallDeployStep(BuildStepList *bc)
+ : AbstractMaemoDeployByMountStep(bc, Id)
+{
+ ctor();
+}
+
+MaemoMountAndInstallDeployStep::MaemoMountAndInstallDeployStep(BuildStepList *bc,
+ MaemoMountAndInstallDeployStep *other)
+ : AbstractMaemoDeployByMountStep(bc, other)
+{
+ ctor();
+}
+
+void MaemoMountAndInstallDeployStep::ctor()
+{
+ //: MaemoMountAndInstallDeployStep default display name
+ setDefaultDisplayName(DisplayName);
+
+ if (qobject_cast<AbstractDebBasedQt4MaemoTarget *>(target()))
+ m_installer = new MaemoDebianPackageInstaller(this);
+ else
+ m_installer = new MaemoRpmPackageInstaller(this);
+ connect(m_installer, SIGNAL(stdoutData(QString)),
+ SLOT(handleRemoteStdout(QString)));
+ connect(m_installer, SIGNAL(stderrData(QString)),
+ SLOT(handleRemoteStderr(QString)));
+ connect(m_installer, SIGNAL(finished(QString)),
+ SLOT(handleInstallationFinished(QString)));
+}
+
+const AbstractMaemoPackageCreationStep *MaemoMountAndInstallDeployStep::packagingStep() const
+{
+ return MaemoGlobal::earlierBuildStep<MaemoDebianPackageCreationStep>(maemoDeployConfig(), this);
+}
+
+bool MaemoMountAndInstallDeployStep::isDeploymentPossibleInternal(QString &whyNot) const
+{
+ if (!packagingStep()) {
+ whyNot = tr("No matching packaging step found.");
+ return false;
+ }
+ return true;
+}
+
+bool MaemoMountAndInstallDeployStep::isDeploymentNeeded(const QString &hostName) const
+{
+ const AbstractMaemoPackageCreationStep * const pStep = packagingStep();
+ Q_ASSERT(pStep);
+ const MaemoDeployable d(pStep->packageFilePath(), QString());
+ return currentlyNeedsDeployment(hostName, d);
+}
+
+QList<MaemoMountSpecification> MaemoMountAndInstallDeployStep::mountSpecifications() const
+{
+ const QString localDir
+ = QFileInfo(packagingStep()->packageFilePath()).absolutePath();
+ return QList<MaemoMountSpecification>()
+ << MaemoMountSpecification(localDir, deployMountPoint());
+}
+
+void MaemoMountAndInstallDeployStep::deploy()
+{
+ const QString remoteFilePath = deployMountPoint() + QLatin1Char('/')
+ + QFileInfo(packagingStep()->packageFilePath()).fileName();
+ m_installer->installPackage(connection(), remoteFilePath, false);
+}
+
+void MaemoMountAndInstallDeployStep::cancelInstallation()
+{
+ m_installer->cancelInstallation();
+}
+
+void MaemoMountAndInstallDeployStep::handleInstallationSuccess()
+{
+ setDeployed(connection()->connectionParameters().host,
+ MaemoDeployable(packagingStep()->packageFilePath(), QString()));
+ writeOutput(tr("Package installed."));
+}
+
+const QString MaemoMountAndInstallDeployStep::Id("MaemoMountAndInstallDeployStep");
+const QString MaemoMountAndInstallDeployStep::DisplayName
+ = tr("Deploy package via UTFS mount");
+
+
+MaemoMountAndCopyDeployStep::MaemoMountAndCopyDeployStep(BuildStepList *bc)
+ : AbstractMaemoDeployByMountStep(bc, Id)
+{
+ ctor();
+}
+
+MaemoMountAndCopyDeployStep::MaemoMountAndCopyDeployStep(BuildStepList *bc,
+ MaemoMountAndCopyDeployStep *other)
+ : AbstractMaemoDeployByMountStep(bc, other)
+{
+ ctor();
+}
+
+void MaemoMountAndCopyDeployStep::ctor()
+{
+ //: MaemoMountAndCopyDeployStep default display name
+ setDefaultDisplayName(DisplayName);
+
+ m_copyFacility = new MaemoRemoteCopyFacility(this);
+ connect(m_copyFacility, SIGNAL(stdoutData(QString)),
+ SLOT(handleRemoteStdout(QString)));
+ connect(m_copyFacility, SIGNAL(stderrData(QString)),
+ SLOT(handleRemoteStderr(QString)));
+ connect(m_copyFacility, SIGNAL(progress(QString)),
+ SLOT(handleProgressReport(QString)));
+ connect(m_copyFacility, SIGNAL(fileCopied(MaemoDeployable)),
+ SLOT(handleFileCopied(MaemoDeployable)));
+ connect(m_copyFacility, SIGNAL(finished(QString)),
+ SLOT(handleInstallationFinished(QString)));
+}
+
+bool MaemoMountAndCopyDeployStep::isDeploymentPossibleInternal(QString &) const
+{
+ return true;
+}
+
+bool MaemoMountAndCopyDeployStep::isDeploymentNeeded(const QString &hostName) const
+{
+ m_filesToCopy.clear();
+ const QSharedPointer<MaemoDeployables> deployables
+ = maemoDeployConfig()->deployables();
+ const int deployableCount = deployables->deployableCount();
+ for (int i = 0; i < deployableCount; ++i) {
+ const MaemoDeployable &d = deployables->deployableAt(i);
+ if (currentlyNeedsDeployment(hostName, d))
+ m_filesToCopy << d;
+ }
+ return !m_filesToCopy.isEmpty();
+}
+
+QList<MaemoMountSpecification> MaemoMountAndCopyDeployStep::mountSpecifications() const
+{
+ QList<MaemoMountSpecification> mountSpecs;
+#ifdef Q_OS_WIN
+ bool drivesToMount[26];
+ qFill(drivesToMount, drivesToMount + sizeof drivesToMount / sizeof drivesToMount[0], false);
+ for (int i = 0; i < m_filesToCopy.count(); ++i) {
+ const QString localDir
+ = QFileInfo(m_filesToCopy.at(i).localFilePath).canonicalPath();
+ const char driveLetter = localDir.at(0).toLower().toLatin1();
+ if (driveLetter < 'a' || driveLetter > 'z') {
+ qWarning("Weird: drive letter is '%c'.", driveLetter);
+ continue;
+ }
+
+ const int index = driveLetter - 'a';
+ if (drivesToMount[index])
+ continue;
+
+ const QString mountPoint = deployMountPoint() + QLatin1Char('/')
+ + QLatin1Char(driveLetter);
+ const MaemoMountSpecification mountSpec(localDir.left(3), mountPoint);
+ mountSpecs << mountSpec;
+ drivesToMount[index] = true;
+ }
+#else
+ mountSpecs << MaemoMountSpecification(QLatin1String("/"),
+ deployMountPoint());
+#endif
+ return mountSpecs;
+}
+
+void MaemoMountAndCopyDeployStep::deploy()
+{
+ m_copyFacility->copyFiles(connection(), m_filesToCopy, deployMountPoint());
+}
+
+void MaemoMountAndCopyDeployStep::handleFileCopied(const MaemoDeployable &deployable)
+{
+ setDeployed(connection()->connectionParameters().host, deployable);
+}
+
+void MaemoMountAndCopyDeployStep::cancelInstallation()
+{
+ m_copyFacility->cancel();
+}
+
+void MaemoMountAndCopyDeployStep::handleInstallationSuccess()
+{
+ writeOutput(tr("All files copied."));
+}
+
+const QString MaemoMountAndCopyDeployStep::Id("MaemoMountAndCopyDeployStep");
+const QString MaemoMountAndCopyDeployStep::DisplayName
+ = tr("Deploy files via UTFS mount");
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeploybymountstep.h b/src/plugins/qt4projectmanager/qt-maemo/maemodeploybymountstep.h
new file mode 100644
index 0000000000..e4e70938cd
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeploybymountstep.h
@@ -0,0 +1,145 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 MAEMODEPLOYBYMOUNTSTEP_H
+#define MAEMODEPLOYBYMOUNTSTEP_H
+
+#include "abstractmaemodeploystep.h"
+
+#include "maemodeployable.h"
+#include "maemomountspecification.h"
+
+namespace Qt4ProjectManager {
+namespace Internal {
+class AbstractMaemoPackageInstaller;
+class MaemoDeploymentMounter;
+class MaemoRemoteCopyFacility;
+
+class AbstractMaemoDeployByMountStep : public AbstractMaemoDeployStep
+{
+ Q_OBJECT
+public:
+
+private slots:
+ void handleMounted();
+ void handleUnmounted();
+ void handleMountError(const QString &errorMsg);
+ void handleMountDebugOutput(const QString &output);
+ void handleInstallationFinished(const QString &errorMsg);
+
+protected:
+ AbstractMaemoDeployByMountStep(ProjectExplorer::BuildStepList *bc,
+ const QString &id);
+ AbstractMaemoDeployByMountStep(ProjectExplorer::BuildStepList *bc,
+ AbstractMaemoDeployByMountStep *other);
+
+ QString deployMountPoint() const;
+
+private:
+ enum ExtendedState { Inactive, Mounting, Installing, Unmounting };
+
+ virtual void startInternal();
+ virtual void stopInternal();
+
+ virtual QList<MaemoMountSpecification> mountSpecifications() const=0;
+ virtual void deploy()=0;
+ virtual void cancelInstallation()=0;
+ virtual void handleInstallationSuccess()=0;
+
+ void ctor();
+ void mount();
+ void unmount();
+ void setFinished();
+
+ MaemoDeploymentMounter *m_mounter;
+ ExtendedState m_extendedState;
+};
+
+
+class MaemoMountAndInstallDeployStep : public AbstractMaemoDeployByMountStep
+{
+ Q_OBJECT
+public:
+ MaemoMountAndInstallDeployStep(ProjectExplorer::BuildStepList *bc);
+ MaemoMountAndInstallDeployStep(ProjectExplorer::BuildStepList *bc,
+ MaemoMountAndInstallDeployStep *other);
+
+ static const QString Id;
+ static const QString DisplayName;
+private:
+ virtual const AbstractMaemoPackageCreationStep *packagingStep() const;
+ virtual bool isDeploymentPossibleInternal(QString &whynot) const;
+ virtual bool isDeploymentNeeded(const QString &hostName) const;
+
+ virtual QList<MaemoMountSpecification> mountSpecifications() const;
+ virtual void deploy();
+ virtual void cancelInstallation();
+ virtual void handleInstallationSuccess();
+
+ void ctor();
+
+ AbstractMaemoPackageInstaller *m_installer;
+};
+
+
+class MaemoMountAndCopyDeployStep : public AbstractMaemoDeployByMountStep
+{
+ Q_OBJECT
+public:
+ MaemoMountAndCopyDeployStep(ProjectExplorer::BuildStepList *bc);
+ MaemoMountAndCopyDeployStep(ProjectExplorer::BuildStepList *bc,
+ MaemoMountAndCopyDeployStep *other);
+
+ static const QString Id;
+ static const QString DisplayName;
+private:
+ virtual const AbstractMaemoPackageCreationStep *packagingStep() const { return 0; }
+ virtual bool isDeploymentPossibleInternal(QString &whynot) const;
+ virtual bool isDeploymentNeeded(const QString &hostName) const;
+
+ virtual QList<MaemoMountSpecification> mountSpecifications() const;
+ virtual void deploy();
+ virtual void cancelInstallation();
+ virtual void handleInstallationSuccess();
+
+ void ctor();
+ Q_SLOT void handleFileCopied(const MaemoDeployable &deployable);
+
+ MaemoRemoteCopyFacility *m_copyFacility;
+ mutable QList<MaemoDeployable> m_filesToCopy;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMODEPLOYBYMOUNTSTEP_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeployconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeployconfigurationwidget.cpp
new file mode 100644
index 0000000000..8da5f77150
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeployconfigurationwidget.cpp
@@ -0,0 +1,174 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+#include "maemodeployconfigurationwidget.h"
+#include "ui_maemodeployconfigurationwidget.h"
+
+#include "maemodeployablelistmodel.h"
+#include "maemodeployables.h"
+#include "qt4maemodeployconfiguration.h"
+
+#include <utils/qtcassert.h>
+
+#include <QtGui/QFileDialog>
+#include <QtGui/QMessageBox>
+#include <QtGui/QPixmap>
+
+using namespace ProjectExplorer;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+MaemoDeployConfigurationWidget::MaemoDeployConfigurationWidget(QWidget *parent)
+ : DeployConfigurationWidget(parent),
+ ui(new Ui::MaemoDeployConfigurationWidget)
+{
+ ui->setupUi(this);
+}
+
+MaemoDeployConfigurationWidget::~MaemoDeployConfigurationWidget()
+{
+ delete ui;
+}
+
+void MaemoDeployConfigurationWidget::init(DeployConfiguration *dc)
+{
+ m_deployConfig = qobject_cast<Qt4MaemoDeployConfiguration *>(dc);
+ Q_ASSERT(m_deployConfig);
+
+ ui->modelComboBox->setModel(m_deployConfig->deployables().data());
+ connect(m_deployConfig->deployables().data(), SIGNAL(modelAboutToBeReset()),
+ SLOT(handleModelListToBeReset()));
+
+ // Queued connection because of race condition with combo box's reaction
+ // to modelReset().
+ connect(m_deployConfig->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();
+}
+
+void MaemoDeployConfigurationWidget::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 MaemoDeployConfigurationWidget::handleModelListReset()
+{
+ QTC_ASSERT(m_deployConfig->deployables()->modelCount() == ui->modelComboBox->count(), return);
+ if (m_deployConfig->deployables()->modelCount() > 0) {
+ if (ui->modelComboBox->currentIndex() == -1)
+ ui->modelComboBox->setCurrentIndex(0);
+ else
+ setModel(ui->modelComboBox->currentIndex());
+ }
+}
+
+void MaemoDeployConfigurationWidget::setModel(int row)
+{
+ bool canAddDesktopFile = false;
+ bool canAddIconFile = false;
+ if (row != -1) {
+ MaemoDeployableListModel * const model
+ = m_deployConfig->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 MaemoDeployConfigurationWidget::addDesktopFile()
+{
+ const int modelRow = ui->modelComboBox->currentIndex();
+ if (modelRow == -1)
+ return;
+ MaemoDeployableListModel *const model
+ = m_deployConfig->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 MaemoDeployConfigurationWidget::addIcon()
+{
+ const int modelRow = ui->modelComboBox->currentIndex();
+ if (modelRow == -1)
+ return;
+
+ MaemoDeployableListModel *const model
+ = m_deployConfig->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
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeployconfigurationwidget.h b/src/plugins/qt4projectmanager/qt-maemo/maemodeployconfigurationwidget.h
new file mode 100644
index 0000000000..d0770f56da
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeployconfigurationwidget.h
@@ -0,0 +1,68 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+#ifndef MAEMODEPLOYCONFIGURATIONWIDGET_H
+#define MAEMODEPLOYCONFIGURATIONWIDGET_H
+
+#include <projectexplorer/deployconfiguration.h>
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class MaemoDeployConfigurationWidget;
+}
+QT_END_NAMESPACE
+
+namespace Qt4ProjectManager {
+namespace Internal {
+class Qt4MaemoDeployConfiguration;
+
+class MaemoDeployConfigurationWidget : public ProjectExplorer::DeployConfigurationWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MaemoDeployConfigurationWidget(QWidget *parent = 0);
+ ~MaemoDeployConfigurationWidget();
+
+ void init(ProjectExplorer::DeployConfiguration *dc);
+
+private:
+ Q_SLOT void handleModelListToBeReset();
+ Q_SLOT void handleModelListReset();
+ Q_SLOT void setModel(int row);
+ Q_SLOT void addDesktopFile();
+ Q_SLOT void addIcon();
+
+ Ui::MaemoDeployConfigurationWidget *ui;
+ Qt4MaemoDeployConfiguration * m_deployConfig;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMODEPLOYCONFIGURATIONWIDGET_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeployconfigurationwidget.ui b/src/plugins/qt4projectmanager/qt-maemo/maemodeployconfigurationwidget.ui
new file mode 100644
index 0000000000..48a9c43293
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeployconfigurationwidget.ui
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MaemoDeployConfigurationWidget</class>
+ <widget class="QWidget" name="MaemoDeployConfigurationWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>584</width>
+ <height>315</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLabel" name="installLabel">
+ <property name="toolTip">
+ <string>These show the INSTALLS settings from the project file(s).</string>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;Files to install for subproject:&lt;/b&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="modelComboBox">
+ <property name="sizeAdjustPolicy">
+ <enum>QComboBox::AdjustToContents</enum>
+ </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>
+ <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="toolTip">
+ <string>Edit the project file to add or remove entries.</string>
+ </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>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeploymentmounter.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeploymentmounter.cpp
new file mode 100644
index 0000000000..1c0616162f
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeploymentmounter.cpp
@@ -0,0 +1,204 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "maemodeploymentmounter.h"
+
+#include "maemoglobal.h"
+#include "maemoremotemounter.h"
+#include "maemousedportsgatherer.h"
+
+#include <qt4projectmanager/qt4buildconfiguration.h>
+#include <utils/ssh/sshconnection.h>
+
+#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(State, state, m_state)
+
+using namespace Utils;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+MaemoDeploymentMounter::MaemoDeploymentMounter(QObject *parent)
+ : QObject(parent),
+ m_state(Inactive),
+ m_mounter(new MaemoRemoteMounter(this)),
+ m_portsGatherer(new MaemoUsedPortsGatherer(this))
+{
+ connect(m_mounter, SIGNAL(error(QString)), SLOT(handleMountError(QString)));
+ connect(m_mounter, SIGNAL(mounted()), SLOT(handleMounted()));
+ connect(m_mounter, SIGNAL(unmounted()), SLOT(handleUnmounted()));
+ connect(m_mounter, SIGNAL(reportProgress(QString)),
+ SIGNAL(reportProgress(QString)));
+ connect(m_mounter, SIGNAL(debugOutput(QString)),
+ SIGNAL(debugOutput(QString)));
+
+ connect(m_portsGatherer, SIGNAL(error(QString)),
+ SLOT(handlePortsGathererError(QString)));
+ connect(m_portsGatherer, SIGNAL(portListReady()),
+ SLOT(handlePortListReady()));
+}
+
+void MaemoDeploymentMounter::setupMounts(const SshConnection::Ptr &connection,
+ const QList<MaemoMountSpecification> &mountSpecs,
+ const MaemoPortList &freePorts, const Qt4BuildConfiguration *bc)
+{
+ ASSERT_STATE(Inactive);
+
+ m_freePorts = freePorts;
+ m_mountSpecs = mountSpecs;
+ m_connection = connection;
+ m_mounter->setConnection(m_connection);
+ m_buildConfig = bc;
+ connect(m_connection.data(), SIGNAL(error(Utils::SshError)),
+ SLOT(handleConnectionError()));
+ setState(UnmountingOldDirs);
+ unmount();
+}
+
+void MaemoDeploymentMounter::tearDownMounts()
+{
+ ASSERT_STATE(Mounted);
+
+ setState(UnmountingCurrentMounts);
+ unmount();
+}
+
+void MaemoDeploymentMounter::setupMounter()
+{
+ ASSERT_STATE(UnmountingOldDirs);
+ setState(UnmountingCurrentDirs);
+
+ m_mounter->resetMountSpecifications();
+ m_mounter->setBuildConfiguration(m_buildConfig);
+ foreach (const MaemoMountSpecification &mountSpec, m_mountSpecs)
+ m_mounter->addMountSpecification(mountSpec, true);
+ unmount();
+}
+
+void MaemoDeploymentMounter::unmount()
+{
+ ASSERT_STATE(QList<State>() << UnmountingOldDirs << UnmountingCurrentDirs
+ << UnmountingCurrentMounts);
+
+ if (m_mounter->hasValidMountSpecifications())
+ m_mounter->unmount();
+ else
+ handleUnmounted();
+}
+
+void MaemoDeploymentMounter::handleMounted()
+{
+ ASSERT_STATE(QList<State>() << Mounting << Inactive);
+
+ if (m_state == Inactive)
+ return;
+
+ setState(Mounted);
+ emit setupDone();
+}
+
+void MaemoDeploymentMounter::handleUnmounted()
+{
+ ASSERT_STATE(QList<State>() << UnmountingOldDirs << UnmountingCurrentDirs
+ << UnmountingCurrentMounts << Inactive);
+
+ switch (m_state) {
+ case UnmountingOldDirs:
+ setupMounter();
+ break;
+ case UnmountingCurrentDirs:
+ setState(GatheringPorts);
+ m_portsGatherer->start(m_connection, m_freePorts);
+ break;
+ case UnmountingCurrentMounts:
+ setState(Inactive);
+ emit tearDownDone();
+ break;
+ case Inactive:
+ default:
+ break;
+ }
+}
+
+void MaemoDeploymentMounter::handlePortsGathererError(const QString &errorMsg)
+{
+ ASSERT_STATE(QList<State>() << GatheringPorts << Inactive);
+ if (m_state == Inactive)
+ return;
+
+ setState(Inactive);
+ m_mounter->resetMountSpecifications();
+ emit error(errorMsg);
+}
+
+void MaemoDeploymentMounter::handlePortListReady()
+{
+ ASSERT_STATE(QList<State>() << GatheringPorts << Inactive);
+ if (m_state == Inactive)
+ return;
+
+ setState(Mounting);
+ m_mounter->mount(&m_freePorts, m_portsGatherer);
+}
+
+void MaemoDeploymentMounter::handleMountError(const QString &errorMsg)
+{
+ ASSERT_STATE(QList<State>() << UnmountingOldDirs << UnmountingCurrentDirs
+ << UnmountingCurrentMounts << Mounting << Mounted << Inactive);
+ if (m_state == Inactive)
+ return;
+
+ setState(Inactive);
+ emit error(errorMsg);
+}
+
+void MaemoDeploymentMounter::handleConnectionError()
+{
+ if (m_state == Inactive)
+ return;
+
+ setState(Inactive);
+ emit error(tr("Connection failed: %1").arg(m_connection->errorString()));
+}
+
+void MaemoDeploymentMounter::setState(State newState)
+{
+ if (m_state == newState)
+ return;
+ if (newState == Inactive && m_connection) {
+ disconnect(m_connection.data(), 0, this, 0);
+ m_connection.clear();
+ }
+ m_state = newState;
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeploymentmounter.h b/src/plugins/qt4projectmanager/qt-maemo/maemodeploymentmounter.h
new file mode 100644
index 0000000000..0de6910507
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeploymentmounter.h
@@ -0,0 +1,100 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 MAEMODEPLOYMENTMOUNTER_H
+#define MAEMODEPLOYMENTMOUNTER_H
+
+#include "maemodeviceconfigurations.h"
+#include "maemomountspecification.h"
+
+#include <QtCore/QList>
+#include <QtCore/QObject>
+#include <QtCore/QSharedPointer>
+
+namespace Utils { class SshConnection; }
+
+namespace Qt4ProjectManager {
+class Qt4BuildConfiguration;
+namespace Internal {
+class MaemoRemoteMounter;
+class MaemoUsedPortsGatherer;
+
+class MaemoDeploymentMounter : public QObject
+{
+ Q_OBJECT
+public:
+ explicit MaemoDeploymentMounter(QObject *parent = 0);
+
+ // Connection must be in connected state.
+ void setupMounts(const QSharedPointer<Utils::SshConnection> &connection,
+ const QList<MaemoMountSpecification> &mountSpecs,
+ const MaemoPortList &freePorts, const Qt4BuildConfiguration *bc);
+ void tearDownMounts();
+
+signals:
+ void debugOutput(const QString &output);
+ void setupDone();
+ void tearDownDone();
+ void error(const QString &error);
+ void reportProgress(const QString &message);
+
+private slots:
+ void handleMounted();
+ void handleUnmounted();
+ void handleMountError(const QString &errorMsg);
+ void handlePortsGathererError(const QString &errorMsg);
+ void handlePortListReady();
+ void handleConnectionError();
+
+private:
+ enum State {
+ Inactive, UnmountingOldDirs, UnmountingCurrentDirs, GatheringPorts,
+ Mounting, Mounted, UnmountingCurrentMounts
+ };
+
+ void unmount();
+ void setupMounter();
+ void setState(State newState);
+
+ State m_state;
+ QSharedPointer<Utils::SshConnection> m_connection;
+ MaemoRemoteMounter * const m_mounter;
+ MaemoUsedPortsGatherer * const m_portsGatherer;
+ MaemoPortList m_freePorts;
+ QList<MaemoMountSpecification> m_mountSpecs;
+ const Qt4BuildConfiguration *m_buildConfig;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMODEPLOYMENTMOUNTER_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.cpp
deleted file mode 100644
index 7636a8837e..0000000000
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.cpp
+++ /dev/null
@@ -1,1061 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (info@qt.nokia.com)
-**
-**
-** GNU Lesser General Public License Usage
-**
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this file.
-** Please review the following information to ensure the GNU Lesser General
-** Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**************************************************************************/
-
-#include "maemodeploystep.h"
-
-#include "maemoconstants.h"
-#include "maemodeploystepwidget.h"
-#include "maemoglobal.h"
-#include "maemopackagecreationstep.h"
-#include "maemopertargetdeviceconfigurationlistmodel.h"
-#include "maemoqemumanager.h"
-#include "maemoremotemounter.h"
-#include "maemorunconfiguration.h"
-#include "maemotoolchain.h"
-#include "maemousedportsgatherer.h"
-#include "qt4maemotarget.h"
-
-#include <utils/ssh/sftpchannel.h>
-#include <utils/ssh/sshconnection.h>
-#include <utils/ssh/sshremoteprocess.h>
-
-#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/target.h>
-
-#include <qt4projectmanager/qt4buildconfiguration.h>
-#include <qt4projectmanager/qt4projectmanagerconstants.h>
-#include <qt4projectmanager/qt4target.h>
-
-#include <QtCore/QCoreApplication>
-#include <QtCore/QDir>
-#include <QtCore/QEventLoop>
-#include <QtCore/QFileInfo>
-#include <QtCore/QTimer>
-
-#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(State, state, m_state)
-
-using namespace Core;
-using namespace Utils;
-using namespace ProjectExplorer;
-
-namespace Qt4ProjectManager {
-namespace Internal {
-namespace { const int DefaultMountPort = 1050; }
-
-const QLatin1String MaemoDeployStep::Id("Qt4ProjectManager.MaemoDeployStep");
-
-MaemoDeployStep::MaemoDeployStep(ProjectExplorer::BuildStepList *parent)
- : BuildStep(parent, Id)
-{
- ctor();
-}
-
-MaemoDeployStep::MaemoDeployStep(ProjectExplorer::BuildStepList *parent,
- MaemoDeployStep *other)
- : BuildStep(parent, other), m_lastDeployed(other->m_lastDeployed)
-{
- ctor();
-}
-
-MaemoDeployStep::~MaemoDeployStep() { }
-
-void MaemoDeployStep::ctor()
-{
- //: MaemoDeployStep default display name
- if (target()->id() == QLatin1String(Constants::MAEMO5_DEVICE_TARGET_ID))
- setDefaultDisplayName(tr("Deploy to Maemo5 device"));
- else if (target()->id() == QLatin1String(Constants::HARMATTAN_DEVICE_TARGET_ID))
- setDefaultDisplayName(tr("Deploy to Harmattan device"));
- else if (target()->id() == QLatin1String(Constants::MEEGO_DEVICE_TARGET_ID))
- setDefaultDisplayName(tr("Deploy to Meego device"));
-
- // 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()) {
- const AbstractQt4MaemoTarget * const qt4Target = qobject_cast<AbstractQt4MaemoTarget *>(target());
- Q_ASSERT(qt4Target);
- m_deployables = QSharedPointer<MaemoDeployables>(new MaemoDeployables(qt4Target));
- } else {
- const MaemoDeployStep *const other
- = MaemoGlobal::buildStep<MaemoDeployStep>(deployConfigs.first());
- m_deployables = other->deployables();
- }
-
- m_state = Inactive;
- m_deviceConfig = maemotarget()->deviceConfigurationsModel()->defaultDeviceConfig();
- m_needsInstall = false;
- m_sysrootInstaller = new QProcess(this);
- connect(m_sysrootInstaller, SIGNAL(finished(int,QProcess::ExitStatus)),
- this, SLOT(handleSysrootInstallerFinished()));
- connect(m_sysrootInstaller, SIGNAL(readyReadStandardOutput()), this,
- SLOT(handleSysrootInstallerOutput()));
- connect(m_sysrootInstaller, SIGNAL(readyReadStandardError()), this,
- SLOT(handleSysrootInstallerErrorOutput()));
- m_mounter = new MaemoRemoteMounter(this);
- connect(m_mounter, SIGNAL(mounted()), this, SLOT(handleMounted()));
- connect(m_mounter, SIGNAL(unmounted()), this, SLOT(handleUnmounted()));
- connect(m_mounter, SIGNAL(error(QString)), this,
- SLOT(handleMountError(QString)));
- connect(m_mounter, SIGNAL(reportProgress(QString)), this,
- 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()));
- connect(maemotarget()->deviceConfigurationsModel(), SIGNAL(updated()),
- SLOT(handleDeviceConfigurationsUpdated()));
-}
-
-bool MaemoDeployStep::init()
-{
- return true;
-}
-
-void MaemoDeployStep::run(QFutureInterface<bool> &fi)
-{
- // Move to GUI thread for connection sharing with run control.
- QTimer::singleShot(0, this, SLOT(start()));
-
- MaemoDeployEventHandler eventHandler(this, fi);
-}
-
-BuildStepConfigWidget *MaemoDeployStep::createConfigWidget()
-{
- return new MaemoDeployStepWidget(this);
-}
-
-QVariantMap MaemoDeployStep::toMap() const
-{
- QVariantMap map(BuildStep::toMap());
- addDeployTimesToMap(map);
- map.insert(DeployToSysrootKey, m_deployToSysroot);
- map.insert(DeviceIdKey,
- MaemoDeviceConfigurations::instance()->internalId(m_deviceConfig));
- return map;
-}
-
-void MaemoDeployStep::addDeployTimesToMap(QVariantMap &map) const
-{
- QVariantList hostList;
- QVariantList fileList;
- QVariantList remotePathList;
- QVariantList timeList;
- typedef QHash<DeployablePerHost, QDateTime>::ConstIterator DepIt;
- for (DepIt it = m_lastDeployed.begin(); it != m_lastDeployed.end(); ++it) {
- fileList << it.key().first.localFilePath;
- remotePathList << it.key().first.remoteDir;
- hostList << it.key().second;
- timeList << it.value();
- }
- map.insert(LastDeployedHostsKey, hostList);
- map.insert(LastDeployedFilesKey, fileList);
- map.insert(LastDeployedRemotePathsKey, remotePathList);
- map.insert(LastDeployedTimesKey, timeList);
-}
-
-bool MaemoDeployStep::fromMap(const QVariantMap &map)
-{
- if (!BuildStep::fromMap(map))
- return false;
- getDeployTimesFromMap(map);
- setDeviceConfig(map.value(DeviceIdKey, MaemoDeviceConfig::InvalidId).toULongLong());
- m_deployToSysroot = map.value(DeployToSysrootKey, true).toBool();
- return true;
-}
-
-void MaemoDeployStep::getDeployTimesFromMap(const QVariantMap &map)
-{
- const QVariantList &hostList = map.value(LastDeployedHostsKey).toList();
- const QVariantList &fileList = map.value(LastDeployedFilesKey).toList();
- const QVariantList &remotePathList
- = map.value(LastDeployedRemotePathsKey).toList();
- const QVariantList &timeList = map.value(LastDeployedTimesKey).toList();
- const int elemCount
- = qMin(qMin(hostList.size(), fileList.size()),
- qMin(remotePathList.size(), timeList.size()));
- for (int i = 0; i < elemCount; ++i) {
- const MaemoDeployable d(fileList.at(i).toString(),
- remotePathList.at(i).toString());
- m_lastDeployed.insert(DeployablePerHost(d, hostList.at(i).toString()),
- timeList.at(i).toDateTime());
- }
-}
-
-const MaemoPackageCreationStep *MaemoDeployStep::packagingStep() const
-{
- const MaemoPackageCreationStep * const step
- = MaemoGlobal::buildStep<MaemoPackageCreationStep>(target()->activeDeployConfiguration());
- Q_ASSERT_X(step, Q_FUNC_INFO,
- "Impossible: Maemo build configuration without packaging step.");
- return step;
-}
-
-void MaemoDeployStep::raiseError(const QString &errorString)
-{
- emit addTask(Task(Task::Error, errorString, QString(), -1,
- ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
- m_hasError = true;
- emit error();
-}
-
-void MaemoDeployStep::writeOutput(const QString &text, OutputFormat format)
-{
- emit addOutput(text, format);
-}
-
-void MaemoDeployStep::stop()
-{
- if (m_state == StopRequested || m_state == Inactive)
- return;
-
- 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.");
- }
-}
-
-QString MaemoDeployStep::uploadDir() const
-{
- return MaemoGlobal::homeDirOnDevice(m_connection->connectionParameters().userName);
-}
-
-bool MaemoDeployStep::currentlyNeedsDeployment(const QString &host,
- const MaemoDeployable &deployable) const
-{
- const QDateTime &lastDeployed
- = m_lastDeployed.value(DeployablePerHost(deployable, host));
- return !lastDeployed.isValid()
- || QFileInfo(deployable.localFilePath).lastModified() > lastDeployed;
-}
-
-void MaemoDeployStep::setDeployed(const QString &host,
- const MaemoDeployable &deployable)
-{
- m_lastDeployed.insert(DeployablePerHost(deployable, host),
- QDateTime::currentDateTime());
-}
-
-void MaemoDeployStep::handleDeviceConfigurationsUpdated()
-{
- setDeviceConfig(MaemoDeviceConfigurations::instance()->internalId(m_deviceConfig));
-}
-
-void MaemoDeployStep::setDeviceConfig(MaemoDeviceConfig::Id internalId)
-{
- m_deviceConfig = maemotarget()->deviceConfigurationsModel()->find(internalId);
- emit deviceConfigChanged();
-}
-
-void MaemoDeployStep::setDeviceConfig(int i)
-{
- m_deviceConfig = maemotarget()->deviceConfigurationsModel()->deviceAt(i);
- emit deviceConfigChanged();
-}
-
-void MaemoDeployStep::start()
-{
- if (m_state != Inactive) {
- raiseError(tr("Cannot deploy: Still cleaning up from last time."));
- emit done();
- return;
- }
-
- m_cachedDeviceConfig = m_deviceConfig;
- if (!m_cachedDeviceConfig) {
- raiseError(tr("Deployment failed: No valid device set."));
- emit done();
- return;
- }
-
- Q_ASSERT(!m_currentDeviceDeployAction);
- Q_ASSERT(!m_needsInstall);
- Q_ASSERT(m_filesToCopy.isEmpty());
- m_installerStderr.clear();
- m_hasError = false;
- const MaemoPackageCreationStep * const pStep = packagingStep();
- const QString hostName = m_cachedDeviceConfig->sshParameters().host;
- if (pStep->isPackagingEnabled()) {
- const MaemoDeployable d(pStep->packageFilePath(), QString());
- if (currentlyNeedsDeployment(hostName, d))
- m_needsInstall = true;
- } else {
- const int deployableCount = m_deployables->deployableCount();
- for (int i = 0; i < deployableCount; ++i) {
- const MaemoDeployable &d = m_deployables->deployableAt(i);
- if (currentlyNeedsDeployment(hostName, d)
- || QFileInfo(d.localFilePath).isDir()) {
- m_filesToCopy << d;
- }
- }
- }
-
- if (m_needsInstall || !m_filesToCopy.isEmpty()) {
- if (m_cachedDeviceConfig->type() == MaemoDeviceConfig::Emulator
- && !MaemoQemuManager::instance().qemuIsRunning()) {
- MaemoQemuManager::instance().startRuntime();
- raiseError(tr("Deployment failed: Qemu was not running. "
- "It has now been started up for you, but it will take "
- "a bit of time until it is ready."));
- m_needsInstall = false;
- m_filesToCopy.clear();
- emit done();
- return;
- }
-
- if (m_deployToSysroot)
- installToSysroot();
- else
- connectToDevice();
- } else {
- writeOutput(tr("All files up to date, no installation necessary."));
- emit done();
- }
-}
-
-void MaemoDeployStep::handleConnectionFailure()
-{
- if (m_state == Inactive)
- return;
-
- const QString errorMsg = m_state == Connecting
- ? MaemoGlobal::failedToConnectToServerMessage(m_connection, m_cachedDeviceConfig)
- : tr("Connection error: %1").arg(m_connection->errorString());
- raiseError(errorMsg);
- setState(Inactive);
-}
-
-void MaemoDeployStep::handleSftpChannelInitialized()
-{
- 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;
- }
- case StopRequested:
- setState(Inactive);
- break;
- default:
- break;
- }
-}
-
-void MaemoDeployStep::handleSftpChannelInitializationFailed(const QString &error)
-{
- 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;
- }
-}
-
-void MaemoDeployStep::handleSftpJobFinished(Utils::SftpJobId,
- const QString &error)
-{
- 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));
- 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();
- runPackageInstaller(remoteFilePath);
- }
-}
-
-void MaemoDeployStep::handleSftpChannelClosed()
-{
- ASSERT_STATE(StopRequested);
- setState(Inactive);
-}
-
-void MaemoDeployStep::handleMounted()
-{
- ASSERT_STATE(QList<State>() << Mounting << StopRequested << Inactive);
-
- switch (m_state) {
- case Mounting:
- if (m_needsInstall) {
- const QString remoteFilePath = deployMountPoint() + QLatin1Char('/')
- + QFileInfo(packagingStep()->packageFilePath()).fileName();
- runPackageInstaller(remoteFilePath);
- } else {
- setState(CopyingFile);
- copyNextFileToDevice();
- }
- break;
- case StopRequested:
- unmount();
- break;
- case Inactive:
- default:
- break;
- }
-}
-
-void MaemoDeployStep::handleUnmounted()
-{
- ASSERT_STATE(QList<State>() << UnmountingOldDirs << UnmountingCurrentDirs
- << UnmountingCurrentMounts << StopRequested << Inactive);
-
- switch (m_state) {
- case StopRequested:
- m_mounter->resetMountSpecifications();
- setState(Inactive);
- break;
- case UnmountingOldDirs:
- if (maemotarget()->allowsRemoteMounts())
- setupMount();
- else
- prepareSftpConnection();
- break;
- case UnmountingCurrentDirs:
- setState(GatheringPorts);
- m_portsGatherer->start(m_connection, freePorts(m_cachedDeviceConfig));
- break;
- case UnmountingCurrentMounts:
- if (m_hasError)
- writeOutput(tr("Deployment failed."), ErrorMessageOutput);
- else
- writeOutput(tr("Deployment finished."));
- setState(Inactive);
- break;
- case Inactive:
- default:
- break;
- }
-}
-
-void MaemoDeployStep::handleMountError(const QString &errorMsg)
-{
- ASSERT_STATE(QList<State>() << UnmountingOldDirs << UnmountingCurrentDirs
- << UnmountingCurrentMounts << Mounting << StopRequested << Inactive);
-
- switch (m_state) {
- case UnmountingOldDirs:
- case UnmountingCurrentDirs:
- case UnmountingCurrentMounts:
- case Mounting:
- case StopRequested:
- raiseError(errorMsg);
- setState(Inactive);
- break;
- case Inactive:
- default:
- break;
- }
-}
-
-void MaemoDeployStep::handleMountDebugOutput(const QString &output)
-{
- ASSERT_STATE(QList<State>() << UnmountingOldDirs << UnmountingCurrentDirs
- << UnmountingCurrentMounts << Mounting << StopRequested << Inactive);
-
- switch (m_state) {
- case UnmountingOldDirs:
- case UnmountingCurrentDirs:
- case UnmountingCurrentMounts:
- case Mounting:
- 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->setBuildConfiguration(qt4BuildConfiguration());
- if (m_needsInstall) {
- const QString localDir
- = QFileInfo(packagingStep()->packageFilePath()).absolutePath();
- const MaemoMountSpecification mountSpec(localDir, deployMountPoint());
- m_mounter->addMountSpecification(mountSpec, true);
- } else {
-#ifdef Q_OS_WIN
- bool drivesToMount[26];
- qFill(drivesToMount, drivesToMount + sizeof drivesToMount / sizeof drivesToMount[0], false);
- for (int i = 0; i < m_filesToCopy.count(); ++i) {
- const QString localDir
- = QFileInfo(m_filesToCopy.at(i).localFilePath).canonicalPath();
- const char driveLetter = localDir.at(0).toLower().toLatin1();
- if (driveLetter < 'a' || driveLetter > 'z') {
- qWarning("Weird: drive letter is '%c'.", driveLetter);
- continue;
- }
-
- const int index = driveLetter - 'a';
- if (drivesToMount[index])
- continue;
-
- const QString mountPoint = deployMountPoint() + QLatin1Char('/')
- + QLatin1Char(driveLetter);
- const MaemoMountSpecification mountSpec(localDir.left(3),
- mountPoint);
- m_mounter->addMountSpecification(mountSpec, true);
- drivesToMount[index] = true;
- }
-#else
- m_mounter->addMountSpecification(MaemoMountSpecification(QLatin1String("/"),
- deployMountPoint()), true);
-#endif
- }
- unmount();
-}
-
-void MaemoDeployStep::prepareSftpConnection()
-{
- setState(InitializingSftp);
- m_uploader = m_connection->createSftpChannel();
- connect(m_uploader.data(), SIGNAL(initialized()), this,
- SLOT(handleSftpChannelInitialized()));
- connect(m_uploader.data(), SIGNAL(initializationFailed(QString)), this,
- SLOT(handleSftpChannelInitializationFailed(QString)));
- connect(m_uploader.data(), SIGNAL(finished(Utils::SftpJobId, QString)),
- this, SLOT(handleSftpJobFinished(Utils::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 QtVersion * const qtVersion = qt4BuildConfiguration()->qtVersion();
- const QString command = QLatin1String(
- packagingStep()->debBasedMaemoTarget() ? "xdpkg" : "xrpm");
- QStringList args = QStringList() << command << QLatin1String("-i");
-
- // Cannot use it, because we have an outdated MADDE version in the SDK.
-// if (packagingStep()->debBasedMaemoTarget())
-// args << QLatin1String("--no-force-downgrade");
-
- args << packagingStep()->packageFilePath();
- MaemoGlobal::callMadAdmin(*m_sysrootInstaller, args, qtVersion, true);
- if (!m_sysrootInstaller->waitForStarted()) {
- writeOutput(tr("Installation to sysroot failed, continuing anyway."),
- ErrorMessageOutput);
- connectToDevice();
- }
- } else {
- writeOutput(tr("Copying files to sysroot ..."));
- Q_ASSERT(!m_filesToCopy.isEmpty());
- QDir sysRootDir(toolChain()->sysroot());
- foreach (const MaemoDeployable &d, m_filesToCopy) {
- const QLatin1Char sep('/');
- const QString targetFilePath = toolChain()->sysroot() + sep
- + d.remoteDir + sep + QFileInfo(d.localFilePath).fileName();
- sysRootDir.mkpath(d.remoteDir.mid(1));
- QFile::remove(targetFilePath);
- QString dummy;
- MaemoGlobal::removeRecursively(targetFilePath, dummy);
- if (!MaemoGlobal::copyRecursively(d.localFilePath, targetFilePath)) {
- writeOutput(tr("Sysroot installation failed: "
- "Could not copy '%1' to '%2'. Continuing anyway.")
- .arg(QDir::toNativeSeparators(d.localFilePath),
- QDir::toNativeSeparators(targetFilePath)),
- ErrorMessageOutput);
- }
- QCoreApplication::processEvents();
- if (m_state == StopRequested) {
- setState(Inactive);
- return;
- }
- }
- connectToDevice();
- }
-}
-
-void MaemoDeployStep::handleSysrootInstallerFinished()
-{
- ASSERT_STATE(QList<State>() << InstallingToSysroot << StopRequested);
-
- if (m_state == StopRequested) {
- setState(Inactive);
- return;
- }
-
- if (m_sysrootInstaller->error() != QProcess::UnknownError
- || m_sysrootInstaller->exitCode() != 0) {
- writeOutput(tr("Installation to sysroot failed, continuing anyway."),
- ErrorMessageOutput);
- }
- connectToDevice();
-}
-
-void MaemoDeployStep::connectToDevice()
-{
- ASSERT_STATE(QList<State>() << Inactive << InstallingToSysroot);
- setState(Connecting);
-
- const bool canReUse = m_connection
- && m_connection->state() == SshConnection::Connected
- && m_connection->connectionParameters() == m_cachedDeviceConfig->sshParameters();
- if (!canReUse)
- m_connection = SshConnection::create();
- connect(m_connection.data(), SIGNAL(connected()), this,
- SLOT(handleConnected()));
- connect(m_connection.data(), SIGNAL(error(Utils::SshError)), this,
- SLOT(handleConnectionFailure()));
- if (canReUse) {
- handleConnected();
- } else {
- writeOutput(tr("Connecting to device..."));
- m_connection->connectToHost(m_cachedDeviceConfig->sshParameters());
- }
-}
-
-void MaemoDeployStep::handleConnected()
-{
- ASSERT_STATE(QList<State>() << Connecting << StopRequested);
-
- if (m_state == Connecting)
- unmountOldDirs();
-}
-
-void MaemoDeployStep::unmountOldDirs()
-{
- setState(UnmountingOldDirs);
- m_mounter->setConnection(m_connection);
- unmount();
-}
-
-void MaemoDeployStep::runPackageInstaller(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 installCommand = packagingStep()->debBasedMaemoTarget()
- ? "dpkg -i --no-force-downgrade"
- : "rpm -U --replacepkgs --replacefiles";
- QByteArray cmd = MaemoGlobal::remoteSudo().toUtf8() + ' '
- + installCommand + ' ' + 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)));
- connect(m_deviceInstaller.data(), SIGNAL(outputAvailable(QByteArray)),
- this, SLOT(handleDeviceInstallerOutput(QByteArray)));
- connect(m_deviceInstaller.data(),
- SIGNAL(errorOutputAvailable(QByteArray)), this,
- SLOT(handleDeviceInstallerErrorOutput(QByteArray)));
- m_deviceInstaller->start();
-}
-
-void MaemoDeployStep::handleProgressReport(const QString &progressMsg)
-{
- ASSERT_STATE(QList<State>() << UnmountingOldDirs << UnmountingCurrentDirs
- << UnmountingCurrentMounts << Mounting << StopRequested << Inactive);
-
- switch (m_state) {
- case UnmountingOldDirs:
- case UnmountingCurrentDirs:
- case UnmountingCurrentMounts:
- case Mounting:
- 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();
- QString sourceFilePath = deployMountPoint();
-#ifdef Q_OS_WIN
- const QString localFilePath = QDir::fromNativeSeparators(d.localFilePath);
- sourceFilePath += QLatin1Char('/') + localFilePath.at(0).toLower()
- + localFilePath.mid(2);
-#else
- sourceFilePath += d.localFilePath;
-#endif
-
- QString command = QString::fromLatin1("%1 mkdir -p %3 && %1 cp -r %2 %3")
- .arg(MaemoGlobal::remoteSudo(), sourceFilePath, d.remoteDir);
- SshRemoteProcess::Ptr copyProcess
- = m_connection->createRemoteProcess(command.toUtf8());
- connect(copyProcess.data(), SIGNAL(errorOutputAvailable(QByteArray)),
- this, SLOT(handleDeviceInstallerErrorOutput(QByteArray)));
- connect(copyProcess.data(), SIGNAL(closed(int)), this,
- SLOT(handleCopyProcessFinished(int)));
- m_currentDeviceDeployAction.reset(new DeviceDeployAction(d, copyProcess));
- writeOutput(tr("Copying file '%1' to path '%2' on the device...")
- .arg(d.localFilePath, d.remoteDir));
- copyProcess->start();
-}
-
-void MaemoDeployStep::handleCopyProcessFinished(int exitStatus)
-{
- ASSERT_STATE(QList<State>() << CopyingFile << StopRequested << Inactive);
-
- 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 {
- 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(m_cachedDeviceConfig->sshParameters().userName)
- + QLatin1String("/deployMountPoint_") + packagingStep()->projectName();
-}
-
-const MaemoToolChain *MaemoDeployStep::toolChain() const
-{
- return static_cast<MaemoToolChain *>(qt4BuildConfiguration()->toolChain());
-}
-
-const AbstractQt4MaemoTarget *MaemoDeployStep::maemotarget() const
-{
- return static_cast<AbstractQt4MaemoTarget *>(qt4BuildConfiguration()->target());
-}
-
-void MaemoDeployStep::handleSysrootInstallerOutput()
-{
- 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()
-{
- 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)
-{
- 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 if (m_installerStderr.contains("Will not downgrade")) {
- raiseError(tr("Installation failed: "
- "You tried to downgrade a package, which is not allowed."));
- } 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);
- }
-}
-
-void MaemoDeployStep::handlePortListReady()
-{
- ASSERT_STATE(QList<State>() << GatheringPorts << StopRequested);
-
- if (m_state == GatheringPorts) {
- setState(Mounting);
- m_freePorts = freePorts(m_cachedDeviceConfig);
- 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;
- 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);
- m_cachedDeviceConfig.clear();
- emit done();
- }
-}
-
-void MaemoDeployStep::unmount()
-{
- if (m_mounter->hasValidMountSpecifications())
- m_mounter->unmount();
- else
- handleUnmounted();
-}
-
-void MaemoDeployStep::handleDeviceInstallerOutput(const QByteArray &output)
-{
- 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)
-{
- ASSERT_STATE(QList<State>() << InstallingToDevice << CopyingFile
- << StopRequested);
-
- switch (m_state) {
- case InstallingToDevice:
- case CopyingFile:
- case StopRequested:
- m_installerStderr += output;
- writeOutput(QString::fromUtf8(output), ErrorOutput);
- break;
- default:
- break;
- }
-}
-
-MaemoPortList MaemoDeployStep::freePorts() const
-{
- return freePorts(m_deviceConfig);
-}
-
-MaemoPortList MaemoDeployStep::freePorts(const MaemoDeviceConfig::ConstPtr &devConf) const
-{
- const Qt4BuildConfiguration * const qt4bc = qt4BuildConfiguration();
- if (!devConf)
- return MaemoPortList();
- if (devConf->type() == MaemoDeviceConfig::Emulator && qt4bc) {
- MaemoQemuRuntime rt;
- const int id = qt4bc->qtVersion()->uniqueId();
- if (MaemoQemuManager::instance().runtimeForQtVersion(id, &rt))
- return rt.m_freePorts;
- }
- return devConf->freePorts();
-}
-
-const Qt4BuildConfiguration *MaemoDeployStep::qt4BuildConfiguration() const
-{
- return static_cast<Qt4BuildConfiguration *>(buildConfiguration());
-}
-
-
-MaemoDeployEventHandler::MaemoDeployEventHandler(MaemoDeployStep *deployStep,
- QFutureInterface<bool> &future)
- : 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()));
- QTimer cancelChecker;
- connect(&cancelChecker, SIGNAL(timeout()), this, SLOT(checkForCanceled()));
- cancelChecker.start(500);
- future.reportResult(m_eventLoop->exec() == 0);
-}
-
-void MaemoDeployEventHandler::handleDeployingDone()
-{
- m_eventLoop->exit(m_error ? 1 : 0);
-}
-
-void MaemoDeployEventHandler::handleDeployingFailed()
-{
- m_error = true;
-}
-
-void MaemoDeployEventHandler::checkForCanceled()
-{
- if (!m_error && m_future.isCanceled()) {
- QMetaObject::invokeMethod(m_deployStep, "stop");
- m_error = true;
- handleDeployingDone();
- }
-}
-
-} // namespace Internal
-} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.h b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.h
index 06815c61a6..9bccdc39bc 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.h
@@ -36,9 +36,7 @@
#include "maemodeployable.h"
#include "maemodeployables.h"
#include "maemodeviceconfigurations.h"
-#include "maemomountspecification.h"
-#include <utils/ssh/sftpdefs.h>
#include <projectexplorer/buildstep.h>
#include <QtCore/QHash>
@@ -49,24 +47,23 @@
QT_BEGIN_NAMESPACE
class QEventLoop;
-class QProcess;
-class QTimer;
QT_END_NAMESPACE
namespace Utils {
-class SftpChannel;
class SshConnection;
-class SshRemoteProcess;
}
namespace Qt4ProjectManager {
class Qt4BuildConfiguration;
namespace Internal {
-class MaemoRemoteMounter;
+class AbstractMaemoPackageCreationStep;
+class AbstractMaemoPackageInstaller;
+class MaemoDeploymentMounter;
class MaemoDeviceConfig;
-class MaemoPackageCreationStep;
+class MaemoPackageUploader;
+class MaemoRemoteCopyFacility;
class MaemoToolChain;
-class MaemoUsedPortsGatherer;
+class Qt4MaemoDeployConfiguration;
class MaemoDeployStep : public ProjectExplorer::BuildStep
{
@@ -82,12 +79,8 @@ public:
bool currentlyNeedsDeployment(const QString &host,
const MaemoDeployable &deployable) const;
void setDeployed(const QString &host, const MaemoDeployable &deployable);
- QSharedPointer<MaemoDeployables> deployables() const { return m_deployables; }
- QSharedPointer<Utils::SshConnection> sshConnection() const { return m_connection; }
MaemoPortList freePorts() const;
-
- bool isDeployToSysrootEnabled() const { return m_deployToSysroot; }
- void setDeployToSysrootEnabled(bool deploy) { m_deployToSysroot = deploy; }
+ Qt4MaemoDeployConfiguration *maemoDeployConfig() const;
Q_INVOKABLE void stop();
@@ -105,27 +98,18 @@ private slots:
void handleMountError(const QString &errorMsg);
void handleMountDebugOutput(const QString &output);
void handleProgressReport(const QString &progressMsg);
- void handleCopyProcessFinished(int exitStatus);
- void handleSysrootInstallerFinished();
- void handleSysrootInstallerOutput();
- void handleSysrootInstallerErrorOutput();
- void handleSftpChannelInitialized();
- void handleSftpChannelInitializationFailed(const QString &error);
- void handleSftpJobFinished(Utils::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();
+ void handleUploadFinished(const QString &errorMsg);
+ void handleInstallationFinished(const QString &errorMsg);
+ void handleFileCopied(const MaemoDeployable &deployable);
+ void handleCopyingFinished(const QString &errorMsg);
+ void handleRemoteStdout(const QString &output);
+ void handleRemoteStderr(const QString &output);
void handleDeviceConfigurationsUpdated();
private:
enum State {
- Inactive, StopRequested, InstallingToSysroot, Connecting,
- UnmountingOldDirs, UnmountingCurrentDirs, GatheringPorts, Mounting,
- InstallingToDevice, UnmountingCurrentMounts, CopyingFile,
- InitializingSftp, Uploading
+ Inactive, StopRequested, Connecting, Uploading, Mounting, Installing,
+ Copying, Unmounting
};
MaemoDeployStep(ProjectExplorer::BuildStepList *bc,
@@ -133,7 +117,6 @@ private:
virtual bool init();
virtual void run(QFutureInterface<bool> &fi);
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
- virtual bool immutable() const { return true; }
virtual QVariantMap toMap() const;
virtual bool fromMap(const QVariantMap &map);
@@ -142,44 +125,34 @@ private:
void writeOutput(const QString &text, OutputFormat = MessageOutput);
void addDeployTimesToMap(QVariantMap &map) const;
void getDeployTimesFromMap(const QVariantMap &map);
- const MaemoPackageCreationStep *packagingStep() const;
+ const AbstractMaemoPackageCreationStep *packagingStep() const;
QString deployMountPoint() const;
const MaemoToolChain *toolChain() const;
- void copyNextFileToDevice();
- void installToSysroot();
QString uploadDir() const;
void connectToDevice();
- void unmountOldDirs();
- void setupMount();
- void prepareSftpConnection();
+ void upload();
void runPackageInstaller(const QString &packageFilePath);
+ void mount();
+ void setDeploymentFinished();
void setState(State newState);
- void unmount();
void setDeviceConfig(MaemoDeviceConfig::Id internalId);
const Qt4BuildConfiguration *qt4BuildConfiguration() const;
MaemoPortList freePorts(const QSharedPointer<const MaemoDeviceConfig> &devConfig) const;
static const QLatin1String Id;
- QSharedPointer<MaemoDeployables> m_deployables;
QSharedPointer<Utils::SshConnection> m_connection;
- QProcess *m_sysrootInstaller;
- typedef QPair<MaemoDeployable, QSharedPointer<Utils::SshRemoteProcess> > DeviceDeployAction;
- QScopedPointer<DeviceDeployAction> m_currentDeviceDeployAction;
QList<MaemoDeployable> m_filesToCopy;
- MaemoRemoteMounter *m_mounter;
- bool m_deployToSysroot;
- QSharedPointer<Utils::SftpChannel> m_uploader;
- QSharedPointer<Utils::SshRemoteProcess> m_deviceInstaller;
+ MaemoDeploymentMounter *m_mounter;
+ MaemoPackageUploader *m_uploader;
+ AbstractMaemoPackageInstaller *m_installer;
+ MaemoRemoteCopyFacility *m_copyFacility;
bool m_needsInstall;
typedef QPair<MaemoDeployable, QString> DeployablePerHost;
QHash<DeployablePerHost, QDateTime> m_lastDeployed;
QSharedPointer<const MaemoDeviceConfig> m_deviceConfig;
QSharedPointer<const MaemoDeviceConfig> m_cachedDeviceConfig;
- MaemoUsedPortsGatherer *m_portsGatherer;
- MaemoPortList m_freePorts;
- QByteArray m_installerStderr;
State m_state;
bool m_hasError;
};
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepfactory.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepfactory.cpp
index 9a0257c4db..70a7751e4d 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepfactory.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepfactory.cpp
@@ -32,8 +32,13 @@
#include "maemodeploystepfactory.h"
-#include "maemodeploystep.h"
+#include "maemodeploybymountstep.h"
+#include "maemodirectdeviceuploadstep.h"
#include "maemoglobal.h"
+#include "maemoinstalltosysrootstep.h"
+#include "maemouploadandinstalldeploystep.h"
+#include "qt4maemodeployconfiguration.h"
+#include "qt4maemotarget.h"
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildsteplist.h>
@@ -47,6 +52,9 @@ using namespace ProjectExplorer;
namespace Qt4ProjectManager {
namespace Internal {
+namespace {
+const QString OldMaemoDeployStepId(QLatin1String("Qt4ProjectManager.MaemoDeployStep"));
+} // anonymous namespace
MaemoDeployStepFactory::MaemoDeployStepFactory(QObject *parent)
: IBuildStepFactory(parent)
@@ -55,44 +63,97 @@ MaemoDeployStepFactory::MaemoDeployStepFactory(QObject *parent)
QStringList MaemoDeployStepFactory::availableCreationIds(BuildStepList *parent) const
{
- if (parent->id() == QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY)
- && MaemoGlobal::isMaemoTargetId(parent->target()->id())
- && !parent->contains(MaemoDeployStep::Id))
- return QStringList() << MaemoDeployStep::Id;
- return QStringList();
+ if (!qobject_cast<Qt4MaemoDeployConfiguration *>(parent->parent()))
+ return QStringList();
+
+ QStringList ids;
+ if (qobject_cast<AbstractQt4MaemoTarget *>(parent->target()))
+ ids << MaemoCopyToSysrootStep::Id;
+ if (!qobject_cast<Qt4HarmattanTarget *>(parent->target()))
+ ids << MaemoUploadAndInstallTarPackageStep::Id;
+ if (qobject_cast<AbstractDebBasedQt4MaemoTarget *>(parent->target())) {
+ ids << MaemoInstallDebianPackageToSysrootStep::Id;
+ ids << MaemoUploadAndInstallDpkgPackageStep::Id;
+ } else if (qobject_cast<AbstractRpmBasedQt4MaemoTarget *>(parent->target())) {
+ ids << MaemoInstallRpmPackageToSysrootStep::Id;
+ ids << MaemoUploadAndInstallRpmPackageStep::Id;
+ }
+ if (qobject_cast<Qt4Maemo5Target *>(parent->target())) {
+ ids << MaemoMountAndInstallDeployStep::Id
+ << MaemoMountAndCopyDeployStep::Id;
+ }
+
+ return ids;
}
QString MaemoDeployStepFactory::displayNameForId(const QString &id) const
{
- if (id == MaemoDeployStep::Id)
- return QCoreApplication::translate("Qt4ProjectManager::Internal::MaemoDeployStepFactory",
- "Deploy to device");
+ if (id == MaemoMountAndInstallDeployStep::Id)
+ return MaemoMountAndInstallDeployStep::DisplayName;
+ else if (id == MaemoMountAndCopyDeployStep::Id)
+ return MaemoMountAndCopyDeployStep::DisplayName;
+ else if (id == MaemoUploadAndInstallDpkgPackageStep::Id)
+ return MaemoUploadAndInstallDpkgPackageStep::DisplayName;
+ else if (id == MaemoUploadAndInstallRpmPackageStep::Id)
+ return MaemoUploadAndInstallRpmPackageStep::DisplayName;
+ else if (id == MaemoUploadAndInstallTarPackageStep::Id)
+ return MaemoUploadAndInstallTarPackageStep::DisplayName;
+ else if (id == MaemoInstallDebianPackageToSysrootStep::Id)
+ return MaemoInstallDebianPackageToSysrootStep::DisplayName;
+ else if (id == MaemoInstallRpmPackageToSysrootStep::Id)
+ return MaemoInstallRpmPackageToSysrootStep::DisplayName;
+ else if (id == MaemoCopyToSysrootStep::Id)
+ return MaemoCopyToSysrootStep::DisplayName;
+ else if (id == MaemoDirectDeviceUploadStep::Id)
+ return MaemoDirectDeviceUploadStep::DisplayName;
return QString();
}
bool MaemoDeployStepFactory::canCreate(BuildStepList *parent, const QString &id) const
{
- return parent->id() == QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY)
- && id == QLatin1String(MaemoDeployStep::Id)
- && MaemoGlobal::isMaemoTargetId(parent->target()->id())
- && !parent->contains(MaemoDeployStep::Id);
+ return availableCreationIds(parent).contains(id) && !parent->contains(id);
}
BuildStep *MaemoDeployStepFactory::create(BuildStepList *parent, const QString &id)
{
- Q_ASSERT(canCreate(parent, id));
- return new MaemoDeployStep(parent);
+ const Target * const t = parent->target();
+
+ if (id == MaemoInstallDebianPackageToSysrootStep::Id) {
+ return new MaemoInstallDebianPackageToSysrootStep(parent);
+ } else if (id == MaemoInstallRpmPackageToSysrootStep::Id) {
+ return new MaemoInstallRpmPackageToSysrootStep(parent);
+ } else if (id == MaemoCopyToSysrootStep::Id) {
+ return new MaemoCopyToSysrootStep(parent);
+ } else if (id == MaemoMountAndInstallDeployStep::Id
+ || (id == OldMaemoDeployStepId && qobject_cast< const Qt4Maemo5Target *>(t))) {
+ return new MaemoMountAndInstallDeployStep(parent);
+ } else if (id == MaemoMountAndCopyDeployStep::Id) {
+ return new MaemoMountAndCopyDeployStep(parent);
+ } else if (id == MaemoUploadAndInstallDpkgPackageStep::Id
+ || (id == OldMaemoDeployStepId && (qobject_cast<const Qt4HarmattanTarget *>(t)))) {
+ return new MaemoUploadAndInstallDpkgPackageStep(parent);
+ } else if (id == MaemoUploadAndInstallRpmPackageStep::Id
+ || (id == OldMaemoDeployStepId && (qobject_cast<const Qt4MeegoTarget *>(t)))) {
+ return new MaemoUploadAndInstallRpmPackageStep(parent);
+ } else if (id == MaemoUploadAndInstallTarPackageStep::Id) {
+ return new MaemoUploadAndInstallTarPackageStep(parent);
+ } else if (id == MaemoDirectDeviceUploadStep::Id) {
+ return new MaemoDirectDeviceUploadStep(parent);
+ }
+
+ return 0;
}
bool MaemoDeployStepFactory::canRestore(BuildStepList *parent, const QVariantMap &map) const
{
- return canCreate(parent, idFromMap(map));
+ return canCreate(parent, idFromMap(map))
+ || idFromMap(map) == OldMaemoDeployStepId;
}
BuildStep *MaemoDeployStepFactory::restore(BuildStepList *parent, const QVariantMap &map)
{
Q_ASSERT(canRestore(parent, map));
- MaemoDeployStep * const step = new MaemoDeployStep(parent);
+ BuildStep * const step = create(parent, idFromMap(map));
if (!step->fromMap(map)) {
delete step;
return 0;
@@ -108,7 +169,35 @@ bool MaemoDeployStepFactory::canClone(BuildStepList *parent, BuildStep *product)
BuildStep *MaemoDeployStepFactory::clone(BuildStepList *parent, BuildStep *product)
{
Q_ASSERT(canClone(parent, product));
- return new MaemoDeployStep(parent, static_cast<MaemoDeployStep*>(product));
+ if (product->id() == MaemoMountAndInstallDeployStep::Id) {
+ return new MaemoMountAndInstallDeployStep(parent,
+ qobject_cast<MaemoMountAndInstallDeployStep *>(product));
+ } else if (product->id() == MaemoMountAndCopyDeployStep::Id) {
+ return new MaemoMountAndCopyDeployStep(parent,
+ qobject_cast<MaemoMountAndCopyDeployStep *>(product));
+ } else if (product->id() == MaemoUploadAndInstallDpkgPackageStep::Id) {
+ return new MaemoUploadAndInstallDpkgPackageStep(parent,
+ qobject_cast<MaemoUploadAndInstallDpkgPackageStep*>(product));
+ } else if (product->id() == MaemoUploadAndInstallRpmPackageStep::Id) {
+ return new MaemoUploadAndInstallRpmPackageStep(parent,
+ qobject_cast<MaemoUploadAndInstallRpmPackageStep*>(product));
+ } else if (product->id() == MaemoUploadAndInstallTarPackageStep::Id) {
+ return new MaemoUploadAndInstallTarPackageStep(parent,
+ qobject_cast<MaemoUploadAndInstallTarPackageStep*>(product));
+ } else if (product->id() == MaemoInstallDebianPackageToSysrootStep::Id) {
+ return new MaemoInstallDebianPackageToSysrootStep(parent,
+ qobject_cast<MaemoInstallDebianPackageToSysrootStep *>(product));
+ } else if (product->id() == MaemoInstallRpmPackageToSysrootStep::Id) {
+ return new MaemoInstallRpmPackageToSysrootStep(parent,
+ qobject_cast<MaemoInstallRpmPackageToSysrootStep *>(product));
+ } else if (product->id() == MaemoCopyToSysrootStep::Id) {
+ return new MaemoCopyToSysrootStep(parent,
+ qobject_cast<MaemoCopyToSysrootStep *>(product));
+ } else if (product->id() == MaemoDirectDeviceUploadStep::Id) {
+ return new MaemoDirectDeviceUploadStep(parent,
+ qobject_cast<MaemoDirectDeviceUploadStep *>(product));
+ }
+ return 0;
}
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.cpp
index 5a789cc878..afca943d8b 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.cpp
@@ -33,15 +33,14 @@
#include "maemodeploystepwidget.h"
#include "ui_maemodeploystepwidget.h"
-#include "maemodeploystep.h"
-#include "maemodeployablelistmodel.h"
-#include "maemodeployables.h"
+#include "abstractmaemodeploystep.h"
#include "maemodeviceconfigurations.h"
#include "maemosettingspages.h"
#include "maemoglobal.h"
#include "maemomanager.h"
#include "maemopertargetdeviceconfigurationlistmodel.h"
#include "maemorunconfiguration.h"
+#include "qt4maemodeployconfiguration.h"
#include "qt4maemotarget.h"
#include <coreplugin/icore.h>
@@ -49,35 +48,22 @@
#include <projectexplorer/target.h>
#include <utils/qtcassert.h>
-#include <QtGui/QFileDialog>
-#include <QtGui/QMessageBox>
-#include <QtGui/QPixmap>
-
namespace Qt4ProjectManager {
namespace Internal {
-MaemoDeployStepWidget::MaemoDeployStepWidget(MaemoDeployStep *step) :
+MaemoDeployStepWidget::MaemoDeployStepWidget(AbstractMaemoDeployStep *step) :
ProjectExplorer::BuildStepConfigWidget(),
ui(new Ui::MaemoDeployStepWidget),
m_step(step)
{
ui->setupUi(this);
- 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().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();
-
+ ProjectExplorer::BuildStepList * const list
+ = qobject_cast<ProjectExplorer::BuildStepList *>(step->parent());
+ connect(list, SIGNAL(stepInserted(int)), SIGNAL(updateSummary()));
+ connect(list, SIGNAL(stepMoved(int,int)), SIGNAL(updateSummary()));
+ connect(list, SIGNAL(stepRemoved(int)), SIGNAL(updateSummary()));
+ connect(list, SIGNAL(aboutToRemoveStep(int)),
+ SLOT(handleStepToBeRemoved(int)));
}
MaemoDeployStepWidget::~MaemoDeployStepWidget()
@@ -87,14 +73,11 @@ MaemoDeployStepWidget::~MaemoDeployStepWidget()
void MaemoDeployStepWidget::init()
{
- ui->deviceConfigComboBox->setModel(m_step->maemotarget()->deviceConfigurationsModel());
+ ui->deviceConfigComboBox->setModel(m_step->maemoDeployConfig()->deviceConfigModel());
connect(m_step, SIGNAL(deviceConfigChanged()), SLOT(handleDeviceUpdate()));
handleDeviceUpdate();
connect(ui->deviceConfigComboBox, SIGNAL(activated(int)), this,
SLOT(setCurrentDeviceConfig(int)));
- ui->deployToSysrootCheckBox->setChecked(m_step->isDeployToSysrootEnabled());
- connect(ui->deployToSysrootCheckBox, SIGNAL(toggled(bool)), this,
- SLOT(setDeployToSysroot(bool)));
connect(ui->manageDevConfsLabel, SIGNAL(linkActivated(QString)),
SLOT(showDeviceConfigurations()));
}
@@ -104,14 +87,28 @@ void MaemoDeployStepWidget::handleDeviceUpdate()
const MaemoDeviceConfig::ConstPtr &devConf = m_step->deviceConfig();
const MaemoDeviceConfig::Id internalId
= MaemoDeviceConfigurations::instance()->internalId(devConf);
- const int newIndex = m_step->maemotarget()->deviceConfigurationsModel()
+ const int newIndex = m_step->maemoDeployConfig()->deviceConfigModel()
->indexForInternalId(internalId);
ui->deviceConfigComboBox->setCurrentIndex(newIndex);
emit updateSummary();
}
+void MaemoDeployStepWidget::handleStepToBeRemoved(int step)
+{
+ ProjectExplorer::BuildStepList * const list
+ = qobject_cast<ProjectExplorer::BuildStepList *>(m_step->parent());
+ if (list->steps().at(step) == m_step)
+ disconnect(list, 0, this, 0);
+}
+
QString MaemoDeployStepWidget::summaryText() const
{
+ QString error;
+ if (!m_step->isDeploymentPossible(error)) {
+ return QLatin1String("<font color=\"red\">")
+ + tr("Cannot deploy: %1").arg(error)
+ + QLatin1String("</font>");
+ }
return tr("<b>Deploy to device</b>: %1")
.arg(MaemoGlobal::deviceConfigurationName(m_step->deviceConfig()));
}
@@ -130,103 +127,6 @@ void MaemoDeployStepWidget::setCurrentDeviceConfig(int index)
updateSummary();
}
-void MaemoDeployStepWidget::setDeployToSysroot(bool doDeploy)
-{
- m_step->setDeployToSysrootEnabled(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()
-{
- QTC_ASSERT(m_step->deployables()->modelCount() == ui->modelComboBox->count(), return);
- if (m_step->deployables()->modelCount() > 0) {
- if (ui->modelComboBox->currentIndex() == -1)
- ui->modelComboBox->setCurrentIndex(0);
- else
- setModel(ui->modelComboBox->currentIndex());
- }
-}
-
-void MaemoDeployStepWidget::setModel(int row)
-{
- bool canAddDesktopFile = false;
- bool canAddIconFile = false;
- if (row != -1) {
- 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();
-}
-
void MaemoDeployStepWidget::showDeviceConfigurations()
{
MaemoDeviceConfigurationsSettingsPage *page
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.h b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.h
index b97b20d281..1134353bb6 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.h
@@ -43,33 +43,28 @@ QT_END_NAMESPACE
namespace Qt4ProjectManager {
namespace Internal {
-class MaemoDeployStep;
+class AbstractMaemoDeployStep;
class MaemoDeployStepWidget : public ProjectExplorer::BuildStepConfigWidget
{
Q_OBJECT
public:
- MaemoDeployStepWidget(MaemoDeployStep *step);
+ MaemoDeployStepWidget(AbstractMaemoDeployStep *step);
~MaemoDeployStepWidget();
private:
Q_SLOT void handleDeviceUpdate();
Q_SLOT void setCurrentDeviceConfig(int index);
- Q_SLOT void setDeployToSysroot(bool doDeloy);
- Q_SLOT void setModel(int row);
- Q_SLOT void handleModelListToBeReset();
- Q_SLOT void handleModelListReset();
- Q_SLOT void addDesktopFile();
- Q_SLOT void addIcon();
Q_SLOT void showDeviceConfigurations();
+ Q_SLOT void handleStepToBeRemoved(int step);
virtual void init();
virtual QString summaryText() const;
virtual QString displayName() const;
Ui::MaemoDeployStepWidget *ui;
- MaemoDeployStep * const m_step;
+ AbstractMaemoDeployStep * const m_step;
};
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.ui b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.ui
index d629642caa..a724ba6ad6 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.ui
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystepwidget.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>662</width>
- <height>418</height>
+ <width>597</width>
+ <height>74</height>
</rect>
</property>
<property name="windowTitle">
@@ -53,144 +53,17 @@
</layout>
</item>
<item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="QCheckBox" name="deployToSysrootCheckBox">
- <property name="text">
- <string>Also deploy to sysroot</string>
- </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>
- <widget class="Line" name="line">
+ <spacer name="verticalSpacer">
<property name="orientation">
- <enum>Qt::Horizontal</enum>
+ <enum>Qt::Vertical</enum>
</property>
- </widget>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <item>
- <widget class="QLabel" name="installLabel">
- <property name="toolTip">
- <string>These show the INSTALLS settings from the project file(s).</string>
- </property>
- <property name="text">
- <string>&lt;b&gt;Files to install for subproject:&lt;/b&gt;</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QComboBox" name="modelComboBox">
- <property name="sizeAdjustPolicy">
- <enum>QComboBox::AdjustToContents</enum>
- </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>
- <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="toolTip">
- <string>Edit the project file to add or remove entries.</string>
- </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>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
</item>
</layout>
</widget>
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.cpp
index 982f377b24..b4552253f2 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.cpp
@@ -70,8 +70,6 @@ namespace {
const int DefaultSshPortSim(6666);
const int DefaultGdbServerPortHW(10000);
const int DefaultGdbServerPortSim(13219);
- const QString DefaultHostNameHW(QLatin1String("192.168.2.15"));
- const QString DefaultHostNameSim(QLatin1String("localhost"));
const AuthType DefaultAuthType(Utils::SshConnectionParameters::AuthenticationByKey);
const int DefaultTimeout(30);
const MaemoDeviceConfig::DeviceType DefaultDeviceType(MaemoDeviceConfig::Physical);
@@ -226,28 +224,58 @@ MaemoDeviceConfig::Ptr MaemoDeviceConfig::create(const ConstPtr &other)
}
MaemoDeviceConfig::Ptr MaemoDeviceConfig::createHardwareConfig(const QString &name,
- MaemoGlobal::MaemoVersion osVersion, const QString &hostName,
- const QString privateKeyFilePath, Id &nextId)
+ MaemoGlobal::OsVersion osVersion, const QString &hostName,
+ const QString &privateKeyFilePath, Id &nextId)
{
Utils::SshConnectionParameters sshParams(Utils::SshConnectionParameters::NoProxy);
sshParams.authenticationType = Utils::SshConnectionParameters::AuthenticationByKey;
sshParams.host = hostName;
+ sshParams.userName = defaultUser(osVersion);
sshParams.privateKeyFile = privateKeyFilePath;
return Ptr(new MaemoDeviceConfig(name, osVersion, Physical, sshParams, nextId));
}
+MaemoDeviceConfig::Ptr MaemoDeviceConfig::createGenericLinuxConfigUsingPassword(const QString &name,
+ const QString &hostName, const QString &userName, const QString &password,
+ Id &nextId)
+{
+ Utils::SshConnectionParameters sshParams(Utils::SshConnectionParameters::NoProxy);
+ sshParams.authenticationType
+ = Utils::SshConnectionParameters::AuthenticationByPassword;
+ sshParams.host = hostName;
+ sshParams.userName = userName;
+ sshParams.password = password;
+ return Ptr(new MaemoDeviceConfig(name, MaemoGlobal::GenericLinux, Physical,
+ sshParams, nextId));
+}
+
+MaemoDeviceConfig::Ptr MaemoDeviceConfig::createGenericLinuxConfigUsingKey(const QString &name,
+ const QString &hostName, const QString &userName, const QString &privateKeyFile,
+ Id &nextId)
+{
+ Utils::SshConnectionParameters sshParams(Utils::SshConnectionParameters::NoProxy);
+ sshParams.authenticationType
+ = Utils::SshConnectionParameters::AuthenticationByKey;
+ sshParams.host = hostName;
+ sshParams.userName = userName;
+ sshParams.privateKeyFile = privateKeyFile;
+ return Ptr(new MaemoDeviceConfig(name, MaemoGlobal::GenericLinux, Physical,
+ sshParams, nextId));
+}
+
MaemoDeviceConfig::Ptr MaemoDeviceConfig::createEmulatorConfig(const QString &name,
- MaemoGlobal::MaemoVersion osVersion, Id &nextId)
+ MaemoGlobal::OsVersion osVersion, Id &nextId)
{
Utils::SshConnectionParameters sshParams(Utils::SshConnectionParameters::NoProxy);
sshParams.authenticationType = Utils::SshConnectionParameters::AuthenticationByPassword;
- sshParams.host = defaultHost(Emulator);
+ sshParams.host = defaultHost(Emulator, osVersion);
+ sshParams.userName = defaultUser(osVersion);
sshParams.password = defaultQemuPassword(osVersion);
return Ptr(new MaemoDeviceConfig(name, osVersion, Emulator, sshParams, nextId));
}
MaemoDeviceConfig::MaemoDeviceConfig(const QString &name,
- MaemoGlobal::MaemoVersion osVersion, DeviceType devType,
+ MaemoGlobal::OsVersion osVersion, DeviceType devType,
const Utils::SshConnectionParameters &sshParams, Id &nextId)
: m_sshParameters(sshParams),
m_name(name),
@@ -258,7 +286,6 @@ MaemoDeviceConfig::MaemoDeviceConfig(const QString &name,
m_internalId(nextId++)
{
m_sshParameters.port = defaultSshPort(m_type);
- m_sshParameters.userName = defaultUser(m_osVersion);
m_sshParameters.timeout = DefaultTimeout;
}
@@ -266,7 +293,7 @@ MaemoDeviceConfig::MaemoDeviceConfig(const QSettings &settings,
Id &nextId)
: m_sshParameters(Utils::SshConnectionParameters::NoProxy),
m_name(settings.value(NameKey).toString()),
- m_osVersion(static_cast<MaemoGlobal::MaemoVersion>(settings.value(OsVersionKey, MaemoGlobal::Maemo5).toInt())),
+ m_osVersion(static_cast<MaemoGlobal::OsVersion>(settings.value(OsVersionKey, MaemoGlobal::Maemo5).toInt())),
m_type(static_cast<DeviceType>(settings.value(TypeKey, DefaultDeviceType).toInt())),
m_portsSpec(settings.value(PortsSpecKey, defaultPortsSpec(m_type)).toString()),
m_isDefault(settings.value(IsDefaultKey, false).toBool()),
@@ -274,7 +301,7 @@ MaemoDeviceConfig::MaemoDeviceConfig(const QSettings &settings,
{
if (m_internalId == nextId)
++nextId;
- m_sshParameters.host = settings.value(HostKey, defaultHost(m_type)).toString();
+ m_sshParameters.host = settings.value(HostKey, defaultHost(m_type, m_osVersion)).toString();
m_sshParameters.port = settings.value(SshPortKey, defaultSshPort(m_type)).toInt();
m_sshParameters.userName = settings.value(UserNameKey, defaultUser(m_osVersion)).toString();
m_sshParameters.authenticationType
@@ -313,9 +340,19 @@ QString MaemoDeviceConfig::defaultPortsSpec(DeviceType type) const
return QLatin1String(type == Physical ? "10000-10100" : "13219,14168");
}
-QString MaemoDeviceConfig::defaultHost(DeviceType type)
+QString MaemoDeviceConfig::defaultHost(DeviceType type, MaemoGlobal::OsVersion osVersion)
{
- return type == Physical ? DefaultHostNameHW : DefaultHostNameSim;
+ switch (osVersion) {
+ case MaemoGlobal::Maemo5:
+ case MaemoGlobal::Maemo6:
+ case MaemoGlobal::Meego:
+ return QLatin1String(type == Physical ? "192.168.2.15" : "localhost");
+ case MaemoGlobal::GenericLinux:
+ return QString();
+ default:
+ qFatal("%s: Missing case in switch", Q_FUNC_INFO);
+ return QString();
+ }
}
QString MaemoDeviceConfig::defaultPrivateKeyFilePath()
@@ -329,7 +366,7 @@ QString MaemoDeviceConfig::defaultPublicKeyFilePath()
return defaultPrivateKeyFilePath() + QLatin1String(".pub");
}
-QString MaemoDeviceConfig::defaultUser(MaemoGlobal::MaemoVersion osVersion)
+QString MaemoDeviceConfig::defaultUser(MaemoGlobal::OsVersion osVersion)
{
switch (osVersion) {
case MaemoGlobal::Maemo5:
@@ -337,13 +374,15 @@ QString MaemoDeviceConfig::defaultUser(MaemoGlobal::MaemoVersion osVersion)
return QLatin1String("developer");
case MaemoGlobal::Meego:
return QLatin1String("meego");
+ case MaemoGlobal::GenericLinux:
+ return QString();
default:
qDebug("%s: Unknown OS Version %d.", Q_FUNC_INFO, osVersion);
return QString();
}
}
-QString MaemoDeviceConfig::defaultQemuPassword(MaemoGlobal::MaemoVersion osVersion)
+QString MaemoDeviceConfig::defaultQemuPassword(MaemoGlobal::OsVersion osVersion)
{
switch (osVersion) {
case MaemoGlobal::Maemo5:
@@ -437,16 +476,33 @@ void MaemoDeviceConfigurations::save()
}
void MaemoDeviceConfigurations::addHardwareDeviceConfiguration(const QString &name,
- MaemoGlobal::MaemoVersion osVersion, const QString &hostName,
- const QString privateKeyFilePath)
+ MaemoGlobal::OsVersion osVersion, const QString &hostName,
+ const QString &privateKeyFilePath)
{
const MaemoDeviceConfig::Ptr &devConf = MaemoDeviceConfig::createHardwareConfig(name,
osVersion, hostName, privateKeyFilePath, m_nextId);
addConfiguration(devConf);
}
+void MaemoDeviceConfigurations::addGenericLinuxConfigurationUsingPassword(const QString &name,
+ const QString &hostName, const QString &userName, const QString &password)
+{
+ const MaemoDeviceConfig::Ptr &devConf
+ = MaemoDeviceConfig::createGenericLinuxConfigUsingPassword(name,
+ hostName, userName, password, m_nextId);
+ addConfiguration(devConf);
+}
+
+void MaemoDeviceConfigurations::addGenericLinuxConfigurationUsingKey(const QString &name,
+ const QString &hostName, const QString &userName, const QString &privateKeyFilePath)
+{
+ const MaemoDeviceConfig::Ptr &devConf = MaemoDeviceConfig::createGenericLinuxConfigUsingKey(name,
+ hostName, userName, privateKeyFilePath, m_nextId);
+ addConfiguration(devConf);
+}
+
void MaemoDeviceConfigurations::addEmulatorDeviceConfiguration(const QString &name,
- MaemoGlobal::MaemoVersion osVersion)
+ MaemoGlobal::OsVersion osVersion)
{
const MaemoDeviceConfig::Ptr &devConf
= MaemoDeviceConfig::createEmulatorConfig(name, osVersion, m_nextId);
@@ -467,7 +523,7 @@ void MaemoDeviceConfigurations::removeConfiguration(int idx)
Q_ASSERT(idx >= 0 && idx < rowCount());
beginRemoveRows(QModelIndex(), idx, idx);
const bool wasDefault = deviceAt(idx)->m_isDefault;
- const MaemoGlobal::MaemoVersion osVersion = deviceAt(idx)->osVersion();
+ const MaemoGlobal::OsVersion osVersion = deviceAt(idx)->osVersion();
m_devConfigs.removeAt(idx);
endRemoveRows();
if (wasDefault) {
@@ -550,6 +606,7 @@ void MaemoDeviceConfigurations::load()
ensureDefaultExists(MaemoGlobal::Maemo5);
ensureDefaultExists(MaemoGlobal::Maemo6);
ensureDefaultExists(MaemoGlobal::Meego);
+ ensureDefaultExists(MaemoGlobal::GenericLinux);
}
MaemoDeviceConfig::ConstPtr MaemoDeviceConfigurations::deviceAt(int idx) const
@@ -572,7 +629,7 @@ MaemoDeviceConfig::ConstPtr MaemoDeviceConfigurations::find(MaemoDeviceConfig::I
return index == -1 ? MaemoDeviceConfig::ConstPtr() : deviceAt(index);
}
-MaemoDeviceConfig::ConstPtr MaemoDeviceConfigurations::defaultDeviceConfig(const MaemoGlobal::MaemoVersion osVersion) const
+MaemoDeviceConfig::ConstPtr MaemoDeviceConfigurations::defaultDeviceConfig(const MaemoGlobal::OsVersion osVersion) const
{
foreach (const MaemoDeviceConfig::ConstPtr &devConf, m_devConfigs) {
if (devConf->m_isDefault && devConf->osVersion() == osVersion)
@@ -595,7 +652,7 @@ MaemoDeviceConfig::Id MaemoDeviceConfigurations::internalId(MaemoDeviceConfig::C
return devConf ? devConf->m_internalId : MaemoDeviceConfig::InvalidId;
}
-void MaemoDeviceConfigurations::ensureDefaultExists(MaemoGlobal::MaemoVersion osVersion)
+void MaemoDeviceConfigurations::ensureDefaultExists(MaemoGlobal::OsVersion osVersion)
{
if (!defaultDeviceConfig(osVersion)) {
foreach (const MaemoDeviceConfig::Ptr &devConf, m_devConfigs) {
@@ -621,7 +678,7 @@ QVariant MaemoDeviceConfigurations::data(const QModelIndex &index, int role) con
QString name = devConf->name();
if (devConf->m_isDefault) {
name += QLatin1Char(' ') + tr("(default for %1)")
- .arg(MaemoGlobal::maemoVersionToString(devConf->osVersion()));
+ .arg(MaemoGlobal::osVersionToString(devConf->osVersion()));
}
return name;
}
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.h b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.h
index f1c02ca22e..c6a7f66ade 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.h
@@ -77,25 +77,25 @@ public:
MaemoPortList freePorts() const;
Utils::SshConnectionParameters sshParameters() const { return m_sshParameters; }
QString name() const { return m_name; }
- MaemoGlobal::MaemoVersion osVersion() const { return m_osVersion; }
+ MaemoGlobal::OsVersion osVersion() const { return m_osVersion; }
DeviceType type() const { return m_type; }
QString portsSpec() const { return m_portsSpec; }
Id internalId() const { return m_internalId; }
bool isDefault() const { return m_isDefault; }
static QString portsRegExpr();
- static QString defaultHost(DeviceType type);
+ static QString defaultHost(DeviceType type, MaemoGlobal::OsVersion osVersion);
static QString defaultPrivateKeyFilePath();
static QString defaultPublicKeyFilePath();
- static QString defaultUser(MaemoGlobal::MaemoVersion osVersion);
+ static QString defaultUser(MaemoGlobal::OsVersion osVersion);
static int defaultSshPort(DeviceType type);
- static QString defaultQemuPassword(MaemoGlobal::MaemoVersion osVersion);
+ static QString defaultQemuPassword(MaemoGlobal::OsVersion osVersion);
static const Id InvalidId;
private:
typedef QSharedPointer<MaemoDeviceConfig> Ptr;
- MaemoDeviceConfig(const QString &name, MaemoGlobal::MaemoVersion osVersion,
+ MaemoDeviceConfig(const QString &name, MaemoGlobal::OsVersion osVersion,
DeviceType type, const Utils::SshConnectionParameters &sshParams,
Id &nextId);
MaemoDeviceConfig(const QSettings &settings, Id &nextId);
@@ -105,10 +105,16 @@ private:
MaemoDeviceConfig &operator=(const MaemoDeviceConfig &);
static Ptr createHardwareConfig(const QString &name,
- MaemoGlobal::MaemoVersion osVersion, const QString &hostName,
- const QString privateKeyFilePath, Id &nextId);
+ MaemoGlobal::OsVersion osVersion, const QString &hostName,
+ const QString &privateKeyFilePath, Id &nextId);
+ static Ptr createGenericLinuxConfigUsingPassword(const QString &name,
+ const QString &hostName, const QString &userName,
+ const QString &password, Id &nextId);
+ static Ptr createGenericLinuxConfigUsingKey(const QString &name,
+ const QString &hostName, const QString &userName,
+ const QString &privateKeyFilePath, Id &nextId);
static Ptr createEmulatorConfig(const QString &name,
- MaemoGlobal::MaemoVersion osVersion, Id &nextId);
+ MaemoGlobal::OsVersion osVersion, Id &nextId);
static Ptr create(const QSettings &settings, Id &nextId);
static Ptr create(const ConstPtr &other);
@@ -117,7 +123,7 @@ private:
Utils::SshConnectionParameters m_sshParameters;
QString m_name;
- MaemoGlobal::MaemoVersion m_osVersion;
+ MaemoGlobal::OsVersion m_osVersion;
DeviceType m_type;
QString m_portsSpec;
bool m_isDefault;
@@ -137,7 +143,7 @@ public:
MaemoDeviceConfig::ConstPtr deviceAt(int index) const;
MaemoDeviceConfig::ConstPtr find(MaemoDeviceConfig::Id id) const;
- MaemoDeviceConfig::ConstPtr defaultDeviceConfig(const MaemoGlobal::MaemoVersion osVersion) const;
+ MaemoDeviceConfig::ConstPtr defaultDeviceConfig(const MaemoGlobal::OsVersion osVersion) const;
bool hasConfig(const QString &name) const;
int indexForInternalId(MaemoDeviceConfig::Id internalId) const;
MaemoDeviceConfig::Id internalId(MaemoDeviceConfig::ConstPtr devConf) const;
@@ -146,10 +152,16 @@ public:
QString defaultSshKeyFilePath() const { return m_defaultSshKeyFilePath; }
void addHardwareDeviceConfiguration(const QString &name,
- MaemoGlobal::MaemoVersion osVersion, const QString &hostName,
- const QString privateKeyFilePath);
+ MaemoGlobal::OsVersion osVersion, const QString &hostName,
+ const QString &privateKeyFilePath);
+ void addGenericLinuxConfigurationUsingPassword(const QString &name,
+ const QString &hostName, const QString &userName,
+ const QString &password);
+ void addGenericLinuxConfigurationUsingKey(const QString &name,
+ const QString &hostName, const QString &userName,
+ const QString &privateKeyFilePath);
void addEmulatorDeviceConfiguration(const QString &name,
- MaemoGlobal::MaemoVersion osVersion);
+ MaemoGlobal::OsVersion osVersion);
void removeConfiguration(int index);
void setConfigurationName(int i, const QString &name);
void setSshParameters(int i, const Utils::SshConnectionParameters &params);
@@ -170,7 +182,7 @@ private:
static void copy(const MaemoDeviceConfigurations *source,
MaemoDeviceConfigurations *target, bool deep);
void addConfiguration(const MaemoDeviceConfig::Ptr &devConfig);
- void ensureDefaultExists(MaemoGlobal::MaemoVersion osVersion);
+ void ensureDefaultExists(MaemoGlobal::OsVersion osVersion);
static MaemoDeviceConfigurations *m_instance;
MaemoDeviceConfig::Id m_nextId;
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurationssettingswidget.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurationssettingswidget.cpp
index 40d4b762c3..04af712d83 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurationssettingswidget.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurationssettingswidget.cpp
@@ -194,7 +194,7 @@ void MaemoDeviceConfigurationsSettingsWidget::displayCurrent()
{
const MaemoDeviceConfig::ConstPtr &current = currentConfig();
m_ui->defaultDeviceButton->setEnabled(!current->isDefault());
- m_ui->osTypeValueLabel->setText(MaemoGlobal::maemoVersionToString(current->osVersion()));
+ m_ui->osTypeValueLabel->setText(MaemoGlobal::osVersionToString(current->osVersion()));
const SshConnectionParameters &sshParams = current->sshParameters();
if (current->type() == MaemoDeviceConfig::Physical) {
m_ui->deviceTypeValueLabel->setText(tr("Physical Device"));
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigwizard.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigwizard.cpp
index 12ac5aba59..297c25a46b 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigwizard.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigwizard.cpp
@@ -32,6 +32,7 @@
#include "maemodeviceconfigwizard.h"
#include "ui_maemodeviceconfigwizardkeycreationpage.h"
#include "ui_maemodeviceconfigwizardkeydeploymentpage.h"
+#include "ui_maemodeviceconfigwizardlogindatapage.h"
#include "ui_maemodeviceconfigwizardpreviouskeysetupcheckpage.h"
#include "ui_maemodeviceconfigwizardreusekeyscheckpage.h"
#include "ui_maemodeviceconfigwizardstartpage.h"
@@ -48,6 +49,8 @@
#include <QtGui/QMessageBox>
#include <QtGui/QWizardPage>
+using namespace Utils;
+
namespace Qt4ProjectManager {
namespace Internal {
namespace {
@@ -56,15 +59,18 @@ struct WizardData
{
QString configName;
QString hostName;
- MaemoGlobal::MaemoVersion maemoVersion;
+ MaemoGlobal::OsVersion osVersion;
+ SshConnectionParameters::AuthenticationType authType;
MaemoDeviceConfig::DeviceType deviceType;
QString privateKeyFilePath;
QString publicKeyFilePath;
+ QString userName;
+ QString password;
};
enum PageId {
- StartPageId, PreviousKeySetupCheckPageId, ReuseKeysCheckPageId,
- KeyCreationPageId, KeyDeploymentPageId, FinalPageId
+ StartPageId, LoginDataPageId, PreviousKeySetupCheckPageId,
+ ReuseKeysCheckPageId, KeyCreationPageId, KeyDeploymentPageId, FinalPageId
};
class MaemoDeviceConfigWizardStartPage : public QWizardPage
@@ -77,20 +83,33 @@ public:
m_ui->setupUi(this);
setTitle(tr("General Information"));
setSubTitle(QLatin1String(" ")); // For Qt bug (background color)
- m_ui->fremantleButton->setText(MaemoGlobal::maemoVersionToString(MaemoGlobal::Maemo5));
- m_ui->harmattanButton->setText(MaemoGlobal::maemoVersionToString(MaemoGlobal::Maemo6));
- m_ui->meegoButton->setText(MaemoGlobal::maemoVersionToString(MaemoGlobal::Meego));
- QButtonGroup * const buttonGroup = new QButtonGroup(this);
+ m_ui->fremantleButton->setText(MaemoGlobal::osVersionToString(MaemoGlobal::Maemo5));
+ m_ui->harmattanButton->setText(MaemoGlobal::osVersionToString(MaemoGlobal::Maemo6));
+ m_ui->meegoButton->setText(MaemoGlobal::osVersionToString(MaemoGlobal::Meego));
+ m_ui->genericLinuxButton->setText(MaemoGlobal::osVersionToString(MaemoGlobal::GenericLinux));
+
+ QButtonGroup *buttonGroup = new QButtonGroup(this);
buttonGroup->setExclusive(true);
buttonGroup->addButton(m_ui->hwButton);
buttonGroup->addButton(m_ui->qemuButton);
- m_ui->nameLineEdit->setText(QLatin1String("(New Configuration)"));
connect(buttonGroup, SIGNAL(buttonClicked(int)),
SLOT(handleDeviceTypeChanged()));
+
+ buttonGroup = new QButtonGroup(this);
+ buttonGroup->setExclusive(true);
+ buttonGroup->addButton(m_ui->fremantleButton);
+ buttonGroup->addButton(m_ui->harmattanButton);
+ buttonGroup->addButton(m_ui->meegoButton);
+ buttonGroup->addButton(m_ui->genericLinuxButton);
+ connect(buttonGroup, SIGNAL(buttonClicked(int)),
+ SLOT(handleOsTypeChanged()));
+
+ m_ui->nameLineEdit->setText(QLatin1String("(New Configuration)"));
m_ui->harmattanButton->setChecked(true);
m_ui->hwButton->setChecked(true);
handleDeviceTypeChanged();
- m_ui->hostNameLineEdit->setText(MaemoDeviceConfig::defaultHost(deviceType()));
+ m_ui->hostNameLineEdit->setText(MaemoDeviceConfig::defaultHost(deviceType(),
+ osVersion()));
connect(m_ui->nameLineEdit, SIGNAL(textChanged(QString)), this,
SIGNAL(completeChanged()));
connect(m_ui->hostNameLineEdit, SIGNAL(textChanged(QString)), this,
@@ -107,15 +126,16 @@ public:
QString hostName() const
{
return deviceType() == MaemoDeviceConfig::Emulator
- ? MaemoDeviceConfig::defaultHost(MaemoDeviceConfig::Emulator)
+ ? MaemoDeviceConfig::defaultHost(MaemoDeviceConfig::Emulator, osVersion())
: m_ui->hostNameLineEdit->text().trimmed();
}
- MaemoGlobal::MaemoVersion maemoVersion() const
+ MaemoGlobal::OsVersion osVersion() const
{
return m_ui->fremantleButton->isChecked() ? MaemoGlobal::Maemo5
: m_ui->harmattanButton->isChecked() ? MaemoGlobal::Maemo6
- : MaemoGlobal::Meego;
+ : m_ui->meegoButton->isChecked() ? MaemoGlobal::Meego
+ : MaemoGlobal::GenericLinux;
}
MaemoDeviceConfig::DeviceType deviceType() const
@@ -132,10 +152,84 @@ private slots:
m_ui->hostNameLineEdit->setEnabled(enable);
}
+ void handleOsTypeChanged()
+ {
+ if (osVersion() == MaemoGlobal::GenericLinux) {
+ m_ui->hwButton->setChecked(true);
+ m_ui->hwButton->setEnabled(false);
+ m_ui->qemuButton->setEnabled(false);
+ } else {
+ m_ui->hwButton->setEnabled(true);
+ m_ui->qemuButton->setEnabled(true);
+ }
+ handleDeviceTypeChanged();
+ }
+
private:
const QScopedPointer<Ui::MaemoDeviceConfigWizardStartPage> m_ui;
};
+class MaemoDeviceConfigWizardLoginDataPage : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ MaemoDeviceConfigWizardLoginDataPage(WizardData &wizardData, QWidget *parent)
+ : QWizardPage(parent),
+ m_ui(new Ui::MaemoDeviceConfigWizardLoginDataPage),
+ m_wizardData(wizardData)
+ {
+ m_ui->setupUi(this);
+ setTitle(tr("Login Data"));
+ m_ui->privateKeyPathChooser->setExpectedKind(PathChooser::File);
+ setSubTitle(QLatin1String(" ")); // For Qt bug (background color)
+ connect(m_ui->userNameLineEdit, SIGNAL(textChanged(QString)),
+ SIGNAL(completeChanged()));
+ connect(m_ui->privateKeyPathChooser, SIGNAL(validChanged()),
+ SIGNAL(completeChanged()));
+ connect(m_ui->passwordButton, SIGNAL(toggled(bool)),
+ SLOT(handleAuthTypeChanged()));
+ }
+
+ virtual bool isComplete() const
+ {
+ return !userName().isEmpty()
+ && (authType() == SshConnectionParameters::AuthenticationByPassword
+ || m_ui->privateKeyPathChooser->isValid());
+ }
+
+ virtual void initializePage()
+ {
+ m_ui->userNameLineEdit->setText(MaemoDeviceConfig::defaultUser(m_wizardData.osVersion));
+ m_ui->passwordButton->setChecked(true);
+ m_ui->passwordLineEdit->clear();
+ m_ui->privateKeyPathChooser->setPath(MaemoDeviceConfig::defaultPrivateKeyFilePath());
+ handleAuthTypeChanged();
+ }
+
+ SshConnectionParameters::AuthenticationType authType() const
+ {
+ return m_ui->passwordButton->isChecked()
+ ? SshConnectionParameters::AuthenticationByPassword
+ : SshConnectionParameters::AuthenticationByKey;
+ }
+
+ QString userName() const { return m_ui->userNameLineEdit->text().trimmed(); }
+ QString password() const { return m_ui->passwordLineEdit->text(); }
+ QString privateKeyFilePath() const { return m_ui->privateKeyPathChooser->path(); }
+
+private:
+ Q_SLOT void handleAuthTypeChanged()
+ {
+ m_ui->passwordLineEdit->setEnabled(authType() == SshConnectionParameters::AuthenticationByPassword);
+ m_ui->privateKeyPathChooser->setEnabled(authType() == SshConnectionParameters::AuthenticationByKey);
+ emit completeChanged();
+ }
+
+ const QScopedPointer<Ui::MaemoDeviceConfigWizardLoginDataPage> m_ui;
+ const WizardData &m_wizardData;
+};
+
class MaemoDeviceConfigWizardPreviousKeySetupCheckPage : public QWizardPage
{
Q_OBJECT
@@ -145,7 +239,7 @@ public:
m_ui(new Ui::MaemoDeviceConfigWizardCheckPreviousKeySetupPage)
{
m_ui->setupUi(this);
- m_ui->privateKeyFilePathChooser->setExpectedKind(Utils::PathChooser::File);
+ m_ui->privateKeyFilePathChooser->setExpectedKind(PathChooser::File);
setTitle(tr("Device Status Check"));
setSubTitle(QLatin1String(" ")); // For Qt bug (background color)
QButtonGroup * const buttonGroup = new QButtonGroup(this);
@@ -200,8 +294,8 @@ public:
m_ui->setupUi(this);
setTitle(tr("Existing Keys Check"));
setSubTitle(QLatin1String(" ")); // For Qt bug (background color)
- m_ui->publicKeyFilePathChooser->setExpectedKind(Utils::PathChooser::File);
- m_ui->privateKeyFilePathChooser->setExpectedKind(Utils::PathChooser::File);
+ m_ui->publicKeyFilePathChooser->setExpectedKind(PathChooser::File);
+ m_ui->privateKeyFilePathChooser->setExpectedKind(PathChooser::File);
QButtonGroup * const buttonGroup = new QButtonGroup(this);
buttonGroup->setExclusive(true);
buttonGroup->addButton(m_ui->reuseButton);
@@ -305,9 +399,9 @@ private:
m_ui->keyDirPathChooser->setEnabled(false);
m_ui->createKeysButton->setEnabled(false);
m_ui->statusLabel->setText(tr("Creating keys ... "));
- Utils::SshKeyGenerator keyGenerator;
- if (!keyGenerator.generateKeys(Utils::SshKeyGenerator::Rsa,
- Utils::SshKeyGenerator::OpenSsl, 1024)) {
+ SshKeyGenerator keyGenerator;
+ if (!keyGenerator.generateKeys(SshKeyGenerator::Rsa,
+ SshKeyGenerator::OpenSsl, 1024)) {
QMessageBox::critical(this, tr("Cannot Create Keys"),
tr("Key creation failed: %1").arg(keyGenerator.error()));
enableInput();
@@ -382,7 +476,7 @@ public:
m_ui->deviceAddressLineEdit->setText(m_wizardData.hostName);
m_ui->instructionLabel->setText(QString(m_instructionTextTemplate)
.replace(QLatin1String("%%%maddev%%%"),
- MaemoGlobal::madDeveloperUiName(m_wizardData.maemoVersion)));
+ MaemoGlobal::madDeveloperUiName(m_wizardData.osVersion)));
m_ui->passwordLineEdit->clear();
enableInput();
}
@@ -406,13 +500,13 @@ private:
m_ui->deviceAddressLineEdit->setEnabled(false);
m_ui->passwordLineEdit->setEnabled(false);
m_ui->deployButton->setEnabled(false);
- Utils::SshConnectionParameters sshParams(SshConnectionParameters::NoProxy);
+ SshConnectionParameters sshParams(SshConnectionParameters::NoProxy);
sshParams.authenticationType = SshConnectionParameters::AuthenticationByPassword;
sshParams.host = hostAddress();
sshParams.port = MaemoDeviceConfig::defaultSshPort(MaemoDeviceConfig::Physical);
sshParams.password = password();
sshParams.timeout = 30;
- sshParams.userName = MaemoDeviceConfig::defaultUser(m_wizardData.maemoVersion);
+ sshParams.userName = MaemoDeviceConfig::defaultUser(m_wizardData.osVersion);
m_ui->statusLabel->setText(tr("Deploying... "));
m_keyDeployer->deployPublicKey(sshParams, m_wizardData.publicKeyFilePath);
}
@@ -428,7 +522,7 @@ private:
QMessageBox::information(this, tr("Key Deployment Success"),
tr("The key was successfully deployed. You may now close "
"the \"%1\" application and continue.")
- .arg(MaemoGlobal::madDeveloperUiName(m_wizardData.maemoVersion)));
+ .arg(MaemoGlobal::madDeveloperUiName(m_wizardData.osVersion)));
m_ui->statusLabel->setText(m_ui->statusLabel->text() + tr("Done."));
m_isComplete = true;
emit completeChanged();
@@ -498,6 +592,7 @@ struct MaemoDeviceConfigWizardPrivate
QWidget *parent)
: devConfigs(devConfigs),
startPage(parent),
+ loginDataPage(wizardData, parent),
previousKeySetupPage(parent),
reuseKeysCheckPage(parent),
keyCreationPage(parent),
@@ -509,6 +604,7 @@ struct MaemoDeviceConfigWizardPrivate
WizardData wizardData;
MaemoDeviceConfigurations * const devConfigs;
MaemoDeviceConfigWizardStartPage startPage;
+ MaemoDeviceConfigWizardLoginDataPage loginDataPage;
MaemoDeviceConfigWizardPreviousKeySetupCheckPage previousKeySetupPage;
MaemoDeviceConfigWizardReuseKeysCheckPage reuseKeysCheckPage;
MaemoDeviceConfigWizardKeyCreationPage keyCreationPage;
@@ -524,6 +620,7 @@ MaemoDeviceConfigWizard::MaemoDeviceConfigWizard(MaemoDeviceConfigurations *devC
{
setWindowTitle(tr("New Device Configuration Setup"));
setPage(StartPageId, &d->startPage);
+ setPage(LoginDataPageId, &d->loginDataPage);
setPage(PreviousKeySetupCheckPageId, &d->previousKeySetupPage);
setPage(ReuseKeysCheckPageId, &d->reuseKeysCheckPage);
setPage(KeyCreationPageId, &d->keyCreationPage);
@@ -545,13 +642,23 @@ void MaemoDeviceConfigWizard::createDeviceConfig()
while (d->devConfigs->hasConfig(name));
}
- if (d->wizardData.deviceType == MaemoDeviceConfig::Physical) {
+ if (d->wizardData.osVersion == MaemoGlobal::GenericLinux) {
+ if (d->wizardData.authType == SshConnectionParameters::AuthenticationByPassword) {
+ d->devConfigs->addGenericLinuxConfigurationUsingPassword(name,
+ d->wizardData.hostName, d->wizardData.userName,
+ d->wizardData.password);
+ } else {
+ d->devConfigs->addGenericLinuxConfigurationUsingKey(name,
+ d->wizardData.hostName, d->wizardData.userName,
+ d->wizardData.privateKeyFilePath);
+ }
+ } else if (d->wizardData.deviceType == MaemoDeviceConfig::Physical) {
d->devConfigs->addHardwareDeviceConfiguration(name,
- d->wizardData.maemoVersion, d->wizardData.hostName,
+ d->wizardData.osVersion, d->wizardData.hostName,
d->wizardData.privateKeyFilePath);
} else {
d->devConfigs->addEmulatorDeviceConfiguration(name,
- d->wizardData.maemoVersion);
+ d->wizardData.osVersion);
}
}
@@ -560,15 +667,25 @@ int MaemoDeviceConfigWizard::nextId() const
switch (currentId()) {
case StartPageId:
d->wizardData.configName = d->startPage.configName();
- d->wizardData.maemoVersion = d->startPage.maemoVersion();
+ d->wizardData.osVersion = d->startPage.osVersion();
d->wizardData.deviceType = d->startPage.deviceType();
d->wizardData.hostName = d->startPage.hostName();
if (d->wizardData.deviceType == MaemoDeviceConfig::Emulator) {
return FinalPageId;
+ } else if (d->wizardData.osVersion == MaemoGlobal::GenericLinux) {
+ return LoginDataPageId;
} else {
return PreviousKeySetupCheckPageId;
}
+ case LoginDataPageId:
+ d->wizardData.userName = d->loginDataPage.userName();
+ d->wizardData.authType = d->loginDataPage.authType();
+ if (d->wizardData.authType == SshConnectionParameters::AuthenticationByPassword)
+ d->wizardData.password = d->loginDataPage.password();
+ else
+ d->wizardData.privateKeyFilePath = d->loginDataPage.privateKeyFilePath();
+ return FinalPageId;
case PreviousKeySetupCheckPageId:
if (d->previousKeySetupPage.keyBasedLoginWasSetup()) {
d->wizardData.privateKeyFilePath
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigwizardlogindatapage.ui b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigwizardlogindatapage.ui
new file mode 100644
index 0000000000..c36cf115b4
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigwizardlogindatapage.ui
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MaemoDeviceConfigWizardLoginDataPage</class>
+ <widget class="QWizardPage" name="MaemoDeviceConfigWizardLoginDataPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>423</width>
+ <height>127</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>WizardPage</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="userNameLabel">
+ <property name="text">
+ <string>User name:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLineEdit" name="userNameLineEdit"/>
+ </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="label">
+ <property name="text">
+ <string>Authentication type:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QRadioButton" name="passwordButton">
+ <property name="text">
+ <string>Password</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="radioButton">
+ <property name="text">
+ <string>Key</string>
+ </property>
+ </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">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Password:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLineEdit" name="passwordLineEdit">
+ <property name="echoMode">
+ <enum>QLineEdit::Password</enum>
+ </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="3" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Private key:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="Utils::PathChooser" name="privateKeyPathChooser"/>
+ </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>
+ </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/>
+</ui>
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigwizardstartpage.ui b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigwizardstartpage.ui
index 8ca9b6ed6a..443ca96de7 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigwizardstartpage.ui
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigwizardstartpage.ui
@@ -6,14 +6,17 @@
<rect>
<x>0</x>
<y>0</y>
- <width>618</width>
- <height>122</height>
+ <width>727</width>
+ <height>132</height>
</rect>
</property>
<property name="windowTitle">
<string>WizardPage</string>
</property>
<layout class="QFormLayout" name="formLayout">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
<item row="0" column="0">
<widget class="QLabel" name="nameLabel">
<property name="text">
@@ -54,6 +57,26 @@
</property>
</widget>
</item>
+ <item>
+ <widget class="QRadioButton" name="genericLinuxButton">
+ <property name="text">
+ <string>Generic Linux</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="2" column="0">
@@ -79,6 +102,19 @@
</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="3" column="0">
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodirectdeviceuploadstep.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodirectdeviceuploadstep.cpp
new file mode 100644
index 0000000000..b7a1b1c305
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodirectdeviceuploadstep.cpp
@@ -0,0 +1,217 @@
+#include "maemodirectdeviceuploadstep.h"
+
+#include "maemodeployable.h"
+#include "maemoglobal.h"
+#include "qt4maemodeployconfiguration.h"
+
+#include <utils/ssh/sftpchannel.h>
+#include <utils/ssh/sshremoteprocess.h>
+
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+
+#define ASSERT_BASE_STATE(state) ASSERT_STATE_GENERIC(BaseState, state, baseState())
+#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(ExtendedState, state, m_extendedState)
+
+using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+MaemoDirectDeviceUploadStep::MaemoDirectDeviceUploadStep(BuildStepList *parent)
+ : AbstractMaemoDeployStep(parent, Id)
+{
+ ctor();
+}
+
+MaemoDirectDeviceUploadStep::MaemoDirectDeviceUploadStep(BuildStepList *parent,
+ MaemoDirectDeviceUploadStep *other)
+ : AbstractMaemoDeployStep(parent, other)
+{
+ ctor();
+}
+
+MaemoDirectDeviceUploadStep::~MaemoDirectDeviceUploadStep() {}
+
+
+void MaemoDirectDeviceUploadStep::ctor()
+{
+ setDefaultDisplayName(DisplayName);
+ m_extendedState = Inactive;
+}
+
+bool MaemoDirectDeviceUploadStep::isDeploymentPossibleInternal(QString &whyNot) const
+{
+ Q_UNUSED(whyNot);
+ return true;
+}
+
+bool MaemoDirectDeviceUploadStep::isDeploymentNeeded(const QString &hostName) const
+{
+ m_filesToUpload.clear();
+ const QSharedPointer<MaemoDeployables> deployables
+ = maemoDeployConfig()->deployables();
+ const int deployableCount = deployables->deployableCount();
+ for (int i = 0; i < deployableCount; ++i)
+ checkDeploymentNeeded(hostName, deployables->deployableAt(i));
+ return !m_filesToUpload.isEmpty();
+}
+
+void MaemoDirectDeviceUploadStep::checkDeploymentNeeded(const QString &hostName,
+ const MaemoDeployable &deployable) const
+{
+ QFileInfo fileInfo(deployable.localFilePath);
+ if (fileInfo.isDir()) {
+ const QStringList files = QDir(deployable.localFilePath)
+ .entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
+ if (files.isEmpty() && currentlyNeedsDeployment(hostName, deployable))
+ m_filesToUpload << deployable;
+ foreach (const QString &fileName, files) {
+ const QString localFilePath = deployable.localFilePath
+ + QLatin1Char('/') + fileName;
+ const QString remoteDir = deployable.remoteDir + QLatin1Char('/')
+ + fileInfo.fileName();
+ checkDeploymentNeeded(hostName,
+ MaemoDeployable(localFilePath, remoteDir));
+ }
+ } else if (currentlyNeedsDeployment(hostName, deployable)) {
+ m_filesToUpload << deployable;
+ }
+}
+
+
+void MaemoDirectDeviceUploadStep::startInternal()
+{
+ Q_ASSERT(m_extendedState == Inactive);
+
+ m_uploader = connection()->createSftpChannel();
+ connect(m_uploader.data(), SIGNAL(initialized()),
+ SLOT(handleSftpInitialized()));
+ connect(m_uploader.data(), SIGNAL(initializationFailed(QString)),
+ SLOT(handleSftpInitializationFailed(QString)));
+ m_uploader->initialize();
+ m_extendedState = InitializingSftp;
+}
+
+void MaemoDirectDeviceUploadStep::handleSftpInitializationFailed(const QString &errorMessage)
+{
+ ASSERT_STATE(QList<ExtendedState>() << Inactive << InitializingSftp);
+
+ if (m_extendedState == InitializingSftp) {
+ raiseError(tr("SFTP initialization failed: %1").arg(errorMessage));
+ setFinished();
+ }
+}
+
+void MaemoDirectDeviceUploadStep::handleSftpInitialized()
+{
+ ASSERT_STATE(QList<ExtendedState>() << Inactive << InitializingSftp);
+ if (m_extendedState == InitializingSftp) {
+ Q_ASSERT(!m_filesToUpload.isEmpty());
+ connect(m_uploader.data(), SIGNAL(finished(Utils::SftpJobId, QString)),
+ SLOT(handleUploadFinished(Utils::SftpJobId,QString)));
+ uploadNextFile();
+ }
+}
+
+void MaemoDirectDeviceUploadStep::uploadNextFile()
+{
+ if (m_filesToUpload.isEmpty()) {
+ writeOutput(tr("All files successfully deployed."));
+ setFinished();
+ return;
+ }
+
+ const MaemoDeployable &d = m_filesToUpload.first();
+ QString dirToCreate = d.remoteDir;
+ QFileInfo fi(d.localFilePath);
+ if (fi.isDir())
+ dirToCreate += QLatin1Char('/') + fi.fileName();
+ const QByteArray command = "mkdir -p " + dirToCreate.toUtf8();
+ m_mkdirProc = connection()->createRemoteProcess(command);
+ connect(m_mkdirProc.data(), SIGNAL(closed(int)),
+ SLOT(handleMkdirFinished(int)));
+ // TODO: Connect stderr.
+ writeOutput(tr("Uploading file '%1'...")
+ .arg(QDir::toNativeSeparators(d.localFilePath)));
+ m_mkdirProc->start();
+ m_extendedState = Uploading;
+}
+
+void MaemoDirectDeviceUploadStep::handleMkdirFinished(int exitStatus)
+{
+ ASSERT_STATE(QList<ExtendedState>() << Inactive << Uploading);
+ if (m_extendedState == Inactive)
+ return;
+
+ const MaemoDeployable &d = m_filesToUpload.first();
+ QFileInfo fi(d.localFilePath);
+ const QString nativePath = QDir::toNativeSeparators(d.localFilePath);
+ if (exitStatus != SshRemoteProcess::ExitedNormally
+ || m_mkdirProc->exitCode() != 0) {
+ raiseError(tr("Failed to upload file '%1'.").arg(nativePath));
+ setFinished();
+ } else if (fi.isDir()) {
+ setDeployed(deviceConfig()->sshParameters().host, d);
+ m_filesToUpload.removeFirst();
+ uploadNextFile();
+ } else {
+ const SftpJobId job = m_uploader->uploadFile(d.localFilePath,
+ d.remoteDir + QLatin1Char('/') + fi.fileName(),
+ SftpOverwriteExisting);
+ if (job == SftpInvalidJob) {
+ raiseError(tr("Failed to upload file '%1': "
+ "Could not open for reading.").arg(nativePath));
+ setFinished();
+ }
+ }
+}
+
+void MaemoDirectDeviceUploadStep::handleUploadFinished(Utils::SftpJobId jobId,
+ const QString &errorMsg)
+{
+ Q_UNUSED(jobId);
+
+ ASSERT_STATE(QList<ExtendedState>() << Inactive << Uploading);
+ if (m_extendedState == Inactive)
+ return;
+
+ const MaemoDeployable d = m_filesToUpload.takeFirst();
+ if (!errorMsg.isEmpty()) {
+ raiseError(tr("Upload of file '%1' failed: %2")
+ .arg(QDir::toNativeSeparators(d.localFilePath), errorMsg));
+ setFinished();
+ } else {
+ setDeployed(connection()->connectionParameters().host, d);
+ uploadNextFile();
+ }
+}
+
+void MaemoDirectDeviceUploadStep::stopInternal()
+{
+ ASSERT_BASE_STATE(StopRequested);
+ ASSERT_STATE(QList<ExtendedState>() << InitializingSftp << Uploading);
+
+ setFinished();
+}
+
+void MaemoDirectDeviceUploadStep::setFinished()
+{
+ m_extendedState = Inactive;
+ if (m_mkdirProc) {
+ disconnect(m_mkdirProc.data(), 0, this, 0);
+ }
+ if (m_uploader) {
+ disconnect(m_uploader.data(), 0, this, 0);
+ m_uploader->closeChannel();
+ }
+ setDeploymentFinished();
+}
+
+const QString MaemoDirectDeviceUploadStep::Id("MaemoDirectDeviceUploadStep");
+const QString MaemoDirectDeviceUploadStep::DisplayName
+ = tr("Upload files via SFTP");
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodirectdeviceuploadstep.h b/src/plugins/qt4projectmanager/qt-maemo/maemodirectdeviceuploadstep.h
new file mode 100644
index 0000000000..57704580c5
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodirectdeviceuploadstep.h
@@ -0,0 +1,62 @@
+#ifndef MAEMODIRECTDEVICEUPLOADSTEP_H
+#define MAEMODIRECTDEVICEUPLOADSTEP_H
+
+#include "abstractmaemodeploystep.h"
+
+#include <utils/ssh/sftpdefs.h>
+
+#include <QtCore/QList>
+#include <QtCore/QSharedPointer>
+
+namespace Utils {
+class SshRemoteProcess;
+class SftpChannel;
+}
+
+namespace Qt4ProjectManager {
+namespace Internal {
+class MaemoDeployable;
+
+class MaemoDirectDeviceUploadStep : public AbstractMaemoDeployStep
+{
+ Q_OBJECT
+public:
+ MaemoDirectDeviceUploadStep(ProjectExplorer::BuildStepList *bc);
+ MaemoDirectDeviceUploadStep(ProjectExplorer::BuildStepList *bc,
+ MaemoDirectDeviceUploadStep *other);
+ ~MaemoDirectDeviceUploadStep();
+
+ static const QString Id;
+ static const QString DisplayName;
+
+private slots:
+ void handleSftpInitialized();
+ void handleSftpInitializationFailed(const QString &errorMessage);
+ void handleUploadFinished(Utils::SftpJobId jobId, const QString &errorMsg);
+ void handleMkdirFinished(int exitStatus);
+
+private:
+ enum ExtendedState { Inactive, InitializingSftp, Uploading };
+
+ virtual bool isDeploymentPossibleInternal(QString &whynot) const;
+ virtual bool isDeploymentNeeded(const QString &hostName) const;
+ virtual void startInternal();
+ virtual void stopInternal();
+ virtual const AbstractMaemoPackageCreationStep *packagingStep() const { return 0; }
+
+ void ctor();
+ void setFinished();
+ void checkDeploymentNeeded(const QString &hostName,
+ const MaemoDeployable &deployable) const;
+ void uploadNextFile();
+
+ QSharedPointer<Utils::SftpChannel> m_uploader;
+ QSharedPointer<Utils::SshRemoteProcess> m_mkdirProc;
+ mutable QList<MaemoDeployable> m_filesToUpload;
+ ExtendedState m_extendedState;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMODIRECTDEVICEUPLOADSTEP_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.cpp
index ae42de20e4..17823de5f0 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.cpp
@@ -42,10 +42,12 @@
#include <qt4projectmanager/qtversionmanager.h>
#include <utils/environment.h>
-#include <QtGui/QDesktopServices>
+#include <QtCore/QDateTime>
#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
#include <QtCore/QProcess>
#include <QtCore/QString>
+#include <QtGui/QDesktopServices>
namespace Qt4ProjectManager {
namespace Internal {
@@ -55,9 +57,23 @@ static const QLatin1String binQmake("/bin/qmake" EXEC_SUFFIX);
bool MaemoGlobal::isMaemoTargetId(const QString &id)
{
- return id == QLatin1String(Constants::MAEMO5_DEVICE_TARGET_ID)
- || id == QLatin1String(Constants::HARMATTAN_DEVICE_TARGET_ID)
- || id == QLatin1String(Constants::MEEGO_DEVICE_TARGET_ID);
+ return isFremantleTargetId(id) || isHarmattanTargetId(id)
+ || isMeegoTargetId(id);
+}
+
+bool MaemoGlobal::isFremantleTargetId(const QString &id)
+{
+ return id == QLatin1String(Constants::MAEMO5_DEVICE_TARGET_ID);
+}
+
+bool MaemoGlobal::isHarmattanTargetId(const QString &id)
+{
+ return id == QLatin1String(Constants::HARMATTAN_DEVICE_TARGET_ID);
+}
+
+bool MaemoGlobal::isMeegoTargetId(const QString &id)
+{
+ return id == QLatin1String(Constants::MEEGO_DEVICE_TARGET_ID);
}
bool MaemoGlobal::isValidMaemo5QtVersion(const QtVersion *version)
@@ -76,7 +92,7 @@ bool MaemoGlobal::isValidMeegoQtVersion(const Qt4ProjectManager::QtVersion *vers
}
bool MaemoGlobal::isValidMaemoQtVersion(const QtVersion *qtVersion,
- MaemoVersion maemoVersion)
+ OsVersion maemoVersion)
{
if (version(qtVersion) != maemoVersion)
return false;
@@ -106,17 +122,22 @@ QString MaemoGlobal::homeDirOnDevice(const QString &uname)
: QLatin1String("/home/") + uname;
}
-QString MaemoGlobal::remoteSudo()
+QString MaemoGlobal::devrootshPath()
{
return QLatin1String("/usr/lib/mad-developer/devrootsh");
}
-QString MaemoGlobal::remoteCommandPrefix(MaemoVersion maemoVersion,
- const QString &commandFilePath)
+QString MaemoGlobal::remoteSudo(const QString &uname)
+{
+ return uname == QLatin1String("root") ? QString() : devrootshPath();
+}
+
+QString MaemoGlobal::remoteCommandPrefix(OsVersion osVersion,
+ const QString &userName, const QString &commandFilePath)
{
QString prefix = QString::fromLocal8Bit("%1 chmod a+x %2; %3; ")
- .arg(remoteSudo(), commandFilePath, remoteSourceProfilesCommand());
- if (maemoVersion != Maemo5 && maemoVersion != Maemo6)
+ .arg(remoteSudo(userName), commandFilePath, remoteSourceProfilesCommand());
+ if (osVersion != Maemo5 && osVersion != Maemo6)
prefix += QLatin1String("DISPLAY=:0.0 ");
return prefix;
}
@@ -151,7 +172,7 @@ QString MaemoGlobal::failedToConnectToServerMessage(const Utils::SshConnection::
|| connection->errorState() == Utils::SshSocketError) {
errorMsg += tr("\nDid you start Qemu?");
}
- } else if (connection->errorState() == Utils::SshTimeoutError) {
+ } else if (connection->errorState() == Utils::SshTimeoutError) {
errorMsg += tr("\nIs the device connected and set up for network access?");
}
return errorMsg;
@@ -189,13 +210,13 @@ QString MaemoGlobal::madCommand(const QtVersion *qtVersion)
return maddeRoot(qtVersion) + QLatin1String("/bin/mad");
}
-QString MaemoGlobal::madDeveloperUiName(MaemoVersion maemoVersion)
+QString MaemoGlobal::madDeveloperUiName(OsVersion osVersion)
{
- return maemoVersion == Maemo6
+ return osVersion == Maemo6
? tr("SDK Connectivity") : tr("Mad Developer");
}
-MaemoGlobal::MaemoVersion MaemoGlobal::version(const QtVersion *qtVersion)
+MaemoGlobal::OsVersion MaemoGlobal::version(const QtVersion *qtVersion)
{
const QString &name = targetName(qtVersion);
if (name.startsWith(QLatin1String("fremantle")))
@@ -204,7 +225,7 @@ MaemoGlobal::MaemoVersion MaemoGlobal::version(const QtVersion *qtVersion)
return Maemo6;
if (name.startsWith(QLatin1String("meego")))
return Meego;
- return static_cast<MaemoVersion>(-1);
+ return static_cast<OsVersion>(-1);
}
QString MaemoGlobal::architecture(const QtVersion *qtVersion)
@@ -289,6 +310,25 @@ bool MaemoGlobal::copyRecursively(const QString &srcFilePath,
return true;
}
+bool MaemoGlobal::isFileNewerThan(const QString &filePath,
+ const QDateTime &timeStamp)
+{
+ QFileInfo fileInfo(filePath);
+ if (!fileInfo.exists() || fileInfo.lastModified() >= timeStamp)
+ return true;
+ if (fileInfo.isDir()) {
+ const QStringList dirContents = QDir(filePath)
+ .entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
+ foreach (const QString &curFileName, dirContents) {
+ const QString curFilePath
+ = filePath + QLatin1Char('/') + curFileName;
+ if (isFileNewerThan(curFilePath, timeStamp))
+ return true;
+ }
+ }
+ return false;
+}
+
bool MaemoGlobal::callMad(QProcess &proc, const QStringList &args,
const QtVersion *qtVersion, bool useTarget)
{
@@ -334,20 +374,27 @@ QStringList MaemoGlobal::targetArgs(const QtVersion *qtVersion, bool useTarget)
return args;
}
-QString MaemoGlobal::maemoVersionToString(MaemoVersion version)
+QString MaemoGlobal::osVersionToString(OsVersion version)
{
switch (version) {
case Maemo5: return QLatin1String("Maemo5/Fremantle");
case Maemo6: return QLatin1String("Harmattan");
case Meego: return QLatin1String("Meego");
+ case GenericLinux: return QLatin1String("Other Linux");
}
qDebug("%s: Unknown OS Version %d.", Q_FUNC_INFO, version);
return QString();
}
-MaemoGlobal::PackagingSystem MaemoGlobal::packagingSystem(MaemoVersion maemoVersion)
+MaemoGlobal::PackagingSystem MaemoGlobal::packagingSystem(OsVersion osVersion)
{
- return maemoVersion == Meego ? Rpm : Dpkg;
+ switch (osVersion) {
+ case Maemo5: case Maemo6: return Dpkg;
+ case Meego: return Rpm;
+ case GenericLinux: return Tar;
+ default: qFatal("%s: Missing case in switch.", Q_FUNC_INFO);
+ }
+ return static_cast<PackagingSystem>(-1);
}
MaemoGlobal::FileUpdate::FileUpdate(const QString &fileName)
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.h b/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.h
index d4e10eb23f..ea677d443d 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.h
@@ -35,6 +35,7 @@
#include <utils/environment.h>
+#include <projectexplorer/buildstep.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/deployconfiguration.h>
@@ -46,6 +47,7 @@
MaemoGlobal::assertState<State>(expected, actual, Q_FUNC_INFO)
QT_BEGIN_NAMESPACE
+class QDateTime;
class QProcess;
class QString;
QT_END_NAMESPACE
@@ -60,8 +62,8 @@ class MaemoGlobal
{
Q_DECLARE_TR_FUNCTIONS(Qt4ProjectManager::Internal::MaemoGlobal)
public:
- enum MaemoVersion { Maemo5, Maemo6, Meego };
- enum PackagingSystem { Dpkg, Rpm };
+ enum OsVersion { Maemo5, Maemo6, Meego, GenericLinux };
+ enum PackagingSystem { Dpkg, Rpm, Tar };
class FileUpdate {
public:
@@ -72,14 +74,18 @@ public:
};
static bool isMaemoTargetId(const QString &id);
+ static bool isFremantleTargetId(const QString &id);
+ static bool isHarmattanTargetId(const QString &id);
+ static bool isMeegoTargetId(const QString &id);
static bool isValidMaemo5QtVersion(const Qt4ProjectManager::QtVersion *version);
static bool isValidHarmattanQtVersion(const Qt4ProjectManager::QtVersion *version);
static bool isValidMeegoQtVersion(const Qt4ProjectManager::QtVersion *version);
static QString homeDirOnDevice(const QString &uname);
- static QString remoteSudo();
- static QString remoteCommandPrefix(MaemoVersion maemoVersion,
- const QString &commandFilePath);
+ static QString devrootshPath();
+ static QString remoteSudo(const QString &uname);
+ static QString remoteCommandPrefix(OsVersion osVersion,
+ const QString &userName, const QString &commandFilePath);
static QString remoteEnvironment(const QList<Utils::EnvironmentItem> &list);
static QString remoteSourceProfilesCommand();
static QString failedToConnectToServerMessage(const QSharedPointer<Utils::SshConnection> &connection,
@@ -90,8 +96,8 @@ public:
static QString targetRoot(const QtVersion *qtVersion);
static QString targetName(const QtVersion *qtVersion);
static QString madCommand(const QtVersion *qtVersion);
- static QString madDeveloperUiName(MaemoVersion maemoVersion);
- static MaemoVersion version(const QtVersion *qtVersion);
+ static QString madDeveloperUiName(OsVersion maemoVersion);
+ static OsVersion version(const QtVersion *qtVersion);
// TODO: IS this still needed with Qt Version having an Abi?
static QString architecture(const QtVersion *version);
@@ -101,23 +107,27 @@ public:
static bool callMadAdmin(QProcess &proc, const QStringList &args,
const QtVersion *qtVersion, bool useTarget);
- static QString maemoVersionToString(MaemoVersion version);
+ static QString osVersionToString(OsVersion version);
- static PackagingSystem packagingSystem(MaemoVersion maemoVersion);
+ static PackagingSystem packagingSystem(OsVersion osVersion);
static bool removeRecursively(const QString &filePath, QString &error);
static bool copyRecursively(const QString &srcFilePath,
const QString &tgtFilePath, QString *error = 0);
- template<class T> static T *buildStep(const ProjectExplorer::DeployConfiguration *dc)
+ static bool isFileNewerThan(const QString &filePath,
+ const QDateTime &timeStamp);
+
+ template<class T> static T *earlierBuildStep(const ProjectExplorer::DeployConfiguration *dc,
+ const ProjectExplorer::BuildStep *laterBuildStep)
{
if (!dc)
return 0;
- ProjectExplorer::BuildStepList *bsl = dc->stepList();
- if (!bsl)
- return 0;
+ const ProjectExplorer::BuildStepList * const bsl = dc->stepList();
const QList<ProjectExplorer::BuildStep *> &buildSteps = bsl->steps();
- for (int i = buildSteps.count() - 1; i >= 0; --i) {
+ for (int i = 0; i < buildSteps.count(); ++i) {
+ if (buildSteps.at(i) == laterBuildStep)
+ return 0;
if (T * const step = qobject_cast<T *>(buildSteps.at(i)))
return step;
}
@@ -141,7 +151,7 @@ public:
private:
static bool isValidMaemoQtVersion(const Qt4ProjectManager::QtVersion *qtVersion,
- MaemoVersion maemoVersion);
+ OsVersion maemoVersion);
static QString madAdminCommand(const QtVersion *qtVersion);
static bool callMaddeShellScript(QProcess &proc, const QtVersion *qtVersion,
const QString &command, const QStringList &args, bool useTarget);
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoinstalltosysrootstep.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoinstalltosysrootstep.cpp
new file mode 100644
index 0000000000..28aa234c56
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoinstalltosysrootstep.cpp
@@ -0,0 +1,336 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "maemoinstalltosysrootstep.h"
+
+#include "maemodeployables.h"
+#include "maemoglobal.h"
+#include "maemopackagecreationstep.h"
+#include "maemotoolchain.h"
+#include "qt4maemodeployconfiguration.h"
+
+#include <qt4projectmanager/qt4buildconfiguration.h>
+#include <qt4projectmanager/qt4target.h>
+
+#include <QtCore/QLatin1Char>
+#include <QtCore/QProcess>
+
+using namespace ProjectExplorer;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class AbstractMaemoInstallPackageToSysrootWidget : public BuildStepConfigWidget
+{
+ Q_OBJECT
+public:
+ AbstractMaemoInstallPackageToSysrootWidget(AbstractMaemoInstallPackageToSysrootStep *step)
+ : m_step(step) {}
+
+ virtual void init()
+ {
+ BuildStepList * const list
+ = qobject_cast<BuildStepList *>(m_step->parent());
+ connect(list, SIGNAL(stepInserted(int)), SIGNAL(updateSummary()));
+ connect(list, SIGNAL(stepMoved(int,int)), SIGNAL(updateSummary()));
+ connect(list, SIGNAL(aboutToRemoveStep(int)), SLOT(handleStepToBeRemoved(int)));
+ connect(list, SIGNAL(stepRemoved(int)), SIGNAL(updateSummary()));
+ }
+
+ virtual QString summaryText() const
+ {
+ if (!MaemoGlobal::earlierBuildStep<AbstractMaemoPackageCreationStep>(m_step->deployConfiguration(), m_step)) {
+ return QLatin1String("<font color=\"red\">")
+ + tr("Cannot deploy to sysroot: No packaging step found.")
+ + QLatin1String("</font>");
+ }
+ return QLatin1String("<b>") + displayName() + QLatin1String("</b>");
+ }
+
+private:
+ Q_SLOT void handleStepToBeRemoved(int step)
+ {
+ BuildStepList * const list
+ = qobject_cast<BuildStepList *>(m_step->parent());
+ if (list->steps().at(step) == m_step)
+ disconnect(list, 0, this, 0);
+ }
+
+ const AbstractMaemoInstallPackageToSysrootStep * const m_step;
+};
+
+
+class MaemoInstallDebianPackageToSysrootWidget : public AbstractMaemoInstallPackageToSysrootWidget
+{
+ Q_OBJECT
+public:
+ MaemoInstallDebianPackageToSysrootWidget(AbstractMaemoInstallPackageToSysrootStep *step)
+ : AbstractMaemoInstallPackageToSysrootWidget(step) {}
+
+ virtual QString displayName() const { return MaemoInstallDebianPackageToSysrootStep::DisplayName; }
+};
+
+class MaemoInstallRpmPackageToSysrootWidget : public AbstractMaemoInstallPackageToSysrootWidget
+{
+ Q_OBJECT
+public:
+ MaemoInstallRpmPackageToSysrootWidget(AbstractMaemoInstallPackageToSysrootStep *step)
+ : AbstractMaemoInstallPackageToSysrootWidget(step) {}
+
+ virtual QString displayName() const { return MaemoInstallRpmPackageToSysrootStep::DisplayName; }
+};
+
+class MaemoCopyFilesToSysrootWidget : public BuildStepConfigWidget
+{
+ Q_OBJECT
+public:
+ virtual void init() { }
+ virtual QString summaryText() const {
+ return QLatin1String("<b>") + displayName() + QLatin1String("</b>"); }
+ virtual QString displayName() const { return MaemoCopyToSysrootStep::DisplayName; }
+};
+
+
+AbstractMaemoInstallPackageToSysrootStep::AbstractMaemoInstallPackageToSysrootStep(BuildStepList *bsl,
+ const QString &id)
+ : BuildStep(bsl, id)
+{
+}
+
+AbstractMaemoInstallPackageToSysrootStep::AbstractMaemoInstallPackageToSysrootStep(BuildStepList *bsl,
+ AbstractMaemoInstallPackageToSysrootStep *other)
+ : BuildStep(bsl, other)
+{
+}
+
+void AbstractMaemoInstallPackageToSysrootStep::run(QFutureInterface<bool> &fi)
+{
+ const Qt4BuildConfiguration * const bc
+ = qobject_cast<Qt4BaseTarget *>(target())->activeBuildConfiguration();
+ if (!bc) {
+ addOutput(tr("Can't install to sysroot without build configuration."),
+ ErrorMessageOutput);
+ fi.reportResult(false);
+ return;
+ }
+
+ const AbstractMaemoPackageCreationStep * const pStep
+ = MaemoGlobal::earlierBuildStep<AbstractMaemoPackageCreationStep>(deployConfiguration(), this);
+ if (!pStep) {
+ addOutput(tr("Can't install package to sysroot without packaging step."),
+ ErrorMessageOutput);
+ fi.reportResult(false);
+ return;
+ }
+
+ m_installerProcess = new QProcess;
+ connect(m_installerProcess, SIGNAL(readyReadStandardOutput()),
+ SLOT(handleInstallerStdout()));
+ connect(m_installerProcess, SIGNAL(readyReadStandardError()),
+ SLOT(handleInstallerStderr()));
+
+ emit addOutput(tr("Installing package to sysroot ..."), MessageOutput);
+ const QtVersion * const qtVersion = bc->qtVersion();
+ const QString packageFilePath = pStep->packageFilePath();
+ const int packageFileSize = QFileInfo(packageFilePath).size() / (1024*1024);
+ const QStringList args = madArguments() << packageFilePath;
+ MaemoGlobal::callMadAdmin(*m_installerProcess, args, qtVersion, true);
+ if (!m_installerProcess->waitForFinished((2*packageFileSize + 10)*1000)
+ || m_installerProcess->exitStatus() != QProcess::NormalExit
+ || m_installerProcess->exitCode() != 0) {
+ emit addOutput(tr("Installation to sysroot failed, continuing anyway."),
+ ErrorMessageOutput);
+ if (m_installerProcess->state() != QProcess::NotRunning) {
+ m_installerProcess->terminate();
+ m_installerProcess->waitForFinished();
+ m_installerProcess->kill();
+ }
+ fi.reportResult(true);
+ return;
+ }
+
+ fi.reportResult(true);
+ m_installerProcess->deleteLater();
+ m_installerProcess = 0;
+}
+
+void AbstractMaemoInstallPackageToSysrootStep::handleInstallerStdout()
+{
+ if (m_installerProcess)
+ emit addOutput(QString::fromLocal8Bit(m_installerProcess->readAllStandardOutput()), NormalOutput);
+}
+
+void AbstractMaemoInstallPackageToSysrootStep::handleInstallerStderr()
+{
+ if (m_installerProcess)
+ emit addOutput(QString::fromLocal8Bit(m_installerProcess->readAllStandardError()), ErrorOutput);
+}
+
+
+MaemoInstallDebianPackageToSysrootStep::MaemoInstallDebianPackageToSysrootStep(BuildStepList *bsl)
+ : AbstractMaemoInstallPackageToSysrootStep(bsl, Id)
+{
+ setDisplayName(DisplayName);
+}
+
+MaemoInstallDebianPackageToSysrootStep::MaemoInstallDebianPackageToSysrootStep(BuildStepList *bsl,
+ MaemoInstallDebianPackageToSysrootStep *other)
+ : AbstractMaemoInstallPackageToSysrootStep(bsl, other)
+{
+ setDisplayName(DisplayName);
+}
+
+BuildStepConfigWidget *MaemoInstallDebianPackageToSysrootStep::createConfigWidget()
+{
+ return new MaemoInstallDebianPackageToSysrootWidget(this);
+}
+
+
+QStringList MaemoInstallDebianPackageToSysrootStep::madArguments() const
+{
+ return QStringList() << QLatin1String("xdpkg") << QLatin1String("-i")
+ << QLatin1String("--no-force-downgrade");
+}
+
+const QString MaemoInstallDebianPackageToSysrootStep::Id
+ = QLatin1String("MaemoInstallDebianPackageToSysrootStep");
+const QString MaemoInstallDebianPackageToSysrootStep::DisplayName
+ = tr("Install Debian package to sysroot");
+
+MaemoInstallRpmPackageToSysrootStep::MaemoInstallRpmPackageToSysrootStep(BuildStepList *bsl)
+ : AbstractMaemoInstallPackageToSysrootStep(bsl, Id)
+{
+ setDisplayName(DisplayName);
+}
+
+MaemoInstallRpmPackageToSysrootStep::MaemoInstallRpmPackageToSysrootStep(BuildStepList *bsl,
+ MaemoInstallRpmPackageToSysrootStep *other)
+ : AbstractMaemoInstallPackageToSysrootStep(bsl, other)
+{
+ setDisplayName(DisplayName);
+}
+
+BuildStepConfigWidget *MaemoInstallRpmPackageToSysrootStep::createConfigWidget()
+{
+ return new MaemoInstallRpmPackageToSysrootWidget(this);
+}
+
+QStringList MaemoInstallRpmPackageToSysrootStep::madArguments() const
+{
+ return QStringList() << QLatin1String("xrpm") << QLatin1String("-i");
+}
+
+const QString MaemoInstallRpmPackageToSysrootStep::Id
+ = QLatin1String("MaemoInstallRpmPackageToSysrootStep");
+const QString MaemoInstallRpmPackageToSysrootStep::DisplayName
+ = tr("Install RPM package to sysroot");
+
+
+MaemoCopyToSysrootStep::MaemoCopyToSysrootStep(BuildStepList *bsl)
+ : BuildStep(bsl, Id)
+{
+ setDisplayName(DisplayName);
+}
+
+MaemoCopyToSysrootStep::MaemoCopyToSysrootStep(BuildStepList *bsl,
+ MaemoCopyToSysrootStep *other)
+ : BuildStep(bsl, other)
+{
+ setDisplayName(DisplayName);
+}
+
+void MaemoCopyToSysrootStep::run(QFutureInterface<bool> &fi)
+{
+ const Qt4BuildConfiguration * const bc
+ = qobject_cast<Qt4BaseTarget *>(target())->activeBuildConfiguration();
+ if (!bc) {
+ addOutput(tr("Can't copy to sysroot without build configuration."),
+ ErrorMessageOutput);
+ fi.reportResult(false);
+ return;
+ }
+
+ const MaemoToolChain * const tc
+ = dynamic_cast<MaemoToolChain *>(bc->toolChain());
+ if (!tc) {
+ addOutput(tr("Can't copy to sysroot without toolchain."),
+ ErrorMessageOutput);
+ fi.reportResult(false);
+ return;
+ }
+
+ emit addOutput(tr("Copying files to sysroot ..."), MessageOutput);
+ QDir sysRootDir(tc->sysroot());
+ const QSharedPointer<MaemoDeployables> deployables
+ = qobject_cast<Qt4MaemoDeployConfiguration *>(deployConfiguration())->deployables();
+ const QChar sep = QLatin1Char('/');
+ for (int i = 0; i < deployables->deployableCount(); ++i) {
+ const MaemoDeployable &deployable = deployables->deployableAt(i);
+ const QFileInfo localFileInfo(deployable.localFilePath);
+ const QString targetFilePath = tc->sysroot() + sep
+ + deployable.remoteDir + sep + localFileInfo.fileName();
+ if (QFileInfo(targetFilePath).exists()
+ && MaemoGlobal::isFileNewerThan(targetFilePath, localFileInfo.lastModified())) {
+ continue;
+ }
+ sysRootDir.mkpath(deployable.remoteDir.mid(1));
+ QFile::remove(targetFilePath);
+ if (!QFile::copy(deployable.localFilePath, targetFilePath)) {
+ emit addOutput(tr("Sysroot installation failed: "
+ "Could not copy '%1' to '%2'. Continuing anyway.")
+ .arg(QDir::toNativeSeparators(deployable.localFilePath),
+ QDir::toNativeSeparators(targetFilePath)),
+ ErrorMessageOutput);
+ }
+ QCoreApplication::processEvents();
+ if (fi.isCanceled()) {
+ fi.reportResult(false);
+ return;
+ }
+ }
+ fi.reportResult(true);
+}
+
+BuildStepConfigWidget *MaemoCopyToSysrootStep::createConfigWidget()
+{
+ return new MaemoCopyFilesToSysrootWidget;
+}
+
+const QString MaemoCopyToSysrootStep::Id
+ = QLatin1String("MaemoCopyToSysrootStep");
+const QString MaemoCopyToSysrootStep::DisplayName
+ = tr("Copy files to sysroot");
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#include "maemoinstalltosysrootstep.moc"
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoinstalltosysrootstep.h b/src/plugins/qt4projectmanager/qt-maemo/maemoinstalltosysrootstep.h
new file mode 100644
index 0000000000..9fa3d79fba
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoinstalltosysrootstep.h
@@ -0,0 +1,120 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 MAEMOINSTALLTOSYSROOTSTEP_H
+#define MAEMOINSTALLTOSYSROOTSTEP_H
+
+#include <projectexplorer/buildstep.h>
+
+#include <QtCore/QStringList>
+
+QT_FORWARD_DECLARE_CLASS(QProcess);
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class AbstractMaemoInstallPackageToSysrootStep : public ProjectExplorer::BuildStep
+{
+ Q_OBJECT
+public:
+ virtual bool init() { return true; }
+ virtual void run(QFutureInterface<bool> &fi);
+
+protected:
+ AbstractMaemoInstallPackageToSysrootStep(ProjectExplorer::BuildStepList *bsl,
+ const QString &id);
+ AbstractMaemoInstallPackageToSysrootStep(ProjectExplorer::BuildStepList *bsl,
+ AbstractMaemoInstallPackageToSysrootStep *other);
+
+private slots:
+ void handleInstallerStdout();
+ void handleInstallerStderr();
+
+private:
+ virtual QStringList madArguments() const=0;
+
+ QProcess *m_installerProcess;
+};
+
+class MaemoInstallDebianPackageToSysrootStep : public AbstractMaemoInstallPackageToSysrootStep
+{
+ Q_OBJECT
+public:
+ explicit MaemoInstallDebianPackageToSysrootStep(ProjectExplorer::BuildStepList *bsl);
+ MaemoInstallDebianPackageToSysrootStep(ProjectExplorer::BuildStepList *bsl,
+ MaemoInstallDebianPackageToSysrootStep *other);
+
+ virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
+
+ static const QString Id;
+ static const QString DisplayName;
+private:
+ virtual QStringList madArguments() const;
+};
+
+class MaemoInstallRpmPackageToSysrootStep : public AbstractMaemoInstallPackageToSysrootStep
+{
+ Q_OBJECT
+public:
+ explicit MaemoInstallRpmPackageToSysrootStep(ProjectExplorer::BuildStepList *bsl);
+ MaemoInstallRpmPackageToSysrootStep(ProjectExplorer::BuildStepList *bsl,
+ MaemoInstallRpmPackageToSysrootStep *other);
+
+ virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
+
+ static const QString Id;
+ static const QString DisplayName;
+private:
+ virtual QStringList madArguments() const;
+};
+
+class MaemoCopyToSysrootStep : public ProjectExplorer::BuildStep
+{
+ Q_OBJECT
+public:
+ explicit MaemoCopyToSysrootStep(ProjectExplorer::BuildStepList *bsl);
+ MaemoCopyToSysrootStep(ProjectExplorer::BuildStepList *bsl,
+ MaemoCopyToSysrootStep *other);
+
+ virtual bool init() { return true; }
+ virtual void run(QFutureInterface<bool> &fi);
+ virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
+
+ static const QString Id;
+ static const QString DisplayName;
+private:
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOINSTALLTOSYSROOTSTEP_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp
index dcdbfd9acc..bf36c70a75 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp
@@ -33,6 +33,7 @@
#include "maemomanager.h"
#include "maemoconstants.h"
+#include "maemodeployable.h"
#include "maemodeploystepfactory.h"
#include "maemodeviceconfigurations.h"
#include "maemoglobal.h"
@@ -42,6 +43,7 @@
#include "maemorunfactories.h"
#include "maemosettingspages.h"
#include "maemotoolchain.h"
+#include "qt4maemodeployconfiguration.h"
#include "qt4maemotargetfactory.h"
#include "qt4projectmanager/qtversionmanager.h"
#include "qt4projectmanager/qt4projectmanagerconstants.h"
@@ -64,6 +66,7 @@ MaemoManager::MaemoManager()
: QObject(0)
, m_runControlFactory(new MaemoRunControlFactory(this))
, m_runConfigurationFactory(new MaemoRunConfigurationFactory(this))
+ , m_deployConfigurationFactory(new Qt4MaemoDeployConfigurationFactory(this))
, m_packageCreationFactory(new MaemoPackageCreationFactory(this))
, m_deployStepFactory(new MaemoDeployStepFactory(this))
, m_deviceConfigurationsSettingsPage(new MaemoDeviceConfigurationsSettingsPage(this))
@@ -82,12 +85,15 @@ MaemoManager::MaemoManager()
pluginManager->addObject(m_toolChainFactory);
pluginManager->addObject(m_runControlFactory);
pluginManager->addObject(m_runConfigurationFactory);
+ pluginManager->addObject(m_deployConfigurationFactory);
pluginManager->addObject(m_packageCreationFactory);
pluginManager->addObject(m_deployStepFactory);
pluginManager->addObject(m_deviceConfigurationsSettingsPage);
pluginManager->addObject(m_qemuSettingsPage);
pluginManager->addObject(m_publishingFactoryFremantleFree);
pluginManager->addObject(m_maemoTargetFactory);
+
+ qRegisterMetaType<MaemoDeployable>("MaemoDeployable");
}
MaemoManager::~MaemoManager()
@@ -99,6 +105,7 @@ MaemoManager::~MaemoManager()
pluginManager->removeObject(m_deviceConfigurationsSettingsPage);
pluginManager->removeObject(m_deployStepFactory);
pluginManager->removeObject(m_packageCreationFactory);
+ pluginManager->removeObject(m_deployConfigurationFactory);
pluginManager->removeObject(m_runConfigurationFactory);
pluginManager->removeObject(m_runControlFactory);
pluginManager->removeObject(m_toolChainFactory);
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemomanager.h b/src/plugins/qt4projectmanager/qt-maemo/maemomanager.h
index e36f0509b7..041f20cc10 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemomanager.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemomanager.h
@@ -47,6 +47,7 @@ class MaemoRunConfigurationFactory;
class MaemoDeviceConfigurationsSettingsPage;
class MaemoQemuManager;
class MaemoQemuSettingsPage;
+class Qt4MaemoDeployConfigurationFactory;
class Qt4MaemoTargetFactory;
class MaemoToolChainFactory;
@@ -67,6 +68,7 @@ private:
MaemoRunControlFactory *m_runControlFactory;
MaemoRunConfigurationFactory *m_runConfigurationFactory;
+ Qt4MaemoDeployConfigurationFactory *m_deployConfigurationFactory;
MaemoPackageCreationFactory *m_packageCreationFactory;
MaemoDeployStepFactory *m_deployStepFactory;
MaemoDeviceConfigurationsSettingsPage *m_deviceConfigurationsSettingsPage;
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationfactory.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationfactory.cpp
index cb6a8d4634..c326a4b245 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationfactory.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationfactory.cpp
@@ -33,6 +33,8 @@
#include "maemoglobal.h"
#include "maemopackagecreationstep.h"
+#include "qt4maemodeployconfiguration.h"
+#include "qt4maemotarget.h"
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildsteplist.h>
@@ -48,6 +50,9 @@ using ProjectExplorer::BuildStep;
namespace Qt4ProjectManager {
namespace Internal {
+namespace {
+const QString OldCreatePackageId("Qt4ProjectManager.MaemoPackageCreationStep");
+} // anonymous namespace
MaemoPackageCreationFactory::MaemoPackageCreationFactory(QObject *parent)
: ProjectExplorer::IBuildStepFactory(parent)
@@ -56,47 +61,82 @@ MaemoPackageCreationFactory::MaemoPackageCreationFactory(QObject *parent)
QStringList MaemoPackageCreationFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const
{
- if (parent->id() == QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY)
- && MaemoGlobal::isMaemoTargetId(parent->target()->id())
- && !parent->contains(MaemoPackageCreationStep::CreatePackageId))
- return QStringList() << MaemoPackageCreationStep::CreatePackageId;
- return QStringList();
+ if (!qobject_cast<Qt4MaemoDeployConfiguration *>(parent->parent()))
+ return QStringList();
+
+ QStringList ids;
+ if (qobject_cast<AbstractDebBasedQt4MaemoTarget *>(parent->target())
+ && !parent->contains(MaemoDebianPackageCreationStep::CreatePackageId)) {
+ ids << MaemoDebianPackageCreationStep::CreatePackageId;
+ } else if (qobject_cast<AbstractRpmBasedQt4MaemoTarget *>(parent->target())
+ && !parent->contains(MaemoRpmPackageCreationStep::CreatePackageId)) {
+ ids << MaemoRpmPackageCreationStep::CreatePackageId;
+ }
+ if (!qobject_cast<Qt4HarmattanTarget *>(parent->target())
+ && !parent->contains(MaemoTarPackageCreationStep::CreatePackageId)) {
+ ids << MaemoTarPackageCreationStep::CreatePackageId;
+ }
+ return ids;
}
QString MaemoPackageCreationFactory::displayNameForId(const QString &id) const
{
- if (id == MaemoPackageCreationStep::CreatePackageId)
+ if (id == MaemoDebianPackageCreationStep::CreatePackageId) {
+ return QCoreApplication::translate("Qt4ProjectManager::Internal::MaemoPackageCreationFactory",
+ "Create Debian Package");
+ } else if (id == MaemoRpmPackageCreationStep::CreatePackageId) {
+ return QCoreApplication::translate("Qt4ProjectManager::Internal::MaemoPackageCreationFactory",
+ "Create RPM Package");
+ } else if (id == MaemoTarPackageCreationStep::CreatePackageId) {
return QCoreApplication::translate("Qt4ProjectManager::Internal::MaemoPackageCreationFactory",
- "Create Debian Package");
+ "Create tarball");
+ }
return QString();
}
bool MaemoPackageCreationFactory::canCreate(ProjectExplorer::BuildStepList *parent, const QString &id) const
{
- return parent->id() == QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY)
- && id == QLatin1String(MaemoPackageCreationStep::CreatePackageId)
- && MaemoGlobal::isMaemoTargetId(parent->target()->id())
- && !parent->contains(MaemoPackageCreationStep::CreatePackageId);
+ return availableCreationIds(parent).contains(id);
}
BuildStep *MaemoPackageCreationFactory::create(ProjectExplorer::BuildStepList *parent, const QString &id)
{
Q_ASSERT(canCreate(parent, id));
- return new MaemoPackageCreationStep(parent);
+ if (id == MaemoDebianPackageCreationStep::CreatePackageId)
+ return new MaemoDebianPackageCreationStep(parent);
+ else if (id == MaemoRpmPackageCreationStep::CreatePackageId)
+ return new MaemoRpmPackageCreationStep(parent);
+ else if (id == MaemoTarPackageCreationStep::CreatePackageId)
+ return new MaemoTarPackageCreationStep(parent);
+ return 0;
}
bool MaemoPackageCreationFactory::canRestore(ProjectExplorer::BuildStepList *parent,
const QVariantMap &map) const
{
- return canCreate(parent, ProjectExplorer::idFromMap(map));
+ const QString id = ProjectExplorer::idFromMap(map);
+ return canCreate(parent, id) || id == OldCreatePackageId;
}
BuildStep *MaemoPackageCreationFactory::restore(ProjectExplorer::BuildStepList *parent,
const QVariantMap &map)
{
Q_ASSERT(canRestore(parent, map));
- MaemoPackageCreationStep * const step
- = new MaemoPackageCreationStep(parent);
+ BuildStep * step = 0;
+ const QString id = ProjectExplorer::idFromMap(map);
+ if (id == MaemoDebianPackageCreationStep::CreatePackageId
+ || (id == OldCreatePackageId
+ && qobject_cast<AbstractDebBasedQt4MaemoTarget *>(parent->target()))) {
+ step = new MaemoDebianPackageCreationStep(parent);
+ } else if (id == MaemoRpmPackageCreationStep::CreatePackageId
+ || (id == OldCreatePackageId
+ && qobject_cast<AbstractRpmBasedQt4MaemoTarget *>(parent->target()))) {
+ step = new MaemoRpmPackageCreationStep(parent);
+ } else if (id == MaemoTarPackageCreationStep::CreatePackageId) {
+ step = new MaemoTarPackageCreationStep(parent);
+ }
+ Q_ASSERT(step);
+
if (!step->fromMap(map)) {
delete step;
return 0;
@@ -114,7 +154,20 @@ BuildStep *MaemoPackageCreationFactory::clone(ProjectExplorer::BuildStepList *pa
ProjectExplorer::BuildStep *product)
{
Q_ASSERT(canClone(parent, product));
- return new MaemoPackageCreationStep(parent, static_cast<MaemoPackageCreationStep *>(product));
+ MaemoDebianPackageCreationStep * const debianStep
+ = qobject_cast<MaemoDebianPackageCreationStep *>(product);
+ if (debianStep) {
+ return new MaemoDebianPackageCreationStep(parent, debianStep);
+ } else {
+ MaemoRpmPackageCreationStep * const rpmStep
+ = qobject_cast<MaemoRpmPackageCreationStep *>(product);
+ if (rpmStep) {
+ return new MaemoRpmPackageCreationStep(parent, rpmStep);
+ } else {
+ return new MaemoTarPackageCreationStep(parent,
+ qobject_cast<MaemoTarPackageCreationStep *>(product));
+ }
+ }
}
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.cpp
index 7025cf7cf1..6e3370b93b 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.cpp
@@ -33,9 +33,9 @@
#include "maemoconstants.h"
#include "maemodeployables.h"
-#include "maemodeploystep.h"
#include "maemoglobal.h"
#include "maemopackagecreationwidget.h"
+#include "qt4maemodeployconfiguration.h"
#include "qt4maemotarget.h"
#include <projectexplorer/buildsteplist.h>
@@ -52,7 +52,6 @@
#include <QtGui/QWidget>
namespace {
- const QLatin1String PackagingEnabledKey("Packaging Enabled");
const QLatin1String MagicFileName(".qtcreator");
}
@@ -64,31 +63,27 @@ using ProjectExplorer::Task;
namespace Qt4ProjectManager {
namespace Internal {
-const QLatin1String MaemoPackageCreationStep::DefaultVersionNumber("0.0.1");
+const QLatin1String AbstractMaemoPackageCreationStep::DefaultVersionNumber("0.0.1");
-MaemoPackageCreationStep::MaemoPackageCreationStep(BuildStepList *bsl)
- : ProjectExplorer::BuildStep(bsl, CreatePackageId),
- m_packagingEnabled(true)
+AbstractMaemoPackageCreationStep::AbstractMaemoPackageCreationStep(BuildStepList *bsl,
+ const QString &id)
+ : ProjectExplorer::BuildStep(bsl, id)
{
ctor();
}
-MaemoPackageCreationStep::MaemoPackageCreationStep(BuildStepList *bsl,
- MaemoPackageCreationStep *other)
- : BuildStep(bsl, other),
- m_packagingEnabled(other->m_packagingEnabled)
+AbstractMaemoPackageCreationStep::AbstractMaemoPackageCreationStep(BuildStepList *bsl,
+ AbstractMaemoPackageCreationStep *other) : BuildStep(bsl, other)
{
ctor();
}
-MaemoPackageCreationStep::~MaemoPackageCreationStep()
+AbstractMaemoPackageCreationStep::~AbstractMaemoPackageCreationStep()
{
}
-void MaemoPackageCreationStep::ctor()
+void AbstractMaemoPackageCreationStep::ctor()
{
- setDefaultDisplayName(tr("Packaging for Maemo"));
-
m_lastBuildConfig = qt4BuildConfiguration();
connect(target(),
SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
@@ -96,209 +91,42 @@ void MaemoPackageCreationStep::ctor()
handleBuildConfigChanged();
}
-bool MaemoPackageCreationStep::init()
+bool AbstractMaemoPackageCreationStep::init()
{
return true;
}
-QVariantMap MaemoPackageCreationStep::toMap() const
-{
- QVariantMap map(ProjectExplorer::BuildStep::toMap());
- map.insert(PackagingEnabledKey, m_packagingEnabled);
- return map;
-}
-
-bool MaemoPackageCreationStep::fromMap(const QVariantMap &map)
-{
- m_packagingEnabled = map.value(PackagingEnabledKey, true).toBool();
- return ProjectExplorer::BuildStep::fromMap(map);
-}
-
-void MaemoPackageCreationStep::run(QFutureInterface<bool> &fi)
-{
- bool success;
- if (m_packagingEnabled) {
- // TODO: Make the build process asynchronous; i.e. no waitFor()-functions etc.
- QProcess * const buildProc = new QProcess;
- connect(buildProc, SIGNAL(readyReadStandardOutput()), this,
- SLOT(handleBuildOutput()));
- connect(buildProc, SIGNAL(readyReadStandardError()), this,
- SLOT(handleBuildOutput()));
- success = createPackage(buildProc);
- disconnect(buildProc, 0, this, 0);
- buildProc->deleteLater();
- } else {
- success = true;
- }
- fi.reportResult(success);
-}
-
-BuildStepConfigWidget *MaemoPackageCreationStep::createConfigWidget()
-{
- return new MaemoPackageCreationWidget(this);
-}
-
-bool MaemoPackageCreationStep::createPackage(QProcess *buildProc)
+void AbstractMaemoPackageCreationStep::run(QFutureInterface<bool> &fi)
{
if (!packagingNeeded()) {
emit addOutput(tr("Package up to date."), MessageOutput);
- return true;
+ fi.reportResult(true);
+ return;
}
+ // TODO: Make the build process asynchronous; i.e. no waitFor()-functions etc.
+ QProcess * const buildProc = new QProcess;
+ connect(buildProc, SIGNAL(readyReadStandardOutput()), this,
+ SLOT(handleBuildOutput()));
+ connect(buildProc, SIGNAL(readyReadStandardError()), this,
+ SLOT(handleBuildOutput()));
emit addOutput(tr("Creating package file ..."), MessageOutput);
- checkProjectName();
- preparePackagingProcess(buildProc, qt4BuildConfiguration(),
- buildDirectory());
-
- const QString projectDir
- = buildConfiguration()->target()->project()->projectDirectory();
- const bool inSourceBuild
- = QFileInfo(buildDirectory()) == QFileInfo(projectDir);
- if (debBasedMaemoTarget() && !copyDebianFiles(inSourceBuild))
- return false;
-
- const QtVersion * const qtVersion = qt4BuildConfiguration()->qtVersion();
- const QString madCommand = MaemoGlobal::madCommand(qtVersion);
- QStringList args;
- if (debBasedMaemoTarget()) {
- args << QLatin1String("dpkg-buildpackage") << QLatin1String("-nc")
- << QLatin1String("-uc") << QLatin1String("-us");
- } else {
- args << QLatin1String("rrpmbuild") << QLatin1String("-bb")
- << rpmBasedMaemoTarget()->specFilePath();
- }
- const QString cmdLine = madCommand + QLatin1Char(' ')
- + args.join(QLatin1String(" "));
- emit addOutput(tr("Package Creation: Running command '%1'.").arg(cmdLine),
- BuildStep::MessageOutput);
- MaemoGlobal::callMad(*buildProc, args, qtVersion, true);
- 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;
+ const bool success = createPackage(buildProc, fi);
+ disconnect(buildProc, 0, this, 0);
+ buildProc->deleteLater();
+ if (success) {
+ emit addOutput(tr("Package created."), BuildStep::MessageOutput);
+ deployConfig()->deployables()->setUnmodified();
}
-
- QFile::remove(packageFilePath());
- if (debBasedMaemoTarget()) {
- // Workaround for non-working dh_builddeb --destdir=.
- if (!QDir(buildDirectory()).isRoot()) {
- const AbstractQt4MaemoTarget * const target = maemoTarget();
- QString error;
- const QString pkgFileName = target->packageFileName();
- if (!error.isEmpty())
- raiseError(tr("Packaging failed."), "Failed to get package name.");
- const QString changesSourceFileName = QFileInfo(pkgFileName).completeBaseName()
- + QLatin1String(".changes");
- const QString changesTargetFileName = replaceDots(QFileInfo(pkgFileName).completeBaseName())
- + QLatin1String(".changes");
- const QString packageSourceDir = buildDirectory() + QLatin1String("/../");
- const QString packageSourceFilePath
- = packageSourceDir + pkgFileName;
- const QString changesSourceFilePath
- = packageSourceDir + changesSourceFileName;
- const QString changesTargetFilePath
- = buildDirectory() + QLatin1Char('/') + changesTargetFileName;
- QFile::remove(changesTargetFilePath);
- if (!QFile::rename(packageSourceFilePath, packageFilePath())
- || !QFile::rename(changesSourceFilePath, changesTargetFilePath)) {
- raiseError(tr("Packaging failed."),
- tr("Could not move package files from %1 to %2.")
- .arg(packageSourceDir, buildDirectory()));
- return false;
- }
- }
- } else {
- const QString packageSourceFilePath = rpmBuildDir(qt4BuildConfiguration())
- + QLatin1Char('/') + rpmBasedMaemoTarget()->packageFileName();
- if (!QFile::rename(packageSourceFilePath, packageFilePath())) {
- raiseError(tr("Packaging failed."),
- tr("Could not move package file from %1 to %2.")
- .arg(packageSourceFilePath, packageFilePath()));
- return false;
- }
- }
-
- emit addOutput(tr("Package created."), BuildStep::MessageOutput);
- deployStep()->deployables()->setUnmodified();
- if (inSourceBuild && debBasedMaemoTarget()) {
- buildProc->start(packagingCommand(qt4BuildConfiguration(),
- QLatin1String("dh_clean")));
- buildProc->waitForFinished();
- buildProc->terminate();
- }
- return true;
+ fi.reportResult(success);
}
-bool MaemoPackageCreationStep::copyDebianFiles(bool inSourceBuild)
+BuildStepConfigWidget *AbstractMaemoPackageCreationStep::createConfigWidget()
{
- const QString debianDirPath = buildDirectory() + QLatin1String("/debian");
- const QString magicFilePath
- = debianDirPath + QLatin1Char('/') + MagicFileName;
- if (inSourceBuild && QFileInfo(debianDirPath).isDir()
- && !QFileInfo(magicFilePath).exists()) {
- raiseError(tr("Packaging failed: Foreign debian directory detected."),
- tr("You are not using a shadow build and there is a debian "
- "directory in your project root ('%1'). Qt Creator will not "
- "overwrite that directory. Please remove it or use the "
- "shadow build feature.")
- .arg(QDir::toNativeSeparators(debianDirPath)));
- return false;
- }
- QString error;
- if (!MaemoGlobal::removeRecursively(debianDirPath, error)) {
- raiseError(tr("Packaging failed."),
- tr("Could not remove directory '%1': %2").arg(debianDirPath, error));
- return false;
- }
- QDir buildDir(buildDirectory());
- if (!buildDir.mkdir("debian")) {
- raiseError(tr("Could not create Debian directory '%1'.")
- .arg(debianDirPath));
- return false;
- }
- const QString templatesDirPath = debBasedMaemoTarget()->debianDirPath();
- QDir templatesDir(templatesDirPath);
- const QStringList &files = templatesDir.entryList(QDir::Files);
- foreach (const QString &fileName, files) {
- const QString srcFile
- = templatesDirPath + QLatin1Char('/') + fileName;
- const QString destFile
- = debianDirPath + QLatin1Char('/') + fileName;
- if (!QFile::copy(srcFile, destFile)) {
- raiseError(tr("Could not copy file '%1' to '%2'")
- .arg(QDir::toNativeSeparators(srcFile),
- QDir::toNativeSeparators(destFile)));
- return false;
- }
-
- if (fileName == QLatin1String("rules"))
- adaptRulesFile(destFile);
- }
-
- QFile magicFile(magicFilePath);
- if (!magicFile.open(QIODevice::WriteOnly)) {
- raiseError(tr("Error: Could not create file '%1'.")
- .arg(QDir::toNativeSeparators(magicFilePath)));
- return false;
- }
-
- return true;
+ return new MaemoPackageCreationWidget(this);
}
-void MaemoPackageCreationStep::handleBuildOutput()
+void AbstractMaemoPackageCreationStep::handleBuildOutput()
{
QProcess * const buildProc = qobject_cast<QProcess *>(sender());
if (!buildProc)
@@ -306,15 +134,17 @@ void MaemoPackageCreationStep::handleBuildOutput()
QByteArray stdOut = buildProc->readAllStandardOutput();
stdOut.replace('\0', QByteArray()); // Output contains NUL characters.
if (!stdOut.isEmpty())
- emit addOutput(QString::fromLocal8Bit(stdOut), BuildStep::NormalOutput);
+ emit addOutput(QString::fromLocal8Bit(stdOut), BuildStep::NormalOutput,
+ BuildStep::DontAppendNewline);
QByteArray errorOut = buildProc->readAllStandardError();
errorOut.replace('\0', QByteArray());
if (!errorOut.isEmpty()) {
- emit addOutput(QString::fromLocal8Bit(errorOut), BuildStep::ErrorOutput);
+ emit addOutput(QString::fromLocal8Bit(errorOut), BuildStep::ErrorOutput,
+ BuildStep::DontAppendNewline);
}
}
-void MaemoPackageCreationStep::handleBuildConfigChanged()
+void AbstractMaemoPackageCreationStep::handleBuildConfigChanged()
{
if (m_lastBuildConfig)
disconnect(m_lastBuildConfig, 0, this, 0);
@@ -327,102 +157,61 @@ void MaemoPackageCreationStep::handleBuildConfigChanged()
emit packageFilePathChanged();
}
-const Qt4BuildConfiguration *MaemoPackageCreationStep::qt4BuildConfiguration() const
+const Qt4BuildConfiguration *AbstractMaemoPackageCreationStep::qt4BuildConfiguration() const
{
return static_cast<Qt4BuildConfiguration *>(buildConfiguration());
}
-AbstractQt4MaemoTarget *MaemoPackageCreationStep::maemoTarget() const
+AbstractQt4MaemoTarget *AbstractMaemoPackageCreationStep::maemoTarget() const
{
return qobject_cast<AbstractQt4MaemoTarget *>(buildConfiguration()->target());
}
-AbstractDebBasedQt4MaemoTarget *MaemoPackageCreationStep::debBasedMaemoTarget() const
+AbstractDebBasedQt4MaemoTarget *AbstractMaemoPackageCreationStep::debBasedMaemoTarget() const
{
return qobject_cast<AbstractDebBasedQt4MaemoTarget*>(buildConfiguration()->target());
}
-AbstractRpmBasedQt4MaemoTarget *MaemoPackageCreationStep::rpmBasedMaemoTarget() const
+AbstractRpmBasedQt4MaemoTarget *AbstractMaemoPackageCreationStep::rpmBasedMaemoTarget() const
{
return qobject_cast<AbstractRpmBasedQt4MaemoTarget*>(buildConfiguration()->target());
}
-QString MaemoPackageCreationStep::buildDirectory() const
+Qt4MaemoDeployConfiguration *AbstractMaemoPackageCreationStep::deployConfig() const
{
- return qt4BuildConfiguration()->buildDirectory();
+ return qobject_cast<Qt4MaemoDeployConfiguration *>(parent()->parent());
}
-QString MaemoPackageCreationStep::projectName() const
+QString AbstractMaemoPackageCreationStep::buildDirectory() const
{
- return qt4BuildConfiguration()->qt4Target()->qt4Project()
- ->rootProjectNode()->displayName().toLower();
+ return qt4BuildConfiguration()->buildDirectory();
}
-MaemoDeployStep *MaemoPackageCreationStep::deployStep() const
+QString AbstractMaemoPackageCreationStep::projectName() const
{
- MaemoDeployStep * const deployStep
- = MaemoGlobal::buildStep<MaemoDeployStep>(target()->activeDeployConfiguration());
- Q_ASSERT(deployStep &&
- "Fatal error: Maemo build configuration without deploy step.");
- return deployStep;
+ return qt4BuildConfiguration()->qt4Target()->qt4Project()
+ ->rootProjectNode()->displayName().toLower();
}
-bool MaemoPackageCreationStep::packagingNeeded() const
+bool AbstractMaemoPackageCreationStep::packagingNeeded() const
{
const QSharedPointer<MaemoDeployables> &deployables
- = deployStep()->deployables();
+ = deployConfig()->deployables();
QFileInfo packageInfo(packageFilePath());
if (!packageInfo.exists() || deployables->isModified())
return true;
const int deployableCount = deployables->deployableCount();
for (int i = 0; i < deployableCount; ++i) {
- if (isFileNewerThan(deployables->deployableAt(i).localFilePath,
+ if (MaemoGlobal::isFileNewerThan(deployables->deployableAt(i).localFilePath,
packageInfo.lastModified()))
return true;
}
- if (debBasedMaemoTarget()) {
- const QString debianPath = debBasedMaemoTarget()->debianDirPath();
- if (packageInfo.lastModified() <= QFileInfo(debianPath).lastModified())
- return true;
- const QStringList debianFiles = debBasedMaemoTarget()->debianFiles();
- foreach (const QString &debianFile, debianFiles) {
- const QString absFilePath
- = debianPath + QLatin1Char('/') + debianFile;
- if (packageInfo.lastModified() <= QFileInfo(absFilePath).lastModified())
- return true;
- }
- } else {
- const QDateTime specFileChangeDate
- = QFileInfo(rpmBasedMaemoTarget()->specFilePath()).lastModified();
- if (packageInfo.lastModified() <= specFileChangeDate)
- return true;
- }
-
- return false;
-}
-
-bool MaemoPackageCreationStep::isFileNewerThan(const QString &filePath,
- const QDateTime &timeStamp) const
-{
- QFileInfo fileInfo(filePath);
- if (!fileInfo.exists() || fileInfo.lastModified() >= timeStamp)
- return true;
- if (fileInfo.isDir()) {
- const QStringList dirContents = QDir(filePath)
- .entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
- foreach (const QString &curFileName, dirContents) {
- const QString curFilePath
- = filePath + QLatin1Char('/') + curFileName;
- if (isFileNewerThan(curFilePath, timeStamp))
- return true;
- }
- }
- return false;
+ return isMetaDataNewerThan(packageInfo.lastModified());
}
-QString MaemoPackageCreationStep::packageFilePath() const
+QString AbstractMaemoPackageCreationStep::packageFilePath() const
{
QString error;
const QString &version = versionString(&error);
@@ -434,17 +223,12 @@ QString MaemoPackageCreationStep::packageFilePath() const
+ QLatin1Char('.') + fi.suffix();
}
-bool MaemoPackageCreationStep::isPackagingEnabled() const
-{
- return m_packagingEnabled || !maemoTarget()->allowsPackagingDisabling();
-}
-
-QString MaemoPackageCreationStep::versionString(QString *error) const
+QString AbstractMaemoPackageCreationStep::versionString(QString *error) const
{
return maemoTarget()->projectVersion(error);
}
-bool MaemoPackageCreationStep::setVersionString(const QString &version,
+bool AbstractMaemoPackageCreationStep::setVersionString(const QString &version,
QString *error)
{
const bool success = maemoTarget()->setProjectVersion(version, error);
@@ -453,12 +237,12 @@ bool MaemoPackageCreationStep::setVersionString(const QString &version,
return success;
}
-QString MaemoPackageCreationStep::nativePath(const QFile &file)
+QString AbstractMaemoPackageCreationStep::nativePath(const QFile &file)
{
return QDir::toNativeSeparators(QFileInfo(file).filePath());
}
-void MaemoPackageCreationStep::raiseError(const QString &shortMsg,
+void AbstractMaemoPackageCreationStep::raiseError(const QString &shortMsg,
const QString &detailedMsg)
{
emit addOutput(detailedMsg.isNull() ? shortMsg : detailedMsg, BuildStep::ErrorOutput);
@@ -466,7 +250,39 @@ void MaemoPackageCreationStep::raiseError(const QString &shortMsg,
TASK_CATEGORY_BUILDSYSTEM));
}
-void MaemoPackageCreationStep::preparePackagingProcess(QProcess *proc,
+bool AbstractMaemoPackageCreationStep::callPackagingCommand(QProcess *proc,
+ const QStringList &arguments)
+{
+ preparePackagingProcess(proc, qt4BuildConfiguration(), buildDirectory());
+ const QtVersion * const qtVersion = qt4BuildConfiguration()->qtVersion();
+ const QString madCommand = MaemoGlobal::madCommand(qtVersion);
+ const QString cmdLine = madCommand + QLatin1Char(' ')
+ + arguments.join(QLatin1String(" "));
+ emit addOutput(tr("Package Creation: Running command '%1'.").arg(cmdLine),
+ BuildStep::MessageOutput);
+ MaemoGlobal::callMad(*proc, arguments, qtVersion, true);
+ if (!proc->waitForStarted()) {
+ raiseError(tr("Packaging failed."),
+ tr("Packaging error: Could not start command '%1'. Reason: %2")
+ .arg(cmdLine, proc->errorString()));
+ return false;
+ }
+ proc->waitForFinished(-1);
+ if (proc->error() != QProcess::UnknownError || proc->exitCode() != 0) {
+ QString mainMessage = tr("Packaging Error: Command '%1' failed.")
+ .arg(cmdLine);
+ if (proc->error() != QProcess::UnknownError)
+ mainMessage += tr(" Reason: %1").arg(proc->errorString());
+ else
+ mainMessage += tr("Exit code: %1").arg(proc->exitCode());
+ raiseError(mainMessage);
+ return false;
+ }
+ return true;
+}
+
+
+void AbstractMaemoPackageCreationStep::preparePackagingProcess(QProcess *proc,
const Qt4BuildConfiguration *bc, const QString &workingDir)
{
Utils::Environment env = bc->environment();
@@ -478,7 +294,174 @@ void MaemoPackageCreationStep::preparePackagingProcess(QProcess *proc,
proc->setWorkingDirectory(workingDir);
}
-QString MaemoPackageCreationStep::packagingCommand(const Qt4BuildConfiguration *bc,
+QString AbstractMaemoPackageCreationStep::replaceDots(const QString &name)
+{
+ QString adaptedName = name;
+ return adaptedName.replace(QLatin1Char('.'), QLatin1Char('_'));
+}
+
+
+MaemoDebianPackageCreationStep::MaemoDebianPackageCreationStep(BuildStepList *bsl)
+ : AbstractMaemoPackageCreationStep(bsl, CreatePackageId)
+{
+ ctor();
+}
+
+const QString MaemoDebianPackageCreationStep::CreatePackageId
+ = QLatin1String("MaemoDebianPackageCreationStep");
+
+MaemoDebianPackageCreationStep::MaemoDebianPackageCreationStep(BuildStepList *buildConfig,
+ MaemoDebianPackageCreationStep *other)
+ : AbstractMaemoPackageCreationStep(buildConfig, other)
+{
+ ctor();
+}
+
+void MaemoDebianPackageCreationStep::ctor()
+{
+ setDefaultDisplayName(tr("Create Debian Package"));
+}
+
+bool MaemoDebianPackageCreationStep::createPackage(QProcess *buildProc,
+ const QFutureInterface<bool> &fi)
+{
+ Q_UNUSED(fi);
+ checkProjectName();
+ const QString projectDir
+ = buildConfiguration()->target()->project()->projectDirectory();
+ const bool inSourceBuild
+ = QFileInfo(buildDirectory()) == QFileInfo(projectDir);
+ if (!copyDebianFiles(inSourceBuild))
+ return false;
+ const QStringList args = QStringList() << QLatin1String("dpkg-buildpackage")
+ << QLatin1String("-nc") << QLatin1String("-uc") << QLatin1String("-us");
+ if (!callPackagingCommand(buildProc, args))
+ return false;
+
+ QFile::remove(packageFilePath());
+
+ // Workaround for non-working dh_builddeb --destdir=.
+ if (!QDir(buildDirectory()).isRoot()) {
+ const AbstractQt4MaemoTarget * const target = maemoTarget();
+ QString error;
+ const QString pkgFileName = target->packageFileName();
+ if (!error.isEmpty())
+ raiseError(tr("Packaging failed."), "Failed to get package name.");
+ const QString changesSourceFileName = QFileInfo(pkgFileName).completeBaseName()
+ + QLatin1String(".changes");
+ const QString changesTargetFileName = replaceDots(QFileInfo(pkgFileName).completeBaseName())
+ + QLatin1String(".changes");
+ const QString packageSourceDir = buildDirectory() + QLatin1String("/../");
+ const QString packageSourceFilePath
+ = packageSourceDir + pkgFileName;
+ const QString changesSourceFilePath
+ = packageSourceDir + changesSourceFileName;
+ const QString changesTargetFilePath
+ = buildDirectory() + QLatin1Char('/') + changesTargetFileName;
+ QFile::remove(changesTargetFilePath);
+ if (!QFile::rename(packageSourceFilePath, packageFilePath())
+ || !QFile::rename(changesSourceFilePath, changesTargetFilePath)) {
+ raiseError(tr("Packaging failed."),
+ tr("Could not move package files from %1 to %2.")
+ .arg(packageSourceDir, buildDirectory()));
+ return false;
+ }
+ }
+
+ if (inSourceBuild) {
+ buildProc->start(packagingCommand(qt4BuildConfiguration(),
+ QLatin1String("dh_clean")));
+ buildProc->waitForFinished();
+ buildProc->terminate();
+ }
+ return true;
+}
+
+bool MaemoDebianPackageCreationStep::isMetaDataNewerThan(const QDateTime &packageDate) const
+{
+ const QString debianPath = debBasedMaemoTarget()->debianDirPath();
+ if (packageDate <= QFileInfo(debianPath).lastModified())
+ return true;
+ const QStringList debianFiles = debBasedMaemoTarget()->debianFiles();
+ foreach (const QString &debianFile, debianFiles) {
+ const QString absFilePath
+ = debianPath + QLatin1Char('/') + debianFile;
+ if (packageDate <= QFileInfo(absFilePath).lastModified())
+ return true;
+ }
+ return false;
+}
+
+void MaemoDebianPackageCreationStep::checkProjectName()
+{
+ const QRegExp legalName(QLatin1String("[0-9-+a-z\\.]+"));
+ if (!legalName.exactMatch(buildConfiguration()->target()->project()->displayName())) {
+ emit addTask(Task(Task::Warning,
+ tr("Your project name contains characters not allowed in "
+ "Debian packages.\nThey must only use lower-case letters, "
+ "numbers, '-', '+' and '.'.\n""We will try to work around that, "
+ "but you may experience problems."),
+ QString(), -1, TASK_CATEGORY_BUILDSYSTEM));
+ }
+}
+
+bool MaemoDebianPackageCreationStep::copyDebianFiles(bool inSourceBuild)
+{
+ const QString debianDirPath = buildDirectory() + QLatin1String("/debian");
+ const QString magicFilePath
+ = debianDirPath + QLatin1Char('/') + MagicFileName;
+ if (inSourceBuild && QFileInfo(debianDirPath).isDir()
+ && !QFileInfo(magicFilePath).exists()) {
+ raiseError(tr("Packaging failed: Foreign debian directory detected."),
+ tr("You are not using a shadow build and there is a debian "
+ "directory in your project root ('%1'). Qt Creator will not "
+ "overwrite that directory. Please remove it or use the "
+ "shadow build feature.")
+ .arg(QDir::toNativeSeparators(debianDirPath)));
+ return false;
+ }
+ QString error;
+ if (!MaemoGlobal::removeRecursively(debianDirPath, error)) {
+ raiseError(tr("Packaging failed."),
+ tr("Could not remove directory '%1': %2").arg(debianDirPath, error));
+ return false;
+ }
+ QDir buildDir(buildDirectory());
+ if (!buildDir.mkdir("debian")) {
+ raiseError(tr("Could not create Debian directory '%1'.")
+ .arg(debianDirPath));
+ return false;
+ }
+ const QString templatesDirPath = debBasedMaemoTarget()->debianDirPath();
+ QDir templatesDir(templatesDirPath);
+ const QStringList &files = templatesDir.entryList(QDir::Files);
+ foreach (const QString &fileName, files) {
+ const QString srcFile
+ = templatesDirPath + QLatin1Char('/') + fileName;
+ const QString destFile
+ = debianDirPath + QLatin1Char('/') + fileName;
+ if (!QFile::copy(srcFile, destFile)) {
+ raiseError(tr("Could not copy file '%1' to '%2'")
+ .arg(QDir::toNativeSeparators(srcFile),
+ QDir::toNativeSeparators(destFile)));
+ return false;
+ }
+
+ if (fileName == QLatin1String("rules"))
+ adaptRulesFile(destFile);
+ }
+
+ QFile magicFile(magicFilePath);
+ if (!magicFile.open(QIODevice::WriteOnly)) {
+ raiseError(tr("Error: Could not create file '%1'.")
+ .arg(QDir::toNativeSeparators(magicFilePath)));
+ return false;
+ }
+
+ return true;
+}
+
+QString MaemoDebianPackageCreationStep::packagingCommand(const Qt4BuildConfiguration *bc,
const QString &commandName)
{
QString perl;
@@ -489,21 +472,7 @@ QString MaemoPackageCreationStep::packagingCommand(const Qt4BuildConfiguration *
return perl + maddeRoot % QLatin1String("/madbin/") % commandName;
}
-void MaemoPackageCreationStep::checkProjectName()
-{
- if (debBasedMaemoTarget()) {
- const QRegExp legalName(QLatin1String("[0-9-+a-z\\.]+"));
- if (!legalName.exactMatch(buildConfiguration()->target()->project()->displayName())) {
- emit addTask(Task(Task::Warning,
- tr("Your project name contains characters not allowed in Debian packages.\n"
- "They must only use lower-case letters, numbers, '-', '+' and '.'.\n"
- "We will try to work around that, but you may experience problems."),
- QString(), -1, TASK_CATEGORY_BUILDSYSTEM));
- }
- }
-}
-
-void MaemoPackageCreationStep::ensureShlibdeps(QByteArray &rulesContent)
+void MaemoDebianPackageCreationStep::ensureShlibdeps(QByteArray &rulesContent)
{
QString contentAsString = QString::fromLocal8Bit(rulesContent);
const QString whiteSpace(QLatin1String("[ \\t]*"));
@@ -515,7 +484,7 @@ void MaemoPackageCreationStep::ensureShlibdeps(QByteArray &rulesContent)
rulesContent = contentAsString.toLocal8Bit();
}
-void MaemoPackageCreationStep::adaptRulesFile(const QString &rulesFilePath)
+void MaemoDebianPackageCreationStep::adaptRulesFile(const QString &rulesFilePath)
{
QFile rulesFile(rulesFilePath);
rulesFile.setPermissions(rulesFile.permissions() | QFile::ExeUser);
@@ -534,7 +503,7 @@ void MaemoPackageCreationStep::adaptRulesFile(const QString &rulesFilePath)
+ QLatin1Char('/') + maemoTarget()->packageName()
+ QLatin1String("/usr/share/applications/");
const Qt4BuildConfiguration * const bc = qt4BuildConfiguration();
- const MaemoGlobal::MaemoVersion version
+ const MaemoGlobal::OsVersion version
= MaemoGlobal::version(bc->qtVersion());
if (version == MaemoGlobal::Maemo5)
desktopFileDir += QLatin1String("hildon/");
@@ -543,9 +512,9 @@ void MaemoPackageCreationStep::adaptRulesFile(const QString &rulesFilePath)
desktopFileDir.prepend(QLatin1Char('/'));
#endif
int insertPos = makeInstallEol + 1;
- for (int i = 0; i < deployStep()->deployables()->modelCount(); ++i) {
+ for (int i = 0; i < deployConfig()->deployables()->modelCount(); ++i) {
const MaemoDeployableListModel * const model
- = deployStep()->deployables()->modelAt(i);
+ = deployConfig()->deployables()->modelAt(i);
if (!model->hasDesktopFile())
continue;
if (version == MaemoGlobal::Maemo6) {
@@ -574,7 +543,7 @@ void MaemoPackageCreationStep::adaptRulesFile(const QString &rulesFilePath)
rulesFile.write(content);
}
-void MaemoPackageCreationStep::addWorkaroundForHarmattanBug(QByteArray &rulesFileContent,
+void MaemoDebianPackageCreationStep::addWorkaroundForHarmattanBug(QByteArray &rulesFileContent,
int &insertPos, const MaemoDeployableListModel *model,
const QString &desktopFileDir)
{
@@ -589,7 +558,7 @@ void MaemoPackageCreationStep::addWorkaroundForHarmattanBug(QByteArray &rulesFil
lineBefore, lineAfter);
}
-void MaemoPackageCreationStep::addSedCmdToRulesFile(QByteArray &rulesFileContent,
+void MaemoDebianPackageCreationStep::addSedCmdToRulesFile(QByteArray &rulesFileContent,
int &insertPos, const QString &desktopFilePath, const QByteArray &oldString,
const QByteArray &newString)
{
@@ -605,18 +574,316 @@ void MaemoPackageCreationStep::addSedCmdToRulesFile(QByteArray &rulesFileContent
insertPos += mvCmd.length();
}
-QString MaemoPackageCreationStep::replaceDots(const QString &name)
+
+MaemoRpmPackageCreationStep::MaemoRpmPackageCreationStep(BuildStepList *bsl)
+ : AbstractMaemoPackageCreationStep(bsl, CreatePackageId)
{
- QString adaptedName = name;
- return adaptedName.replace(QLatin1Char('.'), QLatin1Char('_'));
+ ctor();
+}
+
+MaemoRpmPackageCreationStep::MaemoRpmPackageCreationStep(BuildStepList *buildConfig,
+ MaemoRpmPackageCreationStep *other)
+ : AbstractMaemoPackageCreationStep(buildConfig, other)
+{
+ ctor();
+}
+
+void MaemoRpmPackageCreationStep::ctor()
+{
+ setDefaultDisplayName(tr("Create RPM Package"));
+}
+
+bool MaemoRpmPackageCreationStep::createPackage(QProcess *buildProc,
+ const QFutureInterface<bool> &fi)
+{
+ Q_UNUSED(fi);
+ const QStringList args = QStringList() << QLatin1String("rrpmbuild")
+ << QLatin1String("-bb") << rpmBasedMaemoTarget()->specFilePath();
+ if (!callPackagingCommand(buildProc, args))
+ return false;
+ QFile::remove(packageFilePath());
+ const QString packageSourceFilePath = rpmBuildDir(qt4BuildConfiguration())
+ + QLatin1Char('/') + rpmBasedMaemoTarget()->packageFileName();
+ if (!QFile::rename(packageSourceFilePath, packageFilePath())) {
+ raiseError(tr("Packaging failed."),
+ tr("Could not move package file from %1 to %2.")
+ .arg(packageSourceFilePath, packageFilePath()));
+ return false;
+ }
+
+ return true;
}
-QString MaemoPackageCreationStep::rpmBuildDir(const Qt4BuildConfiguration *bc)
+bool MaemoRpmPackageCreationStep::isMetaDataNewerThan(const QDateTime &packageDate) const
+{
+ const QDateTime specFileChangeDate
+ = QFileInfo(rpmBasedMaemoTarget()->specFilePath()).lastModified();
+ return packageDate <= specFileChangeDate;
+}
+
+QString MaemoRpmPackageCreationStep::rpmBuildDir(const Qt4BuildConfiguration *bc)
{
return bc->buildDirectory() + QLatin1String("/rrpmbuild");
}
-const QLatin1String MaemoPackageCreationStep::CreatePackageId("Qt4ProjectManager.MaemoPackageCreationStep");
+const QString MaemoRpmPackageCreationStep::CreatePackageId
+ = QLatin1String("MaemoRpmPackageCreationStep");
+
+
+
+class CreateTarStepWidget : public BuildStepConfigWidget
+{
+ Q_OBJECT
+public:
+ CreateTarStepWidget(MaemoTarPackageCreationStep *step) : m_step(step) {}
+
+ virtual void init()
+ {
+ connect(m_step, SIGNAL(packageFilePathChanged()),
+ SIGNAL(updateSummary()));
+ }
+
+ virtual QString summaryText() const
+ {
+ return QLatin1String("<b>") + tr("Create tarball:")
+ + QLatin1String("</b> ") + m_step->packageFilePath();
+ }
+
+ virtual QString displayName() const { return QString(); }
+
+private:
+ const MaemoTarPackageCreationStep * const m_step;
+};
+
+namespace {
+const int TarBlockSize = 512;
+struct TarFileHeader {
+ char fileName[100];
+ char fileMode[8];
+ char uid[8];
+ char gid[8];
+ char length[12];
+ char mtime[12];
+ char chksum[8];
+ char typeflag;
+ char linkname[100];
+ char magic[6];
+ char version[2];
+ char uname[32];
+ char gname[32];
+ char devmajor[8];
+ char devminor[8];
+ char fileNamePrefix[155];
+ char padding[12];
+};
+} // Anonymous namespace.
+
+MaemoTarPackageCreationStep::MaemoTarPackageCreationStep(BuildStepList *bsl)
+ : AbstractMaemoPackageCreationStep(bsl, CreatePackageId)
+{
+ ctor();
+}
+
+MaemoTarPackageCreationStep::MaemoTarPackageCreationStep(BuildStepList *buildConfig,
+ MaemoTarPackageCreationStep *other)
+ : AbstractMaemoPackageCreationStep(buildConfig, other)
+{
+ ctor();
+}
+
+void MaemoTarPackageCreationStep::ctor()
+{
+ setDefaultDisplayName(tr("Create tar ball"));
+}
+
+bool MaemoTarPackageCreationStep::createPackage(QProcess *buildProc,
+ const QFutureInterface<bool> &fi)
+{
+ Q_UNUSED(buildProc);
+
+ // TODO: Optimization: Only package changed files (needs refactoring in upper level; worth the effort?)
+ QFile tarFile(packageFilePath());
+ if (!tarFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ raiseError(tr("Error: tar file %1 cannot be opened (%2).")
+ .arg(QDir::toNativeSeparators(packageFilePath()),
+ tarFile.errorString()));
+ return false;
+ }
+ const QSharedPointer<MaemoDeployables> deployables = deployConfig()->deployables();
+ for (int i = 0; i < deployables->deployableCount(); ++i) {
+ const MaemoDeployable &d = deployables->deployableAt(i);
+ QFileInfo fileInfo(d.localFilePath);
+ if (!appendFile(tarFile, fileInfo, d.remoteDir + QLatin1Char('/')
+ + fileInfo.fileName(), fi)) {
+ return false;
+ }
+ }
+
+ const QByteArray eofIndicator(2*sizeof(TarFileHeader), 0);
+ if (tarFile.write(eofIndicator) != eofIndicator.length()) {
+ raiseError(tr("Error writing tar file '%1': %2.")
+ .arg(QDir::toNativeSeparators(tarFile.fileName()),
+ tarFile.errorString()));
+ return false;
+ }
+
+ return true;
+}
+
+bool MaemoTarPackageCreationStep::appendFile(QFile &tarFile,
+ const QFileInfo &fileInfo, const QString &remoteFilePath,
+ const QFutureInterface<bool> &fi)
+{
+ if (!writeHeader(tarFile, fileInfo, remoteFilePath))
+ return false;
+ if (fileInfo.isDir()) {
+ QDir dir(fileInfo.absoluteFilePath());
+ foreach (const QString &fileName,
+ dir.entryList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
+ const QString thisLocalFilePath
+ = dir.path() + QLatin1Char('/') + fileName;
+ const QString thisRemoteFilePath = remoteFilePath
+ + QLatin1Char('/') + fileName;
+ if (!appendFile(tarFile, QFileInfo(thisLocalFilePath),
+ thisRemoteFilePath, fi)) {
+ return false;
+ }
+ }
+ } else {
+ const QString nativePath
+ = QDir::toNativeSeparators(fileInfo.filePath());
+ QFile file(fileInfo.filePath());
+ if (!file.open(QIODevice::ReadOnly)) {
+ raiseError(tr("Error reading file '%1': %2.")
+ .arg(nativePath, file.errorString()));
+ return false;
+ }
+
+ const int chunkSize = 1024*1024;
+
+ // TODO: Wasteful. Work with fixed-size buffer.
+ while (!file.atEnd() && !file.error() != QFile::NoError
+ && !tarFile.error() != QFile::NoError) {
+ const QByteArray data = file.read(chunkSize);
+ tarFile.write(data);
+ if (fi.isCanceled())
+ return false;
+ }
+ if (file.error() != QFile::NoError) {
+ raiseError(tr("Error reading file '%1': %2.")
+ .arg(nativePath, file.errorString()));
+ return false;
+ }
+
+ const int blockModulo = file.size() % TarBlockSize;
+ if (blockModulo != 0) {
+ tarFile.write(QByteArray(TarBlockSize - blockModulo, 0));
+ }
+
+ if (tarFile.error() != QFile::NoError) {
+ raiseError(tr("Error writing tar file '%1': %2.")
+ .arg(QDir::toNativeSeparators(tarFile.fileName()),
+ tarFile.errorString()));
+ return false;
+ }
+ }
+ return true;
+}
+
+bool MaemoTarPackageCreationStep::writeHeader(QFile &tarFile,
+ const QFileInfo &fileInfo, const QString &remoteFilePath)
+{
+ TarFileHeader header;
+ qMemSet(&header, '\0', sizeof header);
+ const QByteArray &filePath = remoteFilePath.toUtf8();
+ const int maxFilePathLength = sizeof header.fileNamePrefix
+ + sizeof header.fileName;
+ if (filePath.count() > maxFilePathLength) {
+ raiseError(tr("Cannot tar file '%1': path is too long.")
+ .arg(QDir::toNativeSeparators(filePath)));
+ return false;
+ }
+
+ const int fileNameBytesToWrite
+ = qMin<int>(filePath.length(), sizeof header.fileName);
+ const int fileNameOffset = filePath.length() - fileNameBytesToWrite;
+ qMemCopy(&header.fileName, filePath.data() + fileNameOffset,
+ fileNameBytesToWrite);
+ if (fileNameOffset > 0)
+ qMemCopy(&header.fileNamePrefix, filePath.data(), fileNameOffset);
+ int permissions = (0400 * fileInfo.permission(QFile::ReadOwner))
+ | (0200 * fileInfo.permission(QFile::WriteOwner))
+ | (0100 * fileInfo.permission(QFile::ExeOwner))
+ | (040 * fileInfo.permission(QFile::ReadGroup))
+ | (020 * fileInfo.permission(QFile::WriteGroup))
+ | (010 * fileInfo.permission(QFile::ExeGroup))
+ | (04 * fileInfo.permission(QFile::ReadOther))
+ | (02 * fileInfo.permission(QFile::WriteOther))
+ | (01 * fileInfo.permission(QFile::ExeOther));
+ const QByteArray permissionString = QString("%1").arg(permissions,
+ sizeof header.fileMode - 1, 8, QLatin1Char('0')).toAscii();
+ qMemCopy(&header.fileMode, permissionString.data(),
+ permissionString.length());
+ const QByteArray uidString = QString("%1").arg(fileInfo.ownerId(),
+ sizeof header.uid - 1, 8, QLatin1Char('0')).toAscii();
+ qMemCopy(&header.uid, uidString.data(), uidString.length());
+ const QByteArray gidString = QString("%1").arg(fileInfo.groupId(),
+ sizeof header.gid - 1, 8, QLatin1Char('0')).toAscii();
+ qMemCopy(&header.gid, gidString.data(), gidString.length());
+ const QByteArray sizeString = QString("%1").arg(fileInfo.size(),
+ sizeof header.length - 1, 8, QLatin1Char('0')).toAscii();
+ qMemCopy(&header.length, sizeString.data(), sizeString.length());
+ const QByteArray mtimeString = QString("%1").arg(fileInfo.lastModified().toTime_t(),
+ sizeof header.mtime - 1, 8, QLatin1Char('0')).toAscii();
+ qMemCopy(&header.mtime, mtimeString.data(), mtimeString.length());
+ if (fileInfo.isDir())
+ header.typeflag = '5';
+ qMemCopy(&header.magic, "ustar", sizeof "ustar");
+ qMemCopy(&header.version, "00", 2);
+ const QByteArray &owner = fileInfo.owner().toUtf8();
+ qMemCopy(&header.uname, owner.data(),
+ qMin<int>(owner.length(), sizeof header.uname - 1));
+ const QByteArray &group = fileInfo.group().toUtf8();
+ qMemCopy(&header.gname, group.data(),
+ qMin<int>(group.length(), sizeof header.gname - 1));
+ qMemSet(&header.chksum, ' ', sizeof header.chksum);
+ quint64 checksum = 0;
+ for (size_t i = 0; i < sizeof header; ++i)
+ checksum += reinterpret_cast<char *>(&header)[i];
+ const QByteArray checksumString = QString("%1").arg(checksum,
+ sizeof header.chksum - 1, 8, QLatin1Char('0')).toAscii();
+ qMemCopy(&header.chksum, checksumString.data(), checksumString.length());
+ header.chksum[sizeof header.chksum-1] = 0;
+ if (!tarFile.write(reinterpret_cast<char *>(&header), sizeof header)) {
+ raiseError(tr("Error writing tar file '%1': %2")
+ .arg(QDir::toNativeSeparators(packageFilePath()),
+ tarFile.errorString()));
+ return false;
+ }
+ return true;
+}
+
+bool MaemoTarPackageCreationStep::isMetaDataNewerThan(const QDateTime &packageDate) const
+{
+ Q_UNUSED(packageDate);
+ return false;
+}
+
+QString MaemoTarPackageCreationStep::packageFilePath() const
+{
+ return buildDirectory() + QLatin1Char('/') + projectName()
+ + QLatin1String(".tar");
+}
+
+BuildStepConfigWidget *MaemoTarPackageCreationStep::createConfigWidget()
+{
+ return new CreateTarStepWidget(this);
+}
+
+const QString MaemoTarPackageCreationStep::CreatePackageId
+ = QLatin1String("MaemoTarPackageCreationStep");
} // namespace Internal
} // namespace Qt4ProjectManager
+
+#include "maemopackagecreationstep.moc"
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.h b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.h
index 297cec5903..d630a230d4 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.h
@@ -37,6 +37,7 @@
QT_BEGIN_NAMESPACE
class QDateTime;
class QFile;
+class QFileInfo;
class QProcess;
QT_END_NAMESPACE
@@ -44,38 +45,32 @@ namespace Qt4ProjectManager {
class Qt4BuildConfiguration;
namespace Internal {
-class MaemoDeployStep;
class MaemoDeployableListModel;
class AbstractQt4MaemoTarget;
class AbstractDebBasedQt4MaemoTarget;
class AbstractRpmBasedQt4MaemoTarget;
+class Qt4MaemoDeployConfiguration;
-class MaemoPackageCreationStep : public ProjectExplorer::BuildStep
+class AbstractMaemoPackageCreationStep : public ProjectExplorer::BuildStep
{
Q_OBJECT
- friend class MaemoPackageCreationFactory;
public:
- MaemoPackageCreationStep(ProjectExplorer::BuildStepList *bsl);
- ~MaemoPackageCreationStep();
+ virtual ~AbstractMaemoPackageCreationStep();
- QString packageFilePath() const;
- bool isPackagingEnabled() const;
- void setPackagingEnabled(bool enabled) { m_packagingEnabled = enabled; }
+ virtual QString packageFilePath() const;
QString versionString(QString *error) const;
bool setVersionString(const QString &version, QString *error);
static void preparePackagingProcess(QProcess *proc,
const Qt4BuildConfiguration *bc, const QString &workingDir);
- static QString packagingCommand(const Qt4BuildConfiguration *bc,
- const QString &commandName);
- static void ensureShlibdeps(QByteArray &rulesContent);
QString projectName() const;
const Qt4BuildConfiguration *qt4BuildConfiguration() const;
AbstractQt4MaemoTarget *maemoTarget() const;
AbstractDebBasedQt4MaemoTarget *debBasedMaemoTarget() const;
AbstractRpmBasedQt4MaemoTarget *rpmBasedMaemoTarget() const;
+ Qt4MaemoDeployConfiguration *deployConfig() const;
static const QLatin1String DefaultVersionNumber;
@@ -83,47 +78,113 @@ signals:
void packageFilePathChanged();
void qtVersionChanged();
+protected:
+ AbstractMaemoPackageCreationStep(ProjectExplorer::BuildStepList *bsl,
+ const QString &id);
+ AbstractMaemoPackageCreationStep(ProjectExplorer::BuildStepList *buildConfig,
+ AbstractMaemoPackageCreationStep *other);
+
+ void raiseError(const QString &shortMsg,
+ const QString &detailedMsg = QString());
+ bool callPackagingCommand(QProcess *proc, const QStringList &arguments);
+ static QString replaceDots(const QString &name);
+ QString buildDirectory() const;
+
private slots:
void handleBuildOutput();
void handleBuildConfigChanged();
private:
- MaemoPackageCreationStep(ProjectExplorer::BuildStepList *buildConfig,
- MaemoPackageCreationStep *other);
-
void ctor();
virtual bool init();
virtual void run(QFutureInterface<bool> &fi);
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
- virtual bool immutable() const { return true; }
- virtual QVariantMap toMap() const;
- virtual bool fromMap(const QVariantMap &map);
- bool createPackage(QProcess *buildProc);
- bool copyDebianFiles(bool inSourceBuild);
+ virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi)=0;
+ virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const=0;
+
static QString nativePath(const QFile &file);
bool packagingNeeded() const;
- bool isFileNewerThan(const QString &filePath,
- const QDateTime &timeStamp) const;
- void raiseError(const QString &shortMsg,
- const QString &detailedMsg = QString());
- QString buildDirectory() const;
- MaemoDeployStep * deployStep() const;
- void checkProjectName();
- void adaptRulesFile(const QString &rulesFilePath);
- void addWorkaroundForHarmattanBug(QByteArray &rulesFileContent,
- int &insertPos, const MaemoDeployableListModel *model,
- const QString &desktopFileDir);
+
+ const Qt4BuildConfiguration *m_lastBuildConfig;
+};
+
+
+class MaemoDebianPackageCreationStep : public AbstractMaemoPackageCreationStep
+{
+ Q_OBJECT
+ friend class MaemoPackageCreationFactory;
+public:
+ MaemoDebianPackageCreationStep(ProjectExplorer::BuildStepList *bsl);
+
+ static void ensureShlibdeps(QByteArray &rulesContent);
+
+private:
+ MaemoDebianPackageCreationStep(ProjectExplorer::BuildStepList *buildConfig,
+ MaemoDebianPackageCreationStep *other);
+
+ virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi);
+ virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const;
+
+ void ctor();
+ static QString packagingCommand(const Qt4BuildConfiguration *bc,
+ const QString &commandName);
+ bool copyDebianFiles(bool inSourceBuild);
void addSedCmdToRulesFile(QByteArray &rulesFileContent, int &insertPos,
const QString &desktopFilePath, const QByteArray &oldString,
const QByteArray &newString);
- static QString replaceDots(const QString &name);
+ void addWorkaroundForHarmattanBug(QByteArray &rulesFileContent,
+ int &insertPos, const MaemoDeployableListModel *model,
+ const QString &desktopFileDir);
+ void checkProjectName();
+ void adaptRulesFile(const QString &rulesFilePath);
+
+ static const QString CreatePackageId;
+};
+
+class MaemoRpmPackageCreationStep : public AbstractMaemoPackageCreationStep
+{
+ Q_OBJECT
+ friend class MaemoPackageCreationFactory;
+public:
+ MaemoRpmPackageCreationStep(ProjectExplorer::BuildStepList *bsl);
+
+private:
+ virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi);
+ virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const;
+
+ MaemoRpmPackageCreationStep(ProjectExplorer::BuildStepList *buildConfig,
+ MaemoRpmPackageCreationStep *other);
+
+ void ctor();
static QString rpmBuildDir(const Qt4BuildConfiguration *bc);
- static const QLatin1String CreatePackageId;
+ static const QString CreatePackageId;
+};
- bool m_packagingEnabled;
- const Qt4BuildConfiguration *m_lastBuildConfig;
+class MaemoTarPackageCreationStep : public AbstractMaemoPackageCreationStep
+{
+ Q_OBJECT
+ friend class MaemoPackageCreationFactory;
+public:
+ MaemoTarPackageCreationStep(ProjectExplorer::BuildStepList *bsl);
+
+ virtual QString packageFilePath() const;
+private:
+ virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi);
+ virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const;
+ virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
+
+ MaemoTarPackageCreationStep(ProjectExplorer::BuildStepList *buildConfig,
+ MaemoTarPackageCreationStep *other);
+
+ void ctor();
+ bool appendFile(QFile &tarFile, const QFileInfo &fileInfo,
+ const QString &remoteFilePath, const QFutureInterface<bool> &fi);
+ bool writeHeader(QFile &tarFile, const QFileInfo &fileInfo,
+ const QString &remoteFilePath);
+
+ static const QString CreatePackageId;
};
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.cpp
index f1abd97a0e..6bd29b0f72 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.cpp
@@ -52,13 +52,13 @@ using namespace ProjectExplorer;
namespace Qt4ProjectManager {
namespace Internal {
-MaemoPackageCreationWidget::MaemoPackageCreationWidget(MaemoPackageCreationStep *step)
+// TODO: Split up into dedicated widgets for Debian and RPM steps.
+MaemoPackageCreationWidget::MaemoPackageCreationWidget(AbstractMaemoPackageCreationStep *step)
: ProjectExplorer::BuildStepConfigWidget(),
m_step(step),
m_ui(new Ui::MaemoPackageCreationWidget)
{
m_ui->setupUi(this);
- m_ui->skipCheckBox->setChecked(!m_step->isPackagingEnabled());
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QTimer::singleShot(0, this, SLOT(initGui()));
}
@@ -74,12 +74,6 @@ void MaemoPackageCreationWidget::init()
void MaemoPackageCreationWidget::initGui()
{
- // The "remove" stuff below is fragile; be careful when editing the UI file.
- m_ui->skipCheckBox->setChecked(!m_step->isPackagingEnabled());
- if (!m_step->maemoTarget()->allowsPackagingDisabling()) {
- m_ui->skipCheckBox->hide();
- m_ui->formLayout->removeItem(m_ui->formLayout->itemAt(0, QFormLayout::FieldRole));
- }
m_ui->shortDescriptionLineEdit->setMaxLength(60);
updateVersionInfo();
versionInfoChanged();
@@ -105,12 +99,14 @@ void MaemoPackageCreationWidget::initGui()
m_ui->editDebianFileLabel->hide();
m_ui->debianFilesComboBox->hide();
m_ui->editDebianFileButton->hide();
+
+ // This is fragile; be careful when editing the UI file.
+ m_ui->formLayout->removeItem(m_ui->formLayout->itemAt(4, QFormLayout::LabelRole));
+ m_ui->formLayout->removeItem(m_ui->formLayout->itemAt(4, QFormLayout::FieldRole));
m_ui->formLayout->removeItem(m_ui->formLayout->itemAt(5, QFormLayout::LabelRole));
m_ui->formLayout->removeItem(m_ui->formLayout->itemAt(5, QFormLayout::FieldRole));
m_ui->formLayout->removeItem(m_ui->formLayout->itemAt(6, QFormLayout::LabelRole));
m_ui->formLayout->removeItem(m_ui->formLayout->itemAt(6, QFormLayout::FieldRole));
- m_ui->formLayout->removeItem(m_ui->formLayout->itemAt(7, QFormLayout::LabelRole));
- m_ui->formLayout->removeItem(m_ui->formLayout->itemAt(7, QFormLayout::FieldRole));
handleSpecFileUpdate();
connect(m_step->rpmBasedMaemoTarget(), SIGNAL(specFileChanged()),
SLOT(handleSpecFileUpdate()));
@@ -142,7 +138,7 @@ void MaemoPackageCreationWidget::updateVersionInfo()
QString versionString = m_step->versionString(&error);
if (versionString.isEmpty()) {
QMessageBox::critical(this, tr("No Version Available."), error);
- versionString = MaemoPackageCreationStep::DefaultVersionNumber;
+ versionString = AbstractMaemoPackageCreationStep::DefaultVersionNumber;
}
const QStringList list = versionString.split(QLatin1Char('.'),
QString::SkipEmptyParts);
@@ -238,11 +234,8 @@ void MaemoPackageCreationWidget::setShortDescription()
QString MaemoPackageCreationWidget::summaryText() const
{
- const QString constantString = tr("<b>Create Package:</b> ");
- const QString dynamicString = m_step->isPackagingEnabled()
- ? QDir::toNativeSeparators(m_step->packageFilePath())
- : tr("(Packaging disabled)");
- return constantString + dynamicString;
+ return tr("<b>Create Package:</b> ")
+ + QDir::toNativeSeparators(m_step->packageFilePath());
}
QString MaemoPackageCreationWidget::displayName() const
@@ -250,22 +243,6 @@ QString MaemoPackageCreationWidget::displayName() const
return m_step->displayName();
}
-void MaemoPackageCreationWidget::handleSkipButtonToggled(bool checked)
-{
- m_ui->major->setEnabled(!checked);
- m_ui->minor->setEnabled(!checked);
- m_ui->patch->setEnabled(!checked);
- m_ui->debianFilesComboBox->setEnabled(!checked);
- m_ui->editDebianFileButton->setEnabled(!checked);
- m_ui->editSpecFileButton->setEnabled(!checked);
- m_ui->packageManagerIconButton->setEnabled(!checked);
- m_ui->packageNameLineEdit->setEnabled(!checked);
- m_ui->packageManagerNameLineEdit->setEnabled(!checked);
- m_ui->shortDescriptionLineEdit->setEnabled(!checked);
- m_step->setPackagingEnabled(!checked);
- emit updateSummary();
-}
-
void MaemoPackageCreationWidget::versionInfoChanged()
{
QString error;
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.h b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.h
index 2ad8082a00..585ca7e5d9 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.h
@@ -40,13 +40,13 @@ QT_END_NAMESPACE
namespace Qt4ProjectManager {
namespace Internal {
-class MaemoPackageCreationStep;
+class AbstractMaemoPackageCreationStep;
class MaemoPackageCreationWidget : public ProjectExplorer::BuildStepConfigWidget
{
Q_OBJECT
public:
- MaemoPackageCreationWidget(MaemoPackageCreationStep *step);
+ MaemoPackageCreationWidget(AbstractMaemoPackageCreationStep *step);
~MaemoPackageCreationWidget();
virtual void init();
@@ -54,7 +54,6 @@ public:
virtual QString displayName() const;
private slots:
- void handleSkipButtonToggled(bool checked);
void editDebianFile();
void editSpecFile();
void versionInfoChanged();
@@ -75,7 +74,7 @@ private:
void updateShortDescription();
void editFile(const QString &filePath);
- MaemoPackageCreationStep * const m_step;
+ AbstractMaemoPackageCreationStep * 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 7f7ded704f..922a768f63 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.ui
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.ui
@@ -18,44 +18,21 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
- <widget class="QCheckBox" name="skipCheckBox">
- <property name="toolTip">
- <string>Check this if you want the files below to be deployed directly.</string>
- </property>
- <property name="text">
- <string>Skip packaging step</string>
- </property>
- </widget>
- </item>
- <item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
- <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">
+ <item row="0" column="0">
<widget class="QLabel" name="packageNameLabel">
<property name="text">
<string>Package name:</string>
</property>
</widget>
</item>
- <item row="1" column="1">
+ <item row="0" column="1">
<widget class="QLineEdit" name="packageNameLineEdit"/>
</item>
- <item row="2" column="0">
+ <item row="1" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@@ -74,7 +51,7 @@
</property>
</widget>
</item>
- <item row="2" column="1">
+ <item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
@@ -169,35 +146,35 @@
</item>
</layout>
</item>
- <item row="4" column="0">
+ <item row="3" column="0">
<widget class="QLabel" name="shortDescriptionLabel">
<property name="text">
<string>Short package description:</string>
</property>
</widget>
</item>
- <item row="4" column="1">
+ <item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLineEdit" name="shortDescriptionLineEdit"/>
</item>
</layout>
</item>
- <item row="5" column="0">
+ <item row="4" column="0">
<widget class="QLabel" name="packageManagerNameLabel">
<property name="text">
<string>Name to be displayed in Package Manager:</string>
</property>
</widget>
</item>
- <item row="5" column="1">
+ <item row="4" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLineEdit" name="packageManagerNameLineEdit"/>
</item>
</layout>
</item>
- <item row="6" column="0">
+ <item row="5" column="0">
<widget class="QLabel" name="packageManagerIconLabel">
<property name="minimumSize">
<size>
@@ -210,7 +187,7 @@
</property>
</widget>
</item>
- <item row="6" column="1">
+ <item row="5" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QToolButton" name="packageManagerIconButton">
@@ -249,14 +226,14 @@
</item>
</layout>
</item>
- <item row="7" column="0">
+ <item row="6" column="0">
<widget class="QLabel" name="editDebianFileLabel">
<property name="text">
<string>Adapt Debian file:</string>
</property>
</widget>
</item>
- <item row="7" column="1">
+ <item row="6" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QComboBox" name="debianFilesComboBox"/>
@@ -283,7 +260,7 @@
</item>
</layout>
</item>
- <item row="8" column="1">
+ <item row="7" column="1">
<widget class="QPushButton" name="editSpecFileButton">
<property name="text">
<string>Edit spec file</string>
@@ -297,22 +274,6 @@
<resources/>
<connections>
<connection>
- <sender>skipCheckBox</sender>
- <signal>toggled(bool)</signal>
- <receiver>MaemoPackageCreationWidget</receiver>
- <slot>handleSkipButtonToggled(bool)</slot>
- <hints>
- <hint type="sourcelabel">
- <x>129</x>
- <y>18</y>
- </hint>
- <hint type="destinationlabel">
- <x>240</x>
- <y>31</y>
- </hint>
- </hints>
- </connection>
- <connection>
<sender>major</sender>
<signal>valueChanged(int)</signal>
<receiver>MaemoPackageCreationWidget</receiver>
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackageinstaller.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopackageinstaller.cpp
new file mode 100644
index 0000000000..1a3d8214ae
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackageinstaller.cpp
@@ -0,0 +1,214 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "maemopackageinstaller.h"
+
+#include "maemoglobal.h"
+
+#include <utils/ssh/sshconnection.h>
+#include <utils/ssh/sshremoteprocessrunner.h>
+
+using namespace Utils;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+AbstractMaemoPackageInstaller::AbstractMaemoPackageInstaller(QObject *parent)
+ : QObject(parent), m_isRunning(false)
+{
+}
+
+AbstractMaemoPackageInstaller::~AbstractMaemoPackageInstaller() {}
+
+void AbstractMaemoPackageInstaller::installPackage(const SshConnection::Ptr &connection,
+ const QString &packageFilePath, bool removePackageFile)
+{
+ Q_ASSERT(connection && connection->state() == SshConnection::Connected);
+ Q_ASSERT(!m_isRunning);
+
+ prepareInstallation();
+ m_installer = SshRemoteProcessRunner::create(connection);
+ connect(m_installer.data(), SIGNAL(connectionError(Utils::SshError)),
+ SLOT(handleConnectionError()));
+ connect(m_installer.data(), SIGNAL(processOutputAvailable(QByteArray)),
+ SLOT(handleInstallerOutput(QByteArray)));
+ connect(m_installer.data(), SIGNAL(processErrorOutputAvailable(QByteArray)),
+ SLOT(handleInstallerErrorOutput(QByteArray)));
+ connect(m_installer.data(), SIGNAL(processClosed(int)),
+ SLOT(handleInstallationFinished(int)));
+
+ const QString space = QLatin1String(" ");
+ QString cmdLine = QLatin1String("cd ") + workingDirectory()
+ + QLatin1String(" && ")
+ + MaemoGlobal::remoteSudo(m_installer->connection()->connectionParameters().userName)
+ + space + installCommand()
+ + space + installCommandArguments().join(space) + space
+ + packageFilePath;
+ if (removePackageFile) {
+ cmdLine += QLatin1String(" && (rm ") + packageFilePath
+ + QLatin1String(" || :)");
+ }
+ m_installer->run(cmdLine.toUtf8());
+ m_isRunning = true;
+}
+
+void AbstractMaemoPackageInstaller::cancelInstallation()
+{
+ Q_ASSERT(m_isRunning);
+ const SshRemoteProcessRunner::Ptr killProcess
+ = SshRemoteProcessRunner::create(m_installer->connection());
+ killProcess->run("pkill " + installCommand().toUtf8());
+ setFinished();
+}
+
+void AbstractMaemoPackageInstaller::handleConnectionError()
+{
+ if (!m_isRunning)
+ return;
+ emit finished(tr("Connection failure: %1")
+ .arg(m_installer->connection()->errorString()));
+ setFinished();
+}
+
+void AbstractMaemoPackageInstaller::handleInstallationFinished(int exitStatus)
+{
+ if (!m_isRunning)
+ return;
+
+ if (exitStatus != SshRemoteProcess::ExitedNormally
+ || m_installer->process()->exitCode() != 0) {
+ emit finished(tr("Installing package failed."));
+ } else if (!errorString().isEmpty()) {
+ emit finished(errorString());
+ } else {
+ emit finished();
+ }
+
+ setFinished();
+}
+
+void AbstractMaemoPackageInstaller::handleInstallerOutput(const QByteArray &output)
+{
+ emit stdoutData(QString::fromUtf8(output));
+}
+
+void AbstractMaemoPackageInstaller::handleInstallerErrorOutput(const QByteArray &output)
+{
+ emit stderrData(QString::fromUtf8(output));
+}
+
+void AbstractMaemoPackageInstaller::setFinished()
+{
+ disconnect(m_installer.data(), 0, this, 0);
+ m_installer.clear();
+ m_isRunning = false;
+}
+
+
+MaemoDebianPackageInstaller::MaemoDebianPackageInstaller(QObject *parent)
+ : AbstractMaemoPackageInstaller(parent)
+{
+ connect(this, SIGNAL(stderrData(QString)),
+ SLOT(handleInstallerErrorOutput(QString)));
+}
+
+void MaemoDebianPackageInstaller::prepareInstallation()
+{
+ m_installerStderr.clear();
+}
+
+QString MaemoDebianPackageInstaller::installCommand() const
+{
+ return QLatin1String("dpkg");
+}
+
+QStringList MaemoDebianPackageInstaller::installCommandArguments() const
+{
+ return QStringList() << QLatin1String("-i")
+ << QLatin1String("--no-force-downgrade");
+}
+
+void MaemoDebianPackageInstaller::handleInstallerErrorOutput(const QString &output)
+{
+ m_installerStderr += output;
+}
+
+QString MaemoDebianPackageInstaller::errorString() const
+{
+ if (m_installerStderr.contains(QLatin1String("Will not downgrade"))) {
+ return tr("Installation failed: "
+ "You tried to downgrade a package, which is not allowed.");
+ } else {
+ return QString();
+ }
+}
+
+
+MaemoRpmPackageInstaller::MaemoRpmPackageInstaller(QObject *parent)
+ : AbstractMaemoPackageInstaller(parent)
+{
+}
+
+QString MaemoRpmPackageInstaller::installCommand() const
+{
+ return QLatin1String("rpm");
+}
+
+QStringList MaemoRpmPackageInstaller::installCommandArguments() const
+{
+ // rpm -U does not allow to re-install a package with the same version
+ // number, so we need --replacepkgs. Even then, it inexplicably reports
+ // a conflict if the files are not identical to the installed version,
+ // so we need --replacefiles as well.
+ // TODO: --replacefiles is dangerous. Is there perhaps a way around it
+ // after all?
+ return QStringList() << QLatin1String("-Uhv") << QLatin1String("--replacepkgs") << QLatin1String("--replacefiles");
+}
+
+
+MaemoTarPackageInstaller::MaemoTarPackageInstaller(QObject *parent)
+ : AbstractMaemoPackageInstaller(parent)
+{
+}
+
+QString MaemoTarPackageInstaller::installCommand() const
+{
+ return QLatin1String("tar");
+}
+
+QStringList MaemoTarPackageInstaller::installCommandArguments() const
+{
+ return QStringList() << QLatin1String("xvf");
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackageinstaller.h b/src/plugins/qt4projectmanager/qt-maemo/maemopackageinstaller.h
new file mode 100644
index 0000000000..2b61f356d3
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackageinstaller.h
@@ -0,0 +1,133 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 ABSTRACTMAEMOPACKAGEINSTALLER_H
+#define ABSTRACTMAEMOPACKAGEINSTALLER_H
+
+namespace Utils {
+class SshConnection;
+class SshRemoteProcessRunner;
+}
+
+#include <QtCore/QObject>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class AbstractMaemoPackageInstaller : public QObject
+{
+ Q_OBJECT
+public:
+ ~AbstractMaemoPackageInstaller();
+
+ void installPackage(const QSharedPointer<Utils::SshConnection> &connection,
+ const QString &packageFilePath, bool removePackageFile);
+ void cancelInstallation();
+
+signals:
+ void stdoutData(const QString &output);
+ void stderrData(const QString &output);
+ void finished(const QString &errorMsg = QString());
+
+protected:
+ explicit AbstractMaemoPackageInstaller(QObject *parent = 0);
+ bool isRunning() const { return m_isRunning; }
+
+private slots:
+ void handleConnectionError();
+ void handleInstallationFinished(int exitStatus);
+ void handleInstallerOutput(const QByteArray &output);
+ void handleInstallerErrorOutput(const QByteArray &output);
+
+private:
+ virtual void prepareInstallation() {}
+ virtual QString workingDirectory() const { return QLatin1String("/tmp"); }
+ virtual QString installCommand() const=0;
+ virtual QStringList installCommandArguments() const=0;
+ virtual QString errorString() const { return QString(); }
+ void setFinished();
+
+ bool m_isRunning;
+ QSharedPointer<Utils::SshRemoteProcessRunner> m_installer;
+};
+
+
+class MaemoDebianPackageInstaller: public AbstractMaemoPackageInstaller
+{
+ Q_OBJECT
+public:
+ MaemoDebianPackageInstaller(QObject *parent);
+
+private slots:
+ virtual void prepareInstallation();
+ virtual QString installCommand() const;
+ virtual QStringList installCommandArguments() const;
+ virtual QString errorString() const;
+ void handleInstallerErrorOutput(const QString &output);
+
+private:
+ QString m_installerStderr;
+};
+
+
+class MaemoRpmPackageInstaller : public AbstractMaemoPackageInstaller
+{
+ Q_OBJECT
+public:
+ MaemoRpmPackageInstaller(QObject *parent);
+
+private:
+ virtual QString installCommand() const;
+ virtual QStringList installCommandArguments() const;
+};
+
+
+class MaemoTarPackageInstaller : public AbstractMaemoPackageInstaller
+{
+ Q_OBJECT
+public:
+ MaemoTarPackageInstaller(QObject *parent);
+
+private:
+ virtual QString installCommand() const;
+ virtual QStringList installCommandArguments() const;
+ virtual QString workingDirectory() const { return QLatin1String("/"); }
+};
+
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // ABSTRACTMAEMOPACKAGEINSTALLER_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackageuploader.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopackageuploader.cpp
new file mode 100644
index 0000000000..242f6afc5e
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackageuploader.cpp
@@ -0,0 +1,159 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "maemopackageuploader.h"
+
+#include "maemoglobal.h"
+
+#include <utils/ssh/sftpchannel.h>
+#include <utils/ssh/sshconnection.h>
+
+#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(State, state, m_state)
+
+using namespace Utils;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+MaemoPackageUploader::MaemoPackageUploader(QObject *parent) :
+ QObject(parent), m_state(Inactive)
+{
+}
+
+MaemoPackageUploader::~MaemoPackageUploader()
+{
+}
+
+void MaemoPackageUploader::uploadPackage(const SshConnection::Ptr &connection,
+ const QString &localFilePath, const QString &remoteFilePath)
+{
+ ASSERT_STATE(Inactive);
+ setState(InitializingSftp);
+ emit progress(tr("Preparing SFTP connection..."));
+
+ m_localFilePath = localFilePath;
+ m_remoteFilePath = remoteFilePath;
+ m_connection = connection;
+ connect(m_connection.data(), SIGNAL(error(Utils::SshError)),
+ SLOT(handleConnectionFailure()));
+ m_uploader = m_connection->createSftpChannel();
+ connect(m_uploader.data(), SIGNAL(initialized()), this,
+ SLOT(handleSftpChannelInitialized()));
+ connect(m_uploader.data(), SIGNAL(initializationFailed(QString)), this,
+ SLOT(handleSftpChannelInitializationFailed(QString)));
+ connect(m_uploader.data(), SIGNAL(finished(Utils::SftpJobId, QString)),
+ this, SLOT(handleSftpJobFinished(Utils::SftpJobId, QString)));
+ m_uploader->initialize();
+}
+
+void MaemoPackageUploader::cancelUpload()
+{
+ ASSERT_STATE(QList<State>() << InitializingSftp << Uploading);
+
+ cleanup();
+}
+
+void MaemoPackageUploader::handleConnectionFailure()
+{
+ if (m_state == Inactive)
+ return;
+
+ const QString errorMsg = m_connection->errorString();
+ setState(Inactive);
+ emit uploadFinished(tr("Connection failed: %1").arg(errorMsg));
+}
+
+void MaemoPackageUploader::handleSftpChannelInitializationFailed(const QString &errorMsg)
+{
+ ASSERT_STATE(QList<State>() << InitializingSftp << Inactive);
+ if (m_state == Inactive)
+ return;
+
+ setState(Inactive);
+ emit uploadFinished(tr("SFTP error: %1").arg(errorMsg));
+}
+
+void MaemoPackageUploader::handleSftpChannelInitialized()
+{
+ ASSERT_STATE(QList<State>() << InitializingSftp << Inactive);
+ if (m_state == Inactive)
+ return;
+
+ const SftpJobId job = m_uploader->uploadFile(m_localFilePath,
+ m_remoteFilePath, SftpOverwriteExisting);
+ if (job == SftpInvalidJob) {
+ setState(Inactive);
+ emit uploadFinished(tr("Package upload failed: Could not open file."));
+ } else {
+ emit progress("Starting upload...");
+ setState(Uploading);
+ }
+}
+
+void MaemoPackageUploader::handleSftpJobFinished(SftpJobId, const QString &errorMsg)
+{
+ ASSERT_STATE(QList<State>() << Uploading << Inactive);
+ if (m_state == Inactive)
+ return;
+
+ if (!errorMsg.isEmpty())
+ emit uploadFinished(tr("Failed to upload package: %2").arg(errorMsg));
+ else
+ emit uploadFinished();
+ cleanup();
+}
+
+void MaemoPackageUploader::cleanup()
+{
+ m_uploader->closeChannel();
+ setState(Inactive);
+}
+
+void MaemoPackageUploader::setState(State newState)
+{
+ if (m_state == newState)
+ return;
+ if (newState == Inactive) {
+ if (m_uploader) {
+ disconnect(m_uploader.data(), 0, this, 0);
+ m_uploader.clear();
+ }
+ if (m_connection) {
+ disconnect(m_connection.data(), 0, this, 0);
+ m_connection.clear();
+ }
+ }
+ m_state = newState;
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackageuploader.h b/src/plugins/qt4projectmanager/qt-maemo/maemopackageuploader.h
new file mode 100644
index 0000000000..d05d2581f4
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackageuploader.h
@@ -0,0 +1,88 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 MAEMOPACKAGEUPLOADER_H
+#define MAEMOPACKAGEUPLOADER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QString>
+
+#include <utils/ssh/sftpdefs.h>
+
+namespace Utils {
+class SftpChannel;
+class SshConnection;
+}
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class MaemoPackageUploader : public QObject
+{
+ Q_OBJECT
+public:
+ explicit MaemoPackageUploader(QObject *parent = 0);
+ ~MaemoPackageUploader();
+
+ // Connection has to be established already.
+ void uploadPackage(const QSharedPointer<Utils::SshConnection> &connection,
+ const QString &localFilePath, const QString &remoteFilePath);
+ void cancelUpload();
+
+signals:
+ void progress(const QString &message);
+ void uploadFinished(const QString &errorMsg = QString());
+
+private slots:
+ void handleConnectionFailure();
+ void handleSftpChannelInitialized();
+ void handleSftpChannelInitializationFailed(const QString &error);
+ void handleSftpJobFinished(Utils::SftpJobId job, const QString &error);
+
+private:
+ enum State { InitializingSftp, Uploading, Inactive };
+
+ void cleanup();
+ void setState(State newState);
+
+ State m_state;
+ QSharedPointer<Utils::SshConnection> m_connection;
+ QSharedPointer<Utils::SftpChannel> m_uploader;
+ QString m_localFilePath;
+ QString m_remoteFilePath;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOPACKAGEUPLOADER_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopertargetdeviceconfigurationlistmodel.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopertargetdeviceconfigurationlistmodel.cpp
index d51eb5e846..0f905c3562 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemopertargetdeviceconfigurationlistmodel.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopertargetdeviceconfigurationlistmodel.cpp
@@ -38,17 +38,17 @@ using namespace ProjectExplorer;
namespace Qt4ProjectManager {
namespace Internal {
-MaemoPerTargetDeviceConfigurationListModel::MaemoPerTargetDeviceConfigurationListModel(Target *target)
- : QAbstractListModel(target)
+MaemoPerTargetDeviceConfigurationListModel::MaemoPerTargetDeviceConfigurationListModel(QObject *parent,
+ const Target *target) : QAbstractListModel(parent)
{
- if (qobject_cast<Qt4Maemo5Target *>(target))
+ if (qobject_cast<const Qt4Maemo5Target *>(target))
m_targetOsVersion = MaemoGlobal::Maemo5;
- else if (qobject_cast<Qt4HarmattanTarget *>(target))
+ else if (qobject_cast<const Qt4HarmattanTarget *>(target))
m_targetOsVersion = MaemoGlobal::Maemo6;
- else if (qobject_cast<Qt4MeegoTarget *>(target))
+ else if (qobject_cast<const Qt4MeegoTarget *>(target))
m_targetOsVersion = MaemoGlobal::Meego;
else
- Q_ASSERT(false);
+ m_targetOsVersion = MaemoGlobal::GenericLinux;
const MaemoDeviceConfigurations * const devConfs
= MaemoDeviceConfigurations::instance();
connect(devConfs, SIGNAL(modelReset()), this, SIGNAL(modelReset()));
@@ -63,6 +63,8 @@ int MaemoPerTargetDeviceConfigurationListModel::rowCount(const QModelIndex &pare
const MaemoDeviceConfigurations * const devConfs
= MaemoDeviceConfigurations::instance();
const int devConfsCount = devConfs->rowCount();
+ if (m_targetOsVersion == MaemoGlobal::GenericLinux)
+ return devConfsCount;
for (int i = 0; i < devConfsCount; ++i) {
if (devConfs->deviceAt(i)->osVersion() == m_targetOsVersion)
++count;
@@ -78,7 +80,7 @@ QVariant MaemoPerTargetDeviceConfigurationListModel::data(const QModelIndex &ind
const MaemoDeviceConfig::ConstPtr &devConf = deviceAt(index.row());
Q_ASSERT(devConf);
QString displayedName = devConf->name();
- if (devConf->isDefault())
+ if (devConf->isDefault() && devConf->osVersion() == m_targetOsVersion)
displayedName += QLatin1Char(' ') + tr("(default)");
return displayedName;
}
@@ -88,6 +90,8 @@ MaemoDeviceConfig::ConstPtr MaemoPerTargetDeviceConfigurationListModel::deviceAt
int currentRow = -1;
const MaemoDeviceConfigurations * const devConfs
= MaemoDeviceConfigurations::instance();
+ if (m_targetOsVersion == MaemoGlobal::GenericLinux)
+ return devConfs->deviceAt(idx);
const int devConfsCount = devConfs->rowCount();
for (int i = 0; i < devConfsCount; ++i) {
if (devConfs->deviceAt(i)->osVersion() == m_targetOsVersion) {
@@ -108,7 +112,8 @@ MaemoDeviceConfig::ConstPtr MaemoPerTargetDeviceConfigurationListModel::find(Mae
{
const MaemoDeviceConfig::ConstPtr &devConf
= MaemoDeviceConfigurations::instance()->find(id);
- return devConf && devConf->osVersion() == m_targetOsVersion
+ return devConf && (devConf->osVersion() == m_targetOsVersion
+ || m_targetOsVersion == MaemoGlobal::GenericLinux)
? devConf : defaultDeviceConfig();
}
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopertargetdeviceconfigurationlistmodel.h b/src/plugins/qt4projectmanager/qt-maemo/maemopertargetdeviceconfigurationlistmodel.h
index 73d9c9b8ab..814f4ca9ee 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemopertargetdeviceconfigurationlistmodel.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopertargetdeviceconfigurationlistmodel.h
@@ -47,7 +47,8 @@ class MaemoPerTargetDeviceConfigurationListModel : public QAbstractListModel
{
Q_OBJECT
public:
- explicit MaemoPerTargetDeviceConfigurationListModel(ProjectExplorer::Target *target);
+ explicit MaemoPerTargetDeviceConfigurationListModel(QObject *parent, const
+ ProjectExplorer::Target *target);
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
virtual QVariant data(const QModelIndex &index,
@@ -62,7 +63,7 @@ signals:
void updated();
private:
- MaemoGlobal::MaemoVersion m_targetOsVersion;
+ MaemoGlobal::OsVersion m_targetOsVersion;
};
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopublisherfremantlefree.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopublisherfremantlefree.cpp
index d3e69e15e7..20e10aa5af 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemopublisherfremantlefree.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemopublisherfremantlefree.cpp
@@ -32,10 +32,10 @@
#include "maemopublisherfremantlefree.h"
#include "maemodeployablelistmodel.h"
-#include "maemodeploystep.h"
#include "maemoglobal.h"
#include "maemopackagecreationstep.h"
#include "maemopublishingfileselectiondialog.h"
+#include "qt4maemodeployconfiguration.h"
#include "qt4maemotarget.h"
#include <coreplugin/ifile.h>
@@ -155,7 +155,7 @@ void MaemoPublisherFremantleFree::createPackage()
}
emit progressReport(tr("Cleaning up temporary directory ..."));
- MaemoPackageCreationStep::preparePackagingProcess(m_process,
+ AbstractMaemoPackageCreationStep::preparePackagingProcess(m_process,
m_buildConfig, m_tmpProjectDir);
setState(RunningQmake);
ProjectExplorer::AbstractProcessStep * const qmakeStep
@@ -222,7 +222,7 @@ bool MaemoPublisherFremantleFree::copyRecursively(const QString &srcFilePath,
rulesContents.replace("$(MAKE) clean", "# $(MAKE) clean");
rulesContents.replace("# Add here commands to configure the package.",
"qmake " + QFileInfo(m_project->file()->fileName()).fileName().toLocal8Bit());
- MaemoPackageCreationStep::ensureShlibdeps(rulesContents);
+ MaemoDebianPackageCreationStep::ensureShlibdeps(rulesContents);
rulesFile.resize(0);
rulesFile.write(rulesContents);
}
@@ -519,12 +519,12 @@ void MaemoPublisherFremantleFree::finishWithFailure(const QString &progressMsg,
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);
+ const Qt4MaemoDeployConfiguration * const deployConfig
+ = qobject_cast<Qt4MaemoDeployConfiguration *>(m_buildConfig->target()->activeDeployConfiguration());
+ const QSharedPointer<MaemoDeployables> deployables
+ = deployConfig->deployables();
+ for (int i = 0; i < deployables->modelCount(); ++i) {
+ const MaemoDeployableListModel * const model = deployables->modelAt(i);
QString desktopFilePath = model->localDesktopFilePath();
if (desktopFilePath.isEmpty())
continue;
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoqemuruntimeparser.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoqemuruntimeparser.cpp
index fb56383d36..59fc4cf633 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoqemuruntimeparser.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoqemuruntimeparser.cpp
@@ -423,7 +423,8 @@ MaemoQemuSettings::OpenGlMode MaemoQemuRuntimeParserV2::openGlTagToEnum(const QS
return MaemoQemuSettings::SoftwareRendering;
if (tag == QLatin1String("autodetect"))
return MaemoQemuSettings::AutoDetect;
- QTC_ASSERT(false, return MaemoQemuSettings::AutoDetect);
+ QTC_ASSERT(false, /**/);
+ return MaemoQemuSettings::AutoDetect;
}
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoremotecopyfacility.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoremotecopyfacility.cpp
new file mode 100644
index 0000000000..df81b8c07c
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoremotecopyfacility.cpp
@@ -0,0 +1,156 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "maemoremotecopyfacility.h"
+
+#include "maemoglobal.h"
+#include <QtCore/QDir>
+
+#include <utils/ssh/sshconnection.h>
+#include <utils/ssh/sshremoteprocessrunner.h>
+
+using namespace Utils;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+MaemoRemoteCopyFacility::MaemoRemoteCopyFacility(QObject *parent) :
+ QObject(parent), m_isCopying(false)
+{
+}
+
+MaemoRemoteCopyFacility::~MaemoRemoteCopyFacility() {}
+
+void MaemoRemoteCopyFacility::copyFiles(const SshConnection::Ptr &connection,
+ const QList<MaemoDeployable> &deployables, const QString &mountPoint)
+{
+ Q_ASSERT(connection->state() == SshConnection::Connected);
+ Q_ASSERT(!m_isCopying);
+
+ m_deployables = deployables;
+ m_mountPoint = mountPoint;
+
+ m_copyRunner = SshRemoteProcessRunner::create(connection);
+ connect(m_copyRunner.data(), SIGNAL(connectionError(Utils::SshError)),
+ SLOT(handleConnectionError()));
+ connect(m_copyRunner.data(), SIGNAL(processOutputAvailable(QByteArray)),
+ SLOT(handleRemoteStdout(QByteArray)));
+ connect(m_copyRunner.data(),
+ SIGNAL(processErrorOutputAvailable(QByteArray)),
+ SLOT(handleRemoteStderr(QByteArray)));
+ connect(m_copyRunner.data(), SIGNAL(processClosed(int)),
+ SLOT(handleCopyFinished(int)));
+
+ m_isCopying = true;
+ copyNextFile();
+}
+
+void MaemoRemoteCopyFacility::cancel()
+{
+ Q_ASSERT(m_isCopying);
+
+ SshRemoteProcessRunner::Ptr killProcess
+ = SshRemoteProcessRunner::create(m_copyRunner->connection());
+ killProcess->run("pkill cp");
+ setFinished();
+}
+
+void MaemoRemoteCopyFacility::handleConnectionError()
+{
+ const QString errMsg = m_copyRunner->connection()->errorString();
+ setFinished();
+ emit finished(tr("Connection failed: %1").arg(errMsg));
+}
+
+void MaemoRemoteCopyFacility::handleRemoteStdout(const QByteArray &output)
+{
+ emit stdoutData(QString::fromUtf8(output));
+}
+
+void MaemoRemoteCopyFacility::handleRemoteStderr(const QByteArray &output)
+{
+ emit stderrData(QString::fromUtf8(output));
+}
+
+void MaemoRemoteCopyFacility::handleCopyFinished(int exitStatus)
+{
+ if (!m_isCopying)
+ return;
+
+ if (exitStatus != SshRemoteProcess::ExitedNormally
+ || m_copyRunner->process()->exitCode() != 0) {
+ setFinished();
+ emit finished(tr("Error: Copy command failed."));
+ } else {
+ emit fileCopied(m_deployables.takeFirst());
+ copyNextFile();
+ }
+}
+
+void MaemoRemoteCopyFacility::copyNextFile()
+{
+ Q_ASSERT(m_isCopying);
+
+ if (m_deployables.isEmpty()) {
+ setFinished();
+ emit finished();
+ return;
+ }
+
+ const MaemoDeployable &d = m_deployables.first();
+ QString sourceFilePath = m_mountPoint;
+#ifdef Q_OS_WIN
+ const QString localFilePath = QDir::fromNativeSeparators(d.localFilePath);
+ sourceFilePath += QLatin1Char('/') + localFilePath.at(0).toLower()
+ + localFilePath.mid(2);
+#else
+ sourceFilePath += d.localFilePath;
+#endif
+
+ QString command = QString::fromLatin1("%1 mkdir -p %3 && %1 cp -r %2 %3")
+ .arg(MaemoGlobal::remoteSudo(m_copyRunner->connection()->connectionParameters().userName),
+ sourceFilePath, d.remoteDir);
+ emit progress(tr("Copying file '%1' to directory '%2' on the device...")
+ .arg(d.localFilePath, d.remoteDir));
+ m_copyRunner->run(command.toUtf8());
+}
+
+void MaemoRemoteCopyFacility::setFinished()
+{
+ disconnect(m_copyRunner.data(), 0, this, 0);
+ m_copyRunner.clear();
+ m_deployables.clear();
+ m_isCopying = false;
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoremotecopyfacility.h b/src/plugins/qt4projectmanager/qt-maemo/maemoremotecopyfacility.h
new file mode 100644
index 0000000000..c61ea7f8a1
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoremotecopyfacility.h
@@ -0,0 +1,88 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 MAEMOREMOTECOPYFACILITY_H
+#define MAEMOREMOTECOPYFACILITY_H
+
+#include "maemodeployable.h"
+
+#include <QtCore/QList>
+#include <QtCore/QObject>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QString>
+
+namespace Utils {
+class SshConnection;
+class SshRemoteProcessRunner;
+}
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class MaemoRemoteCopyFacility : public QObject
+{
+ Q_OBJECT
+public:
+ explicit MaemoRemoteCopyFacility(QObject *parent = 0);
+ ~MaemoRemoteCopyFacility();
+
+ void copyFiles(const QSharedPointer<Utils::SshConnection> &connection,
+ const QList<MaemoDeployable> &deployables, const QString &mountPoint);
+ void cancel();
+
+signals:
+ void stdoutData(const QString &output);
+ void stderrData(const QString &output);
+ void progress(const QString &message);
+ void fileCopied(const MaemoDeployable &deployable);
+ void finished(const QString &errorMsg = QString());
+
+private slots:
+ void handleConnectionError();
+ void handleCopyFinished(int exitStatus);
+ void handleRemoteStdout(const QByteArray &output);
+ void handleRemoteStderr(const QByteArray &output);
+
+private:
+ void copyNextFile();
+ void setFinished();
+
+ QSharedPointer<Utils::SshRemoteProcessRunner> m_copyRunner;
+ QList<MaemoDeployable> m_deployables;
+ QString m_mountPoint;
+ bool m_isCopying;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMOREMOTECOPYFACILITY_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoremotemounter.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoremotemounter.cpp
index 3c0c248633..2165b65875 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoremotemounter.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoremotemounter.cpp
@@ -123,7 +123,7 @@ void MaemoRemoteMounter::unmount()
QString remoteCall;
for (int i = 0; i < m_mountSpecs.count(); ++i) {
remoteCall += QString::fromLocal8Bit("%1 umount %2 && %1 rmdir %2;")
- .arg(MaemoGlobal::remoteSudo(),
+ .arg(MaemoGlobal::remoteSudo(m_connection->connectionParameters().userName),
m_mountSpecs.at(i).mountSpec.remoteMountPoint);
}
@@ -182,8 +182,9 @@ void MaemoRemoteMounter::stop()
void MaemoRemoteMounter::startUtfsClients()
{
- const QString chmodFuse
- = MaemoGlobal::remoteSudo() + QLatin1String(" chmod a+r+w /dev/fuse");
+ const QString userName = m_connection->connectionParameters().userName;
+ const QString chmodFuse = MaemoGlobal::remoteSudo(userName)
+ + QLatin1String(" chmod a+r+w /dev/fuse");
const QString chmodUtfsClient
= QLatin1String("chmod a+x ") + utfsClientOnDevice();
const QLatin1String andOp(" && ");
@@ -200,15 +201,15 @@ void MaemoRemoteMounter::startUtfsClients()
const MaemoMountSpecification &mountSpec = mountInfo.mountSpec;
const QString mkdir = QString::fromLocal8Bit("%1 mkdir -p %2")
- .arg(MaemoGlobal::remoteSudo(), mountSpec.remoteMountPoint);
+ .arg(MaemoGlobal::remoteSudo(userName), mountSpec.remoteMountPoint);
const QString chmod = QString::fromLocal8Bit("%1 chmod a+r+w+x %2")
- .arg(MaemoGlobal::remoteSudo(), mountSpec.remoteMountPoint);
+ .arg(MaemoGlobal::remoteSudo(userName), mountSpec.remoteMountPoint);
QString utfsClient
= QString::fromLocal8Bit("%1 -l %2 -r %2 -b %2 %4 -o nonempty")
.arg(utfsClientOnDevice()).arg(mountInfo.remotePort)
.arg(mountSpec.remoteMountPoint);
if (mountInfo.mountAsRoot)
- utfsClient.prepend(MaemoGlobal::remoteSudo() + QLatin1Char(' '));
+ utfsClient.prepend(MaemoGlobal::remoteSudo(userName) + QLatin1Char(' '));
QLatin1String seqOp("; ");
remoteCall += seqOp + MaemoGlobal::remoteSourceProfilesCommand()
+ seqOp + mkdir + andOp + chmod + andOp + utfsClient;
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp
index 8fef401076..e521d155b5 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp
@@ -32,13 +32,14 @@
#include "maemorunconfiguration.h"
+#include "abstractmaemodeploystep.h"
#include "maemodeployables.h"
-#include "maemodeploystep.h"
#include "maemoglobal.h"
#include "maemoqemumanager.h"
#include "maemoremotemountsmodel.h"
#include "maemorunconfigurationwidget.h"
#include "maemotoolchain.h"
+#include "qt4maemodeployconfiguration.h"
#include "qt4maemotarget.h"
#include "qtoutputformatter.h"
@@ -212,7 +213,7 @@ QString MaemoRunConfiguration::defaultDisplayName()
MaemoDeviceConfig::ConstPtr MaemoRunConfiguration::deviceConfig() const
{
- const MaemoDeployStep * const step = deployStep();
+ const AbstractMaemoDeployStep * const step = deployStep();
return step ? step->deviceConfig() : MaemoDeviceConfig::ConstPtr();
}
@@ -230,9 +231,14 @@ const QString MaemoRunConfiguration::gdbCmd() const
return QDir::toNativeSeparators(activeBuildConfiguration()->toolChain()->debuggerCommand());
}
-MaemoDeployStep *MaemoRunConfiguration::deployStep() const
+Qt4MaemoDeployConfiguration *MaemoRunConfiguration::deployConfig() const
{
- return MaemoGlobal::buildStep<MaemoDeployStep>(target()->activeDeployConfiguration());
+ return qobject_cast<Qt4MaemoDeployConfiguration *>(target()->activeDeployConfiguration());
+}
+
+AbstractMaemoDeployStep *MaemoRunConfiguration::deployStep() const
+{
+ return MaemoGlobal::earlierBuildStep<AbstractMaemoDeployStep>(deployConfig(), 0);
}
const QString MaemoRunConfiguration::sysRoot() const
@@ -298,15 +304,12 @@ QString MaemoRunConfiguration::localExecutableFilePath() const
QString MaemoRunConfiguration::remoteExecutableFilePath() const
{
- const MaemoDeployStep * const step = deployStep();
- return step
- ? step->deployables()->remoteExecutableFilePath(localExecutableFilePath())
- : QString();
+ return deployConfig()->deployables()->remoteExecutableFilePath(localExecutableFilePath());
}
MaemoPortList MaemoRunConfiguration::freePorts() const
{
- return deployStep()->freePorts();
+ return deployStep() ? deployStep()->freePorts() : MaemoPortList();
}
bool MaemoRunConfiguration::useRemoteGdb() const
@@ -350,23 +353,25 @@ void MaemoRunConfiguration::updateDeviceConfigurations()
void MaemoRunConfiguration::handleDeployConfigChanged()
{
- const QList<DeployConfiguration *> &deployConfigs
- = target()->deployConfigurations();
DeployConfiguration * const activeDeployConf
= target()->activeDeployConfiguration();
- for (int i = 0; i < deployConfigs.count(); ++i) {
- MaemoDeployStep * const step
- = MaemoGlobal::buildStep<MaemoDeployStep>(deployConfigs.at(i));
- if (!step)
- continue;
- if (deployConfigs.at(i) == activeDeployConf) {
+ if (activeDeployConf) {
+ connect(activeDeployConf->stepList(), SIGNAL(stepInserted(int)),
+ SLOT(handleDeployConfigChanged()), Qt::UniqueConnection);
+ connect(activeDeployConf->stepList(), SIGNAL(stepInserted(int)),
+ SLOT(handleDeployConfigChanged()), Qt::UniqueConnection);
+ connect(activeDeployConf->stepList(), SIGNAL(stepMoved(int,int)),
+ SLOT(handleDeployConfigChanged()), Qt::UniqueConnection);
+ connect(activeDeployConf->stepList(), SIGNAL(stepRemoved(int)),
+ SLOT(handleDeployConfigChanged()), Qt::UniqueConnection);
+ AbstractMaemoDeployStep * const step
+ = MaemoGlobal::earlierBuildStep<AbstractMaemoDeployStep>(activeDeployConf, 0);
+ if (step) {
connect(step, SIGNAL(deviceConfigChanged()),
- SLOT(updateDeviceConfigurations()));
- } else {
- disconnect(step, 0, this,
- SLOT(updateDeviceConfigurations()));
+ SLOT(updateDeviceConfigurations()), Qt::UniqueConnection);
}
}
+
updateDeviceConfigurations();
updateFactoryState();
}
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h
index 4a5bbedac5..9906612eb5 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h
@@ -55,14 +55,15 @@ class Qt4BaseTarget;
namespace Internal {
class Qt4ProFileNode;
-class AbstractQt4MaemoTarget;
+class AbstractQt4MaemoTarget;
+class AbstractMaemoDeployStep;
class MaemoDeviceConfigListModel;
-class MaemoDeployStep;
class MaemoManager;
class MaemoRemoteMountsModel;
class MaemoRunConfigurationFactory;
class MaemoToolChain;
+class Qt4MaemoDeployConfiguration;
class MaemoRunConfiguration : public ProjectExplorer::RunConfiguration
{
@@ -87,7 +88,8 @@ public:
AbstractQt4MaemoTarget *maemoTarget() const;
Qt4BuildConfiguration *activeQt4BuildConfiguration() const;
- MaemoDeployStep *deployStep() const;
+ Qt4MaemoDeployConfiguration *deployConfig() const;
+ AbstractMaemoDeployStep *deployStep() const;
MaemoRemoteMountsModel *remoteMounts() const { return m_remoteMounts; }
const MaemoToolChain *toolchain() const;
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.cpp
index 44b13fc0db..869062064e 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.cpp
@@ -32,13 +32,13 @@
#include "maemorunconfigurationwidget.h"
#include "maemodeployables.h"
-#include "maemodeploystep.h"
#include "maemodeviceenvreader.h"
#include "maemomanager.h"
#include "maemoglobal.h"
#include "maemoremotemountsmodel.h"
#include "maemorunconfiguration.h"
#include "maemosettingspages.h"
+#include "qt4maemodeployconfiguration.h"
#include "qt4maemotarget.h"
#include <coreplugin/coreconstants.h>
@@ -310,11 +310,8 @@ void MaemoRunConfigurationWidget::handleActiveDeployConfigurationChanged()
{
if (m_deployablesConnected)
return;
- MaemoDeployStep * const deployStep = m_runConfiguration->deployStep();
- if (!deployStep)
- return;
- connect(deployStep->deployables().data(), SIGNAL(modelReset()),
- SLOT(handleDeploySpecsChanged()));
+ connect(m_runConfiguration->deployConfig()->deployables().data(),
+ SIGNAL(modelReset()), SLOT(handleDeploySpecsChanged()));
handleDeploySpecsChanged();
m_deployablesConnected = true;
disconnect(m_runConfiguration->target(),
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp
index 21fb6b71d1..c635e279bc 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp
@@ -31,7 +31,6 @@
#include "maemoruncontrol.h"
-#include "maemodeploystep.h"
#include "maemoglobal.h"
#include "maemorunconfiguration.h"
#include "maemosshrunner.h"
@@ -41,7 +40,6 @@
#include <QtGui/QMessageBox>
-using namespace Core;
using namespace ProjectExplorer;
namespace Qt4ProjectManager {
@@ -97,9 +95,10 @@ void MaemoRunControl::handleSshError(const QString &error)
void MaemoRunControl::startExecution()
{
- appendMessage(tr("Starting remote process ..."), NormalMessageFormat);
+ appendMessage(tr("Starting remote process ...\n"), NormalMessageFormat);
m_runner->startExecution(QString::fromLocal8Bit("%1 %2 %3 %4")
.arg(MaemoGlobal::remoteCommandPrefix(m_runner->devConfig()->osVersion(),
+ m_runner->connection()->connectionParameters().userName,
m_runner->remoteExecutable()))
.arg(MaemoGlobal::remoteEnvironment(m_runner->userEnvChanges()))
.arg(m_runner->remoteExecutable())
@@ -109,7 +108,7 @@ void MaemoRunControl::startExecution()
void MaemoRunControl::handleRemoteProcessFinished(qint64 exitCode)
{
if (exitCode != MaemoSshRunner::InvalidExitCode) {
- appendMessage(tr("Finished running remote process. Exit code was %1.")
+ appendMessage(tr("Finished running remote process. Exit code was %1.\n")
.arg(exitCode), NormalMessageFormat);
}
setFinished();
@@ -127,7 +126,7 @@ void MaemoRunControl::handleRemoteErrorOutput(const QByteArray &output)
void MaemoRunControl::handleProgressReport(const QString &progressString)
{
- appendMessage(progressString, NormalMessageFormat);
+ appendMessage(progressString + QLatin1Char('\n'), NormalMessageFormat);
}
void MaemoRunControl::handleMountDebugOutput(const QString &output)
@@ -140,6 +139,11 @@ bool MaemoRunControl::isRunning() const
return m_running;
}
+QIcon MaemoRunControl::icon() const
+{
+ return QIcon(ProjectExplorer::Constants::ICON_RUN_SMALL);
+}
+
void MaemoRunControl::handleError(const QString &errString)
{
stop();
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.h b/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.h
index 509aef06fd..d5b8f4758e 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.h
@@ -52,6 +52,7 @@ public:
virtual void start();
virtual StopResult stop();
virtual bool isRunning() const;
+ virtual QIcon icon() const;
private slots:
void startExecution();
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunfactories.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemorunfactories.cpp
index 15a6de02fd..fb1162d646 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemorunfactories.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunfactories.cpp
@@ -33,6 +33,7 @@
#include "maemoconstants.h"
#include "maemodebugsupport.h"
+#include "maemoanalyzersupport.h"
#include "maemoglobal.h"
#include "maemoremotemountsmodel.h"
#include "maemorunconfiguration.h"
@@ -44,6 +45,7 @@
#include <debugger/debuggerconstants.h>
#include <qt4projectmanager/qt4project.h>
#include <qt4projectmanager/qt4projectmanagerconstants.h>
+#include <analyzerbase/analyzerconstants.h>
namespace Qt4ProjectManager {
namespace Internal {
@@ -176,7 +178,8 @@ bool MaemoRunControlFactory::canRun(RunConfiguration *runConfiguration,
: 0;
if (mode == Debugger::Constants::DEBUGMODE)
return freePortCount >= mountDirCount + maemoRunConfig->portsUsedByDebuggers();
- if (mode == ProjectExplorer::Constants::RUNMODE)
+ if (mode == ProjectExplorer::Constants::RUNMODE
+ || Analyzer::Constants::MODE_ANALYZE)
return freePortCount >= mountDirCount;
return false;
}
@@ -185,12 +188,15 @@ RunControl* MaemoRunControlFactory::create(RunConfiguration *runConfig,
const QString &mode)
{
Q_ASSERT(mode == ProjectExplorer::Constants::RUNMODE
- || mode == Debugger::Constants::DEBUGMODE);
+ || mode == Debugger::Constants::DEBUGMODE
+ || mode == Analyzer::Constants::MODE_ANALYZE);
Q_ASSERT(canRun(runConfig, mode));
MaemoRunConfiguration *rc = qobject_cast<MaemoRunConfiguration *>(runConfig);
Q_ASSERT(rc);
if (mode == ProjectExplorer::Constants::RUNMODE)
return new MaemoRunControl(rc);
+ if (mode == Analyzer::Constants::MODE_ANALYZE)
+ return MaemoAnalyzerSupport::createAnalyzerRunControl(rc);
return MaemoDebugSupport::createDebugRunControl(rc);
}
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.cpp
index b594c722a6..37395add3a 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.cpp
@@ -31,7 +31,6 @@
#include "maemosshrunner.h"
-#include "maemodeploystep.h"
#include "maemoglobal.h"
#include "maemoqemumanager.h"
#include "maemoremotemounter.h"
@@ -40,6 +39,7 @@
#include "maemousedportsgatherer.h"
#include <utils/ssh/sshconnection.h>
+#include <utils/ssh/sshconnectionmanager.h>
#include <utils/ssh/sshremoteprocess.h>
#include <QtCore/QFileInfo>
@@ -66,7 +66,7 @@ MaemoSshRunner::MaemoSshRunner(QObject *parent,
m_mountSpecs(runConfig->remoteMounts()->mountSpecs()),
m_state(Inactive)
{
- m_connection = runConfig->deployStep()->sshConnection();
+ m_connection = SshConnectionManager::instance().acquireConnection(m_devConfig->sshParameters());
m_mounter->setBuildConfiguration(runConfig->activeQt4BuildConfiguration());
if (debugging && runConfig->useRemoteGdb()) {
m_mountSpecs << MaemoMountSpecification(runConfig->localDirToMountForRemoteGdb(),
@@ -115,20 +115,15 @@ void MaemoSshRunner::start()
setState(Connecting);
m_exitStatus = -1;
m_freePorts = m_initialFreePorts;
- if (m_connection)
- disconnect(m_connection.data(), 0, this, 0);
- const bool reUse = isConnectionUsable();
- if (!reUse)
- m_connection = SshConnection::create();
connect(m_connection.data(), SIGNAL(connected()), this,
SLOT(handleConnected()));
connect(m_connection.data(), SIGNAL(error(Utils::SshError)), this,
SLOT(handleConnectionFailure()));
- if (reUse) {
+ if (isConnectionUsable()) {
handleConnected();
} else {
emit reportProgress(tr("Connecting to device..."));
- m_connection->connectToHost(m_devConfig->sshParameters());
+ m_connection->connectToHost();
}
}
@@ -316,6 +311,7 @@ void MaemoSshRunner::setState(State newState)
m_portsGatherer->stop();
if (m_connection) {
disconnect(m_connection.data(), 0, this, 0);
+ SshConnectionManager::instance().releaseConnection(m_connection);
m_connection = SshConnection::Ptr();
}
if (m_cleaner)
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.cpp
index 6cfa6315e8..d5edfb5b71 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.cpp
@@ -213,7 +213,7 @@ void MaemoToolChain::updateId()
}
// --------------------------------------------------------------------------
-// ToolChainConfigWidget
+// MaemoToolChainConfigWidget
// --------------------------------------------------------------------------
MaemoToolChainConfigWidget::MaemoToolChainConfigWidget(MaemoToolChain *tc) :
@@ -249,7 +249,7 @@ bool MaemoToolChainConfigWidget::isDirty() const
}
// --------------------------------------------------------------------------
-// ToolChainFactory
+// MaemoToolChainFactory
// --------------------------------------------------------------------------
MaemoToolChainFactory::MaemoToolChainFactory() :
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemouploadandinstalldeploystep.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemouploadandinstalldeploystep.cpp
new file mode 100644
index 0000000000..e7216ca94a
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemouploadandinstalldeploystep.cpp
@@ -0,0 +1,278 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "maemouploadandinstalldeploystep.h"
+
+#include "maemoglobal.h"
+#include "maemopackagecreationstep.h"
+#include "maemopackageinstaller.h"
+#include "maemopackageuploader.h"
+#include "qt4maemodeployconfiguration.h"
+#include "qt4maemotarget.h"
+
+#include <qt4projectmanager/qt4buildconfiguration.h>
+
+#include <QtCore/QFileInfo>
+
+#define ASSERT_BASE_STATE(state) ASSERT_STATE_GENERIC(BaseState, state, baseState())
+#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(ExtendedState, state, m_extendedState)
+
+using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+AbstractMaemoUploadAndInstallStep::AbstractMaemoUploadAndInstallStep(BuildStepList *parent, const QString &id)
+ : AbstractMaemoDeployStep(parent, id)
+{
+}
+
+AbstractMaemoUploadAndInstallStep::AbstractMaemoUploadAndInstallStep(BuildStepList *parent,
+ AbstractMaemoUploadAndInstallStep *other)
+ : AbstractMaemoDeployStep(parent, other)
+{
+}
+
+void AbstractMaemoUploadAndInstallStep::finishInitialization(const QString &displayName,
+ AbstractMaemoPackageInstaller *installer)
+{
+ setDefaultDisplayName(displayName);
+ m_installer = installer;
+ m_extendedState = Inactive;
+
+ m_uploader = new MaemoPackageUploader(this);
+ connect(m_uploader, SIGNAL(progress(QString)),
+ SLOT(handleProgressReport(QString)));
+ connect(m_uploader, SIGNAL(uploadFinished(QString)),
+ SLOT(handleUploadFinished(QString)));
+ connect(m_installer, SIGNAL(stdoutData(QString)),
+ SLOT(handleRemoteStdout(QString)));
+ connect(m_installer, SIGNAL(stderrData(QString)),
+ SLOT(handleRemoteStderr(QString)));
+ connect(m_installer, SIGNAL(finished(QString)),
+ SLOT(handleInstallationFinished(QString)));
+}
+
+bool AbstractMaemoUploadAndInstallStep::isDeploymentPossibleInternal(QString &whyNot) const
+{
+ if (!packagingStep()) {
+ whyNot = tr("No matching packaging step found.");
+ return false;
+ }
+ return true;
+}
+
+bool AbstractMaemoUploadAndInstallStep::isDeploymentNeeded(const QString &hostName) const
+{
+ const AbstractMaemoPackageCreationStep * const pStep = packagingStep();
+ Q_ASSERT(pStep);
+ const MaemoDeployable d(pStep->packageFilePath(), QString());
+ return currentlyNeedsDeployment(hostName, d);
+}
+
+void AbstractMaemoUploadAndInstallStep::startInternal()
+{
+ Q_ASSERT(m_extendedState == Inactive);
+
+ upload();
+}
+
+void AbstractMaemoUploadAndInstallStep::stopInternal()
+{
+ ASSERT_BASE_STATE(StopRequested);
+ ASSERT_STATE(QList<ExtendedState>() << Uploading << Installing);
+
+ switch (m_extendedState) {
+ case Uploading:
+ m_uploader->cancelUpload();
+ break;
+ case Installing:
+ m_installer->cancelInstallation();
+ break;
+ case Inactive:
+ break;
+ default:
+ qFatal("Missing switch case in %s.", Q_FUNC_INFO);
+
+ }
+ setFinished();
+}
+
+void AbstractMaemoUploadAndInstallStep::upload()
+{
+ m_extendedState = Uploading;
+ const QString localFilePath = packagingStep()->packageFilePath();
+ const QString fileName = QFileInfo(localFilePath).fileName();
+ const QString remoteFilePath = uploadDir() + QLatin1Char('/') + fileName;
+ m_uploader->uploadPackage(connection(), localFilePath, remoteFilePath);
+}
+
+void AbstractMaemoUploadAndInstallStep::handleUploadFinished(const QString &errorMsg)
+{
+ ASSERT_BASE_STATE(QList<BaseState>() << Deploying << StopRequested);
+ ASSERT_STATE(QList<ExtendedState>() << Uploading << Inactive);
+
+ if (m_extendedState == Inactive)
+ return;
+
+ if (!errorMsg.isEmpty()) {
+ raiseError(errorMsg);
+ setFinished();
+ } else {
+ writeOutput(tr("Successfully uploaded package file."));
+ const QString remoteFilePath = uploadDir() + QLatin1Char('/')
+ + QFileInfo(packagingStep()->packageFilePath()).fileName();
+ m_extendedState = Installing;
+ writeOutput(tr("Installing package to device..."));
+ m_installer->installPackage(connection(), remoteFilePath, true);
+ }
+}
+
+void AbstractMaemoUploadAndInstallStep::handleInstallationFinished(const QString &errorMsg)
+{
+ ASSERT_BASE_STATE(QList<BaseState>() << Deploying << StopRequested);
+ ASSERT_STATE(QList<ExtendedState>() << Installing << Inactive);
+
+ if (m_extendedState == Inactive)
+ return;
+
+ if (errorMsg.isEmpty()) {
+ setDeployed(connection()->connectionParameters().host,
+ MaemoDeployable(packagingStep()->packageFilePath(), QString()));
+ writeOutput(tr("Package installed."));
+ } else {
+ raiseError(errorMsg);
+ }
+ setFinished();
+}
+
+void AbstractMaemoUploadAndInstallStep::setFinished()
+{
+ m_extendedState = Inactive;
+ setDeploymentFinished();
+}
+
+QString AbstractMaemoUploadAndInstallStep::uploadDir() const
+{
+ return MaemoGlobal::homeDirOnDevice(connection()->connectionParameters().userName);
+}
+
+
+MaemoUploadAndInstallDpkgPackageStep::MaemoUploadAndInstallDpkgPackageStep(ProjectExplorer::BuildStepList *bc)
+ : AbstractMaemoUploadAndInstallStep(bc, Id)
+{
+ ctor();
+}
+
+MaemoUploadAndInstallDpkgPackageStep::MaemoUploadAndInstallDpkgPackageStep(ProjectExplorer::BuildStepList *bc,
+ MaemoUploadAndInstallDpkgPackageStep *other)
+ : AbstractMaemoUploadAndInstallStep(bc, other)
+{
+ ctor();
+}
+
+void MaemoUploadAndInstallDpkgPackageStep::ctor()
+{
+ finishInitialization(DisplayName, new MaemoDebianPackageInstaller(this));
+}
+
+
+const AbstractMaemoPackageCreationStep *MaemoUploadAndInstallDpkgPackageStep::packagingStep() const
+{
+ return MaemoGlobal::earlierBuildStep<MaemoDebianPackageCreationStep>(maemoDeployConfig(), this);
+}
+
+const QString MaemoUploadAndInstallDpkgPackageStep::Id("MaemoUploadAndInstallDpkgPackageStep");
+const QString MaemoUploadAndInstallDpkgPackageStep::DisplayName
+ = tr("Deploy Debian package via SFTP upload");
+
+
+MaemoUploadAndInstallRpmPackageStep::MaemoUploadAndInstallRpmPackageStep(ProjectExplorer::BuildStepList *bc)
+ : AbstractMaemoUploadAndInstallStep(bc, Id)
+{
+ ctor();
+}
+
+MaemoUploadAndInstallRpmPackageStep::MaemoUploadAndInstallRpmPackageStep(ProjectExplorer::BuildStepList *bc,
+ MaemoUploadAndInstallRpmPackageStep *other)
+ : AbstractMaemoUploadAndInstallStep(bc, other)
+{
+ ctor();
+}
+
+void MaemoUploadAndInstallRpmPackageStep::ctor()
+{
+ finishInitialization(DisplayName, new MaemoRpmPackageInstaller(this));
+}
+
+const AbstractMaemoPackageCreationStep *MaemoUploadAndInstallRpmPackageStep::packagingStep() const
+{
+ return MaemoGlobal::earlierBuildStep<MaemoRpmPackageCreationStep>(maemoDeployConfig(), this);
+}
+
+const QString MaemoUploadAndInstallRpmPackageStep::Id("MaemoUploadAndInstallRpmPackageStep");
+const QString MaemoUploadAndInstallRpmPackageStep::DisplayName
+ = tr("Deploy RPM package via SFTP upload");
+
+
+MaemoUploadAndInstallTarPackageStep::MaemoUploadAndInstallTarPackageStep(ProjectExplorer::BuildStepList *bc)
+ : AbstractMaemoUploadAndInstallStep(bc, Id)
+{
+ ctor();
+}
+
+MaemoUploadAndInstallTarPackageStep::MaemoUploadAndInstallTarPackageStep(ProjectExplorer::BuildStepList *bc,
+ MaemoUploadAndInstallTarPackageStep *other)
+ : AbstractMaemoUploadAndInstallStep(bc, other)
+{
+ ctor();
+}
+
+const AbstractMaemoPackageCreationStep *MaemoUploadAndInstallTarPackageStep::packagingStep() const
+{
+ return MaemoGlobal::earlierBuildStep<MaemoTarPackageCreationStep>(maemoDeployConfig(), this);
+}
+
+void MaemoUploadAndInstallTarPackageStep::ctor()
+{
+ finishInitialization(DisplayName, new MaemoTarPackageInstaller(this));
+}
+
+const QString MaemoUploadAndInstallTarPackageStep::Id("MaemoUploadAndInstallTarPackageStep");
+const QString MaemoUploadAndInstallTarPackageStep::DisplayName
+ = tr("Deploy tar package via SFTP upload");
+
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemouploadandinstalldeploystep.h b/src/plugins/qt4projectmanager/qt-maemo/maemouploadandinstalldeploystep.h
new file mode 100644
index 0000000000..2053520ec4
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemouploadandinstalldeploystep.h
@@ -0,0 +1,132 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 MAEMODEPLOYSTEP_H
+#define MAEMODEPLOYSTEP_H
+
+#include "abstractmaemodeploystep.h"
+
+namespace Qt4ProjectManager {
+namespace Internal {
+class AbstractMaemoPackageInstaller;
+class MaemoPackageUploader;
+
+class AbstractMaemoUploadAndInstallStep : public AbstractMaemoDeployStep
+{
+ Q_OBJECT
+protected:
+ AbstractMaemoUploadAndInstallStep(ProjectExplorer::BuildStepList *bc,
+ const QString &id);
+ AbstractMaemoUploadAndInstallStep(ProjectExplorer::BuildStepList *bc,
+ AbstractMaemoUploadAndInstallStep *other);
+
+ void finishInitialization(const QString &displayName,
+ AbstractMaemoPackageInstaller *installer);
+
+private slots:
+ void handleUploadFinished(const QString &errorMsg);
+ void handleInstallationFinished(const QString &errorMsg);
+
+private:
+ enum ExtendedState { Inactive, Uploading, Installing };
+
+ virtual bool isDeploymentPossibleInternal(QString &whynot) const;
+ virtual bool isDeploymentNeeded(const QString &hostName) const;
+ virtual void startInternal();
+ virtual void stopInternal();
+
+ void upload();
+ void setFinished();
+ QString uploadDir() const;
+
+ MaemoPackageUploader *m_uploader;
+ AbstractMaemoPackageInstaller *m_installer;
+ ExtendedState m_extendedState;
+};
+
+
+class MaemoUploadAndInstallDpkgPackageStep : public AbstractMaemoUploadAndInstallStep
+{
+ Q_OBJECT
+public:
+ MaemoUploadAndInstallDpkgPackageStep(ProjectExplorer::BuildStepList *bc);
+ MaemoUploadAndInstallDpkgPackageStep(ProjectExplorer::BuildStepList *bc,
+ MaemoUploadAndInstallDpkgPackageStep *other);
+
+ static const QString Id;
+ static const QString DisplayName;
+
+private:
+ void ctor();
+
+ virtual const AbstractMaemoPackageCreationStep *packagingStep() const;
+};
+
+class MaemoUploadAndInstallRpmPackageStep : public AbstractMaemoUploadAndInstallStep
+{
+ Q_OBJECT
+public:
+ MaemoUploadAndInstallRpmPackageStep(ProjectExplorer::BuildStepList *bc);
+ MaemoUploadAndInstallRpmPackageStep(ProjectExplorer::BuildStepList *bc,
+ MaemoUploadAndInstallRpmPackageStep *other);
+
+ static const QString Id;
+ static const QString DisplayName;
+
+private:
+ void ctor();
+
+ virtual const AbstractMaemoPackageCreationStep *packagingStep() const;
+};
+
+class MaemoUploadAndInstallTarPackageStep : public AbstractMaemoUploadAndInstallStep
+{
+ Q_OBJECT
+public:
+ MaemoUploadAndInstallTarPackageStep(ProjectExplorer::BuildStepList *bc);
+ MaemoUploadAndInstallTarPackageStep(ProjectExplorer::BuildStepList *bc,
+ MaemoUploadAndInstallTarPackageStep *other);
+
+ static const QString Id;
+ static const QString DisplayName;
+
+private:
+ void ctor();
+
+ virtual const AbstractMaemoPackageCreationStep *packagingStep() const;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // MAEMODEPLOYSTEP_H
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemousedportsgatherer.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemousedportsgatherer.cpp
index 14d23087e7..72b56adcdc 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemousedportsgatherer.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemousedportsgatherer.cpp
@@ -64,7 +64,7 @@ void MaemoUsedPortsGatherer::start(const Utils::SshConnection::Ptr &connection,
SLOT(handleRemoteStdOut(QByteArray)));
connect(m_procRunner.data(), SIGNAL(processErrorOutputAvailable(QByteArray)),
SLOT(handleRemoteStdErr(QByteArray)));
- const QString command = MaemoGlobal::remoteSudo()
+ const QString command = MaemoGlobal::remoteSudo(m_procRunner->connection()->connectionParameters().userName)
+ QLatin1String(" lsof -nPi4tcp:") + portList.toString()
+ QLatin1String(" -F n |grep '^n' |sed -r 's/[^:]*:([[:digit:]]+).*/\\1/g' |sort -n |uniq");
m_procRunner->run(command.toUtf8());
diff --git a/src/plugins/qt4projectmanager/qt-maemo/qt-maemo.pri b/src/plugins/qt4projectmanager/qt-maemo/qt-maemo.pri
index 841c2c067b..d42d24ad40 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/qt-maemo.pri
+++ b/src/plugins/qt4projectmanager/qt-maemo/qt-maemo.pri
@@ -18,12 +18,12 @@ HEADERS += \
$$PWD/maemoqemumanager.h \
$$PWD/maemodeployables.h \
$$PWD/maemodeployable.h \
- $$PWD/maemodeploystep.h \
$$PWD/maemodeploystepwidget.h \
$$PWD/maemodeploystepfactory.h \
$$PWD/maemoglobal.h \
$$PWD/maemosshrunner.h \
$$PWD/maemodebugsupport.h \
+ $$PWD/maemoanalyzersupport.h \
$$PWD/maemoremotemountsmodel.h \
$$PWD/maemodeviceenvreader.h \
$$PWD/maemomountspecification.h \
@@ -49,7 +49,17 @@ HEADERS += \
$$PWD/qt4maemodeployconfiguration.h \
$$PWD/maemodeviceconfigwizard.h \
$$PWD/maemokeydeployer.h \
- $$PWD/maemopertargetdeviceconfigurationlistmodel.h
+ $$PWD/maemopertargetdeviceconfigurationlistmodel.h \
+ $$PWD/maemodeployconfigurationwidget.h \
+ $$PWD/maemoinstalltosysrootstep.h \
+ $$PWD/maemodeploymentmounter.h \
+ $$PWD/maemopackageuploader.h \
+ $$PWD/maemopackageinstaller.h \
+ $$PWD/maemoremotecopyfacility.h \
+ $$PWD/abstractmaemodeploystep.h \
+ $$PWD/maemodeploybymountstep.h \
+ $$PWD/maemouploadandinstalldeploystep.h \
+ $$PWD/maemodirectdeviceuploadstep.h
SOURCES += \
$$PWD/maemoconfigtestdialog.cpp \
@@ -69,12 +79,12 @@ SOURCES += \
$$PWD/maemodeployablelistmodel.cpp \
$$PWD/maemoqemumanager.cpp \
$$PWD/maemodeployables.cpp \
- $$PWD/maemodeploystep.cpp \
$$PWD/maemodeploystepwidget.cpp \
$$PWD/maemodeploystepfactory.cpp \
$$PWD/maemoglobal.cpp \
$$PWD/maemosshrunner.cpp \
$$PWD/maemodebugsupport.cpp \
+ $$PWD/maemoanalyzersupport.cpp \
$$PWD/maemoremotemountsmodel.cpp \
$$PWD/maemodeviceenvreader.cpp \
$$PWD/maemomountspecification.cpp \
@@ -99,7 +109,17 @@ SOURCES += \
$$PWD/qt4maemodeployconfiguration.cpp \
$$PWD/maemodeviceconfigwizard.cpp \
$$PWD/maemokeydeployer.cpp \
- $$PWD/maemopertargetdeviceconfigurationlistmodel.cpp
+ $$PWD/maemopertargetdeviceconfigurationlistmodel.cpp \
+ $$PWD/maemodeployconfigurationwidget.cpp \
+ $$PWD/maemoinstalltosysrootstep.cpp \
+ $$PWD/maemodeploymentmounter.cpp \
+ $$PWD/maemopackageuploader.cpp \
+ $$PWD/maemopackageinstaller.cpp \
+ $$PWD/maemoremotecopyfacility.cpp \
+ $$PWD/abstractmaemodeploystep.cpp \
+ $$PWD/maemodeploybymountstep.cpp \
+ $$PWD/maemouploadandinstalldeploystep.cpp \
+ $$PWD/maemodirectdeviceuploadstep.cpp
FORMS += \
$$PWD/maemoconfigtestdialog.ui \
@@ -118,6 +138,8 @@ FORMS += \
$$PWD/maemodeviceconfigwizardpreviouskeysetupcheckpage.ui \
$$PWD/maemodeviceconfigwizardreusekeyscheckpage.ui \
$$PWD/maemodeviceconfigwizardkeycreationpage.ui \
- $$PWD/maemodeviceconfigwizardkeydeploymentpage.ui
+ $$PWD/maemodeviceconfigwizardkeydeploymentpage.ui \
+ $$PWD/maemodeployconfigurationwidget.ui \
+ $$PWD/maemodeviceconfigwizardlogindatapage.ui
RESOURCES += $$PWD/qt-maemo.qrc
diff --git a/src/plugins/qt4projectmanager/qt-maemo/qt4maemodeployconfiguration.cpp b/src/plugins/qt4projectmanager/qt-maemo/qt4maemodeployconfiguration.cpp
index e82f07a1a6..83caead7ab 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/qt4maemodeployconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/qt4maemodeployconfiguration.cpp
@@ -30,36 +30,191 @@
**
**************************************************************************/
-#include "maemodeploystep.h"
-#include "maemopackagecreationstep.h"
#include "qt4maemodeployconfiguration.h"
+#include "maemodeploybymountstep.h"
+#include "maemodeployconfigurationwidget.h"
+#include "maemodeployables.h"
+#include "maemoinstalltosysrootstep.h"
+#include "maemopertargetdeviceconfigurationlistmodel.h"
+#include "maemopackagecreationstep.h"
+#include "maemouploadandinstalldeploystep.h"
+#include "qt4maemotarget.h"
+
#include <projectexplorer/buildsteplist.h>
-#include <projectexplorer/target.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <qt4projectmanager/qt4projectmanagerconstants.h>
+#include <qt4projectmanager/qt4target.h>
+
+using namespace ProjectExplorer;
+
+namespace Qt4ProjectManager {
+namespace Internal {
+namespace {
+const QString OldDeployConfigId = QLatin1String("2.2MaemoDeployConfig");
+} // namespace
+
+Qt4MaemoDeployConfiguration::Qt4MaemoDeployConfiguration(Target *target,
+ const QString &id) : DeployConfiguration(target, id)
+{
+ // A MaemoDeployables object is only dependent on the active build
+ // configuration and therefore can (and should) be shared among all
+ // deploy steps. The per-target device configurations model is
+ // similarly only dependent on the target.
+ const QList<DeployConfiguration *> &deployConfigs
+ = this->target()->deployConfigurations();
+ foreach (const DeployConfiguration * const dc, deployConfigs) {
+ const Qt4MaemoDeployConfiguration * const mdc
+ = qobject_cast<const Qt4MaemoDeployConfiguration *>(dc);
+ if (mdc) {
+ m_deployables = mdc->deployables();
+ m_devConfModel = mdc->m_devConfModel;
+ break;
+ }
+ }
+ if (!m_deployables) {
+ m_deployables = QSharedPointer<MaemoDeployables>(new MaemoDeployables(qobject_cast<Qt4BaseTarget *>(target)));
+ m_devConfModel = new MaemoPerTargetDeviceConfigurationListModel(this, target);
+ }
+}
+
+Qt4MaemoDeployConfiguration::Qt4MaemoDeployConfiguration(ProjectExplorer::Target *target,
+ DeployConfiguration *source) : DeployConfiguration(target, source)
+{
+ m_deployables = qobject_cast<Qt4MaemoDeployConfiguration *>(source)->deployables();
+}
-using namespace Qt4ProjectManager;
-using namespace Qt4ProjectManager::Internal;
+Qt4MaemoDeployConfiguration::~Qt4MaemoDeployConfiguration() {}
-Qt4MaemoDeployConfigurationFactory::Qt4MaemoDeployConfigurationFactory(QObject *parent) :
- ProjectExplorer::DeployConfigurationFactory(parent)
+DeployConfigurationWidget *Qt4MaemoDeployConfiguration::configurationWidget() const
+{
+ return new MaemoDeployConfigurationWidget;
+}
+
+const QString Qt4MaemoDeployConfiguration::FremantleWithPackagingId
+ = QLatin1String("DeployToFremantleWithPackaging");
+const QString Qt4MaemoDeployConfiguration::FremantleWithoutPackagingId
+ = QLatin1String("DeployToFremantleWithoutPackaging");
+const QString Qt4MaemoDeployConfiguration::HarmattanId
+ = QLatin1String("DeployToHarmattan");
+const QString Qt4MaemoDeployConfiguration::MeegoId
+ = QLatin1String("DeployToMeego");
+const QString Qt4MaemoDeployConfiguration::GenericLinuxId
+ = QLatin1String("DeployToGenericLinux");
+
+
+Qt4MaemoDeployConfigurationFactory::Qt4MaemoDeployConfigurationFactory(QObject *parent)
+ : DeployConfigurationFactory(parent)
{ }
-ProjectExplorer::DeployConfiguration *Qt4MaemoDeployConfigurationFactory::create(ProjectExplorer::Target *parent, const QString &id)
+QStringList Qt4MaemoDeployConfigurationFactory::availableCreationIds(Target *parent) const
{
- ProjectExplorer::DeployConfiguration *dc = ProjectExplorer::DeployConfigurationFactory::create(parent, id);
+ QStringList ids;
+ if (qobject_cast<Qt4Maemo5Target *>(parent)) {
+ ids << Qt4MaemoDeployConfiguration::FremantleWithPackagingId
+ << Qt4MaemoDeployConfiguration::FremantleWithoutPackagingId;
+ } else if (qobject_cast<Qt4HarmattanTarget *>(parent)) {
+ ids << Qt4MaemoDeployConfiguration::HarmattanId;
+ } else if (qobject_cast<Qt4MeegoTarget *>(parent)) {
+ ids << Qt4MaemoDeployConfiguration::MeegoId;
+ } /*else if (qobject_cast<Qt4BaseTarget *>(parent)) { // TODO: Check for Linux
+ ids << Qt4MaemoDeployConfiguration::GenericLinuxId;
+ }*/
- if (!dc)
- return 0;
- if (parent->id() == QLatin1String(Constants::MAEMO5_DEVICE_TARGET_ID))
- dc->setDefaultDisplayName(tr("Deploy to Maemo5 device"));
- if (parent->id() == QLatin1String(Constants::HARMATTAN_DEVICE_TARGET_ID))
- dc->setDefaultDisplayName(tr("Deploy to Harmattan device"));
- if (parent->id() == QLatin1String(Constants::MEEGO_DEVICE_TARGET_ID))
- dc->setDefaultDisplayName(tr("Deploy to Meego device"));
- dc->stepList()->insertStep(0, new MaemoPackageCreationStep(dc->stepList()));
- dc->stepList()->insertStep(1, new MaemoDeployStep(dc->stepList()));
+ return ids;
+}
+
+QString Qt4MaemoDeployConfigurationFactory::displayNameForId(const QString &id) const
+{
+ if (id == Qt4MaemoDeployConfiguration::FremantleWithoutPackagingId)
+ return tr("Copy files to Maemo5 device");
+ else if (id == Qt4MaemoDeployConfiguration::FremantleWithPackagingId)
+ return tr("Build Debian package and install to Maemo5 device");
+ else if (id == Qt4MaemoDeployConfiguration::HarmattanId)
+ return tr("Build Debian package and install to Harmattan device");
+ else if (id == Qt4MaemoDeployConfiguration::MeegoId)
+ return tr("Build RPM package and install to Meego device");
+ else if (id == Qt4MaemoDeployConfiguration::GenericLinuxId)
+ return tr("Build tarball and install to Linux host");
+ return QString();
+}
+bool Qt4MaemoDeployConfigurationFactory::canCreate(Target *parent,
+ const QString &id) const
+{
+ return availableCreationIds(parent).contains(id);
+}
+
+DeployConfiguration *Qt4MaemoDeployConfigurationFactory::create(Target *parent,
+ const QString &id)
+{
+ Q_ASSERT(canCreate(parent, id));
+
+ DeployConfiguration * const dc
+ = new Qt4MaemoDeployConfiguration(parent, id);
+ dc->setDefaultDisplayName(displayNameForId(id));
+
+ if (id == Qt4MaemoDeployConfiguration::FremantleWithoutPackagingId) {
+ dc->stepList()->insertStep(0, new MaemoCopyToSysrootStep(dc->stepList()));
+ dc->stepList()->insertStep(1, new MaemoMountAndCopyDeployStep(dc->stepList()));
+ } else if (id == Qt4MaemoDeployConfiguration::FremantleWithPackagingId) {
+ dc->stepList()->insertStep(0, new MaemoDebianPackageCreationStep(dc->stepList()));
+ dc->stepList()->insertStep(1, new MaemoInstallDebianPackageToSysrootStep(dc->stepList()));
+ dc->stepList()->insertStep(2, new MaemoMountAndInstallDeployStep(dc->stepList()));
+ } else if (id == Qt4MaemoDeployConfiguration::HarmattanId) {
+ dc->stepList()->insertStep(0, new MaemoDebianPackageCreationStep(dc->stepList()));
+ dc->stepList()->insertStep(1, new MaemoInstallDebianPackageToSysrootStep(dc->stepList()));
+ dc->stepList()->insertStep(2, new MaemoUploadAndInstallDpkgPackageStep(dc->stepList()));
+ } else if (id == Qt4MaemoDeployConfiguration::MeegoId) {
+ dc->stepList()->insertStep(0, new MaemoRpmPackageCreationStep(dc->stepList()));
+ dc->stepList()->insertStep(1, new MaemoInstallRpmPackageToSysrootStep(dc->stepList()));
+ dc->stepList()->insertStep(2, new MaemoUploadAndInstallRpmPackageStep(dc->stepList()));
+ } else if (id == Qt4MaemoDeployConfiguration::GenericLinuxId) {
+ dc->stepList()->insertStep(0, new MaemoTarPackageCreationStep(dc->stepList()));
+ dc->stepList()->insertStep(1, new MaemoUploadAndInstallTarPackageStep(dc->stepList()));
+ }
+ return dc;
+}
+
+bool Qt4MaemoDeployConfigurationFactory::canRestore(Target *parent,
+ const QVariantMap &map) const
+{
+ return canCreate(parent, idFromMap(map))
+ || (idFromMap(map) == OldDeployConfigId
+ && qobject_cast<AbstractQt4MaemoTarget *>(parent));
+}
+
+DeployConfiguration *Qt4MaemoDeployConfigurationFactory::restore(Target *parent,
+ const QVariantMap &map)
+{
+ if (!canRestore(parent, map))
+ return 0;
+ QString id = idFromMap(map);
+ if (id == OldDeployConfigId) {
+ if (qobject_cast<Qt4Maemo5Target *>(parent))
+ id = Qt4MaemoDeployConfiguration::FremantleWithPackagingId;
+ else if (qobject_cast<Qt4HarmattanTarget *>(parent))
+ id = Qt4MaemoDeployConfiguration::HarmattanId;
+ else if (qobject_cast<Qt4MeegoTarget *>(parent))
+ id = Qt4MaemoDeployConfiguration::MeegoId;
+ }
+ Qt4MaemoDeployConfiguration * const dc
+ = new Qt4MaemoDeployConfiguration(parent, id);
+ if (!dc->fromMap(map)) {
+ delete dc;
+ return 0;
+ }
return dc;
}
+
+DeployConfiguration *Qt4MaemoDeployConfigurationFactory::clone(Target *parent,
+ DeployConfiguration *product)
+{
+ if (!canClone(parent, product))
+ return 0;
+ return new Qt4MaemoDeployConfiguration(parent, product);
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-maemo/qt4maemodeployconfiguration.h b/src/plugins/qt4projectmanager/qt-maemo/qt4maemodeployconfiguration.h
index bc1fed497b..74932299c7 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/qt4maemodeployconfiguration.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/qt4maemodeployconfiguration.h
@@ -33,12 +33,46 @@
#ifndef QT4PROJECTMANAGER_QT4DEPLOYCONFIGURATION_H
#define QT4PROJECTMANAGER_QT4DEPLOYCONFIGURATION_H
+#include"maemodeployables.h"
+
#include <projectexplorer/deployconfiguration.h>
+#include <QtCore/QSharedPointer>
+
namespace Qt4ProjectManager {
namespace Internal {
+class MaemoPerTargetDeviceConfigurationListModel;
+
+class Qt4MaemoDeployConfiguration : public ProjectExplorer::DeployConfiguration
+{
+ Q_OBJECT
+
+public:
+ virtual ~Qt4MaemoDeployConfiguration();
+
+ virtual ProjectExplorer::DeployConfigurationWidget *configurationWidget() const;
+
+ QSharedPointer<MaemoDeployables> deployables() const { return m_deployables; }
+ MaemoPerTargetDeviceConfigurationListModel *deviceConfigModel() const { return m_devConfModel; }
+
+ static const QString FremantleWithPackagingId;
+ static const QString FremantleWithoutPackagingId;
+ static const QString HarmattanId;
+ static const QString MeegoId;
+ static const QString GenericLinuxId;
+
+private:
+ friend class Qt4MaemoDeployConfigurationFactory;
+
+ Qt4MaemoDeployConfiguration(ProjectExplorer::Target *target,
+ const QString &id);
+ Qt4MaemoDeployConfiguration(ProjectExplorer::Target *target,
+ ProjectExplorer::DeployConfiguration *source);
+
+ QSharedPointer<MaemoDeployables> m_deployables;
+ MaemoPerTargetDeviceConfigurationListModel *m_devConfModel;
+};
-class Target;
class Qt4MaemoDeployConfigurationFactory : public ProjectExplorer::DeployConfigurationFactory
{
@@ -47,7 +81,16 @@ class Qt4MaemoDeployConfigurationFactory : public ProjectExplorer::DeployConfigu
public:
explicit Qt4MaemoDeployConfigurationFactory(QObject *parent = 0);
- ProjectExplorer::DeployConfiguration *create(ProjectExplorer::Target *parent, const QString &id);
+ virtual QStringList availableCreationIds(ProjectExplorer::Target *parent) const;
+ virtual QString displayNameForId(const QString &id) const;
+ virtual bool canCreate(ProjectExplorer::Target *parent, const QString &id) const;
+ virtual ProjectExplorer::DeployConfiguration *create(ProjectExplorer::Target *parent, const QString &id);
+ virtual bool canRestore(ProjectExplorer::Target *parent,
+ const QVariantMap &map) const;
+ virtual ProjectExplorer::DeployConfiguration *restore(ProjectExplorer::Target *parent,
+ const QVariantMap &map);
+ virtual ProjectExplorer::DeployConfiguration *clone(ProjectExplorer::Target *parent,
+ ProjectExplorer::DeployConfiguration *product);
};
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-maemo/qt4maemotarget.cpp b/src/plugins/qt4projectmanager/qt-maemo/qt4maemotarget.cpp
index 5f849ca0b7..cba94e705f 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/qt4maemotarget.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/qt4maemotarget.cpp
@@ -34,7 +34,6 @@
#include "maemoglobal.h"
#include "maemopackagecreationstep.h"
-#include "maemopertargetdeviceconfigurationlistmodel.h"
#include "maemorunconfiguration.h"
#include "maemotoolchain.h"
#include "qt4maemodeployconfiguration.h"
@@ -112,7 +111,6 @@ AbstractQt4MaemoTarget::AbstractQt4MaemoTarget(Qt4Project *parent, const QString
Qt4BaseTarget(parent, id),
m_filesWatcher(new QFileSystemWatcher(this)),
m_buildConfigurationFactory(new Qt4BuildConfigurationFactory(this)),
- m_deployConfigurationFactory(new Qt4MaemoDeployConfigurationFactory(this)),
m_isInitialized(false)
{
setIcon(QIcon(":/projectexplorer/images/MaemoDevice.png"));
@@ -164,20 +162,6 @@ Qt4BuildConfigurationFactory *AbstractQt4MaemoTarget::buildConfigurationFactory(
return m_buildConfigurationFactory;
}
-ProjectExplorer::DeployConfigurationFactory *AbstractQt4MaemoTarget::deployConfigurationFactory() const
-{
- return m_deployConfigurationFactory;
-}
-
-QString AbstractQt4MaemoTarget::defaultBuildDirectory() const
-{
- //TODO why?
-#if defined(Q_OS_WIN)
- return project()->projectDirectory();
-#endif
- return Qt4BaseTarget::defaultBuildDirectory();
-}
-
void AbstractQt4MaemoTarget::createApplicationProFiles()
{
removeUnconfiguredCustomExectutableRunConfigurations();
@@ -384,12 +368,6 @@ bool AbstractQt4MaemoTarget::initPackagingSettingsFromOtherTarget()
return initAdditionalPackagingSettingsFromOtherTarget();
}
-void AbstractQt4MaemoTarget::initDeviceConfigurationsModel()
-{
- m_deviceConfigurationsListModel
- = new MaemoPerTargetDeviceConfigurationListModel(this);
-}
-
void AbstractQt4MaemoTarget::raiseError(const QString &reason)
{
QMessageBox::critical(0, tr("Error creating Maemo templates"), reason);
@@ -758,7 +736,7 @@ AbstractQt4MaemoTarget::ActionStatus AbstractDebBasedQt4MaemoTarget::createSpeci
QProcess dh_makeProc;
QString error;
const Qt4BuildConfiguration * const bc = activeBuildConfiguration();
- MaemoPackageCreationStep::preparePackagingProcess(&dh_makeProc, bc,
+ AbstractMaemoPackageCreationStep::preparePackagingProcess(&dh_makeProc, bc,
projectDir.path() + QLatin1Char('/') + PackagingDirName);
const QString dhMakeDebianDir = projectDir.path() + QLatin1Char('/')
+ PackagingDirName + QLatin1String("/debian");
@@ -766,7 +744,7 @@ AbstractQt4MaemoTarget::ActionStatus AbstractDebBasedQt4MaemoTarget::createSpeci
const QStringList dh_makeArgs = QStringList() << QLatin1String("dh_make")
<< QLatin1String("-s") << QLatin1String("-n") << QLatin1String("-p")
<< (defaultPackageFileName() + QLatin1Char('_')
- + MaemoPackageCreationStep::DefaultVersionNumber);
+ + AbstractMaemoPackageCreationStep::DefaultVersionNumber);
if (!MaemoGlobal::callMad(dh_makeProc, dh_makeArgs, activeBuildConfiguration()->qtVersion(), true)
|| !dh_makeProc.waitForStarted()) {
raiseError(tr("Unable to create Debian templates: dh_make failed (%1)")
@@ -1098,7 +1076,6 @@ Qt4Maemo5Target::Qt4Maemo5Target(Qt4Project *parent, const QString &id)
: AbstractDebBasedQt4MaemoTarget(parent, id)
{
setDisplayName(defaultDisplayName());
- initDeviceConfigurationsModel();
}
Qt4Maemo5Target::~Qt4Maemo5Target() {}
@@ -1128,7 +1105,6 @@ Qt4HarmattanTarget::Qt4HarmattanTarget(Qt4Project *parent, const QString &id)
: AbstractDebBasedQt4MaemoTarget(parent, id)
{
setDisplayName(defaultDisplayName());
- initDeviceConfigurationsModel();
}
Qt4HarmattanTarget::~Qt4HarmattanTarget() {}
@@ -1160,7 +1136,6 @@ Qt4MeegoTarget::Qt4MeegoTarget(Qt4Project *parent, const QString &id)
: AbstractRpmBasedQt4MaemoTarget(parent, id)
{
setDisplayName(defaultDisplayName());
- initDeviceConfigurationsModel();
}
Qt4MeegoTarget::~Qt4MeegoTarget() {}
diff --git a/src/plugins/qt4projectmanager/qt-maemo/qt4maemotarget.h b/src/plugins/qt4projectmanager/qt-maemo/qt4maemotarget.h
index bd0268b9b8..bf996b825c 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/qt4maemotarget.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/qt4maemotarget.h
@@ -45,7 +45,6 @@ QT_FORWARD_DECLARE_CLASS(QFileSystemWatcher)
namespace Qt4ProjectManager {
class Qt4Project;
namespace Internal {
-class MaemoPerTargetDeviceConfigurationListModel;
class Qt4MaemoDeployConfigurationFactory;
class AbstractQt4MaemoTarget : public Qt4BaseTarget
@@ -57,8 +56,6 @@ public:
virtual ~AbstractQt4MaemoTarget();
Internal::Qt4BuildConfigurationFactory *buildConfigurationFactory() const;
- ProjectExplorer::DeployConfigurationFactory *deployConfigurationFactory() const;
- QString defaultBuildDirectory() const;
void createApplicationProFiles();
QList<ProjectExplorer::RunConfiguration *> runConfigurationsForNode(ProjectExplorer::Node *n);
@@ -86,15 +83,11 @@ public:
// TODO: Is this needed with the ABI info we have?
DebugArchitecture debugArchitecture() const;
- MaemoPerTargetDeviceConfigurationListModel *deviceConfigurationsModel() const {
- return m_deviceConfigurationsListModel;
- }
QList<ProjectExplorer::ToolChain *> possibleToolChains(ProjectExplorer::BuildConfiguration *bc) const;
protected:
enum ActionStatus { NoActionRequired, ActionSuccessful, ActionFailed };
- void initDeviceConfigurationsModel();
void raiseError(const QString &reason);
QSharedPointer<QFile> openFile(const QString &filePath,
QIODevice::OpenMode mode, QString *error) const;
@@ -122,8 +115,6 @@ private:
virtual bool initAdditionalPackagingSettingsFromOtherTarget()=0;
Qt4BuildConfigurationFactory *m_buildConfigurationFactory;
- Qt4MaemoDeployConfigurationFactory *m_deployConfigurationFactory;
- MaemoPerTargetDeviceConfigurationListModel * m_deviceConfigurationsListModel;
bool m_isInitialized;
};
diff --git a/src/plugins/qt4projectmanager/qt-maemo/qt4maemotargetfactory.cpp b/src/plugins/qt4projectmanager/qt-maemo/qt4maemotargetfactory.cpp
index c8e12dcce9..5d3db6a0d5 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/qt4maemotargetfactory.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/qt4maemotargetfactory.cpp
@@ -34,15 +34,16 @@
#include "buildconfigurationinfo.h"
#include "qt4project.h"
#include "qt4projectmanagerconstants.h"
-#include "qt-maemo/maemodeploystep.h"
#include "maemoglobal.h"
-#include "qt-maemo/maemopackagecreationstep.h"
-#include "qt-maemo/maemorunconfiguration.h"
-#include "qt-maemo/qt4maemotarget.h"
+#include "maemopackagecreationstep.h"
+#include "maemorunconfiguration.h"
+#include "qt4maemodeployconfiguration.h"
+#include "qt4maemotarget.h"
#include <projectexplorer/deployconfiguration.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/customexecutablerunconfiguration.h>
+#include <utils/qtcassert.h>
using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;
@@ -130,43 +131,28 @@ ProjectExplorer::Target *Qt4MaemoTargetFactory::restore(ProjectExplorer::Project
return 0;
}
-QString Qt4MaemoTargetFactory::defaultShadowBuildDirectory(const QString &projectLocation, const QString &id)
+QString Qt4MaemoTargetFactory::buildNameForId(const QString &id) const
{
- QString suffix;
if (id == QLatin1String(Constants::MAEMO5_DEVICE_TARGET_ID))
- suffix = QLatin1String("maemo");
+ return QLatin1String("maemo");
else if (id == QLatin1String(Constants::HARMATTAN_DEVICE_TARGET_ID))
- suffix = QLatin1String("harmattan");
+ return QLatin1String("harmattan");
else if (id == QLatin1String(Constants::MEEGO_DEVICE_TARGET_ID))
- suffix = QLatin1String("meego");
+ return QLatin1String("meego");
else
return QString();
-
- // currently we can't have the build directory to be deeper than the source directory
- // since that is broken in qmake
- // Once qmake is fixed we can change that to have a top directory and
- // subdirectories per build. (Replacing "QChar('-')" with "QChar('/') )
- return projectLocation + QLatin1Char('-') + suffix;
}
-QList<BuildConfigurationInfo> Qt4MaemoTargetFactory::availableBuildConfigurations(const QString &id, const QString &proFilePath, const QtVersionNumber &minimumQtVersion)
+QString Qt4MaemoTargetFactory::shadowBuildDirectory(const QString &profilePath, const QString &id, const QString &suffix)
{
- QList<BuildConfigurationInfo> infos;
- QList<QtVersion *> knownVersions = QtVersionManager::instance()->versionsForTargetId(id, minimumQtVersion);
-
- foreach (QtVersion *version, knownVersions) {
- if (!version->isValid() || !version->toolChainAvailable(id))
- continue;
- QtVersion::QmakeBuildConfigs config = version->defaultBuildConfig();
-#ifdef Q_OS_WIN
- QString dir = QFileInfo(proFilePath).absolutePath();
+#if defined(Q_OS_WIN)
+ // No shadowbuilding for windows!
+ Q_UNUSED(id);
+ Q_UNUSED(suffix);
+ return QFileInfo(profilePath).absolutePath();
#else
- QString dir = defaultShadowBuildDirectory(Qt4Project::defaultTopLevelBuildDirectory(proFilePath), id);
+ return Qt4BaseTargetFactory::shadowBuildDirectory(profilePath, id, suffix);
#endif
- infos.append(BuildConfigurationInfo(version, config, QString(), dir));
- infos.append(BuildConfigurationInfo(version, config ^ QtVersion::DebugBuild, QString(), dir));
- }
- return infos;
}
bool Qt4MaemoTargetFactory::isMobileTarget(const QString &id)
@@ -211,12 +197,18 @@ ProjectExplorer::Target *Qt4MaemoTargetFactory::create(ProjectExplorer::Project
return 0;
AbstractQt4MaemoTarget *target = 0;
- if (id == QLatin1String(Constants::MAEMO5_DEVICE_TARGET_ID))
+ QStringList deployConfigIds;
+ if (id == QLatin1String(Constants::MAEMO5_DEVICE_TARGET_ID)) {
target = new Qt4Maemo5Target(static_cast<Qt4Project *>(parent), id);
- else if (id == QLatin1String(Constants::HARMATTAN_DEVICE_TARGET_ID))
+ deployConfigIds << Qt4MaemoDeployConfiguration::FremantleWithPackagingId
+ << Qt4MaemoDeployConfiguration::FremantleWithoutPackagingId;
+ } else if (id == QLatin1String(Constants::HARMATTAN_DEVICE_TARGET_ID)) {
target = new Qt4HarmattanTarget(static_cast<Qt4Project *>(parent), id);
- else if (id == QLatin1String(Constants::MEEGO_DEVICE_TARGET_ID))
+ deployConfigIds << Qt4MaemoDeployConfiguration::HarmattanId;
+ } else if (id == QLatin1String(Constants::MEEGO_DEVICE_TARGET_ID)) {
target = new Qt4MeegoTarget(static_cast<Qt4Project *>(parent), id);
+ deployConfigIds << Qt4MaemoDeployConfiguration::MeegoId;
+ }
Q_ASSERT(target);
foreach (const BuildConfigurationInfo &info, infos)
@@ -224,7 +216,9 @@ ProjectExplorer::Target *Qt4MaemoTargetFactory::create(ProjectExplorer::Project
info.version, info.buildConfig,
info.additionalArguments, info.directory);
- target->addDeployConfiguration(target->deployConfigurationFactory()->create(target, ProjectExplorer::Constants::DEFAULT_DEPLOYCONFIGURATION_ID));
+ foreach (const QString &deployConfigId, deployConfigIds) {
+ target->addDeployConfiguration(target->createDeployConfiguration(deployConfigId));
+ }
target->createApplicationProFiles();
if (target->runConfigurations().isEmpty())
target->addRunConfiguration(new ProjectExplorer::CustomExecutableRunConfiguration(target));
diff --git a/src/plugins/qt4projectmanager/qt-maemo/qt4maemotargetfactory.h b/src/plugins/qt4projectmanager/qt-maemo/qt4maemotargetfactory.h
index bf6e2062d3..e5f2a99f1f 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/qt4maemotargetfactory.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/qt4maemotargetfactory.h
@@ -52,14 +52,15 @@ public:
bool canCreate(ProjectExplorer::Project *parent, const QString &id) const;
bool canRestore(ProjectExplorer::Project *parent, const QVariantMap &map) const;
ProjectExplorer::Target *restore(ProjectExplorer::Project *parent, const QVariantMap &map);
- QString defaultShadowBuildDirectory(const QString &projectLocation, const QString &id);
+
+ QString shadowBuildDirectory(const QString &profilePath, const QString &id, const QString &suffix);
+ QString buildNameForId(const QString &id) const;
bool supportsTargetId(const QString &id) const;
ProjectExplorer::Target *create(ProjectExplorer::Project *parent, const QString &id);
ProjectExplorer::Target *create(ProjectExplorer::Project *parent, const QString &id, const QList<BuildConfigurationInfo> &infos);
- QList<BuildConfigurationInfo> availableBuildConfigurations(const QString &id, const QString &proFilePath, const QtVersionNumber &minimumQtVersion);
bool isMobileTarget(const QString &id);
bool supportsShadowBuilds(const QString &id);
};
diff --git a/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.cpp b/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.cpp
index fe92e0a056..278047be81 100644
--- a/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.cpp
@@ -46,6 +46,7 @@
#include <coreplugin/icore.h>
#include <utils/qtcassert.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <symbianutils/symbiandevicemanager.h>
@@ -95,11 +96,11 @@ bool CodaRunControl::doStart()
{
if (m_address.isEmpty() && m_serialPort.isEmpty()) {
cancelProgress();
- QString msg = tr("No device is connected. Please connect a device and try again.");
+ QString msg = tr("No device is connected. Please connect a device and try again.\n");
appendMessage(msg, NormalMessageFormat);
return false;
}
- appendMessage(tr("Executable file: %1").arg(msgListFile(executableFileName())),
+ appendMessage(tr("Executable file: %1\n").arg(msgListFile(executableFileName())),
NormalMessageFormat);
return true;
}
@@ -109,20 +110,25 @@ bool CodaRunControl::isRunning() const
return m_state >= StateConnecting;
}
+QIcon CodaRunControl::icon() const
+{
+ return QIcon(ProjectExplorer::Constants::ICON_DEBUG_SMALL);
+}
+
bool CodaRunControl::setupLauncher()
{
QTC_ASSERT(!m_codaDevice, return false);
if (m_serialPort.length()) {
// We get the port from SymbianDeviceManager
- appendMessage(tr("Connecting to '%1'...").arg(m_serialPort), NormalMessageFormat);
+ appendMessage(tr("Connecting to '%1'...\n").arg(m_serialPort), NormalMessageFormat);
m_codaDevice = SymbianUtils::SymbianDeviceManager::instance()->getCodaDevice(m_serialPort);
if (m_codaDevice.isNull()) {
- appendMessage(tr("Unable to create CODA connection. Please try again."), ErrorMessageFormat);
+ appendMessage(tr("Unable to create CODA connection. Please try again.\n"), ErrorMessageFormat);
return false;
}
if (!m_codaDevice->device()->isOpen()) {
- appendMessage(tr("Could not open serial device: %1").arg(m_codaDevice->device()->errorString()), ErrorMessageFormat);
+ appendMessage(tr("Could not open serial device: %1\n").arg(m_codaDevice->device()->errorString()), ErrorMessageFormat);
return false;
}
connect(SymbianUtils::SymbianDeviceManager::instance(), SIGNAL(deviceRemoved(const SymbianUtils::SymbianDevice)),
@@ -144,7 +150,7 @@ bool CodaRunControl::setupLauncher()
m_codaDevice->setDevice(codaSocket);
codaSocket->connectToHost(m_address, m_port);
m_state = StateConnecting;
- appendMessage(tr("Connecting to %1:%2...").arg(m_address).arg(m_port), NormalMessageFormat);
+ appendMessage(tr("Connecting to %1:%2...\n").arg(m_address).arg(m_port), NormalMessageFormat);
}
QTimer::singleShot(5000, this, SLOT(checkForTimeout()));
if (debug)
@@ -171,7 +177,7 @@ void CodaRunControl::doStop()
void CodaRunControl::slotError(const QString &error)
{
- appendMessage(tr("Error: %1").arg(error), ErrorMessageFormat);
+ appendMessage(tr("Error: %1\n").arg(error), ErrorMessageFormat);
finishRunControl();
}
@@ -231,7 +237,7 @@ void CodaRunControl::handleConnected()
if (m_state >= StateConnected)
return;
m_state = StateConnected;
- appendMessage(tr("Connected."), NormalMessageFormat);
+ appendMessage(tr("Connected.\n"), NormalMessageFormat);
setProgress(maxProgress()*0.80);
initCommunication();
}
@@ -242,7 +248,7 @@ void CodaRunControl::handleContextRemoved(const CodaEvent &event)
= static_cast<const CodaRunControlContextRemovedEvent &>(event).ids();
if (!m_runningProcessId.isEmpty()
&& removedItems.contains(m_runningProcessId.toAscii())) {
- appendMessage(tr("Process has finished."), NormalMessageFormat);
+ appendMessage(tr("Process has finished.\n"), NormalMessageFormat);
finishRunControl();
}
}
@@ -267,7 +273,7 @@ void CodaRunControl::handleContextSuspended(const CodaEvent &event)
switch (me.reason()) {
case TcfSuspendEvent::Other:
case TcfSuspendEvent::Crash:
- appendMessage(tr("Thread has crashed: %1").arg(QString::fromLatin1(me.message())), ErrorMessageFormat);
+ appendMessage(tr("Thread has crashed: %1\n").arg(QString::fromLatin1(me.message())), ErrorMessageFormat);
if (me.reason() == TcfSuspendEvent::Crash)
stop();
@@ -309,7 +315,7 @@ void CodaRunControl::handleFindProcesses(const CodaCommandResult &result)
{
if (result.values.size() && result.values.at(0).type() == JsonValue::Array && result.values.at(0).children().count()) {
//there are processes running. Cannot run mine
- appendMessage(tr("The process is already running on the device. Please first close it."), ErrorMessageFormat);
+ appendMessage(tr("The process is already running on the device. Please first close it.\n"), ErrorMessageFormat);
finishRunControl();
} else {
setProgress(maxProgress()*0.90);
@@ -319,7 +325,7 @@ void CodaRunControl::handleFindProcesses(const CodaCommandResult &result)
commandLineArguments().split(' '),
QString(),
true);
- appendMessage(tr("Launching: %1").arg(executableName()), NormalMessageFormat);
+ appendMessage(tr("Launching: %1\n").arg(executableName()), NormalMessageFormat);
}
}
@@ -328,9 +334,9 @@ void CodaRunControl::handleCreateProcess(const CodaCommandResult &result)
const bool ok = result.type == CodaCommandResult::SuccessReply;
if (ok) {
setProgress(maxProgress());
- appendMessage(tr("Launched."), NormalMessageFormat);
+ appendMessage(tr("Launched.\n"), NormalMessageFormat);
} else {
- appendMessage(tr("Launch failed: %1").arg(result.toString()), ErrorMessageFormat);
+ appendMessage(tr("Launch failed: %1\n").arg(result.toString()), ErrorMessageFormat);
finishRunControl();
}
}
@@ -374,14 +380,14 @@ void CodaRunControl::cancelConnection()
return;
stop();
- appendMessage(tr("Canceled."), ErrorMessageFormat);
+ appendMessage(tr("Canceled.\n"), ErrorMessageFormat);
emit finished();
}
void CodaRunControl::deviceRemoved(const SymbianUtils::SymbianDevice &device)
{
if (m_codaDevice && device.portName() == m_serialPort) {
- QString msg = tr("The device '%1' has been disconnected").arg(device.friendlyName());
+ QString msg = tr("The device '%1' has been disconnected.\n").arg(device.friendlyName());
appendMessage(msg, ErrorMessageFormat);
finishRunControl();
}
diff --git a/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.h b/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.h
index abe700c266..58f7421886 100644
--- a/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.h
+++ b/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.h
@@ -62,6 +62,7 @@ public:
virtual ~CodaRunControl();
virtual bool isRunning() const;
+ virtual QIcon icon() const;
static QMessageBox *createCodaWaitingMessageBox(QWidget *parent = 0);
diff --git a/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.cpp b/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.cpp
index 81fab48aad..93579b8d42 100644
--- a/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.cpp
@@ -42,6 +42,7 @@
#include <projectexplorer/project.h>
#include <projectexplorer/toolchainmanager.h>
#include <symbianutils/symbiandevicemanager.h>
+#include <extensionsystem/pluginmanager.h>
#include <QtGui/QPainter>
#include <QtGui/QApplication>
@@ -52,8 +53,7 @@ Qt4SymbianTarget::Qt4SymbianTarget(Qt4Project *parent, const QString &id) :
Qt4BaseTarget(parent, id),
m_connectedPixmap(QLatin1String(":/projectexplorer/images/ConnectionOn.png")),
m_disconnectedPixmap(QLatin1String(":/projectexplorer/images/ConnectionOff.png")),
- m_buildConfigurationFactory(new Qt4BuildConfigurationFactory(this)),
- m_deployConfigurationFactory(new S60DeployConfigurationFactory(this))
+ m_buildConfigurationFactory(new Qt4BuildConfigurationFactory(this))
{
setDisplayName(defaultDisplayName(id));
setIcon(iconForId(id));
@@ -91,11 +91,6 @@ Qt4BuildConfigurationFactory *Qt4SymbianTarget::buildConfigurationFactory() cons
return m_buildConfigurationFactory;
}
-ProjectExplorer::DeployConfigurationFactory *Qt4SymbianTarget::deployConfigurationFactory() const
-{
- return m_deployConfigurationFactory;
-}
-
QList<ProjectExplorer::ToolChain *> Qt4SymbianTarget::possibleToolChains(ProjectExplorer::BuildConfiguration *bc) const
{
QList<ProjectExplorer::ToolChain *> candidates = Qt4BaseTarget::possibleToolChains(bc);
@@ -116,11 +111,6 @@ QList<ProjectExplorer::ToolChain *> Qt4SymbianTarget::possibleToolChains(Project
return tmp;
}
-QString Qt4SymbianTarget::defaultBuildDirectory() const
-{
- return project()->projectDirectory();
-}
-
void Qt4SymbianTarget::createApplicationProFiles()
{
removeUnconfiguredCustomExectutableRunConfigurations();
diff --git a/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.h b/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.h
index ed76432bb2..0d9a7a6962 100644
--- a/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.h
+++ b/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.h
@@ -51,12 +51,9 @@ public:
virtual ~Qt4SymbianTarget();
Internal::Qt4BuildConfigurationFactory *buildConfigurationFactory() const;
- ProjectExplorer::DeployConfigurationFactory *deployConfigurationFactory() const;
QList<ProjectExplorer::ToolChain *> possibleToolChains(ProjectExplorer::BuildConfiguration *bc) const;
- QString defaultBuildDirectory() const;
-
void createApplicationProFiles();
virtual QList<ProjectExplorer::RunConfiguration *> runConfigurationsForNode(ProjectExplorer::Node *n);
@@ -75,7 +72,6 @@ private:
const QPixmap m_disconnectedPixmap;
Internal::Qt4BuildConfigurationFactory *m_buildConfigurationFactory;
- ProjectExplorer::DeployConfigurationFactory *m_deployConfigurationFactory;
};
} // namespace Internal
} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-s60/qt4symbiantargetfactory.cpp b/src/plugins/qt4projectmanager/qt-s60/qt4symbiantargetfactory.cpp
index e9797673db..ccef9985bb 100644
--- a/src/plugins/qt4projectmanager/qt-s60/qt4symbiantargetfactory.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/qt4symbiantargetfactory.cpp
@@ -127,12 +127,11 @@ ProjectExplorer::Target *Qt4SymbianTargetFactory::restore(ProjectExplorer::Proje
return 0;
}
-QString Qt4SymbianTargetFactory::defaultShadowBuildDirectory(const QString &projectLocation, const QString &id)
+QString Qt4SymbianTargetFactory::shadowBuildDirectory(const QString &profilePath, const QString &id, const QString &suffix)
{
- Q_UNUSED(projectLocation);
Q_UNUSED(id);
- // should not be called from anywhere, since we override Qt4BaseTarget::defaultBuldDirectory()
- return QString();
+ Q_UNUSED(suffix);
+ return QFileInfo(profilePath).absolutePath();
}
QList<ProjectExplorer::Task> Qt4SymbianTargetFactory::reportIssues(const QString &proFile)
@@ -165,25 +164,15 @@ QList<ProjectExplorer::Task> Qt4SymbianTargetFactory::reportIssues(const QString
QList<BuildConfigurationInfo> Qt4SymbianTargetFactory::availableBuildConfigurations(const QString &id, const QString &proFilePath, const QtVersionNumber &minimumQtVersion)
{
- QList<BuildConfigurationInfo> infos;
- QList<QtVersion *> knownVersions = QtVersionManager::instance()->versionsForTargetId(id, minimumQtVersion);
-
- foreach (QtVersion *version, knownVersions) {
- if (!version->isValid() || !version->toolChainAvailable(id))
- continue;
-
- bool buildAll = version->defaultBuildConfig() & QtVersion::BuildAll;
- QtVersion::QmakeBuildConfigs config = buildAll ? QtVersion::BuildAll : QtVersion::QmakeBuildConfig(0);
- QString dir = QFileInfo(proFilePath).absolutePath(), id;
- if (id == Constants::S60_EMULATOR_TARGET_ID) {
- infos.append(BuildConfigurationInfo(version, config | QtVersion::DebugBuild, QString(), dir));
- } else {
- infos.append(BuildConfigurationInfo(version, config, QString(), dir));
- infos.append(BuildConfigurationInfo(version, config ^ QtVersion::DebugBuild, QString(), dir));
- }
- }
-
- return infos;
+ QList<BuildConfigurationInfo> infos = Qt4BaseTargetFactory::availableBuildConfigurations(id, proFilePath, minimumQtVersion);
+ if (id != Constants::S60_EMULATOR_TARGET_ID)
+ return infos;
+ // For emulator filter out all non debug builds
+ QList<BuildConfigurationInfo> tmp;
+ foreach (const BuildConfigurationInfo &info, infos)
+ if (info.buildConfig & QtVersion::DebugBuild)
+ tmp << info;
+ return tmp;
}
bool Qt4SymbianTargetFactory::isMobileTarget(const QString &id)
@@ -234,7 +223,7 @@ ProjectExplorer::Target *Qt4SymbianTargetFactory::create(ProjectExplorer::Projec
info.version, info.buildConfig,
info.additionalArguments, info.directory);
- t->addDeployConfiguration(t->deployConfigurationFactory()->create(t, QLatin1String(Qt4ProjectManager::Constants::S60_DEVICE_TARGET_ID)));
+ t->addDeployConfiguration(t->createDeployConfiguration(QLatin1String(Qt4ProjectManager::Constants::S60_DEVICE_TARGET_ID)));
t->createApplicationProFiles();
diff --git a/src/plugins/qt4projectmanager/qt-s60/qt4symbiantargetfactory.h b/src/plugins/qt4projectmanager/qt-s60/qt4symbiantargetfactory.h
index b4829e1bb2..bc6aef9e92 100644
--- a/src/plugins/qt4projectmanager/qt-s60/qt4symbiantargetfactory.h
+++ b/src/plugins/qt4projectmanager/qt-s60/qt4symbiantargetfactory.h
@@ -57,7 +57,7 @@ public:
virtual ProjectExplorer::Target *create(ProjectExplorer::Project *parent, const QString &id, const QList<BuildConfigurationInfo> &infos);
virtual ProjectExplorer::Target *create(ProjectExplorer::Project *parent, const QString &id, Qt4TargetSetupWidget *widget);
- QString defaultShadowBuildDirectory(const QString &projectLocation, const QString &id);
+ QString shadowBuildDirectory(const QString &profilePath, const QString &id, const QString &suffix);
QList<ProjectExplorer::Task> reportIssues(const QString &proFile);
QList<BuildConfigurationInfo> availableBuildConfigurations(const QString &id, const QString &proFilePath, const QtVersionNumber &minimumQtVersion);
bool isMobileTarget(const QString &id);
diff --git a/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.cpp b/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.cpp
index 4ae7c7b83b..28be45d42b 100644
--- a/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.cpp
@@ -440,6 +440,14 @@ bool RvctToolChainConfigWidget::isDirty() const
|| tc->debuggerCommand() != debuggerCommand();
}
+void RvctToolChainConfigWidget::makeReadOnly()
+{
+ m_ui->versionComboBox->setEnabled(false);
+ m_ui->compilerPath->setEnabled(false);
+ m_ui->environmentView->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ ProjectExplorer::ToolChainConfigWidget::makeReadOnly();
+}
+
QList<Utils::EnvironmentItem> RvctToolChainConfigWidget::environmentChanges() const
{
Utils::Environment baseEnv;
diff --git a/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.h b/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.h
index 289664589a..77cc0b6168 100644
--- a/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.h
+++ b/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.h
@@ -146,6 +146,7 @@ public:
void apply();
void discard() { setFromToolChain(); }
bool isDirty() const;
+ void makeReadOnly();
void changeEvent(QEvent *ev);
private:
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp
index af125d3564..29abad83c9 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp
@@ -582,7 +582,7 @@ void S60CreatePackageStep::stdOutput(const QString &line)
{
if (m_outputParserChain)
m_outputParserChain->stdOutput(line);
- emit addOutput(line, BuildStep::NormalOutput);
+ emit addOutput(line, BuildStep::NormalOutput, BuildStep::DontAppendNewline);
}
void S60CreatePackageStep::processReadyReadStdError()
@@ -598,7 +598,7 @@ void S60CreatePackageStep::stdError(const QString &line)
{
if (m_outputParserChain)
m_outputParserChain->stdError(line);
- emit addOutput(line, BuildStep::ErrorOutput);
+ emit addOutput(line, BuildStep::ErrorOutput, BuildStep::DontAppendNewline);
}
void S60CreatePackageStep::checkForCancel()
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp
index 9b9e56cf5c..dbad2092b9 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp
@@ -104,6 +104,7 @@ static inline bool renameFile(const QString &sourceName, const QString &targetNa
S60DeployStep::S60DeployStep(ProjectExplorer::BuildStepList *bc,
S60DeployStep *bs):
BuildStep(bc, bs), m_timer(0),
+ m_timeoutTimer(new QTimer(this)),
m_releaseDeviceAfterLauncherFinish(bs->m_releaseDeviceAfterLauncherFinish),
m_handleDeviceRemoval(bs->m_handleDeviceRemoval),
m_launcher(0),
@@ -122,6 +123,7 @@ S60DeployStep::S60DeployStep(ProjectExplorer::BuildStepList *bc,
S60DeployStep::S60DeployStep(ProjectExplorer::BuildStepList *bc):
BuildStep(bc, QLatin1String(S60_DEPLOY_STEP_ID)), m_timer(0),
+ m_timeoutTimer(new QTimer(this)),
m_releaseDeviceAfterLauncherFinish(true),
m_handleDeviceRemoval(true),
m_launcher(0),
@@ -142,6 +144,9 @@ void S60DeployStep::ctor()
{
//: Qt4 Deploystep display name
setDefaultDisplayName(tr("Deploy"));
+ m_timeoutTimer->setSingleShot(true);
+ m_timeoutTimer->setInterval(2000);
+ connect(m_timeoutTimer, SIGNAL(timeout()), this, SLOT(timeout()));
}
S60DeployStep::~S60DeployStep()
@@ -312,10 +317,18 @@ void S60DeployStep::stop()
m_launcher->terminate();
} else {
if (m_codaDevice) {
+ switch (state()) {
+ case StateSendingData:
+ closeFiles();
+ break;
+ default:
+ break; //should also stop the package installatrion, but CODA does not support it yet
+ }
disconnect(m_codaDevice.data(), 0, this, 0);
SymbianUtils::SymbianDeviceManager::instance()->releaseCodaDevice(m_codaDevice);
}
}
+ setState(StateUninit);
emit finished(false);
}
@@ -393,7 +406,7 @@ void S60DeployStep::startDeployment()
return;
}
setupConnections();
- m_state = StateConnecting;
+ setState(StateConnecting);
m_codaDevice->sendSerialPing(false);
} else {
m_codaDevice = QSharedPointer<Coda::CodaDevice>(new Coda::CodaDevice);
@@ -401,7 +414,7 @@ void S60DeployStep::startDeployment()
const QSharedPointer<QTcpSocket> codaSocket(new QTcpSocket);
m_codaDevice->setDevice(codaSocket);
codaSocket->connectToHost(m_address, m_port);
- m_state = StateConnecting;
+ setState(StateConnecting);
appendMessage(tr("Connecting to %1:%2...").arg(m_address).arg(m_port), false);
}
QTimer::singleShot(4000, this, SLOT(checkForTimeout()));
@@ -485,9 +498,9 @@ void S60DeployStep::slotCodaEvent(const Coda::CodaEvent &event)
void S60DeployStep::handleConnected()
{
- if (m_state >= StateConnected)
+ if (state() >= StateConnected)
return;
- m_state = StateConnected;
+ setState(StateConnected);
emit codaConnected();
startTransferring();
}
@@ -509,13 +522,16 @@ void S60DeployStep::initFileSending()
m_codaDevice->sendFileSystemOpenCommand(Coda::CodaCallback(this, &S60DeployStep::handleFileSystemOpen),
remoteFileLocation.toAscii(), flags);
appendMessage(tr("Copying \"%1\"...").arg(packageName), false);
+ m_timeoutTimer->start();
}
void S60DeployStep::initFileInstallation()
{
QTC_ASSERT(m_currentFileIndex < m_signedPackages.count(), return);
QTC_ASSERT(m_currentFileIndex >= 0, return);
- QTC_ASSERT(m_codaDevice, return);
+
+ if (!m_codaDevice)
+ return;
QString packageName(QFileInfo(m_signedPackages.at(m_currentFileIndex)).fileName());
QString remoteFileLocation = QString::fromLatin1("%1:\\Data\\%2").arg(m_installationDrive).arg(packageName);
@@ -535,14 +551,14 @@ void S60DeployStep::startTransferring()
{
m_currentFileIndex = 0;
initFileSending();
- m_state = StateSendingData;
+ setState(StateSendingData);
}
void S60DeployStep::startInstalling()
{
m_currentFileIndex = 0;
initFileInstallation();
- m_state = StateInstalling;
+ setState(StateInstalling);
}
void S60DeployStep::handleFileSystemOpen(const Coda::CodaCommandResult &result)
@@ -553,7 +569,7 @@ void S60DeployStep::handleFileSystemOpen(const Coda::CodaCommandResult &result)
}
if (result.values.size() < 1 || result.values.at(0).data().isEmpty()) {
- reportError(QLatin1String("Internal error: No filehandle obtained"));
+ reportError(tr("Internal error: No filehandle obtained"));
return;
}
@@ -572,9 +588,10 @@ void S60DeployStep::handleSymbianInstall(const Coda::CodaCommandResult &result)
{
if (result.type == Coda::CodaCommandResult::SuccessReply) {
appendMessage(tr("Installation has finished"), false);
- if (++m_currentFileIndex >= m_signedPackages.count())
+ if (++m_currentFileIndex >= m_signedPackages.count()) {
+ setState(StateFinished);
emit allFilesInstalled();
- else
+ } else
initFileInstallation();
} else {
reportError(tr("Installation failed: %1; "
@@ -586,7 +603,8 @@ void S60DeployStep::handleSymbianInstall(const Coda::CodaCommandResult &result)
void S60DeployStep::putSendNextChunk()
{
- QTC_ASSERT(m_codaDevice, return);
+ if (!m_codaDevice)
+ return;
QTC_ASSERT(m_putFile, return);
// Read and send off next chunk
@@ -606,6 +624,7 @@ void S60DeployStep::putSendNextChunk()
m_codaDevice->sendFileSystemWriteCommand(Coda::CodaCallback(this, &S60DeployStep::handleFileSystemWrite),
m_remoteFileHandle, data, unsigned(pos));
setCopyProgress((100*(m_putLastChunkSize+pos))/size);
+ m_timeoutTimer->start();
}
}
@@ -614,12 +633,15 @@ void S60DeployStep::closeFiles()
m_putFile.reset();
QTC_ASSERT(m_codaDevice, return);
+ emit addOutput(QLatin1String("\n"), ProjectExplorer::BuildStep::MessageOutput);
m_codaDevice->sendFileSystemCloseCommand(Coda::CodaCallback(this, &S60DeployStep::handleFileSystemClose),
m_remoteFileHandle);
+
}
void S60DeployStep::handleFileSystemWrite(const Coda::CodaCommandResult &result)
{
+ m_timeoutTimer->stop();
// Close remote file even if copy fails
m_putWriteOk = result;
if (!m_putWriteOk) {
@@ -650,7 +672,7 @@ void S60DeployStep::handleFileSystemClose(const Coda::CodaCommandResult &result)
void S60DeployStep::checkForTimeout()
{
- if (m_state != StateConnecting)
+ if (state() != StateConnecting)
return;
QMessageBox *mb = CodaRunControl::createCodaWaitingMessageBox(Core::ICore::instance()->mainWindow());
connect(this, SIGNAL(codaConnected()), mb, SLOT(close()));
@@ -796,6 +818,7 @@ void S60DeployStep::setCopyProgress(int progress)
if (copyProgress() == progress)
return;
m_copyProgress = progress;
+ emit addOutput(QLatin1String("."), ProjectExplorer::BuildStep::MessageOutput, DontAppendNewline);
emit copyProgressChanged(m_copyProgress);
}
@@ -813,6 +836,11 @@ void S60DeployStep::updateProgress(int progress)
m_futureInterface->setProgressValueAndText(entireProgress, tr("Copy progress: %1%").arg(copyProgress));
}
+void S60DeployStep::timeout()
+{
+ reportError(tr("A timeout while deploying has occurred. CODA might not be responding. Try reconnecting the device."));
+}
+
// #pragma mark -- S60DeployStepWidget
BuildStepConfigWidget *S60DeployStep::createConfigWidget()
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h
index bd716bda8a..f65cf32eab 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h
@@ -124,6 +124,7 @@ private slots:
void slotWaitingForTrkClosed();
void checkForCancel();
void checkForTimeout();
+ void timeout();
void slotError(const QString &error);
void slotTrkLogMessage(const QString &log);
@@ -183,9 +184,13 @@ private:
StateConnecting,
StateConnected,
StateSendingData,
- StateInstalling
+ StateInstalling,
+ StateFinished
};
+ inline void setState(State state) { m_state = state; }
+ inline State state() { return m_state; }
+
QString m_serialPortName;
QString m_serialPortFriendlyName;
QStringList m_packageFileNamesWithTarget; // Support for 4.6.1
@@ -194,6 +199,7 @@ private:
unsigned short m_port;
QTimer *m_timer;
+ QTimer* m_timeoutTimer;
bool m_releaseDeviceAfterLauncherFinish;
bool m_handleDeviceRemoval;
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
index a3717df87a..8c4bbffa6f 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
@@ -450,6 +450,7 @@ static Debugger::DebuggerStartParameters s60DebuggerStartParams(const S60DeviceR
const S60DeployConfiguration *activeDeployConf =
qobject_cast<S60DeployConfiguration *>(rc->qt4Target()->activeDeployConfiguration());
+ QTC_ASSERT(activeDeployConf, return sp);
const QString debugFileName = QString::fromLatin1("%1:\\sys\\bin\\%2.exe")
.arg(activeDeployConf->installationDrive()).arg(rc->targetName());
@@ -463,6 +464,16 @@ static Debugger::DebuggerStartParameters s60DebuggerStartParams(const S60DeviceR
sp.serverAddress = activeDeployConf->deviceAddress();
sp.serverPort = activeDeployConf->devicePort().toInt();
sp.displayName = rc->displayName();
+ sp.qmlServerPort = rc->qmlDebugServerPort();
+ // TODO - is this the correct place to put this?
+ if (rc->useQmlDebugger()) {
+ if (sp.processArgs.length())
+ sp.processArgs.prepend(" ");
+ if (activeDeployConf->communicationChannel() == S60DeployConfiguration::CommunicationCodaTcpConnection)
+ sp.processArgs.prepend(QString("-qmljsdebugger=port:%1").arg(sp.qmlServerPort));
+ else
+ sp.processArgs.prepend(QString("-qmljsdebugger=ost"));
+ }
sp.communicationChannel = activeDeployConf->communicationChannel() == S60DeployConfiguration::CommunicationCodaTcpConnection?
Debugger::DebuggerStartParameters::CommunicationChannelTcpIp:
@@ -486,7 +497,7 @@ S60DeviceDebugRunControl::S60DeviceDebugRunControl(S60DeviceRunConfiguration *rc
Debugger::DebuggerRunControl(rc, sp, masterSlaveEngineTypes)
{
if (startParameters().symbolFileName.isEmpty()) {
- const QString msg = tr("Warning: Cannot locate the symbol file belonging to %1.").
+ const QString msg = tr("Warning: Cannot locate the symbol file belonging to %1.\n").
arg(rc->localExecutableFileName());
appendMessage(msg, ErrorMessageFormat);
}
@@ -494,7 +505,7 @@ S60DeviceDebugRunControl::S60DeviceDebugRunControl(S60DeviceRunConfiguration *rc
void S60DeviceDebugRunControl::start()
{
- appendMessage(tr("Launching debugger..."), NormalMessageFormat);
+ appendMessage(tr("Launching debugger...\n"), NormalMessageFormat);
Debugger::DebuggerRunControl::start();
}
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp
index 6e47529e42..3149f007fb 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp
@@ -33,6 +33,7 @@
#include "s60devicerunconfigurationwidget.h"
#include "s60devicerunconfiguration.h"
+#include <utils/debuggerlanguagechooser.h>
#include <utils/detailswidget.h>
#include <QtGui/QLineEdit>
@@ -68,12 +69,26 @@ S60DeviceRunConfigurationWidget::S60DeviceRunConfigurationWidget(
detailsBoxLayout->addLayout(formLayout);
formLayout->addRow(tr("Arguments:"), m_argumentsLineEdit);
+ m_debuggerLanguageChooser = new Utils::DebuggerLanguageChooser(this);
+ formLayout->addRow(tr("Debugger:"), m_debuggerLanguageChooser);
+
+ m_debuggerLanguageChooser->setCppChecked(m_runConfiguration->useCppDebugger());
+ m_debuggerLanguageChooser->setQmlChecked(m_runConfiguration->useQmlDebugger());
+ m_debuggerLanguageChooser->setQmlDebugServerPort(m_runConfiguration->qmlDebugServerPort());
+
connect(m_argumentsLineEdit, SIGNAL(textEdited(QString)),
this, SLOT(argumentsEdited(QString)));
connect(m_runConfiguration, SIGNAL(isEnabledChanged(bool)),
this, SLOT(runConfigurationEnabledChange(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)));
+
setEnabled(m_runConfiguration->isEnabled());
}
@@ -87,5 +102,20 @@ void S60DeviceRunConfigurationWidget::runConfigurationEnabledChange(bool enabled
setEnabled(enabled);
}
+void S60DeviceRunConfigurationWidget::useCppDebuggerToggled(bool enabled)
+{
+ m_runConfiguration->setUseCppDebugger(enabled);
+}
+
+void S60DeviceRunConfigurationWidget::useQmlDebuggerToggled(bool enabled)
+{
+ m_runConfiguration->setUseQmlDebugger(enabled);
+}
+
+void S60DeviceRunConfigurationWidget::qmlDebugServerPortChanged(uint port)
+{
+ m_runConfiguration->setQmlDebugServerPort(port);
+}
+
} // namespace Internal
} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h
index ad436f3235..e95ef0f02a 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h
@@ -41,6 +41,7 @@ QT_END_NAMESPACE
namespace Utils {
class DetailsWidget;
+ class DebuggerLanguageChooser;
}
namespace Qt4ProjectManager {
@@ -57,10 +58,14 @@ public:
private slots:
void argumentsEdited(const QString &text);
void runConfigurationEnabledChange(bool enabled);
+ void useCppDebuggerToggled(bool);
+ void useQmlDebuggerToggled(bool);
+ void qmlDebugServerPortChanged(uint);
private:
S60DeviceRunConfiguration *m_runConfiguration;
Utils::DetailsWidget *m_detailsWidget;
+ Utils::DebuggerLanguageChooser *m_debuggerLanguageChooser;
QLineEdit *m_argumentsLineEdit;
};
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp
index b4c9691490..960dab95cf 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp
@@ -39,6 +39,8 @@
#include "qt4projectmanagerconstants.h"
#include "qtoutputformatter.h"
+#include <projectexplorer/projectexplorerconstants.h>
+
#include <utils/qtcassert.h>
#include <utils/detailswidget.h>
@@ -353,7 +355,7 @@ void S60EmulatorRunControl::start()
m_applicationLauncher.start(ApplicationLauncher::Gui, m_executable, QString());
emit started();
- QString msg = tr("Starting %1...").arg(QDir::toNativeSeparators(m_executable));
+ QString msg = tr("Starting %1...\n").arg(QDir::toNativeSeparators(m_executable));
appendMessage(msg, NormalMessageFormat);
}
@@ -368,6 +370,11 @@ bool S60EmulatorRunControl::isRunning() const
return m_applicationLauncher.isRunning();
}
+QIcon S60EmulatorRunControl::icon() const
+{
+ return QIcon(ProjectExplorer::Constants::ICON_RUN_SMALL);
+}
+
void S60EmulatorRunControl::slotError(const QString & err)
{
appendMessage(err, ErrorMessageFormat);
@@ -385,7 +392,7 @@ void S60EmulatorRunControl::slotAppendMessage(const QString &line, OutputFormat
void S60EmulatorRunControl::processExited(int exitCode)
{
- QString msg = tr("%1 exited with code %2");
+ QString msg = tr("%1 exited with code %2\n");
appendMessage(msg, exitCode ? ErrorMessageFormat : NormalMessageFormat);
emit finished();
}
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h
index a828b43c16..17d5538f29 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h
@@ -145,6 +145,7 @@ public:
void start();
virtual StopResult stop();
bool isRunning() const;
+ QIcon icon() const;
private slots:
void processExited(int exitCode);
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp b/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp
index 2e84981207..691127ff00 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp
@@ -37,6 +37,7 @@
#include "s60emulatorrunconfiguration.h"
#include "s60devicerunconfiguration.h"
#include "s60createpackagestep.h"
+#include "s60deployconfiguration.h"
#include "s60deploystep.h"
#include "s60runcontrolfactory.h"
@@ -124,6 +125,7 @@ S60Manager::S60Manager(QObject *parent) : QObject(parent)
addAutoReleasedObject(new S60DeviceDebugRunControlFactory);
addAutoReleasedObject(new Qt4SymbianTargetFactory);
+ addAutoReleasedObject(new S60DeployConfigurationFactory);
addAutoReleasedObject(new S60PublishingWizardFactoryOvi);
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60publisherovi.cpp b/src/plugins/qt4projectmanager/qt-s60/s60publisherovi.cpp
index c26f066271..f69fc89797 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60publisherovi.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60publisherovi.cpp
@@ -109,7 +109,12 @@ void S60PublisherOvi::setVendorName(const QString &vendorName)
void S60PublisherOvi::setLocalVendorNames(const QString &localVendorNames)
{
- m_localVendorNames = localVendorNames;
+ QStringList vendorNames = localVendorNames.split(',');
+ QStringList resultingList;
+ foreach (QString vendorName, vendorNames) {
+ resultingList.append("\\\"" +vendorName.trimmed()+"\\\"");
+ }
+ m_localVendorNames = resultingList.join(", ");
}
void S60PublisherOvi::setAppUid(const QString &appuid)
@@ -151,11 +156,30 @@ void S60PublisherOvi::completeCreation()
m_createSisProc->setEnvironment(m_qt4bc->environment().toStringList());
m_createSisProc->setWorkingDirectory(m_qt4bc->buildDirectory());
+
+ // set up access to vendor names
+
+ QStringList deploymentLevelVars = m_reader->values("DEPLOYMENT");
+ QStringList vendorInfoVars;
+ QStringList valueLevelVars;
+
+ foreach (QString deploymentLevelVar, deploymentLevelVars) {
+ vendorInfoVars = m_reader->values(deploymentLevelVar+".pkg_prerules");
+ foreach(QString vendorInfoVar, vendorInfoVars) {
+ valueLevelVars = m_reader->values(vendorInfoVar);
+ foreach(QString valueLevelVar, valueLevelVars) {
+ if (valueLevelVar.startsWith("%{\"")) {
+ m_vendorInfoVariable = vendorInfoVar;
+ break;
+ }
+ }
+ }
+ }
}
QString S60PublisherOvi::globalVendorName() const
{
- QStringList vendorinfos = m_reader->values("vendorinfo");
+ QStringList vendorinfos = m_reader->values(m_vendorInfoVariable);
foreach (QString vendorinfo, vendorinfos) {
if (vendorinfo.startsWith(':')) {
@@ -167,7 +191,7 @@ QString S60PublisherOvi::globalVendorName() const
QString S60PublisherOvi::localisedVendorNames() const
{
- QStringList vendorinfos = m_reader->values("vendorinfo");
+ QStringList vendorinfos = m_reader->values(m_vendorInfoVariable);
QString result;
QStringList localisedVendorNames;
@@ -264,7 +288,7 @@ void S60PublisherOvi::updateProFile(const QString &var, const QString &values)
}
ProWriter::putVarValues(profile, &lines, QStringList() << values, var,
- ProWriter::ReplaceValues | ProWriter::OneLine | ProWriter::AssignOperator,
+ ProWriter::ReplaceValues | ProWriter::OneLine | ProWriter::AppendOperator,
"symbian");
if (qfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
@@ -275,7 +299,13 @@ void S60PublisherOvi::updateProFile(const QString &var, const QString &values)
void S60PublisherOvi::updateProFile()
{
- updateProFile("vendorinfo", "\"%{\\\"" + m_localVendorNames + "\\\"}\" \":\\\"" + m_vendorName + "\\\"\"" );
+ if (m_vendorInfoVariable.isEmpty()) {
+ m_vendorInfoVariable = "vendorinfo";
+ updateProFile("my_deployment.pkg_prerules", m_vendorInfoVariable);
+ updateProFile("DEPLOYMENT", "my_deployment");
+ }
+
+ updateProFile(m_vendorInfoVariable, "\"%{" + m_localVendorNames + "}\" \":\\\"" + m_vendorName + "\\\"\"" );
updateProFile("TARGET.UID3", m_appUid);
}
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60publisherovi.h b/src/plugins/qt4projectmanager/qt-s60/s60publisherovi.h
index b9ff1eba61..3ca20dc0a0 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60publisherovi.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60publisherovi.h
@@ -161,6 +161,7 @@ private:
QStringList m_rejectedVendorNames;
QStringList m_capabilitiesForCertifiedSigned;
QStringList m_capabilitesForManufacturerApproved;
+ QString m_vendorInfoVariable;
QString m_vendorName;
QString m_localVendorNames;
QString m_appUid;
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60runcontrolbase.cpp b/src/plugins/qt4projectmanager/qt-s60/s60runcontrolbase.cpp
index 7c51002e27..8d1b8970ec 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60runcontrolbase.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60runcontrolbase.cpp
@@ -114,7 +114,7 @@ void S60RunControlBase::start()
if (m_runSmartInstaller) { //Smart Installer does the running by itself
cancelProgress();
- appendMessage(tr("Please finalise the installation on your device."), NormalMessageFormat);
+ appendMessage(tr("Please finalise the installation on your device.\n"), NormalMessageFormat);
emit finished();
return;
}
@@ -167,7 +167,7 @@ void S60RunControlBase::startLaunching()
void S60RunControlBase::handleFinished()
{
- appendMessage(tr("Finished."), NormalMessageFormat);
+ appendMessage(tr("Finished.\n"), NormalMessageFormat);
}
void S60RunControlBase::setProgress(int value)
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60runcontrolbase.h b/src/plugins/qt4projectmanager/qt-s60/s60runcontrolbase.h
index 8a24c5b34a..29e075449e 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60runcontrolbase.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60runcontrolbase.h
@@ -77,6 +77,7 @@ protected:
private:
void startLaunching();
+
protected slots:
void reportLaunchFinished();
diff --git a/src/plugins/qt4projectmanager/qt-s60/trkruncontrol.cpp b/src/plugins/qt4projectmanager/qt-s60/trkruncontrol.cpp
index 498738bc24..eb5635fe91 100644
--- a/src/plugins/qt4projectmanager/qt-s60/trkruncontrol.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/trkruncontrol.cpp
@@ -44,6 +44,7 @@
#include <symbianutils/bluetoothlistener_gui.h>
#include <symbianutils/launcher.h>
#include <symbianutils/symbiandevicemanager.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <utils/qtcassert.h>
@@ -81,12 +82,12 @@ bool TrkRunControl::doStart()
{
if (m_serialPortName.isEmpty()) {
cancelProgress();
- QString msg = tr("No device is connected. Please connect a device and try again.");
+ QString msg = tr("No device is connected. Please connect a device and try again.\n");
appendMessage(msg, NormalMessageFormat);
return false;
}
- appendMessage(tr("Executable file: %1").arg(msgListFile(executableFileName())),
+ appendMessage(tr("Executable file: %1\n").arg(msgListFile(executableFileName())),
NormalMessageFormat);
return true;
}
@@ -96,7 +97,11 @@ bool TrkRunControl::isRunning() const
return m_launcher && (m_launcher->state() == trk::Launcher::Connecting
|| m_launcher->state() == trk::Launcher::Connected
|| m_launcher->state() == trk::Launcher::WaitingForTrk);
+}
+QIcon TrkRunControl::icon() const
+{
+ return QIcon(ProjectExplorer::Constants::ICON_DEBUG_SMALL);
}
bool TrkRunControl::setupLauncher()
@@ -143,7 +148,7 @@ void TrkRunControl::doStop()
void TrkRunControl::printConnectFailed(const QString &errorMessage)
{
- appendMessage(tr("Could not connect to App TRK on device: %1. Restarting App TRK might help.").arg(errorMessage),
+ appendMessage(tr("Could not connect to App TRK on device: %1. Restarting App TRK might help.\n").arg(errorMessage),
ErrorMessageFormat);
}
@@ -188,7 +193,7 @@ void TrkRunControl::slotWaitingForTrkClosed()
{
if (m_launcher && m_launcher->state() == trk::Launcher::WaitingForTrk) {
stop();
- appendMessage(tr("Canceled."), ErrorMessageFormat);
+ appendMessage(tr("Canceled.\n"), ErrorMessageFormat);
emit finished();
}
}
@@ -209,7 +214,7 @@ void TrkRunControl::deviceRemoved(const SymbianUtils::SymbianDevice &d)
trk::Launcher::releaseToDeviceManager(m_launcher);
m_launcher->deleteLater();
m_launcher = 0;
- QString msg = tr("The device '%1' has been disconnected").arg(d.friendlyName());
+ QString msg = tr("The device '%1' has been disconnected.\n").arg(d.friendlyName());
appendMessage(msg, ErrorMessageFormat);
emit finished();
}
@@ -227,16 +232,16 @@ void TrkRunControl::initLauncher(const QString &executable, trk::Launcher *launc
void TrkRunControl::printStartingNotice()
{
- appendMessage(tr("Starting application..."), NormalMessageFormat);
+ appendMessage(tr("Starting application...\n"), NormalMessageFormat);
}
void TrkRunControl::applicationRunNotice(uint pid)
{
- appendMessage(tr("Application running with pid %1.").arg(pid), NormalMessageFormat);
+ appendMessage(tr("Application running with pid %1.\n").arg(pid), NormalMessageFormat);
setProgress(maxProgress());
}
void TrkRunControl::applicationRunFailedNotice(const QString &errorMessage)
{
- appendMessage(tr("Could not start application: %1").arg(errorMessage), NormalMessageFormat);
+ appendMessage(tr("Could not start application: %1\n").arg(errorMessage), NormalMessageFormat);
}
diff --git a/src/plugins/qt4projectmanager/qt-s60/trkruncontrol.h b/src/plugins/qt4projectmanager/qt-s60/trkruncontrol.h
index 842b040b60..d8e6324c1d 100644
--- a/src/plugins/qt4projectmanager/qt-s60/trkruncontrol.h
+++ b/src/plugins/qt4projectmanager/qt-s60/trkruncontrol.h
@@ -59,6 +59,7 @@ public:
TrkRunControl(ProjectExplorer::RunConfiguration *runConfiguration, const QString &mode);
~TrkRunControl();
virtual bool isRunning() const;
+ virtual QIcon icon() const;
static QMessageBox *createTrkWaitingMessageBox(const QString &port, QWidget *parent = 0);
diff --git a/src/plugins/qt4projectmanager/qt4basetargetfactory.h b/src/plugins/qt4projectmanager/qt4basetargetfactory.h
index a2f91e67c1..a0879ab98f 100644
--- a/src/plugins/qt4projectmanager/qt4basetargetfactory.h
+++ b/src/plugins/qt4projectmanager/qt4basetargetfactory.h
@@ -43,6 +43,7 @@
namespace Qt4ProjectManager {
class Qt4TargetSetupWidget;
class QtVersionNumber;
+class QtVersion;
struct BuildConfigurationInfo;
class QT4PROJECTMANAGER_EXPORT Qt4BaseTargetFactory : public ProjectExplorer::ITargetFactory
@@ -58,10 +59,15 @@ public:
bool importEnabled,
QList<BuildConfigurationInfo> importInfos);
- virtual QString defaultShadowBuildDirectory(const QString &projectLocation, const QString &id) =0;
+ /// suffix should be unique
+ virtual QString shadowBuildDirectory(const QString &profilePath, const QString &id, const QString &suffix);
+ /// used by the default implementation of shadowBuildDirectory
+ virtual QString buildNameForId(const QString &id) const;
+
/// used by the default implementation of createTargetSetupWidget
/// not needed otherwise
- virtual QList<BuildConfigurationInfo> availableBuildConfigurations(const QString &id, const QString &proFilePath, const QtVersionNumber &minimumQtVersion) = 0;
+ /// by default creates one debug + one release buildconfiguration per qtversion
+ virtual QList<BuildConfigurationInfo> availableBuildConfigurations(const QString &id, const QString &proFilePath, const QtVersionNumber &minimumQtVersion);
virtual QList<ProjectExplorer::Task> reportIssues(const QString &proFile);
/// only used in the TargetSetupPage
diff --git a/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp b/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp
index df7868fa81..69fc841711 100644
--- a/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp
@@ -124,17 +124,21 @@ static inline QString msgBuildConfigNotApplicable(const QString &d, const QtVers
arg(d, qtVersion->displayName(), qtVersion->qmakeCommand(), target->id());
}
+#include "qt4basetargetfactory.h"
+
bool Qt4BuildConfiguration::fromMap(const QVariantMap &map)
{
if (!BuildConfiguration::fromMap(map))
return false;
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();
ProjectExplorer::ToolChain *tc = 0;
tc = ProjectExplorer::ToolChainManager::instance()->findToolChain(map.value(QLatin1String(TOOLCHAIN_KEY)).toString());
m_qmakeBuildConfiguration = QtVersion::QmakeBuildConfigs(map.value(QLatin1String(BUILD_CONFIGURATION_KEY)).toInt());
+ m_buildDirectory = map.value(QLatin1String(BUILD_DIRECTORY_KEY), defaultShadowBuildDirectory()).toString();
+
+ m_lastEmmitedBuildDirectory = buildDirectory();
// Pick a Qt version if the default version is used:
// We assume that the default Qt version was used in earlier versions of Qt creator.
@@ -189,12 +193,6 @@ bool Qt4BuildConfiguration::fromMap(const QVariantMap &map)
void Qt4BuildConfiguration::ctor()
{
- m_buildDirectory = qt4Target()->defaultBuildDirectory();
- if (m_buildDirectory == target()->project()->projectDirectory())
- m_shadowBuild = false;
-
- m_lastEmmitedBuildDirectory = buildDirectory();
-
connect(this, SIGNAL(environmentChanged()),
this, SLOT(emitBuildDirectoryChanged()));
@@ -236,6 +234,13 @@ Utils::Environment Qt4BuildConfiguration::baseEnvironment() const
return env;
}
+QString Qt4BuildConfiguration::defaultShadowBuildDirectory() const
+{
+ Qt4BaseTargetFactory *factory = Qt4BaseTargetFactory::qt4BaseTargetFactoryForId(qt4Target()->id());
+ // todo displayName isn't ideal
+ return factory->shadowBuildDirectory(qt4Target()->qt4Project()->file()->fileName(), qt4Target()->id(), displayName());
+}
+
/// returns the unexpanded build directory
QString Qt4BuildConfiguration::rawBuildDirectory() const
{
@@ -244,7 +249,7 @@ QString Qt4BuildConfiguration::rawBuildDirectory() const
if (!m_buildDirectory.isEmpty())
workingDirectory = m_buildDirectory;
else
- workingDirectory = qt4Target()->defaultBuildDirectory();
+ workingDirectory = defaultShadowBuildDirectory();
}
if (workingDirectory.isEmpty())
workingDirectory = target()->project()->projectDirectory();
@@ -290,7 +295,7 @@ bool Qt4BuildConfiguration::shadowBuild() const
QString Qt4BuildConfiguration::shadowBuildDirectory() const
{
if (m_buildDirectory.isEmpty())
- return qt4Target()->defaultBuildDirectory();
+ return defaultShadowBuildDirectory();
return m_buildDirectory;
}
@@ -391,6 +396,7 @@ void Qt4BuildConfiguration::setQMakeBuildConfiguration(QtVersion::QmakeBuildConf
emit proFileEvaluateNeeded(this);
emit qmakeBuildConfigurationChanged();
+ emitBuildDirectoryChanged();
}
void Qt4BuildConfiguration::emitProFileEvaluteNeeded()
diff --git a/src/plugins/qt4projectmanager/qt4buildconfiguration.h b/src/plugins/qt4projectmanager/qt4buildconfiguration.h
index fbe88d817c..52c116125b 100644
--- a/src/plugins/qt4projectmanager/qt4buildconfiguration.h
+++ b/src/plugins/qt4projectmanager/qt4buildconfiguration.h
@@ -157,6 +157,7 @@ private:
void ctor();
void pickValidQtVersion();
QString rawBuildDirectory() const;
+ QString defaultShadowBuildDirectory() const;
bool m_shadowBuild;
bool m_isEnabled;
diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp
index 74ca4d2046..3a96a3be4a 100644
--- a/src/plugins/qt4projectmanager/qt4project.cpp
+++ b/src/plugins/qt4projectmanager/qt4project.cpp
@@ -45,6 +45,7 @@
#include "qmldumptool.h"
#include <coreplugin/icore.h>
+#include <coreplugin/icontext.h>
#include <coreplugin/messagemanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/progressmanager/progressmanager.h>
@@ -56,6 +57,7 @@
#include <projectexplorer/buildenvironmentwidget.h>
#include <projectexplorer/customexecutablerunconfiguration.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <utils/qtcassert.h>
#include <QtCore/QDebug>
@@ -260,6 +262,9 @@ Qt4Project::Qt4Project(Qt4Manager *manager, const QString& fileName) :
m_asyncUpdateState(NoState),
m_cancelEvaluate(false)
{
+ setProjectContext(Core::Context(Qt4ProjectManager::Constants::PROJECT_ID));
+ setProjectLanguage(Core::Context(ProjectExplorer::Constants::LANG_CXX));
+
m_asyncUpdateTimer.setSingleShot(true);
m_asyncUpdateTimer.setInterval(3000);
connect(&m_asyncUpdateTimer, SIGNAL(timeout()), this, SLOT(asyncUpdate()));
@@ -746,19 +751,6 @@ bool Qt4Project::wasEvaluateCanceled()
return m_cancelEvaluate;
}
-QString Qt4Project::defaultTopLevelBuildDirectory() const
-{
- return defaultTopLevelBuildDirectory(file()->fileName());
-}
-
-QString Qt4Project::defaultTopLevelBuildDirectory(const QString &profilePath)
-{
- if (profilePath.isEmpty())
- return QString();
- QFileInfo info(profilePath);
- return QDir::cleanPath(projectDirectory(profilePath) + QLatin1String("/../") + info.baseName() + QLatin1String("-build"));
-}
-
void Qt4Project::asyncUpdate()
{
if (debug)
diff --git a/src/plugins/qt4projectmanager/qt4project.h b/src/plugins/qt4projectmanager/qt4project.h
index 1135005a15..97e290dd59 100644
--- a/src/plugins/qt4projectmanager/qt4project.h
+++ b/src/plugins/qt4projectmanager/qt4project.h
@@ -178,9 +178,6 @@ public:
/// \internal
bool wasEvaluateCanceled();
- QString defaultTopLevelBuildDirectory() const;
- static QString defaultTopLevelBuildDirectory(const QString &profilePath);
-
Internal::CentralizedFolderWatcher *centralizedFolderWatcher();
// For Qt4ProFileNode after a on disk change
diff --git a/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp b/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp
index fac017fce3..3d7e781ff6 100644
--- a/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp
+++ b/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp
@@ -113,6 +113,9 @@ Qt4ProjectConfigWidget::Qt4ProjectConfigWidget(Qt4BaseTarget *target)
connect(target->qt4Project(), SIGNAL(buildDirectoryInitialized()),
this, SLOT(updateImportLabel()));
+
+ connect(ProjectExplorer::ToolChainManager::instance(), SIGNAL(toolChainsChanged()),
+ this, SLOT(updateToolChainCombo()));
}
Qt4ProjectConfigWidget::~Qt4ProjectConfigWidget()
diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.cpp b/src/plugins/qt4projectmanager/qt4projectmanager.cpp
index f106754c99..e3494a19cf 100644
--- a/src/plugins/qt4projectmanager/qt4projectmanager.cpp
+++ b/src/plugins/qt4projectmanager/qt4projectmanager.cpp
@@ -38,8 +38,10 @@
#include "qt4project.h"
#include "qt4target.h"
#include "profilereader.h"
+#include "profileeditor.h"
#include "qmakestep.h"
#include "qt4buildconfiguration.h"
+#include "addlibrarywizard.h"
#include "wizards/qtquickapp.h"
#include "wizards/html5app.h"
@@ -202,16 +204,6 @@ void Qt4Manager::uiEditorContentsChanged()
m_dirty = true;
}
-Core::Context Qt4Manager::projectContext() const
-{
- return m_plugin->projectContext();
-}
-
-Core::Context Qt4Manager::projectLanguage() const
-{
- return Core::Context(ProjectExplorer::Constants::LANG_CXX);
-}
-
QString Qt4Manager::mimeType() const
{
return QLatin1String(Qt4ProjectManager::Constants::PROFILE_MIMETYPE);
@@ -294,6 +286,52 @@ ProjectExplorer::Project *Qt4Manager::contextProject() const
return m_contextProject;
}
+void Qt4Manager::addLibrary()
+{
+ Core::EditorManager *em = Core::EditorManager::instance();
+ ProFileEditorWidget *editor = qobject_cast<ProFileEditorWidget*>(em->currentEditor()->widget());
+ if (editor)
+ addLibrary(editor->file()->fileName(), editor);
+}
+
+void Qt4Manager::addLibraryContextMenu()
+{
+ ProjectExplorer::Node *node = ProjectExplorer::ProjectExplorerPlugin::instance()->currentNode();
+ if (qobject_cast<Qt4ProFileNode *>(node))
+ addLibrary(node->path());
+}
+
+void Qt4Manager::addLibrary(const QString &fileName, ProFileEditorWidget *editor)
+{
+ AddLibraryWizard wizard(fileName, Core::EditorManager::instance());
+ if (wizard.exec() != QDialog::Accepted)
+ return;
+
+ TextEditor::BaseTextEditor *editable = 0;
+ if (editor) {
+ editable = editor->editor();
+ } else {
+ Core::EditorManager *em = Core::EditorManager::instance();
+ editable = qobject_cast<TextEditor::BaseTextEditor *>
+ (em->openEditor(fileName, Qt4ProjectManager::Constants::PROFILE_EDITOR_ID));
+ }
+ if (!editable)
+ return;
+
+ const int endOfDoc = editable->position(TextEditor::ITextEditor::EndOfDoc);
+ editable->setCursorPosition(endOfDoc);
+ QString snippet = wizard.snippet();
+
+ // add extra \n in case the last line is not empty
+ int line, column;
+ editable->convertPosition(endOfDoc, &line, &column);
+ if (!editable->textAt(endOfDoc - column, column).simplified().isEmpty())
+ snippet = QLatin1Char('\n') + snippet;
+
+ editable->insert(snippet);
+}
+
+
void Qt4Manager::runQMake()
{
runQMake(projectExplorer()->startupProject(), 0);
diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.h b/src/plugins/qt4projectmanager/qt4projectmanager.h
index 548ada2072..f4fdce5ae2 100644
--- a/src/plugins/qt4projectmanager/qt4projectmanager.h
+++ b/src/plugins/qt4projectmanager/qt4projectmanager.h
@@ -77,10 +77,6 @@ public:
ProjectExplorer::ProjectExplorerPlugin *projectExplorer() const;
- // ProjectExplorer::IProjectManager
- Core::Context projectContext() const;
- Core::Context projectLanguage() const;
-
virtual QString mimeType() const;
ProjectExplorer::Project *openProject(const QString &fileName);
@@ -96,6 +92,8 @@ public:
enum Action { BUILD, REBUILD, CLEAN };
public slots:
+ void addLibrary();
+ void addLibraryContextMenu();
void runQMake();
void runQMakeContextMenu();
void buildSubDirContextMenu();
@@ -111,6 +109,7 @@ private slots:
private:
QList<Qt4Project *> m_projects;
void handleSubDirContexMenu(Action action);
+ void addLibrary(const QString &fileName, Internal::ProFileEditorWidget *editor = 0);
void runQMake(ProjectExplorer::Project *p, ProjectExplorer::Node *node);
Internal::Qt4ProjectManagerPlugin *m_plugin;
diff --git a/src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri b/src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri
index 93c68b8b37..1a8b3dff3a 100644
--- a/src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri
+++ b/src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri
@@ -1,5 +1,6 @@
include(../../plugins/projectexplorer/projectexplorer.pri)
include(../../plugins/cpptools/cpptools.pri)
include(../../plugins/debugger/debugger.pri)
+include(../../plugins/analyzerbase/analyzerbase.pri)
include(../../libs/symbianutils/symbianutils.pri)
include(../../libs/qmljs/qmljs.pri)
diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h b/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h
index 136bd298a3..69c87c5738 100644
--- a/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h
+++ b/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h
@@ -40,7 +40,6 @@ namespace Constants {
//contexts
const char * const C_PROFILEEDITOR = ".pro File Editor";
-const char * const C_PROFILEEDITOR_PANEL = ".pro File Editor (embedded)";
// menus
const char * const M_CONTEXT = "ProFileEditor.ContextMenu";
@@ -58,36 +57,15 @@ const char * const FORM_MIMETYPE = "application/x-designer";
const char * const LINGUIST_MIMETYPE = "application/x-linguist";
//actions
-const char * const NEWMENU = "Qt4.NewMenu";
-const char * const PROJECT_NEWMENU_SEPARATOR = "Qt4.NewMenuSeparator";
-const char * const SUBPROJECT_NEWMENU_SEPARATOR = "Qt4.SubProjectNewMenuSeparator";
-const char * const ADDTOPROJECT = "Qt4.AddToProject";
const char * const RUNQMAKE = "Qt4Builder.RunQMake";
const char * const RUNQMAKECONTEXTMENU = "Qt4Builder.RunQMakeContextMenu";
const char * const BUILDSUBDIR = "Qt4Builder.BuildSubDir";
const char * const REBUILDSUBDIR = "Qt4Builder.RebuildSubDir";
const char * const CLEANSUBDIR = "Qt4Builder.CleanSubDir";
-const char * const RUNSUBDIR = "Qt4Builder.RunSubDir";
-const char * const RUNMENUSUBDIR = "Qt4Builder.RunMenuSubDir";
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";
-const char * const CONFIG_RELEASE = "release";
-
-//global configurations
-const char * const GC_BUILDCONFIG = "Qt4.BuildConfig";
-const char * const GC_QTVERSION = "Qt4.QtVersion";
-const char * const GC_COMPILER = "Qt4.Compiler";
-
-// qmakestep
-const char * const QMAKESTEP = "trolltech.qt4projectmanager.qmake";
-const char * const MAKESTEP = "trolltech.qt4projectmanager.make";
-const char * const QT4RUNSTEP = "trolltech.qt4projectmanager.qt4runstep";
-const char * const DEPLOYHELPERRUNSTEP = "trolltech.qt4projectmanager.deployhelperrunstep";
-
//Qt4 settings pages
const char * const QT_SETTINGS_CATEGORY = "L.Qt4";
const char * const QT_SETTINGS_CATEGORY_ICON = ":/core/images/category_qt.png";
diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp
index b351adb769..0f7c77c744 100644
--- a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp
+++ b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp
@@ -107,7 +107,8 @@ Qt4ProjectManagerPlugin::~Qt4ProjectManagerPlugin()
bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
Q_UNUSED(arguments)
- m_projectContext = Core::Context(Qt4ProjectManager::Constants::PROJECT_ID);
+ const Core::Context projectContext(Qt4ProjectManager::Constants::PROJECT_ID);
+ Core::Context projecTreeContext(ProjectExplorer::Constants::C_PROJECT_TREE);
ProFileParser::initialize();
ProFileEvaluator::initialize();
@@ -198,13 +199,13 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString *
QIcon qmakeIcon(QLatin1String(":/qt4projectmanager/images/run_qmake.png"));
qmakeIcon.addFile(QLatin1String(":/qt4projectmanager/images/run_qmake_small.png"));
m_runQMakeAction = new QAction(qmakeIcon, tr("Run qmake"), this);
- command = am->registerAction(m_runQMakeAction, Constants::RUNQMAKE, m_projectContext);
+ command = am->registerAction(m_runQMakeAction, Constants::RUNQMAKE, projectContext);
command->setAttribute(Core::Command::CA_Hide);
mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_PROJECT);
connect(m_runQMakeAction, SIGNAL(triggered()), m_qt4ProjectManager, SLOT(runQMake()));
m_runQMakeActionContextMenu = new QAction(qmakeIcon, tr("Run qmake"), this);
- command = am->registerAction(m_runQMakeActionContextMenu, Constants::RUNQMAKECONTEXTMENU, m_projectContext);
+ command = am->registerAction(m_runQMakeActionContextMenu, Constants::RUNQMAKECONTEXTMENU, projectContext);
command->setAttribute(Core::Command::CA_Hide);
mproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
@@ -213,7 +214,7 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString *
QIcon buildIcon(ProjectExplorer::Constants::ICON_BUILD);
buildIcon.addFile(ProjectExplorer::Constants::ICON_BUILD_SMALL);
m_buildSubProjectContextMenu = new QAction(buildIcon, tr("Build"), this);
- command = am->registerAction(m_buildSubProjectContextMenu, Constants::BUILDSUBDIR, m_projectContext);
+ command = am->registerAction(m_buildSubProjectContextMenu, Constants::BUILDSUBDIR, projectContext);
command->setAttribute(Core::Command::CA_Hide);
msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
connect(m_buildSubProjectContextMenu, SIGNAL(triggered()), m_qt4ProjectManager, SLOT(buildSubDirContextMenu()));
@@ -221,7 +222,7 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString *
QIcon rebuildIcon(ProjectExplorer::Constants::ICON_REBUILD);
rebuildIcon.addFile(ProjectExplorer::Constants::ICON_REBUILD_SMALL);
m_rebuildSubProjectContextMenu = new QAction(rebuildIcon, tr("Rebuild"), this);
- command = am->registerAction(m_rebuildSubProjectContextMenu, Constants::REBUILDSUBDIR, m_projectContext);
+ command = am->registerAction(m_rebuildSubProjectContextMenu, Constants::REBUILDSUBDIR, projectContext);
command->setAttribute(Core::Command::CA_Hide);
msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
connect(m_rebuildSubProjectContextMenu, SIGNAL(triggered()), m_qt4ProjectManager, SLOT(rebuildSubDirContextMenu()));
@@ -229,7 +230,7 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString *
QIcon cleanIcon(ProjectExplorer::Constants::ICON_CLEAN);
cleanIcon.addFile(ProjectExplorer::Constants::ICON_CLEAN_SMALL);
m_cleanSubProjectContextMenu = new QAction(cleanIcon, tr("Clean"), this);
- command = am->registerAction(m_cleanSubProjectContextMenu, Constants::CLEANSUBDIR, m_projectContext);
+ command = am->registerAction(m_cleanSubProjectContextMenu, Constants::CLEANSUBDIR, projectContext);
command->setAttribute(Core::Command::CA_Hide);
msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
connect(m_cleanSubProjectContextMenu, SIGNAL(triggered()), m_qt4ProjectManager, SLOT(cleanSubDirContextMenu()));
@@ -242,35 +243,43 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString *
this, SLOT(buildStateChanged(ProjectExplorer::Project *)));
connect(m_projectExplorer, SIGNAL(currentProjectChanged(ProjectExplorer::Project *)),
this, SLOT(currentProjectChanged()));
+ connect(m_projectExplorer, SIGNAL(currentNodeChanged(ProjectExplorer::Node*,ProjectExplorer::Project*)),
+ this, SLOT(currentNodeChanged(ProjectExplorer::Node*)));
Core::ActionContainer *contextMenu = am->createMenu(Qt4ProjectManager::Constants::M_CONTEXT);
- Core::Command *cmd;
-
Core::Context proFileEditorContext = Core::Context(Qt4ProjectManager::Constants::C_PROFILEEDITOR);
QAction *jumpToFile = new QAction(tr("Jump to File Under Cursor"), this);
- cmd = am->registerAction(jumpToFile,
+ command = am->registerAction(jumpToFile,
Constants::JUMP_TO_FILE, proFileEditorContext);
- cmd->setDefaultKeySequence(QKeySequence(Qt::Key_F2));
+ command->setDefaultKeySequence(QKeySequence(Qt::Key_F2));
connect(jumpToFile, SIGNAL(triggered()),
this, SLOT(jumpToFile()));
- contextMenu->addAction(cmd);
+ contextMenu->addAction(command);
- QAction *addLibrary = new QAction(tr("Add Library..."), this);
- cmd = am->registerAction(addLibrary,
+ m_addLibraryAction = new QAction(tr("Add Library..."), this);
+ command = am->registerAction(m_addLibraryAction,
Constants::ADDLIBRARY, proFileEditorContext);
- connect(addLibrary, SIGNAL(triggered()),
- this, SLOT(addLibrary()));
- contextMenu->addAction(cmd);
+ connect(m_addLibraryAction, SIGNAL(triggered()),
+ m_qt4ProjectManager, SLOT(addLibrary()));
+ contextMenu->addAction(command);
+
+ m_addLibraryActionContextMenu = new QAction(tr("Add Library..."), this);
+ command = am->registerAction(m_addLibraryActionContextMenu,
+ Constants::ADDLIBRARY, projecTreeContext);
+ connect(m_addLibraryActionContextMenu, SIGNAL(triggered()),
+ m_qt4ProjectManager, SLOT(addLibraryContextMenu()));
+ mproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_FILES);
+ msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_FILES);
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);
+ command = am->command(TextEditor::Constants::UN_COMMENT_SELECTION);
+ contextMenu->addAction(command);
return true;
}
@@ -316,6 +325,11 @@ void Qt4ProjectManagerPlugin::currentProjectChanged()
m_runQMakeAction->setEnabled(!m_projectExplorer->buildManager()->isBuilding(m_projectExplorer->currentProject()));
}
+void Qt4ProjectManagerPlugin::currentNodeChanged(ProjectExplorer::Node *node)
+{
+ m_addLibraryActionContextMenu->setEnabled(qobject_cast<Qt4ProFileNode *>(node));
+}
+
void Qt4ProjectManagerPlugin::buildStateChanged(ProjectExplorer::Project *pro)
{
ProjectExplorer::Project *currentProject = m_projectExplorer->currentProject();
@@ -325,14 +339,6 @@ void Qt4ProjectManagerPlugin::buildStateChanged(ProjectExplorer::Project *pro)
m_runQMakeActionContextMenu->setEnabled(!m_projectExplorer->buildManager()->isBuilding(pro));
}
-void Qt4ProjectManagerPlugin::addLibrary()
-{
- Core::EditorManager *em = Core::EditorManager::instance();
- ProFileEditorWidget *editor = qobject_cast<ProFileEditorWidget*>(em->currentEditor()->widget());
- if (editor)
- editor->addLibrary();
-}
-
void Qt4ProjectManagerPlugin::jumpToFile()
{
Core::EditorManager *em = Core::EditorManager::instance();
diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.h b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.h
index daf9387f58..33015ae255 100644
--- a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.h
+++ b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.h
@@ -64,14 +64,12 @@ public:
bool initialize(const QStringList &arguments, QString *error_message);
void extensionsInitialized();
- Core::Context projectContext() const { return m_projectContext; }
-
private slots:
void updateContextMenu(ProjectExplorer::Project *project,
ProjectExplorer::Node *node);
void currentProjectChanged();
+ void currentNodeChanged(ProjectExplorer::Node *node);
void buildStateChanged(ProjectExplorer::Project *pro);
- void addLibrary();
void jumpToFile();
#ifdef WITH_TESTS
@@ -99,6 +97,8 @@ private:
QAction *m_buildSubProjectContextMenu;
QAction *m_rebuildSubProjectContextMenu;
QAction *m_cleanSubProjectContextMenu;
+ QAction *m_addLibraryAction;
+ QAction *m_addLibraryActionContextMenu;
GettingStartedWelcomePage *m_welcomePage;
Core::Context m_projectContext;
};
diff --git a/src/plugins/qt4projectmanager/qt4target.cpp b/src/plugins/qt4projectmanager/qt4target.cpp
index 841a3ee302..e2d58eb7f6 100644
--- a/src/plugins/qt4projectmanager/qt4target.cpp
+++ b/src/plugins/qt4projectmanager/qt4target.cpp
@@ -53,6 +53,7 @@
#include <QtGui/QPushButton>
#include <QtGui/QMessageBox>
#include <QtGui/QCheckBox>
+#include <QtGui/QComboBox>
#include <QtGui/QMainWindow>
using namespace Qt4ProjectManager;
@@ -93,9 +94,71 @@ ProjectExplorer::Target *Qt4BaseTargetFactory::create(ProjectExplorer::Project *
return 0;
Q_ASSERT(qobject_cast<Qt4DefaultTargetSetupWidget *>(widget));
Qt4DefaultTargetSetupWidget *w = static_cast<Qt4DefaultTargetSetupWidget *>(widget);
+ w->storeSettings();
return create(parent, id, w->buildConfigurationInfos());
}
+QList<BuildConfigurationInfo> Qt4BaseTargetFactory::availableBuildConfigurations(const QString &id, const QString &proFilePath, const QtVersionNumber &minimumQtVersion)
+{
+ QList<BuildConfigurationInfo> infoList;
+ QList<QtVersion *> knownVersions = QtVersionManager::instance()->versionsForTargetId(id, minimumQtVersion);
+
+ foreach (QtVersion *version, knownVersions) {
+ if (!version->isValid() || !version->toolChainAvailable(id))
+ continue;
+ QtVersion::QmakeBuildConfigs config = version->defaultBuildConfig();
+ BuildConfigurationInfo info = BuildConfigurationInfo(version, config, QString(), QString());
+ info.directory = shadowBuildDirectory(proFilePath, id, msgBuildConfigurationName(info));
+ infoList.append(info);
+
+ info.buildConfig = config ^ QtVersion::DebugBuild;
+ info.directory = shadowBuildDirectory(proFilePath, id, msgBuildConfigurationName(info));
+ infoList.append(info);
+ }
+ return infoList;
+}
+
+QString sanitize(const QString &input)
+{
+ QString result;
+ result.reserve(input.size());
+ foreach (const QChar &c, input) {
+ if ((c >= 'a' && c <='z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9')
+ || c == '-'
+ || c == '_')
+ result.append(c);
+ else
+ result.append('_');
+ }
+ return result;
+}
+
+QString projectDirectory(const QString &proFile)
+{
+ if (proFile.isEmpty())
+ return QString();
+ QFileInfo info(proFile);
+ return info.absoluteDir().path();
+}
+
+QString Qt4BaseTargetFactory::shadowBuildDirectory(const QString &profilePath, const QString &id, const QString &suffix)
+{
+ if (profilePath.isEmpty())
+ return QString();
+ QFileInfo info(profilePath);
+
+ QString base = QDir::cleanPath(projectDirectory(profilePath) + QLatin1String("/../") + info.baseName() + QLatin1String("-build-"));
+ return base + buildNameForId(id) + QLatin1String("-") + sanitize(suffix);
+}
+
+QString Qt4BaseTargetFactory::buildNameForId(const QString &id) const
+{
+ Q_UNUSED(id);
+ return QString();
+}
+
Qt4BaseTargetFactory *Qt4BaseTargetFactory::qt4BaseTargetFactoryForId(const QString &id)
{
QList<Qt4BaseTargetFactory *> factories = ExtensionSystem::PluginManager::instance()->getObjects<Qt4BaseTargetFactory>();
@@ -157,12 +220,6 @@ Qt4Project *Qt4BaseTarget::qt4Project() const
return static_cast<Qt4Project *>(project());
}
-QString Qt4BaseTarget::defaultBuildDirectory() const
-{
- Qt4BaseTargetFactory *fac = Qt4BaseTargetFactory::qt4BaseTargetFactoryForId(id());
- return fac->defaultShadowBuildDirectory(qt4Project()->defaultTopLevelBuildDirectory(), id());
-}
-
QList<ProjectExplorer::ToolChain *> Qt4BaseTarget::possibleToolChains(ProjectExplorer::BuildConfiguration *bc) const
{
QList<ProjectExplorer::ToolChain *> tmp;
@@ -319,8 +376,12 @@ Qt4DefaultTargetSetupWidget::Qt4DefaultTargetSetupWidget(Qt4BaseTargetFactory *f
m_hasInSourceBuild(false),
m_ignoreChange(false),
m_showImport(importEnabled),
- m_selected(0)
+ m_buildConfigurationTemplateUnchanged(true),
+ m_shadowBuildCheckBoxVisible(false),
+ m_selected(0),
+ m_qtVersionId(-1)
{
+ QSettings *s = Core::ICore::instance()->settings();
QString sourceDir = QFileInfo(m_proFilePath).absolutePath();
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
@@ -330,7 +391,7 @@ Qt4DefaultTargetSetupWidget::Qt4DefaultTargetSetupWidget(Qt4BaseTargetFactory *f
m_detailsWidget = new Utils::DetailsWidget(this);
m_detailsWidget->setSummaryText(factory->displayNameForId(id));
m_detailsWidget->setUseCheckBox(true);
- m_detailsWidget->setChecked(true);
+ m_detailsWidget->setChecked(false);
m_detailsWidget->setSummaryFontBold(true);
m_detailsWidget->setIcon(factory->iconForId(id));
m_detailsWidget->setAdditionalSummaryText(issuesListToString(factory->reportIssues(m_proFilePath)));
@@ -373,11 +434,46 @@ Qt4DefaultTargetSetupWidget::Qt4DefaultTargetSetupWidget(Qt4BaseTargetFactory *f
m_importLinePath->setVisible(false);
m_importLineButton->setVisible(m_showImport);
+ m_buildConfigurationLabel = new QLabel;
+ m_buildConfigurationLabel->setText("Create Build Configurations:");
+ m_buildConfigurationLabel->setVisible(false);
+
+ m_buildConfigurationComboBox = new QComboBox;
+ m_buildConfigurationComboBox->addItem("per Qt Version a Debug and Release", PERQT);
+ m_buildConfigurationComboBox->addItem("for one Qt Version a Debug and Release", ONEQT);
+ m_buildConfigurationComboBox->addItem("manually", MANUALLY);
+ m_buildConfigurationComboBox->addItem("none", NONE);
+
+ if (m_importInfos.isEmpty())
+ m_buildConfigurationComboBox->setCurrentIndex(s->value("Qt4ProjectManager.TargetSetupPage.BuildTemplate", 0).toInt());
+ else
+ m_buildConfigurationComboBox->setCurrentIndex(3); // NONE
+
+ m_buildConfigurationComboBox->setVisible(false);
+
+ QHBoxLayout *hbox = new QHBoxLayout();
+ hbox->addWidget(m_buildConfigurationLabel);
+ hbox->addWidget(m_buildConfigurationComboBox);
+ hbox->addStretch();
+ layout->addLayout(hbox);
+
m_shadowBuildEnabled = new QCheckBox;
m_shadowBuildEnabled->setText(tr("Use Shadow Building"));
m_shadowBuildEnabled->setVisible(false);
+
layout->addWidget(m_shadowBuildEnabled);
+ m_versionLabel = new QLabel;
+ m_versionLabel->setText("Qt Version:");
+ m_versionLabel->setVisible(false);
+ m_versionComboBox = new QComboBox;
+ m_versionComboBox->setVisible(false);
+ hbox = new QHBoxLayout();
+ hbox->addWidget(m_versionLabel);
+ hbox->addWidget(m_versionComboBox);
+ hbox->addStretch();
+ layout->addLayout(hbox);
+
w = new QWidget;
m_newBuildsLayout = new QGridLayout;
m_newBuildsLayout->setMargin(0);
@@ -387,6 +483,7 @@ Qt4DefaultTargetSetupWidget::Qt4DefaultTargetSetupWidget(Qt4BaseTargetFactory *f
w->setLayout(m_newBuildsLayout);
layout->addWidget(w);
+ widget->setEnabled(false);
m_detailsWidget->setWidget(widget);
for (int i = 0; i < m_importInfos.size(); ++i) {
@@ -395,7 +492,10 @@ Qt4DefaultTargetSetupWidget::Qt4DefaultTargetSetupWidget(Qt4BaseTargetFactory *f
m_importEnabled << true;
}
- m_shadowBuildEnabled->setChecked(!m_hasInSourceBuild);
+ if (m_hasInSourceBuild)
+ m_shadowBuildEnabled->setChecked(false);
+ else
+ m_shadowBuildEnabled->setChecked(s->value("Qt4ProjectManager.TargetSetupPage.ShadowBuilding", true).toBool());
m_selected += m_importInfos.size();
@@ -403,6 +503,12 @@ Qt4DefaultTargetSetupWidget::Qt4DefaultTargetSetupWidget(Qt4BaseTargetFactory *f
setBuildConfigurationInfos(infos);
+ int qtVersionId = s->value("Qt4ProjectManager.TargetSetupPage.QtVersionId", -1).toInt();
+ int index = m_versionComboBox->findData(qtVersionId);
+ if (index != -1)
+ m_versionComboBox->setCurrentIndex(index);
+ qtVersionChanged();
+
if (!m_importInfos.isEmpty())
m_detailsWidget->setState(Utils::DetailsWidget::Expanded);
@@ -410,33 +516,58 @@ Qt4DefaultTargetSetupWidget::Qt4DefaultTargetSetupWidget(Qt4BaseTargetFactory *f
this, SLOT(addImportClicked()));
connect(m_detailsWidget, SIGNAL(checked(bool)),
- this, SIGNAL(selectedToggled()));
- connect(m_detailsWidget, SIGNAL(checked(bool)),
- widget, SLOT(setEnabled(bool)));
+ this, SLOT(targetCheckBoxToggled(bool)));
connect(m_shadowBuildEnabled, SIGNAL(toggled(bool)),
this, SLOT(shadowBuildingToggled()));
-
+ connect(m_buildConfigurationComboBox, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(buildConfigurationComboBoxChanged()));
+ connect(m_versionComboBox, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(qtVersionChanged()));
}
Qt4DefaultTargetSetupWidget::~Qt4DefaultTargetSetupWidget()
{
+
}
bool Qt4DefaultTargetSetupWidget::isTargetSelected() const
{
- return m_detailsWidget->isChecked() && m_selected;
+ if (!m_detailsWidget->isChecked())
+ return false;
+
+ return !buildConfigurationInfos().isEmpty();
}
void Qt4DefaultTargetSetupWidget::setTargetSelected(bool b)
{
// Only check target if there are build configurations possible
b == b && !buildConfigurationInfos().isEmpty();
+ m_ignoreChange = true;
m_detailsWidget->setChecked(b);
+ m_detailsWidget->widget()->setEnabled(b);
+ m_ignoreChange = false;
// We want the shadow build option to be visible
- if (m_shadowBuildEnabled->isVisible() && b)
+ if (b && (m_shadowBuildEnabled->isVisibleTo(m_shadowBuildEnabled->parentWidget())
+ || m_buildConfigurationComboBox->isVisibleTo(m_buildConfigurationComboBox->parentWidget())))
m_detailsWidget->setState(Utils::DetailsWidget::Expanded);
}
+void Qt4DefaultTargetSetupWidget::targetCheckBoxToggled(bool b)
+{
+ if (m_ignoreChange)
+ return;
+ m_detailsWidget->widget()->setEnabled(b);
+ if (b) {
+ foreach (bool error, m_issues) {
+ if (error) {
+ m_detailsWidget->setState(Utils::DetailsWidget::Expanded);
+ break;
+ }
+ }
+ }
+ emit selectedToggled();
+}
+
QString Qt4DefaultTargetSetupWidget::displayNameFrom(const BuildConfigurationInfo &info)
{
QString buildType;
@@ -466,9 +597,56 @@ void Qt4DefaultTargetSetupWidget::setShadowBuildSupported(bool b)
void Qt4DefaultTargetSetupWidget::setShadowBuildCheckBoxVisible(bool b)
{
+ m_shadowBuildCheckBoxVisible = b;
m_shadowBuildEnabled->setVisible(b);
}
+void Qt4DefaultTargetSetupWidget::setBuildConfiguraionComboBoxVisible(bool b)
+{
+ m_buildConfigurationLabel->setVisible(true);
+ m_buildConfigurationComboBox->setVisible(true);
+ updateWidgetVisibility();
+}
+
+
+Qt4DefaultTargetSetupWidget::BuildConfigurationTemplate Qt4DefaultTargetSetupWidget::buildConfigurationTemplate() const
+{
+ if (!m_buildConfigurationComboBox->isVisibleTo(m_buildConfigurationComboBox->parentWidget()))
+ return MANUALLY; // the default
+ return static_cast<BuildConfigurationTemplate>(m_buildConfigurationComboBox->itemData(m_buildConfigurationComboBox->currentIndex()).toInt());
+}
+
+void Qt4DefaultTargetSetupWidget::setBuildConfigurationTemplate(Qt4DefaultTargetSetupWidget::BuildConfigurationTemplate value)
+{
+ int index = m_buildConfigurationComboBox->findData(QVariant::fromValue(int(value)));
+ m_buildConfigurationComboBox->setCurrentIndex(index);
+}
+
+void Qt4DefaultTargetSetupWidget::storeSettings() const
+{
+ bool importing = false;
+ for (int i=0; i < m_importEnabled.size(); ++i) {
+ if (m_importEnabled.at(i)) {
+ importing = true;
+ break;
+ }
+ }
+
+ QSettings *s = Core::ICore::instance()->settings();
+ s->setValue("Qt4ProjectManager.TargetSetupPage.ShadowBuilding", m_shadowBuildEnabled->isChecked());
+ int id = -1;
+ int ci = m_versionComboBox->currentIndex();
+ if (ci != -1)
+ id = m_versionComboBox->itemData(ci).toInt();
+ s->setValue("Qt4ProjectManager.TargetSetupPage.QtVersionId", id);
+
+ // if we are importing we don't save the template setting
+ // essentially we assume that the settings apply for the new project case
+ // and for the importing case "None" is likely the most sensible
+ if (!importing)
+ s->setValue("Qt4ProjectManager.TargetSetupPage.BuildTemplate", m_buildConfigurationComboBox->currentIndex());
+}
+
QList<BuildConfigurationInfo> Qt4DefaultTargetSetupWidget::buildConfigurationInfos() const
{
QList<BuildConfigurationInfo> infos;
@@ -477,11 +655,18 @@ QList<BuildConfigurationInfo> Qt4DefaultTargetSetupWidget::buildConfigurationInf
infos << m_importInfos.at(i);
}
- QString sourceDir = QFileInfo(m_proFilePath).absolutePath();
+ BuildConfigurationTemplate state = buildConfigurationTemplate();
+ if (state == NONE)
+ return infos;
+
+ int qtVersionId = -1;
+ if (state == ONEQT && m_versionComboBox->currentIndex() != -1)
+ qtVersionId = m_versionComboBox->itemData(m_versionComboBox->currentIndex()).toInt();
+ QString sourceDir = QFileInfo(m_proFilePath).absolutePath();
int size = m_infos.size();
for (int i=0; i < size; ++i) {
- if (m_enabled.at(i)) {
+ if (state == PERQT || (m_enabled.at(i) && (state == MANUALLY || (state == ONEQT && m_infos.at(i).version->uniqueId() == qtVersionId)))) {
BuildConfigurationInfo info = m_infos.at(i);
if (!m_shadowBuildEnabled->isChecked())
info.directory = sourceDir;
@@ -513,17 +698,10 @@ void Qt4DefaultTargetSetupWidget::addImportClicked()
tr("The Build found in %1 is incompatible with this target").arg(m_importLinePath->path()));
return;
}
- if (m_selected == m_enabled.size() && m_importInfos.isEmpty()) {
- // All regular builds are enabled and we didn't have a import before
- // That means we are still in the default setup, in that case
- // we disable all the builds
- m_selected = 0;
- for (int i=0; i<m_enabled.size(); ++i) {
- m_enabled[i] = false;
- m_checkboxes.at(i)->setChecked(false);
- }
- }
+ // We switch from to "NONE" on importing if the user has not changed it
+ if (m_buildConfigurationTemplateUnchanged)
+ setBuildConfigurationTemplate(NONE);
++m_selected;
m_importEnabled << true;
@@ -587,9 +765,28 @@ void Qt4DefaultTargetSetupWidget::setBuildConfigurationInfos(const QList<BuildCo
foundIssues |= reportIssues(i);
}
m_ignoreChange = false;
- if (foundIssues)
+ if (foundIssues && isTargetSelected())
m_detailsWidget->setState(Utils::DetailsWidget::Expanded);
}
+
+ // update version combobox
+ int oldQtVersionId = -1;
+ if (m_versionComboBox->currentIndex() != -1)
+ oldQtVersionId = m_versionComboBox->itemData(m_versionComboBox->currentIndex()).toInt();
+ QList<QtVersion *> list;
+ foreach (const BuildConfigurationInfo &info, m_infos) {
+ if (!list.contains(info.version))
+ list << info.version;
+ }
+ m_ignoreChange = true;
+ m_versionComboBox->clear();
+ foreach (QtVersion *v, list) {
+ m_versionComboBox->addItem(v->displayName(), v->uniqueId());
+ if (v->uniqueId() == oldQtVersionId)
+ m_versionComboBox->setCurrentIndex(m_versionComboBox->count() - 1);
+ }
+ m_ignoreChange = false;
+ updateWidgetVisibility();
}
void Qt4DefaultTargetSetupWidget::setupImportWidgets()
@@ -640,6 +837,7 @@ void Qt4DefaultTargetSetupWidget::setupWidgets()
QLabel *reportIssuesLabel = new QLabel;
reportIssuesLabel->setIndent(32);
m_newBuildsLayout->addWidget(reportIssuesLabel, i * 2 + 1, 0, 1, 2);
+ reportIssuesLabel->setVisible(false);
connect(checkbox, SIGNAL(toggled(bool)),
this, SLOT(checkBoxToggled(bool)));
@@ -650,9 +848,11 @@ void Qt4DefaultTargetSetupWidget::setupWidgets()
m_checkboxes.append(checkbox);
m_pathChoosers.append(pathChooser);
m_reportIssuesLabels.append(reportIssuesLabel);
- foundIssues |= reportIssues(i);
+ m_issues.append(false);
+ bool issue = reportIssues(i);
+ foundIssues |= issue;
}
- if (foundIssues)
+ if (foundIssues && isTargetSelected())
m_detailsWidget->setState(Utils::DetailsWidget::Expanded);
m_ignoreChange = false;
}
@@ -665,6 +865,7 @@ void Qt4DefaultTargetSetupWidget::clearWidgets()
m_pathChoosers.clear();
qDeleteAll(m_reportIssuesLabels);
m_reportIssuesLabels.clear();
+ m_issues.clear();
}
void Qt4DefaultTargetSetupWidget::checkBoxToggled(bool b)
@@ -733,13 +934,66 @@ void Qt4DefaultTargetSetupWidget::shadowBuildingToggled()
m_ignoreChange = false;
}
+void Qt4DefaultTargetSetupWidget::buildConfigurationComboBoxChanged()
+{
+ m_buildConfigurationTemplateUnchanged = false;
+ updateWidgetVisibility();
+}
+
+void Qt4DefaultTargetSetupWidget::updateWidgetVisibility()
+{
+ m_versionLabel->setVisible(false);
+ m_versionComboBox->setVisible(false);
+ BuildConfigurationTemplate state = buildConfigurationTemplate();
+ if (state == NONE || state == PERQT) {
+ foreach (QCheckBox *cb, m_checkboxes)
+ cb->setVisible(false);
+ foreach (Utils::PathChooser *pc, m_pathChoosers)
+ pc->setVisible(false);
+ foreach (QLabel *label, m_reportIssuesLabels)
+ label->setVisible(false);
+ } else if (state == MANUALLY) {
+ foreach (QCheckBox *cb, m_checkboxes)
+ cb->setVisible(true);
+ foreach (Utils::PathChooser *pc, m_pathChoosers)
+ pc->setVisible(true);
+ for (int i = 0; i < m_reportIssuesLabels.count(); ++i)
+ m_reportIssuesLabels.at(i)->setVisible(m_issues.at(i));
+ } else if (state == ONEQT) {
+ m_versionLabel->setVisible(true);
+ m_versionComboBox->setVisible(true);
+ qtVersionChanged();
+ }
+ m_shadowBuildEnabled->setVisible(m_shadowBuildCheckBoxVisible && (state != NONE));
+ emit selectedToggled();
+}
+
+void Qt4DefaultTargetSetupWidget::qtVersionChanged()
+{
+ if (m_ignoreChange)
+ return;
+ int id = -1;
+ if (m_versionComboBox->currentIndex() != -1)
+ id = m_versionComboBox->itemData(m_versionComboBox->currentIndex()).toInt();
+ if (buildConfigurationTemplate() != ONEQT)
+ return;
+ for (int i = 0; i < m_infos.size(); ++i) {
+ bool visible = m_infos.at(i).version->uniqueId() == id;
+ m_checkboxes.at(i)->setVisible(visible);
+ m_pathChoosers.at(i)->setVisible(visible);
+ m_reportIssuesLabels.at(i)->setVisible(m_issues.at(i));
+ }
+}
+
bool Qt4DefaultTargetSetupWidget::reportIssues(int index)
{
QPair<ProjectExplorer::Task::TaskType, QString> issues = findIssues(m_infos.at(index));
QLabel *reportIssuesLabel = m_reportIssuesLabels.at(index);
reportIssuesLabel->setText(issues.second);
- reportIssuesLabel->setVisible(issues.first != ProjectExplorer::Task::Unknown);
- return issues.first != ProjectExplorer::Task::Unknown;
+ bool error = issues.first != ProjectExplorer::Task::Unknown;
+ reportIssuesLabel->setVisible(error);
+ m_issues[index] = error;
+ return error;
}
QPair<ProjectExplorer::Task::TaskType, QString> Qt4DefaultTargetSetupWidget::findIssues(const BuildConfigurationInfo &info)
@@ -804,13 +1058,17 @@ QList<BuildConfigurationInfo> BuildConfigurationInfo::importBuildConfigurations(
// Check for builds in build directoy
QList<Qt4BaseTargetFactory *> factories =
ExtensionSystem::PluginManager::instance()->getObjects<Qt4BaseTargetFactory>();
- QString defaultTopLevelBuildDirectory = Qt4Project::defaultTopLevelBuildDirectory(proFilePath);
foreach (Qt4BaseTargetFactory *factory, factories) {
foreach (const QString &id, factory->supportedTargetIds(0)) {
- QString expectedBuild = factory->defaultShadowBuildDirectory(defaultTopLevelBuildDirectory, id);
- BuildConfigurationInfo info = checkForBuild(expectedBuild, proFilePath);
- if (info.isValid())
- result.append(info);
+ QString expectedBuildprefix = factory->shadowBuildDirectory(proFilePath, id, "");
+ QString baseDir = QFileInfo(expectedBuildprefix).absolutePath();
+ foreach (const QString &dir, QDir(baseDir).entryList()) {
+ if (dir.startsWith(expectedBuildprefix)) {
+ BuildConfigurationInfo info = checkForBuild(dir, proFilePath);
+ if (info.isValid())
+ result.append(info);
+ }
+ }
}
}
return result;
diff --git a/src/plugins/qt4projectmanager/qt4target.h b/src/plugins/qt4projectmanager/qt4target.h
index 0ce9e20838..1f41ab1745 100644
--- a/src/plugins/qt4projectmanager/qt4target.h
+++ b/src/plugins/qt4projectmanager/qt4target.h
@@ -51,6 +51,7 @@ class QCheckBox;
class QHBoxLayout;
class QGridLayout;
class QLabel;
+class QComboBox;
class QPushButton;
QT_END_NAMESPACE
@@ -83,7 +84,6 @@ public:
QString directory);
virtual void createApplicationProFiles() = 0;
- virtual QString defaultBuildDirectory() const;
virtual QList<ProjectExplorer::RunConfiguration *> runConfigurationsForNode(ProjectExplorer::Node *n) = 0;
@@ -125,15 +125,28 @@ public:
void setShadowBuildSupported(bool b);
void setShadowBuildCheckBoxVisible(bool b);
+ void setBuildConfiguraionComboBoxVisible(bool b);
-public slots:
+ enum BuildConfigurationTemplate { PERQT = 0,
+ ONEQT = 1,
+ MANUALLY = 2,
+ NONE = 3 };
+ BuildConfigurationTemplate buildConfigurationTemplate() const;
+ void setBuildConfigurationTemplate(BuildConfigurationTemplate value);
+
+ void storeSettings() const;
+private slots:
void addImportClicked();
void checkBoxToggled(bool b);
void importCheckBoxToggled(bool b);
void pathChanged();
void shadowBuildingToggled();
+ void buildConfigurationComboBoxChanged();
+ void qtVersionChanged();
+ void targetCheckBoxToggled(bool b);
private:
+ void updateWidgetVisibility();
void setBuildConfigurationInfos(const QList<BuildConfigurationInfo> &list, bool resetEnabled = true);
bool reportIssues(int index);
QPair<ProjectExplorer::Task::TaskType, QString> findIssues(const BuildConfigurationInfo &info);
@@ -147,6 +160,10 @@ private:
QGridLayout *m_importLayout;
QGridLayout *m_newBuildsLayout;
QCheckBox *m_shadowBuildEnabled;
+ QLabel *m_buildConfigurationLabel;
+ QComboBox *m_buildConfigurationComboBox;
+ QLabel *m_versionLabel;
+ QComboBox *m_versionComboBox;
// import line widgets
QHBoxLayout *m_importLineLayout;
@@ -166,12 +183,15 @@ private:
QList<BuildConfigurationInfo> m_importInfos;
QList<bool> m_importEnabled;
QList<QLabel *> m_reportIssuesLabels;
+ QList<bool> m_issues;
bool m_directoriesEnabled;
bool m_hasInSourceBuild;
bool m_ignoreChange;
bool m_showImport;
- int m_selected;
-
+ bool m_buildConfigurationTemplateUnchanged;
+ bool m_shadowBuildCheckBoxVisible;
+ int m_selected; // Number of selected buildconfiguartions
+ int m_qtVersionId; // version id for "One Qt" entry
};
} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qtoptionspage.cpp b/src/plugins/qt4projectmanager/qtoptionspage.cpp
index 7c18af3fae..e08562ad70 100644
--- a/src/plugins/qt4projectmanager/qtoptionspage.cpp
+++ b/src/plugins/qt4projectmanager/qtoptionspage.cpp
@@ -59,6 +59,7 @@
#include <QtGui/QHelpEvent>
#include <QtGui/QToolTip>
#include <QtGui/QMenu>
+#include <QtGui/QMessageBox>
enum ModelRoles { VersionIdRole = Qt::UserRole, BuildLogRole, BuildRunningRole};
@@ -133,6 +134,7 @@ QtOptionsPageWidget::QtOptionsPageWidget(QWidget *parent, QList<QtVersion *> ver
, m_ui(new Internal::Ui::QtVersionManager())
, m_versionUi(new Internal::Ui::QtVersionInfo())
, m_debuggingHelperUi(new Internal::Ui::DebuggingHelper())
+ , m_invalidVersionIcon(":/projectexplorer/images/compile_error.png")
{
// Initialize m_versions
foreach(QtVersion *version, versions)
@@ -140,6 +142,7 @@ QtOptionsPageWidget::QtOptionsPageWidget(QWidget *parent, QList<QtVersion *> ver
QWidget *versionInfoWidget = new QWidget();
m_versionUi->setupUi(versionInfoWidget);
+
m_versionUi->qmakePath->setExpectedKind(Utils::PathChooser::ExistingCommand);
m_versionUi->qmakePath->setPromptDialogTitle(tr("Select qmake Executable"));
m_versionUi->s60SDKPath->setExpectedKind(Utils::PathChooser::ExistingDirectory);
@@ -211,6 +214,7 @@ QtOptionsPageWidget::QtOptionsPageWidget(QWidget *parent, QList<QtVersion *> ver
connect(m_debuggingHelperUi->showLogButton, SIGNAL(clicked()),
this, SLOT(slotShowDebuggingBuildLog()));
+ connect(m_ui->cleanUpButton, SIGNAL(clicked()), this, SLOT(cleanUpQtVersions()));
showEnvironmentPage(0);
updateState();
}
@@ -297,6 +301,36 @@ void QtOptionsPageWidget::debuggingHelperBuildFinished(int qtVersionId, const QS
showDebuggingBuildLog(item);
}
+void QtOptionsPageWidget::cleanUpQtVersions()
+{
+ QStringList toRemove;
+ foreach (const QtVersion *v, m_versions) {
+ if (!v->isValid() && !v->isAutodetected())
+ toRemove.append(v->displayName());
+ }
+
+ if (toRemove.isEmpty())
+ return;
+
+ if (QMessageBox::warning(0, tr("Remove invalid Qt Versions"),
+ tr("Do you want to remove all invalid Qt Versions?<br>"
+ "<ul><li>%1</li></ul><br>"
+ "will be removed.").arg(toRemove.join(QLatin1String("</li><li>"))),
+ QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
+ return;
+
+ for (int i = m_versions.count() - 1; i >= 0; --i) {
+ if (!m_versions.at(i)->isValid()) {
+ QTreeWidgetItem *item = treeItemForIndex(i);
+ delete item;
+
+ delete m_versions.at(i);
+ m_versions.removeAt(i);
+ }
+ }
+ updateState();
+}
+
void QtOptionsPageWidget::buildDebuggingHelper(DebuggingHelperBuildTask::Tools tools)
{
const int index = currentIndex();
@@ -553,7 +587,6 @@ void QtOptionsPageWidget::updateDebuggingHelperUi()
m_debuggingHelperUi->qmlDebuggingLibBuildButton->setEnabled(canBuildQmlDebuggingLib
&& !isBuildingQmlDebuggingLib);
-
QString qmlObserverStatusText;
Qt::TextInteractionFlags qmlObserverStatusTextFlags = Qt::NoTextInteraction;
if (hasQmlObserver) {
@@ -590,10 +623,24 @@ void QtOptionsPageWidget::updateDebuggingHelperUi()
void QtOptionsPageWidget::updateState()
{
+ bool hasInvalidVersion = false;
+ for (int i = 0; i < m_versions.count(); ++i) {
+ QTreeWidgetItem *item = treeItemForIndex(i);
+ if (!m_versions.at(i)->isValid()) {
+ if (item)
+ item->setIcon(0, m_invalidVersionIcon);
+ hasInvalidVersion = true;
+ } else {
+ if (item)
+ item->setIcon(0, m_validVersionIcon);
+ }
+ }
+
const QtVersion *version = currentVersion();
const bool enabled = version != 0;
const bool isAutodetected = enabled && version->isAutodetected();
m_ui->delButton->setEnabled(enabled && !isAutodetected);
+ m_ui->cleanUpButton->setEnabled(hasInvalidVersion);
m_versionUi->nameEdit->setEnabled(enabled && !isAutodetected);
m_versionUi->qmakePath->setEnabled(enabled && !isAutodetected);
bool s60SDKPathEnabled = enabled &&
@@ -766,21 +813,20 @@ void QtOptionsPageWidget::updateCurrentQMakeLocation()
if (currentItemIndex < 0)
return;
QtVersion *version = m_versions.at(currentItemIndex);
- QFileInfo fi(m_versionUi->qmakePath->path());
- if (!fi.exists() || !fi.isFile() || version->qmakeCommand() == fi.absoluteFilePath())
+ if (version->qmakeCommand() == m_versionUi->qmakePath->path())
return;
- version->setQMakeCommand(fi.absoluteFilePath());
+ version->setQMakeCommand(m_versionUi->qmakePath->path());
currentItem->setText(1, QDir::toNativeSeparators(version->qmakeCommand()));
showEnvironmentPage(currentItem);
- updateDebuggingHelperUi();
-
if (m_versionUi->nameEdit->text().isEmpty() || m_versionUi->nameEdit->text() == m_specifyNameString) {
QString name = ProjectExplorer::DebuggingHelperLibrary::qtVersionForQMake(version->qmakeCommand());
if (!name.isEmpty())
m_versionUi->nameEdit->setText(name);
updateCurrentQtName();
}
+
+ updateState();
}
void QtOptionsPageWidget::updateCurrentS60SDKDirectory()
diff --git a/src/plugins/qt4projectmanager/qtoptionspage.h b/src/plugins/qt4projectmanager/qtoptionspage.h
index ddac99d906..900e80c405 100644
--- a/src/plugins/qt4projectmanager/qtoptionspage.h
+++ b/src/plugins/qt4projectmanager/qtoptionspage.h
@@ -29,6 +29,7 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
+
#ifndef QTOPTIONSPAGE_H
#define QTOPTIONSPAGE_H
@@ -40,6 +41,7 @@
#include <QtCore/QFutureInterface>
#include <QtGui/QWidget>
+#include <QtGui/QIcon>
QT_BEGIN_NAMESPACE
class QTreeWidgetItem;
@@ -85,6 +87,8 @@ private:
Internal::Ui::DebuggingHelper *m_debuggingHelperUi;
QList<QtVersion *> m_versions;
int m_defaultVersion;
+ QIcon m_invalidVersionIcon;
+ QIcon m_validVersionIcon;
private slots:
void versionChanged(QTreeWidgetItem *item, QTreeWidgetItem *old);
@@ -106,6 +110,7 @@ private slots:
void buildQmlObserver();
void slotShowDebuggingBuildLog();
void debuggingHelperBuildFinished(int qtVersionId, const QString &output, DebuggingHelperBuildTask::Tools tools);
+ void cleanUpQtVersions();
private:
void updateDescriptionLabel();
diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp
index bd4a3fce4e..572cc5899d 100644
--- a/src/plugins/qt4projectmanager/qtversionmanager.cpp
+++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp
@@ -1694,6 +1694,12 @@ QString QtVersion::qtCorePath() const
QString QtVersion::sbsV2Directory() const
{
+ QDir dir(m_sbsV2Directory);
+ if (dir.exists(QLatin1String("sbs")))
+ return dir.absolutePath();
+ dir.cd("bin");
+ if (dir.exists(QLatin1String("sbs")))
+ return dir.absolutePath();
return m_sbsV2Directory;
}
@@ -1752,7 +1758,7 @@ void QtVersion::addToEnvironment(Utils::Environment &env) const
if (isBuildWithSymbianSbsV2()) {
QString sbsHome(env.value(QLatin1String("SBS_HOME")));
if (!m_sbsV2Directory.isEmpty()) {
- env.prependOrSetPath(m_sbsV2Directory + QLatin1String("/bin"));
+ env.prependOrSetPath(sbsV2Directory());
env.set(QLatin1String("SBS_HOME"), m_sbsV2Directory); // We need this for Qt 4.6.3 compatibility
} else if (!sbsHome.isEmpty()) {
env.prependOrSetPath(sbsHome + QLatin1Char('/') + QLatin1String("bin"));
@@ -1888,7 +1894,7 @@ QString QtVersion::description() const
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!");
+ envs = QCoreApplication::translate("QtVersion", "unknown", "No idea what this Qt Version is meant for!");
return QCoreApplication::translate("QtVersion", "Qt version %1, using mkspec %2 (%3)")
.arg(qtVersionString(), mkspec(), envs);
}
diff --git a/src/plugins/qt4projectmanager/qtversionmanager.ui b/src/plugins/qt4projectmanager/qtversionmanager.ui
index 626d52587b..12db10607b 100644
--- a/src/plugins/qt4projectmanager/qtversionmanager.ui
+++ b/src/plugins/qt4projectmanager/qtversionmanager.ui
@@ -80,6 +80,13 @@
</property>
</spacer>
</item>
+ <item>
+ <widget class="QPushButton" name="cleanUpButton">
+ <property name="text">
+ <string>Clean up</string>
+ </property>
+ </widget>
+ </item>
</layout>
</item>
</layout>
diff --git a/src/plugins/qt4projectmanager/wizards/qtquickapp.h b/src/plugins/qt4projectmanager/wizards/qtquickapp.h
index 80f8d4491f..bcffa0196a 100644
--- a/src/plugins/qt4projectmanager/wizards/qtquickapp.h
+++ b/src/plugins/qt4projectmanager/wizards/qtquickapp.h
@@ -42,6 +42,7 @@ namespace Qt4ProjectManager {
namespace Internal {
class QtQuickApp;
+struct QmlCppPlugin;
struct QmlModule
{
@@ -63,7 +64,7 @@ struct QmlModule
const QFileInfo qmldir; // 'qmldir' file.
const bool isExternal; // Either external or inside a source paths
const QtQuickApp *qtQuickApp;
- QHash<QString, struct QmlCppPlugin*> cppPlugins; // Just as info. No ownership.
+ QHash<QString, QmlCppPlugin *> cppPlugins; // Just as info. No ownership.
};
struct QmlCppPlugin
@@ -151,8 +152,8 @@ private:
QFileInfo m_mainQmlFile;
Mode m_mainQmlMode;
QStringList m_importPaths;
- QList <QmlModule*> m_modules;
- QList <QmlCppPlugin*> m_cppPlugins;
+ QList<QmlModule *> m_modules;
+ QList<QmlCppPlugin *> m_cppPlugins;
};
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/wizards/targetsetuppage.ui b/src/plugins/qt4projectmanager/wizards/targetsetuppage.ui
index 6ef953889f..ad853261dd 100644
--- a/src/plugins/qt4projectmanager/wizards/targetsetuppage.ui
+++ b/src/plugins/qt4projectmanager/wizards/targetsetuppage.ui
@@ -17,7 +17,11 @@
<item>
<widget class="QLabel" name="noValidQtVersionsLabel">
<property name="text">
- <string>&lt;b&gt;No valid qt versions found.&lt;/b&gt;&lt;br&gt; Please add a qt version in Tools/Options or via the maintenance tool of the SDK.</string>
+ <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:'DejaVu Sans'; font-size:9pt; 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;&lt;span style=&quot; font-weight:600;&quot;&gt;No valid qt versions found.&lt;/span&gt;&lt;br /&gt;Please add a Qt version in Tools/Options or via the maintenance tool of the SDK.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
diff --git a/src/plugins/resourceeditor/resourceeditorfactory.cpp b/src/plugins/resourceeditor/resourceeditorfactory.cpp
index 424eaf8e52..95baed0d53 100644
--- a/src/plugins/resourceeditor/resourceeditorfactory.cpp
+++ b/src/plugins/resourceeditor/resourceeditorfactory.cpp
@@ -47,7 +47,6 @@ using namespace ResourceEditor::Constants;
ResourceEditorFactory::ResourceEditorFactory(ResourceEditorPlugin *plugin) :
Core::IEditorFactory(plugin),
m_mimeTypes(QStringList(QLatin1String("application/vnd.nokia.xml.qt.resource"))),
- m_context(ResourceEditor::Constants::C_RESOURCEEDITOR),
m_plugin(plugin)
{
Core::FileIconProvider *iconProvider = Core::FileIconProvider::instance();
@@ -77,7 +76,8 @@ Core::IFile *ResourceEditorFactory::open(const QString &fileName)
Core::IEditor *ResourceEditorFactory::createEditor(QWidget *parent)
{
- return new ResourceEditorW(m_context, m_plugin, parent);
+ Core::Context context(ResourceEditor::Constants::C_RESOURCEEDITOR);
+ return new ResourceEditorW(context, m_plugin, parent);
}
QStringList ResourceEditorFactory::mimeTypes() const
diff --git a/src/plugins/resourceeditor/resourceeditorfactory.h b/src/plugins/resourceeditor/resourceeditorfactory.h
index a335712aa6..08d81bd01e 100644
--- a/src/plugins/resourceeditor/resourceeditorfactory.h
+++ b/src/plugins/resourceeditor/resourceeditorfactory.h
@@ -60,8 +60,6 @@ public:
private:
const QStringList m_mimeTypes;
- const Core::Context m_context;
-
ResourceEditorPlugin *m_plugin;
};
diff --git a/src/plugins/resourceeditor/resourceeditorw.cpp b/src/plugins/resourceeditor/resourceeditorw.cpp
index d23d18d138..a74735636c 100644
--- a/src/plugins/resourceeditor/resourceeditorw.cpp
+++ b/src/plugins/resourceeditor/resourceeditorw.cpp
@@ -72,11 +72,13 @@ QString ResourceEditorFile::mimeType() const
ResourceEditorW::ResourceEditorW(const Core::Context &context,
ResourceEditorPlugin *plugin,
QWidget *parent)
- : m_context(context),
- m_resourceEditor(new SharedTools::QrcEditor(parent)),
+ : m_resourceEditor(new SharedTools::QrcEditor(parent)),
m_resourceFile(new ResourceEditorFile(this)),
m_plugin(plugin)
{
+ setContext(context);
+ setWidget(m_resourceEditor);
+
m_resourceEditor->setResourceDragEnabled(true);
connect(m_resourceEditor, SIGNAL(dirtyChanged(bool)), this, SLOT(dirtyChanged(bool)));
@@ -241,11 +243,6 @@ void ResourceEditorW::dirtyChanged(bool dirty)
emit changed();
}
-QWidget *ResourceEditorW::widget()
-{
- return m_resourceEditor; /* we know it's a subclass of QWidget...*/
-}
-
void ResourceEditorW::onUndoStackChanged(bool canUndo, bool canRedo)
{
m_plugin->onUndoStackChanged(this, canUndo, canRedo);
diff --git a/src/plugins/resourceeditor/resourceeditorw.h b/src/plugins/resourceeditor/resourceeditorw.h
index 0d2809b075..cd017b44cf 100644
--- a/src/plugins/resourceeditor/resourceeditorw.h
+++ b/src/plugins/resourceeditor/resourceeditorw.h
@@ -97,10 +97,6 @@ public:
QByteArray saveState() const { return QByteArray(); }
bool restoreState(const QByteArray &/*state*/) { return true; }
- // ContextInterface
- Core::Context context() const { return m_context; }
- QWidget *widget();
-
void setSuggestedFileName(const QString &fileName);
bool isTemporary() const { return false; }
@@ -113,7 +109,6 @@ private:
const QString m_fileFilter;
QString m_displayName;
QString m_suggestedName;
- const Core::Context m_context;
QPointer<SharedTools::QrcEditor> m_resourceEditor;
ResourceEditorFile *m_resourceFile;
ResourceEditorPlugin *m_plugin;
diff --git a/src/plugins/subversion/subversionconstants.h b/src/plugins/subversion/subversionconstants.h
index f98c9ddba2..cb299c7cd9 100644
--- a/src/plugins/subversion/subversionconstants.h
+++ b/src/plugins/subversion/subversionconstants.h
@@ -39,9 +39,6 @@ namespace Subversion {
namespace Constants {
const char * const SUBVERSION_SUBMIT_MIMETYPE = "application/vnd.nokia.text.subversion.submit";
-const char * const SUBVERSIONEDITOR = "Subversion Editor";
-const char * const SUBVERSIONEDITOR_ID = "Subversion Editor";
-const char * const SUBVERSIONEDITOR_DISPLAY_NAME = QT_TRANSLATE_NOOP("VCS", "Subversion Editor");
const char * const SUBVERSIONCOMMITEDITOR = "Subversion Commit Editor";
const char * const SUBVERSIONCOMMITEDITOR_ID = "Subversion Commit Editor";
const char * const SUBVERSIONCOMMITEDITOR_DISPLAY_NAME = QT_TRANSLATE_NOOP("VCS", "Subversion Commit Editor");
diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp
index f044427370..6a5dba9f97 100644
--- a/src/plugins/subversion/subversionplugin.cpp
+++ b/src/plugins/subversion/subversionplugin.cpp
@@ -44,6 +44,7 @@
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/basevcssubmiteditorfactory.h>
#include <vcsbase/vcsbaseoutputwindow.h>
+#include <vcsbase/vcsbaseeditorparameterwidget.h>
#include <utils/synchronousprocess.h>
#include <utils/parameteraction.h>
@@ -79,7 +80,8 @@
#include <QtXml/QXmlStreamReader>
#include <limits.h>
-using namespace Subversion::Internal;
+namespace Subversion {
+namespace Internal {
static const char * const CMD_ID_SUBVERSION_MENU = "Subversion.Menu";
static const char * const CMD_ID_ADD = "Subversion.Add";
@@ -150,14 +152,6 @@ static inline QString debugCodec(const QTextCodec *c)
return c ? QString::fromAscii(c->name()) : QString::fromAscii("Null codec");
}
-Core::IEditor* locateEditor(const char *property, const QString &entry)
-{
- foreach (Core::IEditor *ed, Core::EditorManager::instance()->openedEditors())
- if (ed->property(property).toString() == entry)
- return ed;
- return 0;
-}
-
// Parse "svn status" output for added/modified/deleted files
// "M<7blanks>file"
typedef QList<SubversionSubmitEditor::StatusFilePair> StatusList;
@@ -533,6 +527,51 @@ void SubversionPlugin::diffCommitFiles(const QStringList &files)
svnDiff(m_commitRepository, files);
}
+// Collect all parameters required for a diff to be able to associate them
+// with a diff editor and re-run the diff with parameters.
+struct SubversionDiffParameters
+{
+ QString workingDir;
+ QStringList arguments;
+ QStringList files;
+ QString diffName;
+};
+
+// Parameter widget controlling whitespace diff mode, associated with a parameter
+class SubversionDiffParameterWidget : public VCSBase::VCSBaseEditorParameterWidget
+{
+ Q_OBJECT
+public:
+ explicit SubversionDiffParameterWidget(const SubversionDiffParameters &p, QWidget *parent = 0);
+
+signals:
+ void reRunDiff(const Subversion::Internal::SubversionDiffParameters &);
+
+private slots:
+ void triggerReRun();
+
+private:
+ const SubversionDiffParameters m_parameters;
+};
+
+SubversionDiffParameterWidget::SubversionDiffParameterWidget(const SubversionDiffParameters &p, QWidget *parent) :
+ VCSBase::VCSBaseEditorParameterWidget(parent), m_parameters(p)
+{
+ setBaseArguments(p.arguments);
+ addIgnoreWhiteSpaceButton(QString(QLatin1Char('w')));
+ connect(this, SIGNAL(argumentsChanged()), this, SLOT(triggerReRun()));
+}
+
+void SubversionDiffParameterWidget::triggerReRun()
+{
+ SubversionDiffParameters effectiveParameters = m_parameters;
+ // Subversion wants" -x -<ext-args>", default being -u
+ const QStringList a = arguments();
+ if (!a.isEmpty())
+ effectiveParameters.arguments << QLatin1String("-x") << (QLatin1String("-u") + a.join(QString()));
+ emit reRunDiff(effectiveParameters);
+}
+
static inline void setDiffBaseDirectory(Core::IEditor *editor, const QString &db)
{
if (VCSBase::VCSBaseEditorWidget *ve = qobject_cast<VCSBase::VCSBaseEditorWidget*>(editor->widget()))
@@ -541,38 +580,58 @@ static inline void setDiffBaseDirectory(Core::IEditor *editor, const QString &db
void SubversionPlugin::svnDiff(const QString &workingDir, const QStringList &files, QString diffname)
{
+ SubversionDiffParameters p;
+ p.workingDir = workingDir;
+ p.files = files;
+ p.diffName = diffname;
+ svnDiff(p);
+}
+
+void SubversionPlugin::svnDiff(const Subversion::Internal::SubversionDiffParameters &p)
+{
if (Subversion::Constants::debug)
- qDebug() << Q_FUNC_INFO << files << diffname;
- const QString source = VCSBase::VCSBaseEditorWidget::getSource(workingDir, files);
+ qDebug() << Q_FUNC_INFO << p.files << p.diffName;
+ const QString source = VCSBase::VCSBaseEditorWidget::getSource(p.workingDir, p.files);
QTextCodec *codec = source.isEmpty() ? static_cast<QTextCodec *>(0) : VCSBase::VCSBaseEditorWidget::getCodec(source);
- if (files.count() == 1 && diffname.isEmpty())
- diffname = QFileInfo(files.front()).fileName();
+ const QString diffName = p.files.count() == 1 && p.diffName.isEmpty() ?
+ QFileInfo(p.files.front()).fileName() : p.diffName;
QStringList args(QLatin1String("diff"));
- args << files;
+ args.append(p.arguments);
+ args << p.files;
const SubversionResponse response =
- runSvn(workingDir, args, m_settings.timeOutMS(), 0, codec);
+ runSvn(p.workingDir, args, m_settings.timeOutMS(), 0, codec);
if (response.error)
return;
// diff of a single file? re-use an existing view if possible to support
// the common usage pattern of continuously changing and diffing a file
- if (files.count() == 1) {
- // Show in the same editor if diff has been executed before
- if (Core::IEditor *editor = locateEditor("originalFileName", files.front())) {
- editor->createNew(response.stdOut);
- Core::EditorManager::instance()->activateEditor(editor, Core::EditorManager::ModeSwitch);
- setDiffBaseDirectory(editor, workingDir);
- return;
- }
+ const QString tag = VCSBase::VCSBaseEditorWidget::editorTag(VCSBase::DiffOutput, p.workingDir, p.files);
+ // Show in the same editor if diff has been executed before
+ if (Core::IEditor *existingEditor = VCSBase::VCSBaseEditorWidget::locateEditorByTag(tag)) {
+ existingEditor->createNew(response.stdOut);
+ Core::EditorManager::instance()->activateEditor(existingEditor, Core::EditorManager::ModeSwitch);
+ setDiffBaseDirectory(existingEditor, p.workingDir);
+ return;
}
- const QString title = QString::fromLatin1("svn diff %1").arg(diffname);
+ const QString title = QString::fromLatin1("svn diff %1").arg(diffName);
Core::IEditor *editor = showOutputInEditor(title, response.stdOut, VCSBase::DiffOutput, source, codec);
- setDiffBaseDirectory(editor, workingDir);
- if (files.count() == 1)
- editor->setProperty("originalFileName", files.front());
+ setDiffBaseDirectory(editor, p.workingDir);
+ VCSBase::VCSBaseEditorWidget::tagEditor(editor, tag);
+ SubversionEditor *diffEditorWidget = qobject_cast<SubversionEditor *>(editor->widget());
+ QTC_ASSERT(diffEditorWidget, return ; )
+
+ // Wire up the parameter widget to trigger a re-run on
+ // parameter change and 'revert' from inside the diff editor.
+ diffEditorWidget->setRevertDiffChunkEnabled(true);
+ SubversionDiffParameterWidget *pw = new SubversionDiffParameterWidget(p);
+ connect(pw, SIGNAL(reRunDiff(Subversion::Internal::SubversionDiffParameters)),
+ this, SLOT(svnDiff(Subversion::Internal::SubversionDiffParameters)));
+ connect(diffEditorWidget, SIGNAL(diffChunkReverted(VCSBase::DiffChunk)),
+ pw, SLOT(triggerReRun()));
+ diffEditorWidget->setConfigurationWidget(pw);
}
SubversionSubmitEditor *SubversionPlugin::openSubversionSubmitEditor(const QString &fileName)
@@ -864,14 +923,15 @@ void SubversionPlugin::filelog(const QString &workingDir,
// the common usage pattern of continuously changing and diffing a file
const QString id = VCSBase::VCSBaseEditorWidget::getTitleId(workingDir, files);
- if (Core::IEditor *editor = locateEditor("logFileName", id)) {
+ const QString tag = VCSBase::VCSBaseEditorWidget::editorTag(VCSBase::LogOutput, workingDir, files);
+ if (Core::IEditor *editor = VCSBase::VCSBaseEditorWidget::locateEditorByTag(tag)) {
editor->createNew(response.stdOut);
Core::EditorManager::instance()->activateEditor(editor, Core::EditorManager::ModeSwitch);
} else {
const QString title = QString::fromLatin1("svn log %1").arg(id);
const QString source = VCSBase::VCSBaseEditorWidget::getSource(workingDir, files);
Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::LogOutput, source, /*codec*/0);
- newEditor->setProperty("logFileName", id);
+ VCSBase::VCSBaseEditorWidget::tagEditor(newEditor, tag);
if (enableAnnotationContextMenu)
VCSBase::VCSBaseEditorWidget::getVcsBaseEditor(newEditor)->setFileLogAnnotateEnabled(true);
}
@@ -938,16 +998,17 @@ void SubversionPlugin::vcsAnnotate(const QString &workingDir, const QString &fil
if (lineNumber <= 0)
lineNumber = VCSBase::VCSBaseEditorWidget::lineNumberOfCurrentEditor(source);
// Determine id
- const QString id = VCSBase::VCSBaseEditorWidget::getTitleId(workingDir, QStringList(file), revision);
-
- if (Core::IEditor *editor = locateEditor("annotateFileName", id)) {
+ const QStringList files = QStringList(file);
+ const QString id = VCSBase::VCSBaseEditorWidget::getTitleId(workingDir, files, revision);
+ const QString tag = VCSBase::VCSBaseEditorWidget::editorTag(VCSBase::AnnotateOutput, workingDir, files);
+ if (Core::IEditor *editor = VCSBase::VCSBaseEditorWidget::locateEditorByTag(tag)) {
editor->createNew(response.stdOut);
VCSBase::VCSBaseEditorWidget::gotoLineOfEditor(editor, lineNumber);
Core::EditorManager::instance()->activateEditor(editor, Core::EditorManager::ModeSwitch);
} else {
const QString title = QString::fromLatin1("svn annotate %1").arg(id);
Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::AnnotateOutput, source, codec);
- newEditor->setProperty("annotateFileName", id);
+ VCSBase::VCSBaseEditorWidget::tagEditor(newEditor, tag);
VCSBase::VCSBaseEditorWidget::gotoLineOfEditor(newEditor, lineNumber);
}
}
@@ -1005,13 +1066,14 @@ void SubversionPlugin::describe(const QString &source, const QString &changeNr)
// Re-use an existing view if possible to support
// the common usage pattern of continuously changing and diffing a file
const QString id = diffArg + source;
- if (Core::IEditor *editor = locateEditor("describeChange", id)) {
+ const QString tag = VCSBase::VCSBaseEditorWidget::editorTag(VCSBase::DiffOutput, source, QStringList(), changeNr);
+ if (Core::IEditor *editor = VCSBase::VCSBaseEditorWidget::locateEditorByTag(tag)) {
editor->createNew(description);
Core::EditorManager::instance()->activateEditor(editor, Core::EditorManager::ModeSwitch);
} else {
const QString title = QString::fromLatin1("svn describe %1#%2").arg(fi.fileName(), changeNr);
Core::IEditor *newEditor = showOutputInEditor(title, description, VCSBase::DiffOutput, source, codec);
- newEditor->setProperty("describeChange", id);
+ VCSBase::VCSBaseEditorWidget::tagEditor(newEditor, tag);
}
}
@@ -1349,4 +1411,9 @@ SubversionControl *SubversionPlugin::subVersionControl() const
return static_cast<SubversionControl *>(versionControl());
}
-Q_EXPORT_PLUGIN(SubversionPlugin)
+} // Internal
+} // Subversion
+
+Q_EXPORT_PLUGIN(Subversion::Internal::SubversionPlugin)
+
+#include "subversionplugin.moc"
diff --git a/src/plugins/subversion/subversionplugin.h b/src/plugins/subversion/subversionplugin.h
index da2bff2686..ac6485e2b8 100644
--- a/src/plugins/subversion/subversionplugin.h
+++ b/src/plugins/subversion/subversionplugin.h
@@ -65,6 +65,7 @@ namespace Internal {
class SubversionSubmitEditor;
class SubversionControl;
+struct SubversionDiffParameters;
struct SubversionResponse
{
@@ -112,6 +113,7 @@ public:
public slots:
void vcsAnnotate(const QString &workingDir, const QString &file,
const QString &revision = QString(), int lineNumber = -1);
+ void svnDiff(const Subversion::Internal::SubversionDiffParameters &p);
private slots:
void addCurrentFile();
diff --git a/src/plugins/texteditor/basetextdocument.cpp b/src/plugins/texteditor/basetextdocument.cpp
index 5f0e83e23c..ecad01b2ac 100644
--- a/src/plugins/texteditor/basetextdocument.cpp
+++ b/src/plugins/texteditor/basetextdocument.cpp
@@ -83,6 +83,8 @@ class DocumentMarker : public ITextMarkable
public:
DocumentMarker(QTextDocument *);
+ TextMarks marks() const { return m_marksCache; }
+
// ITextMarkable
bool addMark(ITextMark *mark, int line);
TextMarks marksAt(int line) const;
@@ -91,6 +93,9 @@ public:
void updateMark(ITextMark *mark);
private:
+ double recalculateMaxMarkWidthFactor() const;
+
+ TextMarks m_marksCache; // not owned
QTextDocument *document;
};
@@ -103,22 +108,34 @@ bool DocumentMarker::addMark(TextEditor::ITextMark *mark, int line)
{
QTC_ASSERT(line >= 1, return false);
int blockNumber = line - 1;
- BaseTextDocumentLayout *documentLayout = qobject_cast<BaseTextDocumentLayout*>(document->documentLayout());
+ BaseTextDocumentLayout *documentLayout =
+ qobject_cast<BaseTextDocumentLayout*>(document->documentLayout());
QTC_ASSERT(documentLayout, return false);
QTextBlock block = document->findBlockByNumber(blockNumber);
if (block.isValid()) {
TextBlockUserData *userData = BaseTextDocumentLayout::userData(block);
userData->addMark(mark);
+ m_marksCache.append(mark);
mark->updateLineNumber(blockNumber + 1);
mark->updateBlock(block);
documentLayout->hasMarks = true;
+ documentLayout->maxMarkWidthFactor = qMax(mark->widthFactor(),
+ documentLayout->maxMarkWidthFactor);
documentLayout->requestUpdate();
return true;
}
return false;
}
+double DocumentMarker::recalculateMaxMarkWidthFactor() const
+{
+ double maxWidthFactor = 1.0;
+ foreach (const ITextMark *mark, marks())
+ maxWidthFactor = qMax(mark->widthFactor(), maxWidthFactor);
+ return maxWidthFactor;
+}
+
TextEditor::TextMarks DocumentMarker::marksAt(int line) const
{
QTC_ASSERT(line >= 1, return TextMarks());
@@ -134,6 +151,10 @@ TextEditor::TextMarks DocumentMarker::marksAt(int line) const
void DocumentMarker::removeMark(TextEditor::ITextMark *mark)
{
+ BaseTextDocumentLayout *documentLayout =
+ qobject_cast<BaseTextDocumentLayout*>(document->documentLayout());
+ QTC_ASSERT(documentLayout, return)
+
bool needUpdate = false;
QTextBlock block = document->begin();
while (block.isValid()) {
@@ -142,8 +163,12 @@ void DocumentMarker::removeMark(TextEditor::ITextMark *mark)
}
block = block.next();
}
- if (needUpdate)
+ m_marksCache.removeAll(mark);
+
+ if (needUpdate) {
+ documentLayout->maxMarkWidthFactor = recalculateMaxMarkWidthFactor();
updateMark(0);
+ }
}
bool DocumentMarker::hasMark(TextEditor::ITextMark *mark) const
@@ -162,7 +187,8 @@ bool DocumentMarker::hasMark(TextEditor::ITextMark *mark) const
void DocumentMarker::updateMark(ITextMark *mark)
{
Q_UNUSED(mark)
- BaseTextDocumentLayout *documentLayout = qobject_cast<BaseTextDocumentLayout*>(document->documentLayout());
+ BaseTextDocumentLayout *documentLayout =
+ qobject_cast<BaseTextDocumentLayout*>(document->documentLayout());
QTC_ASSERT(documentLayout, return);
documentLayout->requestUpdate();
}
diff --git a/src/plugins/texteditor/basetextdocumentlayout.cpp b/src/plugins/texteditor/basetextdocumentlayout.cpp
index 118c2eb764..e127710756 100644
--- a/src/plugins/texteditor/basetextdocumentlayout.cpp
+++ b/src/plugins/texteditor/basetextdocumentlayout.cpp
@@ -392,6 +392,7 @@ BaseTextDocumentLayout::BaseTextDocumentLayout(QTextDocument *doc)
:QPlainTextDocumentLayout(doc) {
lastSaveRevision = 0;
hasMarks = 0;
+ maxMarkWidthFactor = 1.0;
m_requiredWidth = 0;
}
diff --git a/src/plugins/texteditor/basetextdocumentlayout.h b/src/plugins/texteditor/basetextdocumentlayout.h
index 38eb71da2d..d1dc4e3e9f 100644
--- a/src/plugins/texteditor/basetextdocumentlayout.h
+++ b/src/plugins/texteditor/basetextdocumentlayout.h
@@ -188,6 +188,7 @@ public:
void emitDocumentSizeChanged() { emit documentSizeChanged(documentSize()); }
int lastSaveRevision;
bool hasMarks;
+ double maxMarkWidthFactor;
int m_requiredWidth;
void setRequiredWidth(int width);
diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp
index c66228a7e6..ffb656716a 100644
--- a/src/plugins/texteditor/basetexteditor.cpp
+++ b/src/plugins/texteditor/basetexteditor.cpp
@@ -3558,7 +3558,8 @@ int BaseTextEditorWidget::extraAreaWidth(int *markWidthPtr) const
if (d->m_lineNumbersVisible) {
QFont fnt = d->m_extraArea->font();
- // this works under the assumption that bold or italic can only make a font wider
+ // this works under the assumption that bold or italic
+ // can only make a font wider
fnt.setBold(d->m_currentLineNumberFormat.font().bold());
fnt.setItalic(d->m_currentLineNumberFormat.font().italic());
const QFontMetrics linefm(fnt);
@@ -3574,7 +3575,8 @@ int BaseTextEditorWidget::extraAreaWidth(int *markWidthPtr) const
int markWidth = 0;
if (d->m_marksVisible) {
- markWidth += fm.lineSpacing();
+ markWidth += documentLayout->maxMarkWidthFactor * fm.lineSpacing();
+
// if (documentLayout->doubleMarkCount)
// markWidth += fm.lineSpacing() / 3;
space += markWidth;
@@ -3708,11 +3710,11 @@ void BaseTextEditorWidget::extraAreaPaintEvent(QPaintEvent *e)
if (TextBlockUserData *userData = static_cast<TextBlockUserData*>(block.userData())) {
if (d->m_marksVisible) {
int xoffset = 0;
- foreach (ITextMark *mrk, userData->marks()) {
- int x = 0;
- int radius = fmLineSpacing - 1;
- QRect r(x + xoffset, top, radius, radius);
- mrk->icon().paint(&painter, r, Qt::AlignCenter);
+ foreach (ITextMark *mark, userData->marks()) {
+ const int height = fmLineSpacing - 1;
+ const int width = int(.5 + height * mark->widthFactor());
+ const QRect r(xoffset, top, width, height);
+ mark->paint(&painter, r);
xoffset += 2;
}
}
@@ -4362,34 +4364,41 @@ void BaseTextEditorWidget::indentOrUnindent(bool doIndent)
QTextBlock startBlock = doc->findBlock(start);
QTextBlock endBlock = doc->findBlock(end-1).next();
- for (QTextBlock block = startBlock; block != endBlock; block = block.next()) {
- QString text = block.text();
- int indentPosition = tabSettings.lineIndentPosition(text);
- if (!doIndent && !indentPosition)
- indentPosition = tabSettings.firstNonSpace(text);
- int targetColumn = tabSettings.indentedColumn(tabSettings.columnAt(text, indentPosition), doIndent);
- cursor.setPosition(block.position() + indentPosition);
- cursor.insertText(tabSettings.indentationString(0, targetColumn, block));
- cursor.setPosition(block.position());
- cursor.setPosition(block.position() + indentPosition, QTextCursor::KeepAnchor);
+ if (startBlock.next() == endBlock
+ && (start > startBlock.position() || end < endBlock.position() - 1)) {
+ // Only one line partially selected.
cursor.removeSelectedText();
+ } else {
+ for (QTextBlock block = startBlock; block != endBlock; block = block.next()) {
+ QString text = block.text();
+ int indentPosition = tabSettings.lineIndentPosition(text);
+ if (!doIndent && !indentPosition)
+ indentPosition = tabSettings.firstNonSpace(text);
+ int targetColumn = tabSettings.indentedColumn(tabSettings.columnAt(text, indentPosition), doIndent);
+ cursor.setPosition(block.position() + indentPosition);
+ cursor.insertText(tabSettings.indentationString(0, targetColumn, block));
+ cursor.setPosition(block.position());
+ cursor.setPosition(block.position() + indentPosition, QTextCursor::KeepAnchor);
+ cursor.removeSelectedText();
+ }
+ cursor.endEditBlock();
+ return;
}
- cursor.endEditBlock();
- } else {
- // Indent or unindent at cursor position
- QTextBlock block = cursor.block();
- QString text = block.text();
- int indentPosition = cursor.positionInBlock();
- int spaces = tabSettings.spacesLeftFromPosition(text, indentPosition);
- int startColumn = tabSettings.columnAt(text, indentPosition - spaces);
- int targetColumn = tabSettings.indentedColumn(tabSettings.columnAt(text, indentPosition), doIndent);
- cursor.setPosition(block.position() + indentPosition);
- cursor.setPosition(block.position() + indentPosition - spaces, QTextCursor::KeepAnchor);
- cursor.removeSelectedText();
- cursor.insertText(tabSettings.indentationString(startColumn, targetColumn, block));
- cursor.endEditBlock();
- setTextCursor(cursor);
}
+
+ // Indent or unindent at cursor position
+ QTextBlock block = cursor.block();
+ QString text = block.text();
+ int indentPosition = cursor.positionInBlock();
+ int spaces = tabSettings.spacesLeftFromPosition(text, indentPosition);
+ int startColumn = tabSettings.columnAt(text, indentPosition - spaces);
+ int targetColumn = tabSettings.indentedColumn(tabSettings.columnAt(text, indentPosition), doIndent);
+ cursor.setPosition(block.position() + indentPosition);
+ cursor.setPosition(block.position() + indentPosition - spaces, QTextCursor::KeepAnchor);
+ cursor.removeSelectedText();
+ cursor.insertText(tabSettings.indentationString(startColumn, targetColumn, block));
+ cursor.endEditBlock();
+ setTextCursor(cursor);
}
void BaseTextEditorWidget::handleHomeKey(bool anchor)
@@ -5023,6 +5032,15 @@ void BaseTextEditorWidget::cutLine()
cut();
}
+// ctrl+ins
+void BaseTextEditorWidget::copyLine()
+{
+ QTextCursor prevCursor = textCursor();
+ maybeSelectLine();
+ copy();
+ setTextCursor(prevCursor);
+}
+
void BaseTextEditorWidget::deleteLine()
{
maybeSelectLine();
@@ -5762,6 +5780,7 @@ void BaseTextEditorWidget::appendStandardContextMenuActions(QMenu *menu)
BaseTextEditor::BaseTextEditor(BaseTextEditorWidget *editor)
: e(editor)
{
+ setWidget(e);
using namespace Find;
Aggregation::Aggregate *aggregate = new Aggregation::Aggregate;
BaseTextFind *baseTextFind = new BaseTextFind(editor);
@@ -6140,3 +6159,8 @@ void BaseTextEditorWidget::transformSelection(Internal::TransformationMethod met
cursor.setPosition(pos, QTextCursor::KeepAnchor);
setTextCursor(cursor);
}
+
+void BaseTextEditorWidget::inSnippetMode(bool *active)
+{
+ *active = d->m_snippetOverlay->isVisible();
+}
diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h
index 6edc31474a..61727fd46c 100644
--- a/src/plugins/texteditor/basetexteditor.h
+++ b/src/plugins/texteditor/basetexteditor.h
@@ -246,6 +246,7 @@ public slots:
void zoomReset();
void cutLine();
+ void copyLine();
void deleteLine();
void unfoldAll();
void fold();
@@ -343,6 +344,7 @@ private slots:
bool inFindScope(const QTextCursor &cursor);
bool inFindScope(int selectionStart, int selectionEnd);
void currentEditorChanged(Core::IEditor *editor);
+ void inSnippetMode(bool *active);
private:
Internal::BaseTextEditorPrivate *d;
@@ -555,7 +557,7 @@ public:
BaseTextEditorWidget *editorWidget() const { return e; }
// EditorInterface
- QWidget *widget() { return e; }
+ //QWidget *widget() { return e; }
Core::IFile * file() { return e->file(); }
bool createNew(const QString &contents) { return e->createNew(contents); }
bool open(const QString &fileName = QString()) { return e->open(fileName); }
diff --git a/src/plugins/texteditor/basetextmark.cpp b/src/plugins/texteditor/basetextmark.cpp
index 5884ce4f64..f6a9f9efad 100644
--- a/src/plugins/texteditor/basetextmark.cpp
+++ b/src/plugins/texteditor/basetextmark.cpp
@@ -41,72 +41,34 @@
#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);
- }
-
- virtual Priority priority() const
- {
- return m_parent->priority();
- }
-private:
- BaseTextMark *m_parent;
-};
-
-} // namespace Internal
-
-BaseTextMark::BaseTextMark(const QString &filename, int line)
- : m_markableInterface(0)
- , m_internalMark(0)
- , m_fileName(filename)
- , m_line(line)
- , m_init(false)
-{
- // Why is this?
- QTimer::singleShot(0, this, SLOT(init()));
-}
+BaseTextMark::BaseTextMark()
+ : m_markableInterface(0), m_init(false)
+{}
BaseTextMark::~BaseTextMark()
{
// oha we are deleted
if (m_markableInterface)
- m_markableInterface->removeMark(m_internalMark);
+ m_markableInterface->removeMark(this);
removeInternalMark();
}
+void BaseTextMark::setLocation(const QString &fileName, int line)
+{
+ m_fileName = fileName;
+ m_line = line;
+ //init();
+ // This basically mimics 'two phase initialization'
+ QTimer::singleShot(0, this, SLOT(init()));
+}
+
void BaseTextMark::init()
{
m_init = true;
Core::EditorManager *em = Core::EditorManager::instance();
- connect(em, SIGNAL(editorOpened(Core::IEditor *)), this, SLOT(editorOpened(Core::IEditor *)));
+ connect(em, SIGNAL(editorOpened(Core::IEditor *)),
+ SLOT(editorOpened(Core::IEditor *)));
foreach (Core::IEditor *editor, em->openedEditors())
editorOpened(editor);
@@ -124,9 +86,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 Internal::InternalMark(this);
-
- if (m_markableInterface->addMark(m_internalMark, m_line)) {
+ if (m_markableInterface->addMark(this, m_line)) {
// Handle reload of text documents, readding the mark as necessary
connect(textEditor->file(), SIGNAL(reloaded()),
this, SLOT(documentReloaded()), Qt::UniqueConnection);
@@ -147,56 +107,37 @@ void BaseTextMark::documentReloaded()
return;
m_markableInterface = doc->documentMarker();
- m_internalMark = new Internal::InternalMark(this);
- if (!m_markableInterface->addMark(m_internalMark, m_line))
+ if (!m_markableInterface->addMark(this, m_line))
removeInternalMark();
}
-void BaseTextMark::childRemovedFromEditor(Internal::InternalMark *mark)
-{
- Q_UNUSED(mark)
- // m_internalMark was removed from the editor
- removeInternalMark();
- removedFromEditor();
-}
-
-void BaseTextMark::documentClosingFor(Internal::InternalMark *mark)
-{
- Q_UNUSED(mark)
- removeInternalMark();
-}
-
void BaseTextMark::removeInternalMark()
{
- delete m_internalMark;
- m_internalMark = 0;
m_markableInterface = 0;
}
-//#include <QDebug>
-
void BaseTextMark::updateMarker()
{
- //qDebug()<<"BaseTextMark::updateMarker()"<<m_markableInterface<<m_internalMark;
+ //qDebug()<<"BaseTextMark::updateMarker()"<<m_markableInterface<<this;
if (m_markableInterface)
- m_markableInterface->updateMark(m_internalMark);
+ m_markableInterface->updateMark(this);
}
void BaseTextMark::moveMark(const QString & /* filename */, int /* line */)
{
Core::EditorManager *em = Core::EditorManager::instance();
if (!m_init) {
- connect(em, SIGNAL(editorOpened(Core::IEditor *)), this, SLOT(editorOpened(Core::IEditor *)));
+ connect(em, SIGNAL(editorOpened(Core::IEditor *)),
+ SLOT(editorOpened(Core::IEditor *)));
m_init = true;
}
if (m_markableInterface)
- m_markableInterface->removeMark(m_internalMark);
- // This is only necessary since m_internalMark is created in editorOpened
- removeInternalMark();
+ m_markableInterface->removeMark(this);
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 1ebeacfa68..4f6baf6dbd 100644
--- a/src/plugins/texteditor/basetextmark.h
+++ b/src/plugins/texteditor/basetextmark.h
@@ -36,63 +36,47 @@
#include "texteditor_global.h"
#include "itexteditor.h"
+#include <QtCore/QPointer>
+#include <QtGui/QIcon>
+
QT_BEGIN_NAMESPACE
-class QIcon;
class QTextBlock;
+class QPainter;
QT_END_NAMESPACE
namespace TextEditor {
class ITextMarkable;
-namespace Internal {
-class InternalMark;
-}
-
-class TEXTEDITOR_EXPORT BaseTextMark : public QObject
+class TEXTEDITOR_EXPORT BaseTextMark : public TextEditor::ITextMark
{
- friend class Internal::InternalMark;
Q_OBJECT
public:
- explicit BaseTextMark(const QString &filename, int line);
+ BaseTextMark();
virtual ~BaseTextMark();
- // return your icon here
- virtual QIcon icon() const = 0;
-
- // called if the linenumber changes
- virtual void updateLineNumber(int lineNumber) = 0;
-
- // called whenever the text of the block for the marker changed
- virtual void updateBlock(const QTextBlock &block) = 0;
+ // our location in the "owning" edtitor
+ virtual void setLocation(const QString &fileName, int lineNumber);
- // called if the block containing this mark has been removed
- // if this also removes your mark call this->deleteLater();
- virtual void removedFromEditor() = 0;
// call this if the icon has changed.
void updateMarker();
+
// access to internal data
QString fileName() const { return m_fileName; }
int lineNumber() const { return m_line; }
void moveMark(const QString &filename, int line);
- virtual TextEditor::ITextMark::Priority priority() const = 0;
-
private slots:
void init();
void editorOpened(Core::IEditor *editor);
void documentReloaded();
private:
- void childRemovedFromEditor(Internal::InternalMark *mark);
- void documentClosingFor(Internal::InternalMark *mark);
void removeInternalMark();
- ITextMarkable *m_markableInterface;
- Internal::InternalMark *m_internalMark;
-
+ QPointer<ITextMarkable> m_markableInterface;
QString m_fileName;
int m_line;
bool m_init;
diff --git a/src/plugins/texteditor/itexteditor.cpp b/src/plugins/texteditor/itexteditor.cpp
index b0d440c6b1..e7440b2425 100644
--- a/src/plugins/texteditor/itexteditor.cpp
+++ b/src/plugins/texteditor/itexteditor.cpp
@@ -38,6 +38,48 @@
using namespace TextEditor;
+void ITextMark::paint(QPainter *painter, const QRect &rect) const
+{
+ m_icon.paint(painter, rect, Qt::AlignCenter);
+}
+
+void ITextMark::updateLineNumber(int lineNumber)
+{
+ Q_UNUSED(lineNumber)
+}
+
+void ITextMark::updateBlock(const QTextBlock &)
+{}
+
+void ITextMark::removedFromEditor()
+{}
+
+void ITextMark::documentClosing()
+{}
+
+void ITextMark::setIcon(const QIcon &icon)
+{
+ m_icon = icon;
+}
+
+void ITextMark::setPriority(Priority priority)
+{
+ m_priority = priority;
+}
+
+ITextMark::Priority ITextMark::priority() const
+{
+ return m_priority;
+}
+
+
+double ITextMark::widthFactor() const
+{
+ return 1.0;
+}
+
+
+
QMap<QString, QString> ITextEditor::openedTextEditorsContents()
{
QMap<QString, QString> workingCopy;
diff --git a/src/plugins/texteditor/itexteditor.h b/src/plugins/texteditor/itexteditor.h
index 6c2c5e2f06..6522140ce5 100644
--- a/src/plugins/texteditor/itexteditor.h
+++ b/src/plugins/texteditor/itexteditor.h
@@ -40,13 +40,15 @@
#include <QtCore/QObject>
#include <QtCore/QList>
#include <QtCore/QMap>
+#include <QtGui/QIcon>
QT_BEGIN_NAMESPACE
-class QMenu;
-class QTextBlock;
class QIcon;
-class QRect;
+class QMenu;
+class QPainter;
class QPoint;
+class QRect;
+class QTextBlock;
QT_END_NAMESPACE
namespace TextEditor {
@@ -58,14 +60,6 @@ class TEXTEDITOR_EXPORT ITextMark : public QObject
Q_OBJECT
public:
ITextMark(QObject *parent = 0) : QObject(parent) {}
- virtual ~ITextMark() {}
-
- virtual QIcon icon() const = 0;
-
- virtual void updateLineNumber(int lineNumber) = 0;
- virtual void updateBlock(const QTextBlock &block) = 0;
- virtual void removedFromEditor() = 0;
- virtual void documentClosing() = 0;
// determine order on markers on the same line.
enum Priority
@@ -75,7 +69,19 @@ public:
HighPriority // shown on top.
};
- virtual Priority priority() const = 0;
+ virtual void paint(QPainter *painter, const QRect &rect) const;
+ virtual void updateLineNumber(int lineNumber);
+ virtual void updateBlock(const QTextBlock &block);
+ virtual void removedFromEditor();
+ virtual void documentClosing();
+ virtual void setIcon(const QIcon &icon);
+ virtual Priority priority() const;
+ virtual void setPriority(Priority prioriy);
+ virtual double widthFactor() const;
+
+private:
+ QIcon m_icon;
+ Priority m_priority;
};
typedef QList<ITextMark *> TextMarks;
@@ -86,9 +92,8 @@ class TEXTEDITOR_EXPORT ITextMarkable : public QObject
Q_OBJECT
public:
ITextMarkable(QObject *parent = 0) : QObject(parent) {}
- virtual ~ITextMarkable() {}
- virtual bool addMark(ITextMark *mark, int line) = 0;
+ virtual bool addMark(ITextMark *mark, int line) = 0;
virtual TextMarks marksAt(int line) const = 0;
virtual void removeMark(ITextMark *mark) = 0;
virtual bool hasMark(ITextMark *mark) const = 0;
@@ -108,10 +113,8 @@ public:
};
ITextEditor() {}
- virtual ~ITextEditor() {}
virtual int find(const QString &string) const = 0;
-
virtual int position(PositionOperation posOp = Current, int at = -1) const = 0;
virtual void convertPosition(int pos, int *line, int *column) const = 0;
virtual QRect cursorRect(int pos = -1) const = 0;
diff --git a/src/plugins/texteditor/plaintexteditor.cpp b/src/plugins/texteditor/plaintexteditor.cpp
index 89636beff4..d8e9287990 100644
--- a/src/plugins/texteditor/plaintexteditor.cpp
+++ b/src/plugins/texteditor/plaintexteditor.cpp
@@ -58,9 +58,10 @@ using namespace TextEditor;
using namespace TextEditor::Internal;
PlainTextEditor::PlainTextEditor(PlainTextEditorWidget *editor)
- : BaseTextEditor(editor),
- m_context(Core::Constants::K_DEFAULT_TEXT_EDITOR_ID, TextEditor::Constants::C_TEXTEDITOR)
+ : BaseTextEditor(editor)
{
+ setContext(Core::Context(Core::Constants::K_DEFAULT_TEXT_EDITOR_ID,
+ TextEditor::Constants::C_TEXTEDITOR));
}
PlainTextEditorWidget::PlainTextEditorWidget(QWidget *parent)
@@ -83,14 +84,6 @@ PlainTextEditorWidget::PlainTextEditorWidget(QWidget *parent)
connect(Manager::instance(), SIGNAL(mimeTypesRegistered()), this, SLOT(configure()));
}
-PlainTextEditorWidget::~PlainTextEditorWidget()
-{}
-
-Core::Context PlainTextEditor::context() const
-{
- return m_context;
-}
-
Core::IEditor *PlainTextEditor::duplicate(QWidget *parent)
{
PlainTextEditorWidget *newWidget = new PlainTextEditorWidget(parent);
diff --git a/src/plugins/texteditor/plaintexteditor.h b/src/plugins/texteditor/plaintexteditor.h
index 41ea5abe76..8ed0868a4c 100644
--- a/src/plugins/texteditor/plaintexteditor.h
+++ b/src/plugins/texteditor/plaintexteditor.h
@@ -54,15 +54,11 @@ class TEXTEDITOR_EXPORT PlainTextEditor : public BaseTextEditor
Q_OBJECT
public:
PlainTextEditor(PlainTextEditorWidget *);
- Core::Context context() const;
bool duplicateSupported() const { return true; }
Core::IEditor *duplicate(QWidget *parent);
bool isTemporary() const { return false; }
virtual QString id() const;
-
-private:
- const Core::Context m_context;
};
class TEXTEDITOR_EXPORT PlainTextEditorWidget : public BaseTextEditorWidget
@@ -71,7 +67,6 @@ class TEXTEDITOR_EXPORT PlainTextEditorWidget : public BaseTextEditorWidget
public:
PlainTextEditorWidget(QWidget *parent);
- ~PlainTextEditorWidget();
void configure(const Core::MimeType &mimeType);
bool isMissingSyntaxDefinition() const;
diff --git a/src/plugins/texteditor/snippets/snippeteditor.cpp b/src/plugins/texteditor/snippets/snippeteditor.cpp
index 84e047ae01..0b47ece4d6 100644
--- a/src/plugins/texteditor/snippets/snippeteditor.cpp
+++ b/src/plugins/texteditor/snippets/snippeteditor.cpp
@@ -41,13 +41,11 @@
using namespace TextEditor;
-SnippetEditor::SnippetEditor(SnippetEditorWidget *editor) :
- BaseTextEditor(editor),
- m_context(Constants::SNIPPET_EDITOR_ID, Constants::C_TEXTEDITOR)
-{}
-
-SnippetEditor::~SnippetEditor()
-{}
+SnippetEditor::SnippetEditor(SnippetEditorWidget *editor)
+ : BaseTextEditor(editor)
+{
+ setContext(Core::Context(Constants::SNIPPET_EDITOR_ID, Constants::C_TEXTEDITOR));
+}
QString SnippetEditor::id() const
{
@@ -62,9 +60,6 @@ SnippetEditorWidget::SnippetEditorWidget(QWidget *parent) : BaseTextEditorWidget
setParenthesesMatchingEnabled(true);
}
-SnippetEditorWidget::~SnippetEditorWidget()
-{}
-
void SnippetEditorWidget::setSyntaxHighlighter(TextEditor::SyntaxHighlighter *highlighter)
{
baseTextDocument()->setSyntaxHighlighter(highlighter);
diff --git a/src/plugins/texteditor/snippets/snippeteditor.h b/src/plugins/texteditor/snippets/snippeteditor.h
index 3725c47b7d..8fb2deca84 100644
--- a/src/plugins/texteditor/snippets/snippeteditor.h
+++ b/src/plugins/texteditor/snippets/snippeteditor.h
@@ -54,17 +54,11 @@ class TEXTEDITOR_EXPORT SnippetEditor : public BaseTextEditor
public:
SnippetEditor(SnippetEditorWidget *editorWidget);
- virtual ~SnippetEditor();
-
- 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 SnippetEditorWidget : public BaseTextEditorWidget
@@ -73,7 +67,6 @@ class TEXTEDITOR_EXPORT SnippetEditorWidget : public BaseTextEditorWidget
public:
SnippetEditorWidget(QWidget *parent);
- virtual ~SnippetEditorWidget();
void setSyntaxHighlighter(SyntaxHighlighter *highlighter);
diff --git a/src/plugins/texteditor/texteditoractionhandler.cpp b/src/plugins/texteditor/texteditoractionhandler.cpp
index 0c3fb2adbc..83b2c42ff4 100644
--- a/src/plugins/texteditor/texteditoractionhandler.cpp
+++ b/src/plugins/texteditor/texteditoractionhandler.cpp
@@ -76,6 +76,7 @@ TextEditorActionHandler::TextEditorActionHandler(const char *context,
m_foldAction(0),
m_unfoldAction(0),
m_cutLineAction(0),
+ m_copyLineAction(0),
m_deleteLineAction(0),
m_selectEncodingAction(0),
m_increaseFontSizeAction(0),
@@ -200,6 +201,11 @@ void TextEditorActionHandler::createActions()
command->setDefaultKeySequence(QKeySequence(tr("Shift+Del")));
connect(m_cutLineAction, SIGNAL(triggered()), this, SLOT(cutLine()));
+ m_copyLineAction = new QAction(tr("Copy &Line"), this);
+ command = am->registerAction(m_copyLineAction, Constants::COPY_LINE, m_contextId);
+ command->setDefaultKeySequence(QKeySequence(tr("Ctrl+Ins")));
+ connect(m_copyLineAction, SIGNAL(triggered()), this, SLOT(copyLine()));
+
m_deleteLineAction = new QAction(tr("Delete &Line"), this);
command = am->registerAction(m_deleteLineAction, Constants::DELETE_LINE, m_contextId, true);
connect(m_deleteLineAction, SIGNAL(triggered()), this, SLOT(deleteLine()));
@@ -526,6 +532,7 @@ FUNCTION2(selectAllAction, selectAll)
FUNCTION(cleanWhitespace)
FUNCTION(unCommentSelection)
FUNCTION(cutLine)
+FUNCTION(copyLine)
FUNCTION(deleteLine)
FUNCTION(unfoldAll)
FUNCTION(fold)
diff --git a/src/plugins/texteditor/texteditoractionhandler.h b/src/plugins/texteditor/texteditoractionhandler.h
index 150fa7d229..7e0be3c619 100644
--- a/src/plugins/texteditor/texteditoractionhandler.h
+++ b/src/plugins/texteditor/texteditoractionhandler.h
@@ -101,6 +101,7 @@ private slots:
void fold();
void unfold();
void cutLine();
+ void copyLine();
void deleteLine();
void selectEncoding();
void increaseFontSize();
@@ -164,6 +165,7 @@ private:
QAction *m_foldAction;
QAction *m_unfoldAction;
QAction *m_cutLineAction;
+ QAction *m_copyLineAction;
QAction *m_deleteLineAction;
QAction *m_selectEncodingAction;
QAction *m_increaseFontSizeAction;
diff --git a/src/plugins/texteditor/texteditorconstants.h b/src/plugins/texteditor/texteditorconstants.h
index bf0fe45969..6cf4ec0a0a 100644
--- a/src/plugins/texteditor/texteditorconstants.h
+++ b/src/plugins/texteditor/texteditorconstants.h
@@ -45,14 +45,13 @@ const char * const VISUALIZE_WHITESPACE = "TextEditor.VisualizeWhitespace";
const char * const CLEAN_WHITESPACE = "TextEditor.CleanWhitespace";
const char * const TEXT_WRAPPING = "TextEditor.TextWrapping";
const char * const UN_COMMENT_SELECTION = "TextEditor.UnCommentSelection";
-const char * const REFORMAT = "TextEditor.Reformat";
-const char * const FOLD = "TextEditor.Fold";
+const char * const FOLD = "TextEditor.Fold";
const char * const UNFOLD = "TextEditor.Unfold";
-const char * const UNFOLD_ALL = "TextEditor.UnFoldAll";
+const char * const UNFOLD_ALL = "TextEditor.UnFoldAll";
const char * const AUTO_INDENT_SELECTION = "TextEditor.AutoIndentSelection";
const char * const INCREASE_FONT_SIZE = "TextEditor.IncreaseFontSize";
const char * const DECREASE_FONT_SIZE = "TextEditor.DecreaseFontSize";
-const char * const RESET_FONT_SIZE = "TextEditor.ResetFontSize";
+const char * const RESET_FONT_SIZE = "TextEditor.ResetFontSize";
const char * const GOTO_BLOCK_START = "TextEditor.GotoBlockStart";
const char * const GOTO_BLOCK_START_WITH_SELECTION = "TextEditor.GotoBlockStartWithSelection";
const char * const GOTO_BLOCK_END = "TextEditor.GotoBlockEnd";
@@ -69,20 +68,18 @@ const char * const INSERT_LINE_BELOW = "TextEditor.InsertLineBelowCurrentLin
const char * const UPPERCASE_SELECTION = "TextEditor.UppercaseSelection";
const char * const LOWERCASE_SELECTION = "TextEditor.LowercaseSelection";
const char * const CUT_LINE = "TextEditor.CutLine";
+const char * const COPY_LINE = "TextEditor.CopyLine";
const char * const DELETE_LINE = "TextEditor.DeleteLine";
-const char * const DELETE_WORD = "TextEditor.DeleteWord";
const char * const SELECT_ENCODING = "TextEditor.SelectEncoding";
-const char * const REWRAP_PARAGRAPH = "TextEditor.RewrapParagraph";
-const char * const GOTO_OPENING_PARENTHESIS = "TextEditor.GotoOpeningParenthesis";
-const char * const GOTO_CLOSING_PARENTHESIS = "TextEditor.GotoClosingParenthesis";
-const char * const GOTO_LINE_START = "TextEditor.GotoLineStart";
-const char * const GOTO_LINE_END = "TextEditor.GotoLineEnd";
-const char * const GOTO_NEXT_LINE = "TextEditor.GotoNextLine";
-const char * const GOTO_PREVIOUS_LINE = "TextEditor.GotoPreviousLine";
+const char * const REWRAP_PARAGRAPH = "TextEditor.RewrapParagraph";
+const char * const GOTO_LINE_START = "TextEditor.GotoLineStart";
+const char * const GOTO_LINE_END = "TextEditor.GotoLineEnd";
+const char * const GOTO_NEXT_LINE = "TextEditor.GotoNextLine";
+const char * const GOTO_PREVIOUS_LINE = "TextEditor.GotoPreviousLine";
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_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";
@@ -99,7 +96,7 @@ 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";
const char * const TASK_REGISTER_DEFINITIONS = "TextEditor.Task.Register";
-const char * const TASK_OPEN_FILE = "TextEditor.Task.OpenFile";
+const char * const TASK_OPEN_FILE = "TextEditor.Task.OpenFile";
// Text color and style categories
const char * const C_TEXT = "Text";
diff --git a/src/plugins/valgrindtoolbase/valgrindconfigwidget.cpp b/src/plugins/valgrindtoolbase/valgrindconfigwidget.cpp
index e8989e4b92..166b8d0e72 100644
--- a/src/plugins/valgrindtoolbase/valgrindconfigwidget.cpp
+++ b/src/plugins/valgrindtoolbase/valgrindconfigwidget.cpp
@@ -40,7 +40,7 @@
#include <QtCore/QDebug>
-using namespace Analyzer::Internal;
+using namespace Valgrind::Internal;
ValgrindConfigWidget::ValgrindConfigWidget(ValgrindSettings *settings, QWidget *parent)
: QWidget(parent),
diff --git a/src/plugins/valgrindtoolbase/valgrindconfigwidget.h b/src/plugins/valgrindtoolbase/valgrindconfigwidget.h
index 56558c4c85..05ba74349d 100644
--- a/src/plugins/valgrindtoolbase/valgrindconfigwidget.h
+++ b/src/plugins/valgrindtoolbase/valgrindconfigwidget.h
@@ -38,14 +38,12 @@
#include <QtGui/QWidget>
-QT_BEGIN_NAMESPACE
+namespace Valgrind {
+namespace Internal {
+
namespace Ui {
class ValgrindConfigWidget;
}
-QT_END_NAMESPACE
-
-namespace Analyzer {
-namespace Internal {
class ValgrindSettings;
@@ -63,7 +61,6 @@ private:
};
}
-
}
#endif // ANALYZER_INTERNAL_VALGRINDCONFIGWIDGET_H
diff --git a/src/plugins/valgrindtoolbase/valgrindconfigwidget.ui b/src/plugins/valgrindtoolbase/valgrindconfigwidget.ui
index 385dc8043c..2b929bfc4c 100644
--- a/src/plugins/valgrindtoolbase/valgrindconfigwidget.ui
+++ b/src/plugins/valgrindtoolbase/valgrindconfigwidget.ui
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
- <class>ValgrindConfigWidget</class>
- <widget class="QWidget" name="ValgrindConfigWidget">
+ <class>Valgrind::Internal::ValgrindConfigWidget</class>
+ <widget class="QWidget" name="Valgrind::Internal::ValgrindConfigWidget">
<property name="geometry">
<rect>
<x>0</x>
@@ -20,7 +20,7 @@
</sizepolicy>
</property>
<property name="title">
- <string>Common Valgrind Options</string>
+ <string>Generic Settings</string>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
diff --git a/src/plugins/valgrindtoolbase/valgrindengine.cpp b/src/plugins/valgrindtoolbase/valgrindengine.cpp
index c7af2b2dbc..c72b1d4ff3 100644
--- a/src/plugins/valgrindtoolbase/valgrindengine.cpp
+++ b/src/plugins/valgrindtoolbase/valgrindengine.cpp
@@ -45,26 +45,21 @@
#define VALGRIND_DEBUG_OUTPUT 0
using namespace Analyzer;
-using namespace Analyzer::Internal;
+using namespace Valgrind::Internal;
using namespace Utils;
-ValgrindEngine::ValgrindEngine(ProjectExplorer::RunConfiguration *runConfiguration)
- : IAnalyzerEngine(runConfiguration),
+ValgrindEngine::ValgrindEngine(const AnalyzerStartParameters &sp,
+ ProjectExplorer::RunConfiguration *runConfiguration)
+ : IAnalyzerEngine(sp, runConfiguration),
m_settings(0),
m_progress(new QFutureInterface<void>()) ,
m_isStopping(false)
{
- ProjectExplorer::LocalApplicationRunConfiguration *localAppConfig =
- qobject_cast<ProjectExplorer::LocalApplicationRunConfiguration *>(runConfiguration);
+ if (runConfiguration)
+ m_settings = runConfiguration->extraAspect<AnalyzerProjectSettings>();
- m_settings = runConfiguration->extraAspect<AnalyzerProjectSettings>();
- if (!localAppConfig || !m_settings)
- return;
-
- m_workingDirectory = localAppConfig->workingDirectory();
- m_executable = localAppConfig->executable();
- m_commandLineArguments = localAppConfig->commandLineArguments();
- m_environment = localAppConfig->environment();
+ if (!m_settings)
+ m_settings = AnalyzerGlobalSettings::instance();
}
ValgrindEngine::~ValgrindEngine()
@@ -76,7 +71,7 @@ void ValgrindEngine::start()
{
emit starting(this);
- Core::FutureProgress* fp = Core::ICore::instance()->progressManager()->addTask(m_progress->future(),
+ Core::FutureProgress *fp = Core::ICore::instance()->progressManager()->addTask(m_progress->future(),
progressTitle(), "valgrind");
fp->setKeepOnFinish(Core::FutureProgress::DontKeepOnFinish);
m_progress->reportStarted();
@@ -87,13 +82,16 @@ void ValgrindEngine::start()
emit standardOutputReceived(tr("Command-line arguments: %1").arg(m_commandLineArguments));
#endif
- runner()->setWorkingDirectory(m_workingDirectory);
- runner()->setValgrindExecutable(m_settings->subConfig<ValgrindSettings>()->valgrindExecutable());
+ const AnalyzerStartParameters &sp = startParameters();
+ runner()->setWorkingDirectory(sp.workingDirectory);
+ QString valgrindExe = m_settings->subConfig<ValgrindSettings>()->valgrindExecutable();
+ if (!sp.analyzerCmdPrefix.isEmpty())
+ valgrindExe = sp.analyzerCmdPrefix + ' ' + valgrindExe;
+ runner()->setValgrindExecutable(valgrindExe);
runner()->setValgrindArguments(toolArguments());
- runner()->setDebuggeeExecutable(m_executable);
- // note that m_commandLineArguments may contain several arguments in one string
- runner()->setDebuggeeArguments(m_commandLineArguments);
- runner()->setEnvironment(m_environment);
+ runner()->setDebuggeeExecutable(sp.debuggee);
+ runner()->setDebuggeeArguments(sp.debuggeeArgs);
+ runner()->setEnvironment(sp.environment);
connect(runner(), SIGNAL(standardOutputReceived(QByteArray)),
SLOT(receiveStandardOutput(QByteArray)));
@@ -104,7 +102,10 @@ void ValgrindEngine::start()
connect(runner(), SIGNAL(finished()),
SLOT(runnerFinished()));
- runner()->start();
+ if (sp.startMode == StartRemote)
+ runner()->startRemotely(sp.connParams);
+ else
+ runner()->start();
}
void ValgrindEngine::stop()
@@ -115,12 +116,12 @@ void ValgrindEngine::stop()
QString ValgrindEngine::executable() const
{
- return m_executable;
+ return startParameters().debuggee;
}
void ValgrindEngine::runnerFinished()
{
- emit standardOutputReceived(tr("** Analysing finished **"));
+ emit standardOutputReceived(tr("** Analyzing finished **"));
emit finished();
m_progress->reportFinished();
diff --git a/src/plugins/valgrindtoolbase/valgrindengine.h b/src/plugins/valgrindtoolbase/valgrindengine.h
index 0d13a4c0f0..8622cb207d 100644
--- a/src/plugins/valgrindtoolbase/valgrindengine.h
+++ b/src/plugins/valgrindtoolbase/valgrindengine.h
@@ -35,6 +35,8 @@
#ifndef VALGRINDENGINE_H
#define VALGRINDENGINE_H
+#include <analyzerbase/ianalyzerengine.h>
+
#include "valgrindtoolbase_global.h"
#include <analyzerbase/ianalyzerengine.h>
@@ -48,16 +50,18 @@
#include <QtCore/QFutureInterface>
namespace Analyzer {
-
class AnalyzerSettings;
+}
+namespace Valgrind {
namespace Internal {
-class VALGRINDTOOLBASE_EXPORT ValgrindEngine : public IAnalyzerEngine
+class VALGRINDTOOLBASE_EXPORT ValgrindEngine : public Analyzer::IAnalyzerEngine
{
Q_OBJECT
public:
- explicit ValgrindEngine(ProjectExplorer::RunConfiguration *runConfiguration);
+ explicit ValgrindEngine(const Analyzer::AnalyzerStartParameters &sp,
+ ProjectExplorer::RunConfiguration *runConfiguration);
virtual ~ValgrindEngine();
void start();
@@ -70,7 +74,7 @@ protected:
virtual QStringList toolArguments() const = 0;
virtual Valgrind::ValgrindRunner *runner() = 0;
- AnalyzerSettings *m_settings;
+ Analyzer::AnalyzerSettings *m_settings;
QFutureInterface<void> *m_progress;
private slots:
@@ -81,14 +85,10 @@ private slots:
void receiveProcessError(const QString &, QProcess::ProcessError);
private:
- QString m_workingDirectory;
- QString m_executable;
- QString m_commandLineArguments;
- Utils::Environment m_environment;
bool m_isStopping;
};
} // namespace Internal
-} // namespace Analyzer
+} // namespace Valgrind
#endif // VALGRINDENGINE_H
diff --git a/src/plugins/valgrindtoolbase/valgrindsettings.cpp b/src/plugins/valgrindtoolbase/valgrindsettings.cpp
index ac9052d354..b34b136e1d 100644
--- a/src/plugins/valgrindtoolbase/valgrindsettings.cpp
+++ b/src/plugins/valgrindtoolbase/valgrindsettings.cpp
@@ -41,7 +41,7 @@
#include <QtCore/QSettings>
-using namespace Analyzer::Internal;
+using namespace Valgrind::Internal;
using namespace Analyzer;
static const QLatin1String groupC("Analyzer");
diff --git a/src/plugins/valgrindtoolbase/valgrindsettings.h b/src/plugins/valgrindtoolbase/valgrindsettings.h
index 1c9fd0bf7a..b09d993ac0 100644
--- a/src/plugins/valgrindtoolbase/valgrindsettings.h
+++ b/src/plugins/valgrindtoolbase/valgrindsettings.h
@@ -42,13 +42,13 @@
#include <QtCore/QObject>
#include <QtCore/QVariant>
-namespace Analyzer {
+namespace Valgrind {
namespace Internal {
/**
* Generic Valgrind settings shared by all tools.
*/
-class VALGRINDTOOLBASE_EXPORT ValgrindSettings : public AbstractAnalyzerSubConfig
+class VALGRINDTOOLBASE_EXPORT ValgrindSettings : public Analyzer::AbstractAnalyzerSubConfig
{
Q_OBJECT
public:
diff --git a/src/plugins/valgrindtoolbase/valgrindtoolbaseplugin.cpp b/src/plugins/valgrindtoolbase/valgrindtoolbaseplugin.cpp
index 02c3df73a9..ccca4ccf8b 100644
--- a/src/plugins/valgrindtoolbase/valgrindtoolbaseplugin.cpp
+++ b/src/plugins/valgrindtoolbase/valgrindtoolbaseplugin.cpp
@@ -42,7 +42,7 @@
#include <QtCore/QtPlugin>
using namespace Analyzer;
-using namespace Analyzer::Internal;
+using namespace Valgrind::Internal;
ValgrindToolbasePlugin::ValgrindToolbasePlugin()
{
diff --git a/src/plugins/valgrindtoolbase/valgrindtoolbaseplugin.h b/src/plugins/valgrindtoolbase/valgrindtoolbaseplugin.h
index 5f13d3187b..a555bd7178 100644
--- a/src/plugins/valgrindtoolbase/valgrindtoolbaseplugin.h
+++ b/src/plugins/valgrindtoolbase/valgrindtoolbaseplugin.h
@@ -37,7 +37,7 @@
#include <extensionsystem/iplugin.h>
-namespace Analyzer {
+namespace Valgrind {
namespace Internal {
class ValgrindToolbasePlugin : public ExtensionSystem::IPlugin
diff --git a/src/plugins/vcsbase/baseannotationhighlighter.cpp b/src/plugins/vcsbase/baseannotationhighlighter.cpp
index a2bd937260..7c2434ea1d 100644
--- a/src/plugins/vcsbase/baseannotationhighlighter.cpp
+++ b/src/plugins/vcsbase/baseannotationhighlighter.cpp
@@ -42,6 +42,19 @@
typedef QMap<QString, QTextCharFormat> ChangeNumberFormatMap;
+/*!
+ \class VCSBase::BaseAnnotationHighlighter
+
+ \brief Base for a highlighter for annotation lines of the form 'changenumber:XXXX'.
+
+ The change numbers are assigned a color gradient. Example:
+ \code
+ 112: text1 <color 1>
+ 113: text2 <color 2>
+ 112: text3 <color 1>
+ \endcode
+*/
+
namespace VCSBase {
struct BaseAnnotationHighlighterPrivate {
diff --git a/src/plugins/vcsbase/baseannotationhighlighter.h b/src/plugins/vcsbase/baseannotationhighlighter.h
index e653f05baf..74a0ce1539 100644
--- a/src/plugins/vcsbase/baseannotationhighlighter.h
+++ b/src/plugins/vcsbase/baseannotationhighlighter.h
@@ -41,12 +41,6 @@ namespace VCSBase {
struct BaseAnnotationHighlighterPrivate;
-// Base for a highlighter for annotation lines of the form
-// 'changenumber:XXXX'. The change numbers are assigned a color gradient.
-// Example:
-// 112: text1 <color 1>
-// 113: text2 <color 2>
-// 112: text3 <color 1>
class VCSBASE_EXPORT BaseAnnotationHighlighter : public TextEditor::SyntaxHighlighter
{
Q_OBJECT
diff --git a/src/plugins/vcsbase/basecheckoutwizard.cpp b/src/plugins/vcsbase/basecheckoutwizard.cpp
index 7431887d64..a7a6affff5 100644
--- a/src/plugins/vcsbase/basecheckoutwizard.cpp
+++ b/src/plugins/vcsbase/basecheckoutwizard.cpp
@@ -42,6 +42,27 @@
#include <QtCore/QDir>
#include <QtGui/QMessageBox>
+/*!
+ \class VCSBase::BaseCheckoutWizard
+
+ \brief A Core::IWizard implementing a wizard for initially checking out a project using
+ a version control system.
+
+ Implements all of Core::IWizard with the exception of
+ name()/description() and icon().
+
+ Pops up a QWizard consisting of a Parameter Page which is created
+ by a virtual factory function and a progress
+ page containing a log text. The factory function createJob()
+ creates a job with the output connected to the log window,
+ returning the path to the checkout.
+
+ On success, the wizard tries to locate a project file
+ and open it.
+
+ \sa VCSBase::BaseCheckoutWizardPage
+*/
+
namespace VCSBase {
struct BaseCheckoutWizardPrivate {
diff --git a/src/plugins/vcsbase/basecheckoutwizard.h b/src/plugins/vcsbase/basecheckoutwizard.h
index 5d09c1efc6..d2c1274221 100644
--- a/src/plugins/vcsbase/basecheckoutwizard.h
+++ b/src/plugins/vcsbase/basecheckoutwizard.h
@@ -48,20 +48,6 @@ namespace VCSBase {
class AbstractCheckoutJob;
struct BaseCheckoutWizardPrivate;
-/* A Core::IWizard implementing a wizard for initially checking
- * out a project using a version control system.
- * Implements all of Core::IWizard with the exception of
- * name()/description() and icon().
- * Pops up a QWizard consisting of a Parameter Page which is created
- * by a virtual factory function and a progress
- * page containing a log text. The factory function createJob()
- * creates a job with the output connected to the log window,
- * returning the path to the checkout.
- * On success, the wizard tries to locate a project file
- * and open it.
- * BaseCheckoutWizardPage is provided as a convenience base class
- * for parameter wizard pages. */
-
class VCSBASE_EXPORT BaseCheckoutWizard : public Core::IWizard
{
Q_OBJECT
diff --git a/src/plugins/vcsbase/basecheckoutwizardpage.cpp b/src/plugins/vcsbase/basecheckoutwizardpage.cpp
index 40177cc526..da88359273 100644
--- a/src/plugins/vcsbase/basecheckoutwizardpage.cpp
+++ b/src/plugins/vcsbase/basecheckoutwizardpage.cpp
@@ -35,6 +35,18 @@
#include <QtGui/QIcon>
+/*!
+ \class VCSBase::BaseCheckoutWizardPage
+
+ \brief Base class for a parameter page of a checkout wizard.
+
+ Lets the user specify the repository, a checkout directory and
+ the path. Contains a virtual to derive the checkout directory
+ from the repository as it is entered.
+
+ \sa VCSBase::BaseCheckoutWizard
+*/
+
namespace VCSBase {
struct BaseCheckoutWizardPagePrivate {
diff --git a/src/plugins/vcsbase/basecheckoutwizardpage.h b/src/plugins/vcsbase/basecheckoutwizardpage.h
index 56178bb2cb..760fa4ca76 100644
--- a/src/plugins/vcsbase/basecheckoutwizardpage.h
+++ b/src/plugins/vcsbase/basecheckoutwizardpage.h
@@ -45,11 +45,6 @@ namespace Ui {
struct BaseCheckoutWizardPagePrivate;
-/* Base class for a parameter page of a checkout wizard.
- * Let's the user specify the repository, a checkout directory and
- * the path. Contains a virtual to derive the checkout directory
- * from the repository as it is entered. */
-
class VCSBASE_EXPORT BaseCheckoutWizardPage : public QWizardPage {
Q_OBJECT
Q_PROPERTY(bool isBranchSelectorVisible READ isBranchSelectorVisible WRITE setBranchSelectorVisible)
diff --git a/src/plugins/vcsbase/basevcseditorfactory.cpp b/src/plugins/vcsbase/basevcseditorfactory.cpp
index f11263983e..580f16c238 100644
--- a/src/plugins/vcsbase/basevcseditorfactory.cpp
+++ b/src/plugins/vcsbase/basevcseditorfactory.cpp
@@ -40,6 +40,14 @@
#include <QtCore/QCoreApplication>
+/*!
+ \class VCSBase::BaseVCSEditorFactory
+
+ \brief Base class for editor factories creating instances of VCSBaseEditor subclasses.
+
+ \sa VCSBase::VCSBaseEditorWidget
+*/
+
namespace VCSBase {
struct BaseVCSEditorFactoryPrivate
diff --git a/src/plugins/vcsbase/basevcseditorfactory.h b/src/plugins/vcsbase/basevcseditorfactory.h
index 7c4bbe03b9..cacc51ea88 100644
--- a/src/plugins/vcsbase/basevcseditorfactory.h
+++ b/src/plugins/vcsbase/basevcseditorfactory.h
@@ -44,8 +44,6 @@ namespace VCSBase {
struct BaseVCSEditorFactoryPrivate;
-// Base class for editor factories creating instances of VCSBaseEditor
-// subclasses.
class VCSBASE_EXPORT BaseVCSEditorFactory : public Core::IEditorFactory
{
Q_OBJECT
diff --git a/src/plugins/vcsbase/checkoutjobs.cpp b/src/plugins/vcsbase/checkoutjobs.cpp
index 0bd1c2cb54..dcf5b66add 100644
--- a/src/plugins/vcsbase/checkoutjobs.cpp
+++ b/src/plugins/vcsbase/checkoutjobs.cpp
@@ -42,6 +42,16 @@
#include <utils/qtcassert.h>
enum { debug = 0 };
+
+/*!
+ \class VCSBase::AbstractCheckoutJob
+
+ \brief Abstract base class for a job creating an initial project checkout.
+ It should be something that runs in the background producing log messages.
+
+ \sa VCSBase::BaseCheckoutWizard
+*/
+
namespace VCSBase {
AbstractCheckoutJob::AbstractCheckoutJob(QObject *parent) :
@@ -81,6 +91,12 @@ static inline QSharedPointer<QProcess> createProcess()
return Utils::SynchronousProcess::createProcess(flags);
}
+/*!
+ \class VCSBase::ProcessCheckoutJob
+
+ \brief Convenience implementation of a VCSBase::AbstractCheckoutJob using a QProcess.
+*/
+
ProcessCheckoutJobPrivate::ProcessCheckoutJobPrivate() :
process(createProcess())
{
diff --git a/src/plugins/vcsbase/checkoutjobs.h b/src/plugins/vcsbase/checkoutjobs.h
index cd95388e38..3ce06f2bab 100644
--- a/src/plugins/vcsbase/checkoutjobs.h
+++ b/src/plugins/vcsbase/checkoutjobs.h
@@ -69,8 +69,6 @@ signals:
void output(const QString &what);
};
-/* Convenience implementation using a QProcess. */
-
class VCSBASE_EXPORT ProcessCheckoutJob : public AbstractCheckoutJob
{
Q_OBJECT
diff --git a/src/plugins/vcsbase/checkoutprogresswizardpage.cpp b/src/plugins/vcsbase/checkoutprogresswizardpage.cpp
index 8d3cac568f..79dd6b2f20 100644
--- a/src/plugins/vcsbase/checkoutprogresswizardpage.cpp
+++ b/src/plugins/vcsbase/checkoutprogresswizardpage.cpp
@@ -39,6 +39,15 @@
#include <QtGui/QApplication>
#include <QtGui/QCursor>
+/*!
+ \class VCSBase::CheckoutProgressWizardPage
+
+ \brief Page showing the progress of an initial project checkout. Turns complete when the job
+ succeeds.
+
+ \sa VCSBase::BaseCheckoutWizard
+*/
+
namespace VCSBase {
namespace Internal {
diff --git a/src/plugins/vcsbase/checkoutprogresswizardpage.h b/src/plugins/vcsbase/checkoutprogresswizardpage.h
index bd05cb4208..c7706b27cf 100644
--- a/src/plugins/vcsbase/checkoutprogresswizardpage.h
+++ b/src/plugins/vcsbase/checkoutprogresswizardpage.h
@@ -45,9 +45,6 @@ namespace Ui {
class CheckoutProgressWizardPage;
}
-/* Page showing the progress of an initial project
- * checkout. Turns complete when the job succeeds. */
-
class CheckoutProgressWizardPage : public QWizardPage {
Q_OBJECT
Q_DISABLE_COPY(CheckoutProgressWizardPage)
diff --git a/src/plugins/vcsbase/checkoutwizarddialog.cpp b/src/plugins/vcsbase/checkoutwizarddialog.cpp
index 5d4fd7f7fb..2cda774930 100644
--- a/src/plugins/vcsbase/checkoutwizarddialog.cpp
+++ b/src/plugins/vcsbase/checkoutwizarddialog.cpp
@@ -39,6 +39,13 @@
#include <QtGui/QPushButton>
+/*!
+ \class VCSBase::Internal::CheckoutWizardDialog
+
+ Dialog used by \sa VCSBase::BaseCheckoutWizard. Overwrites reject() to first
+ kill the checkout and then close.
+ */
+
namespace VCSBase {
namespace Internal {
diff --git a/src/plugins/vcsbase/checkoutwizarddialog.h b/src/plugins/vcsbase/checkoutwizarddialog.h
index 4dc85ad728..8c3f574bdc 100644
--- a/src/plugins/vcsbase/checkoutwizarddialog.h
+++ b/src/plugins/vcsbase/checkoutwizarddialog.h
@@ -43,10 +43,6 @@ class AbstractCheckoutJob;
namespace Internal {
class CheckoutProgressWizardPage;
-/* See BaseCheckoutWizard.
- * Overwrites reject() to first kill the checkout
- * and then close. */
-
class CheckoutWizardDialog : public Utils::Wizard {
Q_OBJECT
public:
diff --git a/src/plugins/vcsbase/cleandialog.cpp b/src/plugins/vcsbase/cleandialog.cpp
index e20a9f70e7..588024bcf3 100644
--- a/src/plugins/vcsbase/cleandialog.cpp
+++ b/src/plugins/vcsbase/cleandialog.cpp
@@ -52,6 +52,17 @@
#include <QtCore/QFuture>
#include <QtCore/QtConcurrentRun>
+/*!
+ \class VCSBase::CleanDialog
+
+ \brief File selector dialog for files not under version control.
+
+ Completely clean a directory under version control
+ from all files that are not under version control based on a list
+ generated from the version control system. Presents the user with
+ a checkable list of files and/or directories. Double click opens a file.
+*/
+
enum { nameColumn, columnCount };
enum { fileNameRole = Qt::UserRole, isDirectoryRole = Qt::UserRole + 1 };
diff --git a/src/plugins/vcsbase/cleandialog.h b/src/plugins/vcsbase/cleandialog.h
index 9efa16edf3..10d05121f9 100644
--- a/src/plugins/vcsbase/cleandialog.h
+++ b/src/plugins/vcsbase/cleandialog.h
@@ -44,11 +44,6 @@ QT_END_NAMESPACE
namespace VCSBase {
struct CleanDialogPrivate;
-/* CleanDialog: Completely clean a directory under version control
- * from all files that are not under version control based on a list
- * generated from the version control system. Presents the user with
- * a checkable list of files and/or directories. Double click opens a file. */
-
class VCSBASE_EXPORT CleanDialog : public QDialog {
Q_OBJECT
public:
diff --git a/src/plugins/vcsbase/commonsettingspage.cpp b/src/plugins/vcsbase/commonsettingspage.cpp
index e333a79013..9c1059e771 100644
--- a/src/plugins/vcsbase/commonsettingspage.cpp
+++ b/src/plugins/vcsbase/commonsettingspage.cpp
@@ -57,6 +57,10 @@ CommonSettingsWidget::CommonSettingsWidget(QWidget *parent) :
m_ui->nickNameFieldsFileChooser->setExpectedKind(Utils::PathChooser::File);
m_ui->nickNameMailMapChooser->setExpectedKind(Utils::PathChooser::File);
m_ui->sshPromptChooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
+ const QString patchToolTip = tr("Command used for reverting diff chunks");
+ m_ui->patchCommandLabel->setToolTip(patchToolTip);
+ m_ui->patchChooser->setToolTip(patchToolTip);
+ m_ui->patchChooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
}
CommonSettingsWidget::~CommonSettingsWidget()
@@ -73,6 +77,7 @@ CommonVcsSettings CommonSettingsWidget::settings() const
rc.lineWrap= m_ui->lineWrapCheckBox->isChecked();
rc.lineWrapWidth = m_ui->lineWrapSpinBox->value();
rc.sshPasswordPrompt = m_ui->sshPromptChooser->path();
+ rc.patchCommand = m_ui->patchChooser->path();
return rc;
}
@@ -84,6 +89,7 @@ void CommonSettingsWidget::setSettings(const CommonVcsSettings &s)
m_ui->lineWrapCheckBox->setChecked(s.lineWrap);
m_ui->lineWrapSpinBox->setValue(s.lineWrapWidth);
m_ui->sshPromptChooser->setPath(s.sshPasswordPrompt);
+ m_ui->patchChooser->setPath(s.patchCommand);
}
QString CommonSettingsWidget::searchKeyWordMatchString() const
diff --git a/src/plugins/vcsbase/commonsettingspage.ui b/src/plugins/vcsbase/commonsettingspage.ui
index c15f9cd96f..e4a8cdd6b8 100644
--- a/src/plugins/vcsbase/commonsettingspage.ui
+++ b/src/plugins/vcsbase/commonsettingspage.ui
@@ -2,15 +2,10 @@
<ui version="4.0">
<class>CommonSettingsPage</class>
<widget class="QWidget" name="CommonSettingsPage">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>338</width>
- <height>166</height>
- </rect>
- </property>
<layout class="QFormLayout" name="formLayout">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::ExpandingFieldsGrow</enum>
+ </property>
<item row="0" column="0">
<widget class="QCheckBox" name="lineWrapCheckBox">
<property name="text">
@@ -56,12 +51,15 @@
<string>An executable which is called with the submit message in a temporary file as first argument. It should return with an exit != 0 and a message on standard error to indicate failure.</string>
</property>
<property name="text">
- <string>Submit message check script:</string>
+ <string>Submit message &amp;check script:</string>
+ </property>
+ <property name="buddy">
+ <cstring>submitMessageCheckScriptChooser</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
- <widget class="Utils::PathChooser" name="submitMessageCheckScriptChooser" native="true"/>
+ <widget class="Utils::PathChooser" name="submitMessageCheckScriptChooser"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="nickNameMailMapLabel">
@@ -70,12 +68,15 @@
name &lt;email&gt; alias &lt;email&gt;</string>
</property>
<property name="text">
- <string>User/alias configuration file:</string>
+ <string>User/&amp;alias configuration file:</string>
+ </property>
+ <property name="buddy">
+ <cstring>nickNameMailMapChooser</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
- <widget class="Utils::PathChooser" name="nickNameMailMapChooser" native="true"/>
+ <widget class="Utils::PathChooser" name="nickNameMailMapChooser"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="nickNameFieldsFileLabel">
@@ -83,12 +84,18 @@ name &lt;email&gt; alias &lt;email&gt;</string>
<string>A simple file containing lines with field names like &quot;Reviewed-By:&quot; which will be added below the submit editor.</string>
</property>
<property name="text">
- <string>User fields configuration file:</string>
+ <string>User &amp;fields configuration file:</string>
+ </property>
+ <property name="buddy">
+ <cstring>nickNameFieldsFileChooser</cstring>
</property>
</widget>
</item>
<item row="4" column="1">
- <widget class="Utils::PathChooser" name="nickNameFieldsFileChooser" native="true"/>
+ <widget class="Utils::PathChooser" name="nickNameFieldsFileChooser"/>
+ </item>
+ <item row="5" column="1">
+ <widget class="Utils::PathChooser" name="sshPromptChooser"/>
</item>
<item row="6" column="0" colspan="2">
<spacer name="verticalSpacer">
@@ -106,6 +113,19 @@ name &lt;email&gt; alias &lt;email&gt;</string>
</property>
</spacer>
</item>
+ <item row="7" column="0">
+ <widget class="QLabel" name="patchCommandLabel">
+ <property name="text">
+ <string>&amp;Patch command:</string>
+ </property>
+ <property name="buddy">
+ <cstring>patchChooser</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="1">
+ <widget class="Utils::PathChooser" name="patchChooser"/>
+ </item>
<item row="5" column="0">
<widget class="QLabel" name="sshPromptLabel">
<property name="toolTip">
@@ -113,13 +133,13 @@ name &lt;email&gt; alias &lt;email&gt;</string>
should a repository require SSH-authentication (see documentation on SSH and the environment variable SSH_ASKPASS).</string>
</property>
<property name="text">
- <string>SSH prompt command:</string>
+ <string>&amp;SSH prompt command:</string>
+ </property>
+ <property name="buddy">
+ <cstring>sshPromptChooser</cstring>
</property>
</widget>
</item>
- <item row="5" column="1">
- <widget class="Utils::PathChooser" name="sshPromptChooser" native="true"/>
- </item>
</layout>
</widget>
<customwidgets>
diff --git a/src/plugins/vcsbase/commonvcssettings.cpp b/src/plugins/vcsbase/commonvcssettings.cpp
index 65a71dff3c..0527ebd6ff 100644
--- a/src/plugins/vcsbase/commonvcssettings.cpp
+++ b/src/plugins/vcsbase/commonvcssettings.cpp
@@ -42,6 +42,8 @@ static const char submitMessageCheckScriptKeyC[] = "SubmitMessageCheckScript";
static const char lineWrapKeyC[] = "LineWrap";
static const char lineWrapWidthKeyC[] = "LineWrapWidth";
static const char sshPasswordPromptKeyC[] = "SshPasswordPrompt";
+static const char patchCommandKeyC[] = "PatchCommand";
+static const char patchCommandDefaultC[] = "patch";
static const int lineWrapWidthDefault = 72;
static const bool lineWrapDefault = true;
@@ -64,6 +66,7 @@ namespace Internal {
CommonVcsSettings::CommonVcsSettings() :
sshPasswordPrompt(sshPasswordPromptDefault()),
+ patchCommand(QLatin1String(patchCommandDefaultC)),
lineWrap(lineWrapDefault),
lineWrapWidth(lineWrapWidthDefault)
{
@@ -77,6 +80,7 @@ void CommonVcsSettings::toSettings(QSettings *s) const
s->setValue(QLatin1String(submitMessageCheckScriptKeyC), submitMessageCheckScript);
s->setValue(QLatin1String(lineWrapKeyC), lineWrap);
s->setValue(QLatin1String(lineWrapWidthKeyC), lineWrapWidth);
+ s->setValue(QLatin1String(patchCommandKeyC), patchCommand);
// Do not store the default setting to avoid clobbering the environment.
if (sshPasswordPrompt != sshPasswordPromptDefault()) {
s->setValue(QLatin1String(sshPasswordPromptKeyC), sshPasswordPrompt);
@@ -95,6 +99,7 @@ void CommonVcsSettings::fromSettings(QSettings *s)
lineWrap = s->value(QLatin1String(lineWrapKeyC), lineWrapDefault).toBool();
lineWrapWidth = s->value(QLatin1String(lineWrapWidthKeyC), lineWrapWidthDefault).toInt();
sshPasswordPrompt = s->value(QLatin1String(sshPasswordPromptKeyC), sshPasswordPromptDefault()).toString();
+ patchCommand = s->value(QLatin1String(patchCommandKeyC), QLatin1String(patchCommandDefaultC)).toString();
s->endGroup();
}
@@ -105,7 +110,8 @@ bool CommonVcsSettings::equals(const CommonVcsSettings &rhs) const
&& nickNameMailMap == rhs.nickNameMailMap
&& nickNameFieldListFile == rhs.nickNameFieldListFile
&& submitMessageCheckScript == rhs.submitMessageCheckScript
- && sshPasswordPrompt == rhs.sshPasswordPrompt;
+ && sshPasswordPrompt == rhs.sshPasswordPrompt
+ && patchCommand == rhs.patchCommand;
}
QDebug operator<<(QDebug d,const CommonVcsSettings& s)
@@ -116,6 +122,7 @@ QDebug operator<<(QDebug d,const CommonVcsSettings& s)
<< "' nickNameFieldListFile='" << s.nickNameFieldListFile
<< "'submitMessageCheckScript='" << s.submitMessageCheckScript
<< "'sshPasswordPrompt='" << s.sshPasswordPrompt
+ << "'patchCommand='" << s.patchCommand
<< "'\n";
return d;
}
diff --git a/src/plugins/vcsbase/commonvcssettings.h b/src/plugins/vcsbase/commonvcssettings.h
index e5991f5aae..ad56c76e7a 100644
--- a/src/plugins/vcsbase/commonvcssettings.h
+++ b/src/plugins/vcsbase/commonvcssettings.h
@@ -57,6 +57,8 @@ struct CommonVcsSettings
// Executable run to graphically prompt for a SSH-password.
QString sshPasswordPrompt;
+ QString patchCommand;
+
bool lineWrap;
int lineWrapWidth;
diff --git a/src/plugins/vcsbase/corelistener.cpp b/src/plugins/vcsbase/corelistener.cpp
index 3cf9e4035b..044d5e8ac3 100644
--- a/src/plugins/vcsbase/corelistener.cpp
+++ b/src/plugins/vcsbase/corelistener.cpp
@@ -33,6 +33,17 @@
#include "corelistener.h"
#include "vcsbasesubmiteditor.h"
+/*!
+ \class VCSBase::Internal::CoreListener
+
+ \brief CoreListener catching closing of a submit editor.
+
+ Catch the closing of a submit editor to trigger the submit.
+ One instance of this class exists, connected to the instances
+ of VCSBasePlugin, which dispatch if the editor kind matches theirs
+ (which is why the approach of passing the bool result was chosen).
+*/
+
namespace VCSBase {
namespace Internal {
diff --git a/src/plugins/vcsbase/corelistener.h b/src/plugins/vcsbase/corelistener.h
index 706652b74d..7ba0a4b71e 100644
--- a/src/plugins/vcsbase/corelistener.h
+++ b/src/plugins/vcsbase/corelistener.h
@@ -41,11 +41,6 @@ class VCSBaseSubmitEditor;
namespace Internal {
-// Catch the closing of a submit editor to trigger the submit.
-// One instance of this class exists, connected to the instances
-// of VCSBasePlugin, which dispatch if the editor kind matches theirs
-// (which is why the approach of passing the bool result was chosen).
-
class CoreListener : public Core::ICoreListener
{
Q_OBJECT
@@ -57,6 +52,6 @@ signals:
void submitEditorAboutToClose(VCSBaseSubmitEditor *e, bool *result);
};
-}
-}
+} // Internal
+} // VCSBase
#endif // CORELISTENER_H
diff --git a/src/plugins/vcsbase/diffhighlighter.cpp b/src/plugins/vcsbase/diffhighlighter.cpp
index dc511cd5ba..e392d5a10d 100644
--- a/src/plugins/vcsbase/diffhighlighter.cpp
+++ b/src/plugins/vcsbase/diffhighlighter.cpp
@@ -41,6 +41,28 @@
#include <QtCore/QRegExp>
#include <QtGui/QBrush>
+/*!
+ \class VCSBase::DiffHighlighter
+
+ \brief A highlighter for diffs.
+
+ Parametrizable by the file indicator, which is for example '^====' in case of p4:
+ \code
+ ==== //depot/research/main/qdynamicmainwindow3/qdynamicdockwidgetlayout_p.h#34 (text) ====
+ \endcode
+
+ Or '--- a/|'+++ b/' in case of git:
+ \code
+ diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
+ index 9401ee7..ef35c3b 100644
+ --- a/src/plugins/plugins.pro
+ +++ b/src/plugins/plugins.pro
+ @@ -10,6 +10,7 @@ SUBDIRS = plugin_coreplugin
+ \endcode
+
+ Also highlights trailing blanks.
+ */
+
static const int BASE_LEVEL = 0;
static const int FILE_LEVEL = 1;
static const int LOCATION_LEVEL = 2;
@@ -130,6 +152,12 @@ static inline int trimmedLength(const QString &in)
return 0;
}
+/*
+ * This sets the folding indent:
+ * 0 for the first line of the diff header.
+ * 1 for all the following lines of the diff header and all @@ lines.
+ * 2 for everything else
+ */
void DiffHighlighter::highlightBlock(const QString &text)
{
if (text.isEmpty())
diff --git a/src/plugins/vcsbase/diffhighlighter.h b/src/plugins/vcsbase/diffhighlighter.h
index eacb1a6ff4..0bd9351efd 100644
--- a/src/plugins/vcsbase/diffhighlighter.h
+++ b/src/plugins/vcsbase/diffhighlighter.h
@@ -55,21 +55,6 @@ namespace Internal {
class DiffHighlighterPrivate;
} // namespace Internal
-/* A highlighter for diffs. Parametrizable by the file indicator,
- * which is for example '^====' in case of p4:
- * \code
- ==== //depot/research/main/qdynamicmainwindow3/qdynamicdockwidgetlayout_p.h#34 (text) ====
- * \endcode
- * Or '--- a/|'+++ b/' in case of git:
- * \code
- diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
- index 9401ee7..ef35c3b 100644
- --- a/src/plugins/plugins.pro
- +++ b/src/plugins/plugins.pro
- @@ -10,6 +10,7 @@ SUBDIRS = plugin_coreplugin \
- * \endcode
- * */
-
class VCSBASE_EXPORT DiffHighlighter : public TextEditor::SyntaxHighlighter
{
Q_OBJECT
diff --git a/src/plugins/vcsbase/nicknamedialog.cpp b/src/plugins/vcsbase/nicknamedialog.cpp
index 600f0a7d4e..080a969cd3 100644
--- a/src/plugins/vcsbase/nicknamedialog.cpp
+++ b/src/plugins/vcsbase/nicknamedialog.cpp
@@ -42,6 +42,18 @@
enum { NickNameRole = Qt::UserRole + 1 };
+/*!
+ \class VCSBase::Internal::NickNameDialog
+
+ \brief Show users from mail cap file.
+
+ Manages a list of users read from an extended
+ mail cap file, consisting of 4 columns: "Name Mail [AliasName [AliasMail]]".
+
+ The names can be used for insertion into "RevBy:" fields; aliases will
+ be preferred.
+*/
+
namespace VCSBase {
namespace Internal {
diff --git a/src/plugins/vcsbase/nicknamedialog.h b/src/plugins/vcsbase/nicknamedialog.h
index 35ea09546c..5ceed5c535 100644
--- a/src/plugins/vcsbase/nicknamedialog.h
+++ b/src/plugins/vcsbase/nicknamedialog.h
@@ -48,12 +48,6 @@ QT_END_NAMESPACE
namespace VCSBase {
namespace Internal {
-/* Nick name dialog: Manages a list of users read from an extended
- * mail cap file, consisting of 4 columns:
- * "Name Mail [AliasName [AliasMail]]".
- * The names can be used for insertion into "RevBy:" fields; aliases will
- * be preferred. */
-
class NickNameDialog : public QDialog {
Q_OBJECT
public:
diff --git a/src/plugins/vcsbase/submiteditorfile.cpp b/src/plugins/vcsbase/submiteditorfile.cpp
index 13db70da9c..47e6a629e2 100644
--- a/src/plugins/vcsbase/submiteditorfile.cpp
+++ b/src/plugins/vcsbase/submiteditorfile.cpp
@@ -35,6 +35,12 @@
using namespace VCSBase;
using namespace VCSBase::Internal;
+/*!
+ \class VCSBase::Internal::SubmitEditorFile
+
+ \brief A non-saveable IFile for submit editor files.
+*/
+
SubmitEditorFile::SubmitEditorFile(const QString &mimeType, QObject *parent) :
Core::IFile(parent),
m_mimeType(mimeType),
diff --git a/src/plugins/vcsbase/submiteditorfile.h b/src/plugins/vcsbase/submiteditorfile.h
index 049035cab4..ad22240f7a 100644
--- a/src/plugins/vcsbase/submiteditorfile.h
+++ b/src/plugins/vcsbase/submiteditorfile.h
@@ -38,7 +38,6 @@
namespace VCSBase {
namespace Internal {
-// A non-saveable IFile for submit editor files.
class SubmitEditorFile : public Core::IFile
{
Q_OBJECT
diff --git a/src/plugins/vcsbase/submitfilemodel.cpp b/src/plugins/vcsbase/submitfilemodel.cpp
index 25e32012d1..e3556fda1f 100644
--- a/src/plugins/vcsbase/submitfilemodel.cpp
+++ b/src/plugins/vcsbase/submitfilemodel.cpp
@@ -38,6 +38,13 @@
namespace VCSBase {
+/*!
+ \class VCSBase::SubmitFileModel
+
+ \brief A 2-column (checkable, state, file name) model to be used to list the files
+ in the submit editor. Provides header items and a convience to add files.
+ */
+
SubmitFileModel::SubmitFileModel(QObject *parent) :
QStandardItemModel(0, 2, parent)
{
diff --git a/src/plugins/vcsbase/submitfilemodel.h b/src/plugins/vcsbase/submitfilemodel.h
index d877951f95..e6388ddd10 100644
--- a/src/plugins/vcsbase/submitfilemodel.h
+++ b/src/plugins/vcsbase/submitfilemodel.h
@@ -39,9 +39,6 @@
namespace VCSBase {
-/* A 2-column (checkable, state, file name) model to be used to list the files-
- * in the submit editor. Provides header items and a convience to add files. */
-
class VCSBASE_EXPORT SubmitFileModel : public QStandardItemModel
{
Q_OBJECT
diff --git a/src/plugins/vcsbase/vcsbase.pro b/src/plugins/vcsbase/vcsbase.pro
index d8341917f9..7e383f0738 100644
--- a/src/plugins/vcsbase/vcsbase.pro
+++ b/src/plugins/vcsbase/vcsbase.pro
@@ -30,7 +30,8 @@ HEADERS += vcsbase_global.h \
vcsbaseoptionspage.h \
vcsjobrunner.h \
vcsbaseclient.h \
- vcsbaseclientsettings.h
+ vcsbaseclientsettings.h \
+ vcsbaseeditorparameterwidget.h
SOURCES += vcsplugin.cpp \
vcsbaseplugin.cpp \
@@ -57,7 +58,8 @@ SOURCES += vcsplugin.cpp \
vcsbaseoptionspage.cpp \
vcsjobrunner.cpp \
vcsbaseclient.cpp \
- vcsbaseclientsettings.cpp
+ vcsbaseclientsettings.cpp \
+ vcsbaseeditorparameterwidget.cpp
RESOURCES += vcsbase.qrc
diff --git a/src/plugins/vcsbase/vcsbaseclient.cpp b/src/plugins/vcsbase/vcsbaseclient.cpp
index 986fc90b87..4bd445ae97 100644
--- a/src/plugins/vcsbase/vcsbaseclient.cpp
+++ b/src/plugins/vcsbase/vcsbaseclient.cpp
@@ -55,6 +55,16 @@
#include <QtCore/QByteArray>
#include <QtCore/QMetaType>
+/*!
+ \class VCSBase::VCSBaseClient
+
+ \brief Base class for Mercurial and Bazaar 'clients'.
+
+ Provides base functionality for common commands (diff, log, etc).
+
+ \sa VCSBase::VCSJobRunner
+*/
+
Q_DECLARE_METATYPE(QVariant)
inline Core::IEditor *locateEditor(const Core::ICore *core, const char *property, const QString &entry)
@@ -261,11 +271,12 @@ void VCSBaseClient::annotate(const QString &workingDir, const QString &file,
enqueueJob(job);
}
-void VCSBaseClient::diff(const QString &workingDir, const QStringList &files)
+void VCSBaseClient::diff(const QString &workingDir, const QStringList &files,
+ const ExtraCommandOptions &extraOptions)
{
const QString vcsCmdString = vcsCommandString(DiffCommand);
QStringList args;
- args << vcsCmdString << diffArguments(files);
+ args << vcsCmdString << diffArguments(files, extraOptions);
const QString kind = vcsEditorKind(DiffCommand);
const QString id = VCSBase::VCSBaseEditorWidget::getTitleId(workingDir, files);
const QString title = vcsEditorTitle(vcsCmdString, id);
@@ -273,6 +284,7 @@ void VCSBaseClient::diff(const QString &workingDir, const QStringList &files)
VCSBase::VCSBaseEditorWidget *editor = createVCSEditor(kind, title, source, true,
vcsCmdString.toLatin1().constData(), id);
editor->setDiffBaseDirectory(workingDir);
+ initializeDiffEditor(workingDir, files, extraOptions, editor);
QSharedPointer<VCSJob> job(new VCSJob(workingDir, args, editor));
enqueueJob(job);
@@ -398,7 +410,9 @@ void VCSBaseClient::view(const QString &source, const QString &id)
VCSBase::VCSBaseEditorWidget *editor = createVCSEditor(kind, title, source,
true, "view", id);
- QSharedPointer<VCSJob> job(new VCSJob(QFileInfo(source).absolutePath(), args, editor));
+ const QFileInfo fi(source);
+ const QString workingDirPath = fi.isFile() ? fi.absolutePath() : source;
+ QSharedPointer<VCSJob> job(new VCSJob(workingDirPath, args, editor));
enqueueJob(job);
}
@@ -441,6 +455,12 @@ void VCSBaseClient::settingsChanged()
}
}
+void VCSBaseClient::initializeDiffEditor(const QString & /* workingDir */, const QStringList & /* files */,
+ const ExtraCommandOptions & /* extraOptions */,
+ VCSBaseEditorWidget *)
+{
+}
+
QString VCSBaseClient::vcsEditorTitle(const QString &vcsCmd, const QString &sourceId) const
{
return QFileInfo(d->m_clientSettings.binary()).baseName() +
diff --git a/src/plugins/vcsbase/vcsbaseclient.h b/src/plugins/vcsbase/vcsbaseclient.h
index 3c0201a4eb..3b40330f48 100644
--- a/src/plugins/vcsbase/vcsbaseclient.h
+++ b/src/plugins/vcsbase/vcsbaseclient.h
@@ -88,7 +88,8 @@ public:
const ExtraCommandOptions &extraOptions = ExtraCommandOptions());
void annotate(const QString &workingDir, const QString &file,
const QString revision = QString(), int lineNumber = -1);
- void diff(const QString &workingDir, const QStringList &files = QStringList());
+ void diff(const QString &workingDir, const QStringList &files = QStringList(),
+ const ExtraCommandOptions &extraOptions = ExtraCommandOptions());
void log(const QString &workingDir, const QStringList &files = QStringList(),
bool enableAnnotationContextMenu = false);
void status(const QString &workingDir, const QString &file = QString());
@@ -153,7 +154,10 @@ protected:
virtual QStringList revertAllArguments(const QString &revision) const = 0;
virtual QStringList annotateArguments(const QString &file,
const QString &revision, int lineNumber) const = 0;
- virtual QStringList diffArguments(const QStringList &files) const = 0;
+ virtual QStringList diffArguments(const QStringList &files,
+ const ExtraCommandOptions &extraOptions) const = 0;
+ virtual void initializeDiffEditor(const QString &workingDir, const QStringList &files,
+ const ExtraCommandOptions &extraOptions, VCSBaseEditorWidget *ed);
virtual QStringList logArguments(const QStringList &files) const = 0;
virtual QStringList statusArguments(const QString &file) const = 0;
virtual QStringList viewArguments(const QString &revision) const = 0;
diff --git a/src/plugins/vcsbase/vcsbaseclientsettings.cpp b/src/plugins/vcsbase/vcsbaseclientsettings.cpp
index 417b1cde6c..b2769c6c16 100644
--- a/src/plugins/vcsbase/vcsbaseclientsettings.cpp
+++ b/src/plugins/vcsbase/vcsbaseclientsettings.cpp
@@ -38,6 +38,14 @@ using namespace VCSBase;
enum { timeOutDefaultSeconds = 30 };
+/*!
+ \class VCSBase::VCSBaseClientSettings
+
+ \brief Settings used in VCSBaseClient.
+
+ \sa VCSBase::VCSBaseClient
+*/
+
VCSBaseClientSettings::VCSBaseClientSettings() :
m_binary(),
m_logCount(0),
diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp
index 956bbb5c3f..46ffc6d1ac 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.cpp
+++ b/src/plugins/vcsbase/vcsbaseeditor.cpp
@@ -35,6 +35,8 @@
#include "baseannotationhighlighter.h"
#include "vcsbasetextdocument.h"
#include "vcsbaseconstants.h"
+#include "vcsbaseoutputwindow.h"
+#include "vcsbaseplugin.h"
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/ifile.h>
@@ -46,12 +48,14 @@
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
+#include <texteditor/basetextdocumentlayout.h>
#include <texteditor/fontsettings.h>
#include <texteditor/texteditorconstants.h>
#include <utils/qtcassert.h>
#include <QtCore/QDebug>
#include <QtCore/QFileInfo>
+#include <QtCore/QFile>
#include <QtCore/QProcess>
#include <QtCore/QRegExp>
#include <QtCore/QSet>
@@ -68,20 +72,68 @@
#include <QtGui/QToolBar>
#include <QtGui/QClipboard>
#include <QtGui/QApplication>
+#include <QtGui/QMessageBox>
+
+/*!
+ \enum VCSBase::EditorContentType
+
+ \brief Contents of a VCSBaseEditor and its interaction.
+
+ \value RegularCommandOutput No special handling.
+ \value LogOutput Log of a file under revision control. Provide 'click on change'
+ description and 'Annotate' if is the log of a single file.
+ \value AnnotateOutput Color contents per change number and provide 'click on change' description.
+ Context menu offers "Annotate previous version". Expected format:
+ \code
+ <change description>: file line
+ \endcode
+ \value DiffOutput Diff output. Might includes describe output, which consists of a
+ header and diffs. Interaction is 'double click in hunk' which
+ opens the file. Context menu offers 'Revert chunk'.
+
+ \sa VCSBase::VCSBaseEditorWidget
+*/
namespace VCSBase {
-// VCSBaseEditor: An editor with no support for duplicates.
-// Creates a browse combo in the toolbar for diff output.
-// It also mirrors the signals of the VCSBaseEditor since the editor
-// manager passes the editor around.
+/*!
+ \class VCSBase::DiffChunk
+
+ \brief A diff chunk consisting of file name and chunk data.
+*/
+
+bool DiffChunk::isValid() const
+{
+ return !fileName.isEmpty() && !chunk.isEmpty();
+}
+
+QByteArray DiffChunk::asPatch() const
+{
+ const QByteArray fileNameBA = QFile::encodeName(fileName);
+ QByteArray rc = "--- ";
+ rc += fileNameBA;
+ rc += "\n+++ ";
+ rc += fileNameBA;
+ rc += '\n';
+ rc += chunk;
+ return rc;
+}
+
+/*!
+ \class VCSBase::VCSBaseEditor
+
+ \brief An editor with no support for duplicates.
+
+ Creates a browse combo in the toolbar for diff output.
+ It also mirrors the signals of the VCSBaseEditor since the editor
+ manager passes the editor around.
+*/
+
class VCSBaseEditor : public TextEditor::BaseTextEditor
{
Q_OBJECT
public:
- VCSBaseEditor(VCSBaseEditorWidget *,
- const VCSBaseEditorParameters *type);
- Core::Context context() const;
+ VCSBaseEditor(VCSBaseEditorWidget *, const VCSBaseEditorParameters *type);
bool duplicateSupported() const { return false; }
Core::IEditor *duplicate(QWidget * /*parent*/) { return 0; }
@@ -96,7 +148,6 @@ signals:
private:
QString m_id;
- Core::Context m_context;
bool m_temporary;
};
@@ -104,14 +155,9 @@ VCSBaseEditor::VCSBaseEditor(VCSBaseEditorWidget *widget,
const VCSBaseEditorParameters *type) :
BaseTextEditor(widget),
m_id(type->id),
- m_context(type->context, TextEditor::Constants::C_TEXTEDITOR),
m_temporary(false)
{
-}
-
-Core::Context VCSBaseEditor::context() const
-{
- return m_context;
+ setContext(Core::Context(type->context, TextEditor::Constants::C_TEXTEDITOR));
}
// Diff editor: creates a browse combo in the toolbar for diff output.
@@ -160,6 +206,8 @@ struct VCSBaseEditorWidgetPrivate
bool m_fileLogAnnotateEnabled;
TextEditor::BaseTextEditor *m_editor;
QWidget *m_configurationWidget;
+ bool m_revertChunkEnabled;
+ bool m_mouseDragging;
};
VCSBaseEditorWidgetPrivate::VCSBaseEditorWidgetPrivate(const VCSBaseEditorParameters *type) :
@@ -169,11 +217,35 @@ VCSBaseEditorWidgetPrivate::VCSBaseEditorWidgetPrivate(const VCSBaseEditorParame
m_copyRevisionTextFormat(VCSBaseEditorWidget::tr("Copy \"%1\"")),
m_fileLogAnnotateEnabled(false),
m_editor(0),
- m_configurationWidget(0)
+ m_configurationWidget(0),
+ m_revertChunkEnabled(false),
+ m_mouseDragging(false)
{
}
-// ------------ VCSBaseEditor
+/*!
+ \struct VCSBase::VCSBaseEditorParameters
+
+ \brief Helper struct used to parametrize an editor with mime type, context
+ and id. The extension is currently only a suggestion when running
+ VCS commands with redirection.
+
+ \sa VCSBase::VCSBaseEditorWidget, VCSBase::BaseVCSEditorFactory, VCSBase::EditorContentType
+*/
+
+/*!
+ \class VCSBase::VCSBaseEditorWidget
+
+ \brief Base class for editors showing version control system output
+ of the type enumerated by EditorContentType.
+
+ The source property should contain the file or directory the log
+ refers to and will be emitted with describeRequested().
+ This is for VCS that need a current directory.
+
+ \sa VCSBase::BaseVCSEditorFactory, VCSBase::VCSBaseEditorParameters, VCSBase::EditorContentType
+*/
+
VCSBaseEditorWidget::VCSBaseEditorWidget(const VCSBaseEditorParameters *type, QWidget *parent)
: BaseTextEditorWidget(parent),
d(new VCSBaseEditorWidgetPrivate(type))
@@ -443,7 +515,9 @@ void VCSBaseEditorWidget::contextMenuEvent(QContextMenuEvent *e)
{
QMenu *menu = createStandardContextMenu();
// 'click on change-interaction'
- if (d->m_parameters->type == LogOutput || d->m_parameters->type == AnnotateOutput) {
+ switch (d->m_parameters->type) {
+ case LogOutput:
+ case AnnotateOutput:
d->m_currentChange = changeUnderCursor(cursorForPosition(e->pos()));
if (!d->m_currentChange.isEmpty()) {
switch (d->m_parameters->type) {
@@ -470,6 +544,18 @@ void VCSBaseEditorWidget::contextMenuEvent(QContextMenuEvent *e)
break;
} // switch type
} // has current change
+ break;
+ case DiffOutput: {
+ menu->addSeparator();
+ QAction *revertAction = menu->addAction(tr("Revert Chunk..."));
+ const DiffChunk chunk = diffChunk(cursorForPosition(e->pos()));
+ revertAction->setEnabled(canRevertDiffChunk(chunk));
+ revertAction->setData(qVariantFromValue(chunk));
+ connect(revertAction, SIGNAL(triggered()), this, SLOT(slotRevertDiffChunk()));
+ }
+ break;
+ default:
+ break;
}
menu->exec(e->globalPos());
delete menu;
@@ -477,6 +563,12 @@ void VCSBaseEditorWidget::contextMenuEvent(QContextMenuEvent *e)
void VCSBaseEditorWidget::mouseMoveEvent(QMouseEvent *e)
{
+ if (e->buttons()) {
+ d->m_mouseDragging = true;
+ TextEditor::BaseTextEditorWidget::mouseMoveEvent(e);
+ return;
+ }
+
bool overrideCursor = false;
Qt::CursorShape cursorShape;
@@ -507,7 +599,9 @@ void VCSBaseEditorWidget::mouseMoveEvent(QMouseEvent *e)
void VCSBaseEditorWidget::mouseReleaseEvent(QMouseEvent *e)
{
- if (d->m_parameters->type == LogOutput || d->m_parameters->type == AnnotateOutput) {
+ const bool wasDragging = d->m_mouseDragging;
+ d->m_mouseDragging = false;
+ if (!wasDragging && (d->m_parameters->type == LogOutput || d->m_parameters->type == AnnotateOutput)) {
if (e->button() == Qt::LeftButton &&!(e->modifiers() & Qt::ShiftModifier)) {
QTextCursor cursor = cursorForPosition(e->pos());
d->m_currentChange = changeUnderCursor(cursor);
@@ -606,6 +700,9 @@ void VCSBaseEditorWidget::jumpToChangeFromDiff(QTextCursor cursor)
const QChar deletionIndicator = QLatin1Char('-');
// find nearest change hunk
QTextBlock block = cursor.block();
+ if (TextEditor::BaseTextDocumentLayout::foldingIndent(block) <= 1)
+ /* We are in a diff header, do not jump anywhere. DiffHighlighter sets the foldingIndent for us. */
+ return;
for ( ; block.isValid() ; block = block.previous()) {
const QString line = block.text();
if (checkChunkLine(line, &chunkStart)) {
@@ -642,6 +739,47 @@ void VCSBaseEditorWidget::jumpToChangeFromDiff(QTextCursor cursor)
editor->gotoLine(chunkStart + lineCount);
}
+// cut out chunk and determine file name.
+DiffChunk VCSBaseEditorWidget::diffChunk(QTextCursor cursor) const
+{
+ QTC_ASSERT(d->m_parameters->type == DiffOutput, return DiffChunk(); )
+ DiffChunk rc;
+ // Search back for start of chunk.
+ QTextBlock block = cursor.block();
+ QTextBlock next = block.next();
+ if (next.isValid() && TextEditor::BaseTextDocumentLayout::foldingIndent(next) <= 1)
+ /* We are in a diff header, not in a chunk! DiffHighlighter sets the foldingIndent for us. */
+ return rc;
+
+ int chunkStart = 0;
+ for ( ; block.isValid() ; block = block.previous()) {
+ if (checkChunkLine(block.text(), &chunkStart)) {
+ break;
+ }
+ }
+ if (!chunkStart || !block.isValid())
+ return rc;
+ rc.fileName = fileNameFromDiffSpecification(block);
+ if (rc.fileName.isEmpty())
+ return rc;
+ // Concatenate chunk and convert
+ QString unicode = block.text();
+ if (!unicode.endsWith(QLatin1Char('\n'))) // Missing in case of hg.
+ unicode.append(QLatin1Char('\n'));
+ for (block = block.next() ; block.isValid() ; block = block.next()) {
+ const QString line = block.text();
+ if (checkChunkLine(line, &chunkStart)) {
+ break;
+ } else {
+ unicode += line;
+ unicode += QLatin1Char('\n');
+ }
+ }
+ const QTextCodec *cd = textCodec();
+ rc.chunk = cd ? cd->fromUnicode(unicode) : unicode.toLocal8Bit();
+ return rc;
+}
+
void VCSBaseEditorWidget::setPlainTextData(const QByteArray &data)
{
if (data.size() > Core::EditorManager::maxTextFileSize()) {
@@ -900,6 +1038,89 @@ QStringList VCSBaseEditorWidget::annotationPreviousVersions(const QString &) con
return QStringList();
}
+bool VCSBaseEditorWidget::isRevertDiffChunkEnabled() const
+{
+ return d->m_revertChunkEnabled;
+}
+
+void VCSBaseEditorWidget::setRevertDiffChunkEnabled(bool e)
+{
+ d->m_revertChunkEnabled = e;
+}
+
+bool VCSBaseEditorWidget::canRevertDiffChunk(const DiffChunk &dc) const
+{
+ if (!isRevertDiffChunkEnabled() || !dc.isValid())
+ return false;
+ const QFileInfo fi(dc.fileName);
+ // Default implementation using patch.exe relies on absolute paths.
+ return fi.isFile() && fi.isAbsolute() && fi.isWritable();
+}
+
+// Default implementation of revert: Revert a chunk by piping it into patch
+// with '-R', assuming we got absolute paths from the VCS plugins.
+bool VCSBaseEditorWidget::revertDiffChunk(const DiffChunk &dc) const
+{
+ return VCSBasePlugin::runPatch(dc.asPatch(), QString(), 0, true);
+}
+
+void VCSBaseEditorWidget::slotRevertDiffChunk()
+{
+ const QAction *a = qobject_cast<QAction *>(sender());
+ QTC_ASSERT(a, return ; )
+ const DiffChunk chunk = qvariant_cast<DiffChunk>(a->data());
+ if (QMessageBox::No == QMessageBox::question(this, tr("Revert Chunk"),
+ tr("Would you like to revert the chunk?"),
+ QMessageBox::Yes|QMessageBox::No))
+ return;
+
+ if (revertDiffChunk(chunk))
+ emit diffChunkReverted(chunk);
+}
+
+// Tagging of editors for re-use.
+QString VCSBaseEditorWidget::editorTag(EditorContentType t,
+ const QString &workingDirectory,
+ const QStringList &files,
+ const QString &revision)
+{
+ const QChar colon = QLatin1Char(':');
+ QString rc = QString::number(t);
+ rc += colon;
+ if (!revision.isEmpty()) {
+ rc += revision;
+ rc += colon;
+ }
+ rc += workingDirectory;
+ if (!files.isEmpty()) {
+ rc += colon;
+ rc += files.join(QString(colon));
+ }
+ return rc;
+}
+
+static const char tagPropertyC[] = "_q_VCSBaseEditorTag";
+
+void VCSBaseEditorWidget::tagEditor(Core::IEditor *e, const QString &tag)
+{
+ e->setProperty(tagPropertyC, QVariant(tag));
+}
+
+Core::IEditor* VCSBaseEditorWidget::locateEditorByTag(const QString &tag)
+{
+ Core::IEditor *rc = 0;
+ foreach (Core::IEditor *ed, Core::EditorManager::instance()->openedEditors()) {
+ const QVariant tagPropertyValue = ed->property(tagPropertyC);
+ if (tagPropertyValue.type() == QVariant::String && tagPropertyValue.toString() == tag) {
+ rc = ed;
+ break;
+ }
+ }
+ if (VCSBase::Constants::Internal::debug)
+ qDebug() << "locateEditorByTag " << tag << rc;
+ return rc;
+}
+
} // namespace VCSBase
#include "vcsbaseeditor.moc"
diff --git a/src/plugins/vcsbase/vcsbaseeditor.h b/src/plugins/vcsbase/vcsbaseeditor.h
index 05763b1890..0c9e246850 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.h
+++ b/src/plugins/vcsbase/vcsbaseeditor.h
@@ -55,26 +55,14 @@ struct VCSBaseEditorWidgetPrivate;
class DiffHighlighter;
class BaseAnnotationHighlighter;
-// Contents of a VCSBaseEditor and its interaction.
+// Documentation inside
enum EditorContentType {
- // No special handling.
RegularCommandOutput,
- // Log of a file under revision control. Provide 'click on change'
- // description and 'Annotate' if is the log of a single file.
LogOutput,
- // <change description>: file line
- // Color per change number and provide 'click on change' description.
- // Context menu offers "Annotate previous version".
AnnotateOutput,
- // Diff output. Might includes describe output, which consists of a
- // header and diffs. Interaction is 'double click in hunk' which
- // opens the file
DiffOutput
};
-// Helper struct used to parametrize an editor with mime type, context
-// and id. The extension is currently only a suggestion when running
-// VCS commands with redirection.
struct VCSBASE_EXPORT VCSBaseEditorParameters
{
EditorContentType type;
@@ -85,11 +73,16 @@ struct VCSBASE_EXPORT VCSBaseEditorParameters
const char *extension;
};
-// Base class for editors showing version control system output
-// of the type enumerated by EditorContentType.
-// The source property should contain the file or directory the log
-// refers to and will be emitted with describeRequested().
-// This is for VCS that need a current directory.
+class VCSBASE_EXPORT DiffChunk
+{
+public:
+ bool isValid() const;
+ QByteArray asPatch() const;
+
+ QString fileName;
+ QByteArray chunk;
+};
+
class VCSBASE_EXPORT VCSBaseEditorWidget : public TextEditor::BaseTextEditorWidget
{
Q_PROPERTY(QString source READ source WRITE setSource)
@@ -98,6 +91,7 @@ class VCSBASE_EXPORT VCSBaseEditorWidget : public TextEditor::BaseTextEditorWidg
Q_PROPERTY(QString annotateRevisionTextFormat READ annotateRevisionTextFormat WRITE setAnnotateRevisionTextFormat)
Q_PROPERTY(QString copyRevisionTextFormat READ copyRevisionTextFormat WRITE setCopyRevisionTextFormat)
Q_PROPERTY(bool isFileLogAnnotateEnabled READ isFileLogAnnotateEnabled WRITE setFileLogAnnotateEnabled)
+ Q_PROPERTY(bool revertDiffChunkEnabled READ isRevertDiffChunkEnabled WRITE setRevertDiffChunkEnabled)
Q_OBJECT
protected:
@@ -145,6 +139,10 @@ public:
QString diffBaseDirectory() const;
void setDiffBaseDirectory(const QString &d);
+ // Diff: Can revert?
+ bool isRevertDiffChunkEnabled() const;
+ void setRevertDiffChunkEnabled(bool e);
+
bool isModified() const;
EditorContentType contentType() const;
@@ -187,12 +185,21 @@ public:
bool setConfigurationWidget(QWidget *w);
QWidget *configurationWidget() const;
+ /* Tagging editors: Sometimes, an editor should be re-used, for example, when showing
+ * a diff of the same file with different diff-options. In order to be able to find
+ * the editor, they get a 'tag' containing type and parameters (dynamic property string). */
+ static void tagEditor(Core::IEditor *e, const QString &tag);
+ static Core::IEditor* locateEditorByTag(const QString &tag);
+ static QString editorTag(EditorContentType t, const QString &workingDirectory, const QStringList &files,
+ const QString &revision = QString());
+
signals:
// These signals also exist in the opaque editable (IEditor) that is
// handled by the editor manager for convenience. They are emitted
// for LogOutput/AnnotateOutput content types.
void describeRequested(const QString &source, const QString &change);
void annotateRevisionRequested(const QString &source, const QString &change, int lineNumber);
+ void diffChunkReverted(const VCSBase::DiffChunk &dc);
public slots:
// Convenience slot to set data read from stdout, will use the
@@ -219,6 +226,7 @@ private slots:
void slotDiffCursorPositionChanged();
void slotAnnotateRevision();
void slotCopyRevision();
+ void slotRevertDiffChunk();
protected:
/* A helper that can be used to locate a file in a diff in case it
@@ -226,6 +234,10 @@ protected:
* source and version control. */
QString findDiffFile(const QString &f, Core::IVersionControl *control = 0) const;
+ virtual bool canRevertDiffChunk(const DiffChunk &dc) const;
+ // Revert a patch chunk. Default implemenation uses patch.exe
+ virtual bool revertDiffChunk(const DiffChunk &dc) const;
+
private:
// Implement to return a set of change identifiers in
// annotation mode
@@ -241,6 +253,8 @@ private:
// Implement to return the previous version[s] of an annotation change
// for "Annotate previous version"
virtual QStringList annotationPreviousVersions(const QString &revision) const;
+ // cut out chunk and determine file name.
+ DiffChunk diffChunk(QTextCursor cursor) const;
void jumpToChangeFromDiff(QTextCursor cursor);
QAction *createDescribeAction(const QString &change);
@@ -252,4 +266,6 @@ private:
} // namespace VCSBase
+Q_DECLARE_METATYPE(VCSBase::DiffChunk)
+
#endif // VCSBASE_BASEEDITOR_H
diff --git a/src/plugins/vcsbase/vcsbaseeditorparameterwidget.cpp b/src/plugins/vcsbase/vcsbaseeditorparameterwidget.cpp
new file mode 100644
index 0000000000..4d29dd1460
--- /dev/null
+++ b/src/plugins/vcsbase/vcsbaseeditorparameterwidget.cpp
@@ -0,0 +1,192 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 "vcsbaseeditorparameterwidget.h"
+
+#include <QtGui/QToolButton>
+#include <QtGui/QHBoxLayout>
+
+#include <QtCore/QDebug>
+
+namespace VCSBase {
+namespace Internal {
+
+/*!
+ \class VCSBase::Internal::VCSBaseEditorParameterToggleButton
+
+ \brief ToggleButton to be inserted into VCSBase::VCSBaseEditorParameterWidget
+
+ Inserts a single option into the argument list depending on whether it is checked.
+*/
+
+class VCSBaseEditorParameterToggleButton : public QToolButton
+{
+ Q_OBJECT
+public:
+ explicit VCSBaseEditorParameterToggleButton(QWidget *parent = 0);
+
+ void applyToArguments(QStringList *w) const;
+ void setFromArguments(const QStringList &a);
+
+ void setOption(const QString &o) { m_option = o; }
+ QString option() const { return m_option; }
+
+signals:
+ void changed();
+
+private:
+ QString m_option;
+};
+
+VCSBaseEditorParameterToggleButton::VCSBaseEditorParameterToggleButton(QWidget *parent) :
+ QToolButton(parent)
+{
+ setCheckable(true);
+ connect(this, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
+}
+
+void VCSBaseEditorParameterToggleButton::applyToArguments(QStringList *a) const
+{
+ if (isChecked()) {
+ if (!a->contains(m_option))
+ a->append(m_option);
+ } else {
+ a->removeAll(m_option);
+ }
+}
+
+void VCSBaseEditorParameterToggleButton::setFromArguments(const QStringList &a)
+{
+ setChecked(a.contains(m_option));
+}
+
+} // namespace Internal
+
+class VCSBaseEditorParameterWidgetPrivate
+{
+public:
+ VCSBaseEditorParameterWidgetPrivate() : m_layout(0) {}
+
+ QStringList m_baseArguments;
+ QHBoxLayout *m_layout;
+ QList<Internal::VCSBaseEditorParameterToggleButton *> m_toggles;
+};
+
+/*!
+ \class VCSBase::VCSBaseEditorParameterWidget
+
+ \brief A toolbar-like widget for use with VCSBase::VCSBaseEditor::setConfigurationWidget()
+ influencing for example the generation of VCS diff output.
+
+ The widget maintains a list of command line arguments (starting from baseArguments())
+ which are set according to the state of the inside widgets. A change signal is provided
+ that should trigger the rerun of the VCS operation.
+*/
+
+VCSBaseEditorParameterWidget::VCSBaseEditorParameterWidget(QWidget *parent) :
+ QWidget(parent), d(new VCSBaseEditorParameterWidgetPrivate)
+{
+ d->m_layout = new QHBoxLayout(this);
+ d->m_layout->setContentsMargins(3, 0, 3, 0);
+ d->m_layout->setSpacing(2);
+}
+
+VCSBaseEditorParameterWidget::~VCSBaseEditorParameterWidget()
+{
+}
+
+QStringList VCSBaseEditorParameterWidget::baseArguments() const
+{
+ return d->m_baseArguments;
+}
+
+void VCSBaseEditorParameterWidget::setBaseArguments(const QStringList &b)
+{
+ d->m_baseArguments = b;
+}
+
+QStringList VCSBaseEditorParameterWidget::arguments() const
+{
+ // Compile effective arguments
+ QStringList args = d->m_baseArguments;
+ foreach (const Internal::VCSBaseEditorParameterToggleButton *tb, d->m_toggles)
+ tb->applyToArguments(&args);
+ return args;
+}
+
+void VCSBaseEditorParameterWidget::addToggleButton(const QString &option,
+ const QString &label,
+ const QString &toolTip)
+{
+ Internal::VCSBaseEditorParameterToggleButton *tb = new Internal::VCSBaseEditorParameterToggleButton;
+ tb->setOption(option);
+ tb->setText(label);
+ tb->setToolTip(toolTip);
+ connect(tb, SIGNAL(changed()), this, SIGNAL(argumentsChanged()));
+ d->m_layout->addWidget(tb);
+ d->m_toggles.append(tb);
+}
+
+void VCSBaseEditorParameterWidget::addIgnoreWhiteSpaceButton(const QString &option)
+{
+ addToggleButton(option, msgIgnoreWhiteSpaceLabel(), msgIgnoreWhiteSpaceToolTip());
+}
+
+void VCSBaseEditorParameterWidget::addIgnoreBlankLinesButton(const QString &option)
+{
+ addToggleButton(option, msgIgnoreBlankLinesLabel(), msgIgnoreBlankLinesToolTip());
+}
+
+QString VCSBaseEditorParameterWidget::msgIgnoreWhiteSpaceLabel()
+{
+ return tr("Ignore whitespace");
+}
+
+QString VCSBaseEditorParameterWidget::msgIgnoreWhiteSpaceToolTip()
+{
+ return tr("Ignore whitespace only changes");
+}
+
+QString VCSBaseEditorParameterWidget::msgIgnoreBlankLinesLabel()
+{
+ return tr("Ignore blank lines ");
+}
+
+QString VCSBaseEditorParameterWidget::msgIgnoreBlankLinesToolTip()
+{
+ return tr("Ignore changes in blank lines");
+}
+
+} // namespace VCSBase
+
+#include "vcsbaseeditorparameterwidget.moc"
diff --git a/src/plugins/vcsbase/vcsbaseeditorparameterwidget.h b/src/plugins/vcsbase/vcsbaseeditorparameterwidget.h
new file mode 100644
index 0000000000..cedaedfec1
--- /dev/null
+++ b/src/plugins/vcsbase/vcsbaseeditorparameterwidget.h
@@ -0,0 +1,80 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 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 VCSBASE_VCSBASEEDITORPARAMETERWIDGET_H
+#define VCSBASE_VCSBASEEDITORPARAMETERWIDGET_H
+
+#include "vcsbase_global.h"
+
+#include <QtGui/QWidget>
+#include <QtCore/QStringList>
+
+namespace VCSBase {
+class VCSBaseEditorParameterWidgetPrivate;
+
+// Documentation->inside.
+class VCSBASE_EXPORT VCSBaseEditorParameterWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit VCSBaseEditorParameterWidget(QWidget *parent = 0);
+ ~VCSBaseEditorParameterWidget();
+
+ QStringList baseArguments() const;
+ void setBaseArguments(const QStringList &);
+
+ void addToggleButton(const QString &option, const QString &label,
+ const QString &tooltip = QString());
+ void addIgnoreWhiteSpaceButton(const QString &option);
+ void addIgnoreBlankLinesButton(const QString &option);
+
+ // Return the effective arguments according to setting.
+ QStringList arguments() const;
+
+ // Standard texts
+ static QString msgIgnoreWhiteSpaceLabel();
+ static QString msgIgnoreWhiteSpaceToolTip();
+ static QString msgIgnoreBlankLinesLabel();
+ static QString msgIgnoreBlankLinesToolTip();
+
+signals:
+ // Trigger a re-run to show changed output according to new argument list.
+ void argumentsChanged();
+
+private:
+ QScopedPointer<VCSBaseEditorParameterWidgetPrivate> d;
+};
+
+} // namespace VCSBase
+
+#endif // VCSBASE_VCSBASEEDITORPARAMETERWIDGET_H
diff --git a/src/plugins/vcsbase/vcsbaseoptionspage.cpp b/src/plugins/vcsbase/vcsbaseoptionspage.cpp
index 80525ee413..070c14b3ef 100644
--- a/src/plugins/vcsbase/vcsbaseoptionspage.cpp
+++ b/src/plugins/vcsbase/vcsbaseoptionspage.cpp
@@ -37,6 +37,12 @@
#include <QtCore/QCoreApplication>
#include <QtGui/QIcon>
+/*!
+ \class VCSBase::VCSBaseOptionsPage
+
+ \brief Base class for VCS options pages providing common category/icon.
+ */
+
namespace VCSBase {
VCSBaseOptionsPage::VCSBaseOptionsPage(QObject *parent) :
diff --git a/src/plugins/vcsbase/vcsbaseoptionspage.h b/src/plugins/vcsbase/vcsbaseoptionspage.h
index 7d41459b6f..d2384a0adf 100644
--- a/src/plugins/vcsbase/vcsbaseoptionspage.h
+++ b/src/plugins/vcsbase/vcsbaseoptionspage.h
@@ -39,9 +39,6 @@
namespace VCSBase {
-/**
- * An abstract options page in the Version Control category.
- */
class VCSBASE_EXPORT VCSBaseOptionsPage : public Core::IOptionsPage
{
Q_OBJECT
diff --git a/src/plugins/vcsbase/vcsbaseoutputwindow.cpp b/src/plugins/vcsbase/vcsbaseoutputwindow.cpp
index bb95e78448..4b3c801c18 100644
--- a/src/plugins/vcsbase/vcsbaseoutputwindow.cpp
+++ b/src/plugins/vcsbase/vcsbaseoutputwindow.cpp
@@ -52,6 +52,21 @@
#include <QtCore/QPoint>
#include <QtCore/QFileInfo>
+/*!
+ \class VCSBase::VCSBaseOutputWindow
+
+ \brief Output window for Version Control System command and other output (Singleton).
+
+ Installed by the base plugin and accessible for the other plugins
+ via static instance()-accessor. Provides slots to append output with
+ special formatting.
+
+ It is possible to associate a repository with plain log text, enabling
+ an "Open" context menu action over relative file name tokens in the text
+ (absolute paths will also work). This can be used for "status" logs,
+ showing modified file names, allowing the user to open them.
+*/
+
namespace VCSBase {
namespace Internal {
diff --git a/src/plugins/vcsbase/vcsbaseoutputwindow.h b/src/plugins/vcsbase/vcsbaseoutputwindow.h
index b932cc5181..f3eb0d838f 100644
--- a/src/plugins/vcsbase/vcsbaseoutputwindow.h
+++ b/src/plugins/vcsbase/vcsbaseoutputwindow.h
@@ -41,15 +41,6 @@ namespace VCSBase {
struct VCSBaseOutputWindowPrivate;
-/* Common OutputWindow for Version Control System command and other output.
- * Installed by the base plugin and accessible for the other plugins
- * via static instance()-accessor. Provides slots to append output with
- * special formatting.
- * It is possible to associate a repository with plain log text, enabling
- * an "Open" context menu action over relative file name tokens in the text
- * (absolute paths will also work). This can be used for "status" logs,
- * showing modified file names, allowing the user to open them. */
-
class VCSBASE_EXPORT VCSBaseOutputWindow : public Core::IOutputPane
{
Q_OBJECT
diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp
index fbb179c63c..e2b8c9a9ce 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.cpp
+++ b/src/plugins/vcsbase/vcsbaseplugin.cpp
@@ -48,6 +48,7 @@
#include <projectexplorer/project.h>
#include <utils/qtcassert.h>
#include <utils/synchronousprocess.h>
+#include <utils/environment.h>
#include <QtCore/QDebug>
#include <QtCore/QDir>
@@ -65,12 +66,27 @@
enum { debug = 0, debugRepositorySearch = 0, debugExecution = 0 };
-namespace VCSBase {
+/*!
+ \namespace VCSBase
+ \brief VCSBase plugin namespace
+*/
+
+/*!
+ \namespace VCSBase::Internal
+ \brief Internal namespace of the VCSBase plugin
+ \internal
+*/
+namespace VCSBase {
namespace Internal {
-// Internal state created by the state listener and
-// VCSBasePluginState.
+/*!
+ \struct VCSBase::Internal::State
+
+ \brief Internal state created by the state listener and VCSBasePluginState.
+
+ Aggregated in the QSharedData of VCSBase::VCSBasePluginState.
+*/
struct State {
void clearFile();
@@ -164,8 +180,14 @@ QDebug operator<<(QDebug in, const State &state)
return in;
}
-// StateListener: Connects to the relevant signals, tries to find version
-// controls and emits signals to the plugin instances.
+/*!
+ \class VCSBase::Internal::StateListener
+
+ \brief Connects to the relevant signals of Qt Creator, tries to find version
+ controls and emits signals to the plugin instances.
+
+ Singleton (as not to do checks multiple times).
+*/
class StateListener : public QObject {
Q_OBJECT
@@ -279,6 +301,21 @@ public:
Internal::State m_state;
};
+/*!
+ \class VCSBase::VCSBasePluginState
+
+ \brief Relevant state information of the VCS plugins
+
+ Qt Creator's state relevant to VCS plugins is a tuple of
+
+ \list
+ \o Current file and it's version system control/top level
+ \o Current project and it's version system control/top level
+ \endlist
+
+ \sa VCSBase::VCSBasePlugin
+*/
+
VCSBasePluginState::VCSBasePluginState() : data(new VCSBasePluginStateData)
{
}
@@ -414,7 +451,34 @@ VCSBASE_EXPORT QDebug operator<<(QDebug in, const VCSBasePluginState &state)
return in;
}
-// VCSBasePlugin
+/*!
+ \class VCSBase::VCSBasePlugin
+
+ \brief Base class for all version control plugins.
+
+ The plugin connects to the
+ relevant change signals in Qt Creator and calls the virtual
+ updateActions() for the plugins to update their menu actions
+ according to the new state. This is done centrally to avoid
+ single plugins repeatedly invoking searches/QFileInfo on files,
+ etc.
+
+ Independently, there are accessors for current patch files, which return
+ a file name if the current file could be a patch file which could be applied
+ and a repository exists.
+
+ If current file/project are managed
+ by different version controls, the project is discarded and only
+ the current file is taken into account, allowing to do a diff
+ also when the project of a file is not opened.
+
+ When triggering an action, a copy of the state should be made to
+ keep it, as it may rapidly change due to context changes, etc.
+
+ The class also detects the VCS plugin submit editor closing and calls
+ the virtual submitEditorAboutToClose() to trigger the submit process.
+*/
+
struct VCSBasePluginPrivate {
explicit VCSBasePluginPrivate(const QString &submitEditorId);
@@ -882,6 +946,54 @@ Utils::SynchronousProcessResponse
return response;
}
+
+bool VCSBasePlugin::runPatch(const QByteArray &input, const QString &workingDirectory,
+ int strip, bool reverse)
+{
+ VCSBaseOutputWindow *ow = VCSBaseOutputWindow::instance();
+ const QString patch = Internal::VCSPlugin::instance()->settings().patchCommand;
+ if (patch.isEmpty()) {
+ ow->appendError(tr("There is no patch-command configured in the commone 'Version Control' settings."));
+ return false;
+ }
+
+ QProcess patchProcess;
+ if (!workingDirectory.isEmpty())
+ patchProcess.setWorkingDirectory(workingDirectory);
+ QStringList args(QLatin1String("-p") + QString::number(strip));
+ if (reverse)
+ args << QLatin1String("-R");
+ ow->appendCommand(QString(), patch, args);
+ patchProcess.start(patch, args);
+ if (!patchProcess.waitForStarted()) {
+ ow->appendError(tr("Unable to launch '%1': %2").arg(patch, patchProcess.errorString()));
+ return false;
+ }
+ patchProcess.write(input);
+ patchProcess.closeWriteChannel();
+ QByteArray stdOut;
+ QByteArray stdErr;
+ if (!Utils::SynchronousProcess::readDataFromProcess(patchProcess, 30000, &stdOut, &stdErr, true)) {
+ Utils::SynchronousProcess::stopProcess(patchProcess);
+ ow->appendError(tr("A timeout occurred running '%1'").arg(patch));
+ return false;
+
+ }
+ if (!stdOut.isEmpty())
+ ow->append(QString::fromLocal8Bit(stdOut));
+ if (!stdErr.isEmpty())
+ ow->append(QString::fromLocal8Bit(stdErr));
+
+ if (patchProcess.exitStatus() != QProcess::NormalExit) {
+ ow->appendError(tr("'%1' crashed.").arg(patch));
+ return false;
+ }
+ if (patchProcess.exitCode() != 0) {
+ ow->appendError(tr("'%1' failed (exit code %2).").arg(patch).arg(patchProcess.exitCode()));
+ return false;
+ }
+ return true;
+}
} // namespace VCSBase
#include "vcsbaseplugin.moc"
diff --git a/src/plugins/vcsbase/vcsbaseplugin.h b/src/plugins/vcsbase/vcsbaseplugin.h
index 8d7326ef1e..05a6e007f3 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.h
+++ b/src/plugins/vcsbase/vcsbaseplugin.h
@@ -64,34 +64,7 @@ struct VCSBasePluginPrivate;
class VCSBasePluginStateData;
class VCSBasePlugin;
-/* VCSBasePlugin and VCSBasePluginState: Provide a base class for
- * VCS plugins. It mainly takes care of maintaining the
- * VCS-relevant state of Qt Creator which is a tuple of
- *
- * 1) Current file and it's version system control/top level
- * 2) Current project and it's version system control/top level
- *
- * (reflected in VCSBasePluginState). The plugin connects to the
- * relevant change signals in Qt Creator and calls the virtual
- * updateActions() for the plugins to update their menu actions
- * according to the new state. This is done centrally to avoid
- * single plugins repeatedly invoking searches/QFileInfo on files,
- * etc.
- * Independently, there are accessors for current patch files, which return
- * a file name if the current file could be a patch file which could be applied
- * and a repository exists.
- *
- * If current file/project are managed
- * by different version controls, the project is discarded and only
- * the current file is taken into account, allowing to do a diff
- * also when the project of a file is not opened.
- *
- * When triggering an action, a copy of the state should be made to
- * keep it, as it may rapidly change due to context changes, etc.
- *
- * The class also detects the VCS plugin submit editor closing and calls
- * the virtual submitEditorAboutToClose() to trigger the submit process. */
-
+// Documentation inside.
class VCSBASE_EXPORT VCSBasePluginState
{
public:
@@ -217,6 +190,10 @@ public:
unsigned flags = 0,
QTextCodec *outputCodec = 0);
+ // Utility to run the 'patch' command
+ static bool runPatch(const QByteArray &input, const QString &workingDirectory = QString(),
+ int strip = 0, bool reverse = false);
+
public slots:
// Convenience slot for "Delete current file" action. Prompts to
// delete the file via VCSManager.
diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
index cd35124c18..79ded14dba 100644
--- a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
+++ b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
@@ -77,6 +77,40 @@
enum { debug = 0 };
enum { wantToolBar = 0 };
+/*!
+ \struct VCSBase::VCSBaseSubmitEditorParameters
+
+ \brief Utility struct to parametrize a VCSBaseSubmitEditor.
+*/
+
+/*!
+ \class VCSBase::VCSBaseSubmitEditor
+
+ \brief Base class for a submit editor based on the Utils::SubmitEditorWidget.
+
+ Presents the commit message in a text editor and an
+ checkable list of modified files in a list window. The user can delete
+ files from the list by pressing unchecking them or diff the selection
+ by doubleclicking.
+
+ The action matching the the ids (unless 0) of the parameter struct will be
+ registered with the EditorWidget and submit/diff actions will be added to
+ a toolbar.
+
+ For the given context, there must be only one instance of the editor
+ active.
+ To start a submit, set the submit template on the editor and the output
+ of the VCS status command listing the modified files as fileList and open
+ it.
+
+ The submit process is started by listening on the editor close
+ signal and then asking the IFile interface of the editor to save the file
+ within a IFileManager::blockFileChange() section
+ and to launch the submit process. In addition, the action registered
+ for submit should be connected to a slot triggering the close of the
+ current editor in the editor manager.
+*/
+
namespace VCSBase {
static inline QString submitMessageCheckScript()
@@ -101,7 +135,6 @@ struct VCSBaseSubmitEditorPrivate
QPointer<QAction> m_submitAction;
Internal::NickNameDialog *m_nickNameDialog;
- Core::Context m_contexts;
};
VCSBaseSubmitEditorPrivate::VCSBaseSubmitEditorPrivate(const VCSBaseSubmitEditorParameters *parameters,
@@ -111,8 +144,7 @@ VCSBaseSubmitEditorPrivate::VCSBaseSubmitEditorPrivate(const VCSBaseSubmitEditor
m_toolWidget(0),
m_parameters(parameters),
m_file(new VCSBase::Internal::SubmitEditorFile(QLatin1String(parameters->mimeType), q)),
- m_nickNameDialog(0),
- m_contexts(parameters->context)
+ m_nickNameDialog(0)
{
}
@@ -120,6 +152,9 @@ VCSBaseSubmitEditor::VCSBaseSubmitEditor(const VCSBaseSubmitEditorParameters *pa
Utils::SubmitEditorWidget *editorWidget) :
m_d(new VCSBaseSubmitEditorPrivate(parameters, editorWidget, this))
{
+ setContext(Core::Context(parameters->context));
+ setWidget(m_d->m_widget);
+
// Message font according to settings
const TextEditor::FontSettings fs = TextEditor::TextEditorSettings::instance()->fontSettings();
QFont font = editorWidget->descriptionEdit()->font();
@@ -392,16 +427,6 @@ QWidget *VCSBaseSubmitEditor::toolBar()
return m_d->m_toolWidget;
}
-Core::Context VCSBaseSubmitEditor::context() const
-{
- return m_d->m_contexts;
-}
-
-QWidget *VCSBaseSubmitEditor::widget()
-{
- return m_d->m_widget;
-}
-
QByteArray VCSBaseSubmitEditor::saveState() const
{
return QByteArray();
diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.h b/src/plugins/vcsbase/vcsbasesubmiteditor.h
index 394e8ab4c5..47f3ef3129 100644
--- a/src/plugins/vcsbase/vcsbasesubmiteditor.h
+++ b/src/plugins/vcsbase/vcsbasesubmiteditor.h
@@ -55,7 +55,6 @@ namespace Internal {
}
struct VCSBaseSubmitEditorPrivate;
-/* Utility struct to parametrize a VCSBaseSubmitEditor. */
struct VCSBASE_EXPORT VCSBaseSubmitEditorParameters {
const char *mimeType;
const char *id;
@@ -63,28 +62,6 @@ struct VCSBASE_EXPORT VCSBaseSubmitEditorParameters {
const char *context;
};
-/* Base class for a submit editor based on the Utils::SubmitEditorWidget
- * that presents the commit message in a text editor and an
- * checkable list of modified files in a list window. The user can delete
- * files from the list by pressing unchecking them or diff the selection
- * by doubleclicking.
- *
- * The action matching the the ids (unless 0) of the parameter struct will be
- * registered with the EditorWidget and submit/diff actions will be added to
- * a toolbar.
- *
- * For the given context, there must be only one instance of the editor
- * active.
- * To start a submit, set the submit template on the editor and the output
- * of the VCS status command listing the modified files as fileList and open
- * it.
- * The submit process is started by listening on the editor close
- * signal and then asking the IFile interface of the editor to save the file
- * within a IFileManager::blockFileChange() section
- * and to launch the submit process. In addition, the action registered
- * for submit should be connected to a slot triggering the close of the
- * current editor in the editor manager. */
-
class VCSBASE_EXPORT VCSBaseSubmitEditor : public Core::IEditor
{
Q_OBJECT
@@ -151,8 +128,6 @@ public:
virtual QString id() const;
virtual QWidget *toolBar();
- virtual Core::Context context() const;
- virtual QWidget *widget();
virtual QByteArray saveState() const;
virtual bool restoreState(const QByteArray &state);
diff --git a/src/plugins/vcsbase/vcsjobrunner.cpp b/src/plugins/vcsbase/vcsjobrunner.cpp
index e3b7738a4c..247a8ccc99 100644
--- a/src/plugins/vcsbase/vcsjobrunner.cpp
+++ b/src/plugins/vcsbase/vcsjobrunner.cpp
@@ -49,6 +49,16 @@
#include <QtCore/QWaitCondition>
#include <QtCore/QSharedPointer>
+/*!
+ \class VCSBase::VCSJob
+
+ \brief Version control system background command execution job.
+
+ Takes arguments, etc. as parameters and emits signals on output/termination.
+
+ \sa VCSBase::VCSJobRunner, VCSBase::VCSBaseClient
+*/
+
namespace VCSBase {
VCSJob::VCSJob(const QString &workingDir,
@@ -127,6 +137,17 @@ void VCSJob::setUnixTerminalDisabled(bool v)
m_unixTerminalDisabled = v;
}
+/*!
+ \class VCSBase::VCSJobRunner
+
+ \brief Job queue for version control system background command execution.
+
+ A job queue running in a separate thread, executing commands
+ and emitting status/log signals.
+
+ \sa VCSBase::VCSJob, VCSBase::VCSBaseClient
+*/
+
class VCSJobRunnerPrivate
{
public:
diff --git a/src/plugins/vcsbase/vcsjobrunner.h b/src/plugins/vcsbase/vcsjobrunner.h
index e6ef46c9c1..6cd06a1ffd 100644
--- a/src/plugins/vcsbase/vcsjobrunner.h
+++ b/src/plugins/vcsbase/vcsjobrunner.h
@@ -94,8 +94,6 @@ private:
bool m_unixTerminalDisabled;
};
-/* A job queue running in a separate thread, executing commands
- * and emitting status/log signals. */
class VCSBASE_EXPORT VCSJobRunner : public QThread
{
Q_OBJECT
diff --git a/src/plugins/welcome/welcome.pro b/src/plugins/welcome/welcome.pro
index 9fcb3be5f9..19a6d8745e 100644
--- a/src/plugins/welcome/welcome.pro
+++ b/src/plugins/welcome/welcome.pro
@@ -1,19 +1,22 @@
TEMPLATE = lib
TARGET = Welcome
QT += network
+
include(../../qtcreatorplugin.pri)
include(welcome_dependencies.pri)
+
HEADERS += welcomeplugin.h \
- welcomemode.h \
communitywelcomepagewidget.h \
communitywelcomepage.h \
welcome_global.h
+
SOURCES += welcomeplugin.cpp \
- welcomemode.cpp \
communitywelcomepagewidget.cpp \
communitywelcomepage.cpp
FORMS += welcomemode.ui \
communitywelcomepagewidget.ui
+
RESOURCES += welcome.qrc
+
DEFINES += WELCOME_LIBRARY
diff --git a/src/plugins/welcome/welcomemode.cpp b/src/plugins/welcome/welcomemode.cpp
deleted file mode 100644
index 9750566db6..0000000000
--- a/src/plugins/welcome/welcomemode.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (info@qt.nokia.com)
-**
-**
-** GNU Lesser General Public License Usage
-**
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this file.
-** Please review the following information to ensure the GNU Lesser General
-** Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**************************************************************************/
-
-#include "welcomemode.h"
-#include "ui_welcomemode.h"
-
-#include <extensionsystem/pluginmanager.h>
-
-#include <coreplugin/icore.h>
-#include <coreplugin/coreconstants.h>
-
-#include <utils/styledbar.h>
-#include <utils/welcomemodetreewidget.h>
-#include <utils/iwelcomepage.h>
-
-#include <QtGui/QScrollArea>
-#include <QtGui/QDesktopServices>
-#include <QtGui/QToolButton>
-#include <QtGui/QPainter>
-
-#include <QtCore/QSettings>
-#include <QtCore/QDebug>
-#include <QtCore/QUrl>
-
-enum { debug = 0 };
-
-using namespace ExtensionSystem;
-
-static const char currentPageSettingsKeyC[] = "General/WelcomeTab";
-
-namespace Welcome {
-
-// Helper class introduced to cache the scaled background image
-// so we avoid re-scaling for every repaint.
-class ImageWidget : public QWidget
-{
-public:
- ImageWidget(const QImage &bg, QWidget *parent) : QWidget(parent), m_bg(bg) {}
- void paintEvent(QPaintEvent *e) {
- if (!m_bg.isNull()) {
- QPainter painter(this);
- if (m_stretch.size() != size())
- m_stretch = QPixmap::fromImage(m_bg.scaled(size(), Qt::IgnoreAspectRatio,
- Qt::SmoothTransformation));
- if (!m_stretch.size().isEmpty())
- painter.drawPixmap(rect(), m_stretch);
- }
- QWidget::paintEvent(e);
- }
-private:
- QImage m_bg;
- QPixmap m_stretch;
-};
-
-struct WelcomeModePrivate
-{
- typedef QMap<QToolButton*, QWidget*> ToolButtonWidgetMap;
-
- WelcomeModePrivate() {}
-
- QScrollArea *m_scrollArea;
- QWidget *m_widget;
- ImageWidget *m_welcomePage;
- ToolButtonWidgetMap buttonMap;
- QHBoxLayout * buttonLayout;
- Ui::WelcomeMode ui;
-};
-
-// --- WelcomeMode
-WelcomeMode::WelcomeMode() :
- m_d(new WelcomeModePrivate)
-{
- m_d->m_widget = new QWidget;
- QVBoxLayout *l = new QVBoxLayout(m_d->m_widget);
- l->setMargin(0);
- l->setSpacing(0);
- l->addWidget(new Utils::StyledBar(m_d->m_widget));
- m_d->m_welcomePage = new ImageWidget(QImage(":/welcome/images/welcomebg.png"), m_d->m_widget);
- m_d->ui.setupUi(m_d->m_welcomePage);
- m_d->ui.helpUsLabel->setAttribute(Qt::WA_LayoutUsesWidgetRect);
- m_d->ui.feedbackButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
- l->addWidget(m_d->m_welcomePage);
-
- m_d->m_scrollArea = new QScrollArea;
- m_d->m_scrollArea->setFrameStyle(QFrame::NoFrame);
- m_d->m_scrollArea->setWidget(m_d->m_widget);
- m_d->m_scrollArea->setWidgetResizable(true);
-
- PluginManager *pluginManager = PluginManager::instance();
- connect(pluginManager, SIGNAL(objectAdded(QObject*)), SLOT(welcomePluginAdded(QObject*)));
-
- connect(m_d->ui.feedbackButton, SIGNAL(clicked()), SLOT(slotFeedback()));
-}
-
-WelcomeMode::~WelcomeMode()
-{
- QSettings *settings = Core::ICore::instance()->settings();
- settings->setValue(QLatin1String(currentPageSettingsKeyC), m_d->ui.stackedWidget->currentIndex());
- delete m_d->m_widget;
- delete m_d;
-}
-
-QString WelcomeMode::displayName() const
-{
- return tr("Welcome");
-}
-
-QIcon WelcomeMode::icon() const
-{
- return QIcon(QLatin1String(Core::Constants::ICON_QTLOGO_32));
-}
-
-int WelcomeMode::priority() const
-{
- return Core::Constants::P_MODE_WELCOME;
-}
-
-QWidget* WelcomeMode::widget()
-{
- return m_d->m_scrollArea;
-}
-
-QString WelcomeMode::id() const
-{
- return QLatin1String(Core::Constants::MODE_WELCOME);
-}
-
-QString WelcomeMode::type() const
-{
- return QLatin1String(Core::Constants::MODE_WELCOME_TYPE);
-}
-
-Core::Context WelcomeMode::context() const
-{
- static Core::Context contexts(Core::Constants::C_WELCOME_MODE);
- return contexts;
-}
-
-bool sortFunction(Utils::IWelcomePage * a, Utils::IWelcomePage *b)
-{
- return a->priority() < b->priority();
-}
-
-// Create a QToolButton for a page
-QToolButton *WelcomeMode::addPageToolButton(Utils::IWelcomePage *plugin, int position)
-{
- QToolButton *btn = new QToolButton;
- btn->setCheckable(true);
- btn->setText(plugin->title());
- btn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
- btn->setAutoExclusive(true);
- connect (btn, SIGNAL(clicked()), SLOT(showClickedPage()));
- m_d->buttonMap.insert(btn, plugin->page());
- if (position >= 0) {
- m_d->buttonLayout->insertWidget(position, btn);
- } else {
- m_d->buttonLayout->addWidget(btn);
- }
- return btn;
-}
-
-QString WelcomeMode::contextHelpId() const
-{
- return QLatin1String("Qt Creator Manual");
-}
-
-void WelcomeMode::initPlugins()
-{
- m_d->buttonLayout = new QHBoxLayout(m_d->ui.navFrame);
- m_d->buttonLayout->setMargin(0);
- m_d->buttonLayout->setSpacing(0);
- QList<Utils::IWelcomePage*> plugins = PluginManager::instance()->getObjects<Utils::IWelcomePage>();
- qSort(plugins.begin(), plugins.end(), &sortFunction);
- foreach (Utils::IWelcomePage *plugin, plugins) {
- m_d->ui.stackedWidget->addWidget(plugin->page());
- addPageToolButton(plugin);
- if (debug)
- qDebug() << "WelcomeMode::initPlugins" << plugin->title();
- }
- QSettings *settings = Core::ICore::instance()->settings();
- const int tabId = settings->value(QLatin1String(currentPageSettingsKeyC), 0).toInt();
-
- const int pluginCount = m_d->ui.stackedWidget->count();
- if (tabId >= 0 && tabId < pluginCount) {
- m_d->ui.stackedWidget->setCurrentIndex(tabId);
- if (QToolButton *btn = m_d->buttonMap.key(m_d->ui.stackedWidget->currentWidget()))
- btn->setChecked(true);
- }
-}
-
-void WelcomeMode::welcomePluginAdded(QObject *obj)
-{
- if (Utils::IWelcomePage *plugin = qobject_cast<Utils::IWelcomePage*>(obj)) {
- int insertPos = 0;
- foreach (Utils::IWelcomePage* p, PluginManager::instance()->getObjects<Utils::IWelcomePage>()) {
- if (plugin->priority() < p->priority())
- insertPos++;
- else
- break;
- }
- m_d->ui.stackedWidget->insertWidget(insertPos, plugin->page());
- addPageToolButton(plugin, insertPos);
- if (debug)
- qDebug() << "welcomePluginAdded" << plugin->title() << "at" << insertPos
- << " of " << m_d->buttonMap.size();
- }
-}
-
-void WelcomeMode::showClickedPage()
-{
- QToolButton *btn = qobject_cast<QToolButton*>(sender());
- const WelcomeModePrivate::ToolButtonWidgetMap::const_iterator it = m_d->buttonMap.constFind(btn);
- if (it != m_d->buttonMap.constEnd())
- m_d->ui.stackedWidget->setCurrentWidget(it.value());
-}
-
-void WelcomeMode::slotFeedback()
-{
- QDesktopServices::openUrl(QUrl(QLatin1String(
- "http://qt.nokia.com/forms/feedback-forms/qt-creator-user-feedback/view")));
-}
-
-} // namespace Welcome
diff --git a/src/plugins/welcome/welcomemode.h b/src/plugins/welcome/welcomemode.h
deleted file mode 100644
index 685415dce4..0000000000
--- a/src/plugins/welcome/welcomemode.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (info@qt.nokia.com)
-**
-**
-** GNU Lesser General Public License Usage
-**
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this file.
-** Please review the following information to ensure the GNU Lesser General
-** Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**************************************************************************/
-
-#ifndef WELCOMEMODE_H
-#define WELCOMEMODE_H
-
-#include "welcome_global.h"
-
-#include <coreplugin/imode.h>
-
-QT_BEGIN_NAMESPACE
-class QWidget;
-class QToolButton;
-QT_END_NAMESPACE
-
-namespace Utils {
- class IWelcomePage;
-}
-namespace Welcome {
-
-struct WelcomeModePrivate;
-
-class WELCOME_EXPORT WelcomeMode : public Core::IMode
-{
- Q_OBJECT
-
-public:
- WelcomeMode();
- ~WelcomeMode();
-
- // IMode
- QString displayName() const;
- QIcon icon() const;
- int priority() const;
- QWidget *widget();
- QString id() const;
- QString type() const;
- Core::Context context() const;
- void activated();
- QString contextHelpId() const;
- void initPlugins();
-
-private slots:
- void slotFeedback();
- void welcomePluginAdded(QObject*);
- void showClickedPage();
-
-private:
- QToolButton *addPageToolButton(Utils::IWelcomePage *plugin, int position = -1);
-
- WelcomeModePrivate *m_d;
-};
-
-} // namespace Welcome
-
-#endif // WELCOMEMODE_H
diff --git a/src/plugins/welcome/welcomeplugin.cpp b/src/plugins/welcome/welcomeplugin.cpp
index 8a1caa363e..2e66a7d31a 100644
--- a/src/plugins/welcome/welcomeplugin.cpp
+++ b/src/plugins/welcome/welcomeplugin.cpp
@@ -31,21 +31,222 @@
**************************************************************************/
#include "welcomeplugin.h"
-#include "welcomemode.h"
+
#include "communitywelcomepage.h"
+#include "ui_welcomemode.h"
+
+#include <extensionsystem/pluginmanager.h>
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/imode.h>
#include <coreplugin/modemanager.h>
+#include <utils/styledbar.h>
+#include <utils/welcomemodetreewidget.h>
+#include <utils/iwelcomepage.h>
+
+#include <QtGui/QScrollArea>
+#include <QtGui/QDesktopServices>
+#include <QtGui/QToolButton>
+#include <QtGui/QPainter>
+
+#include <QtCore/QSettings>
+#include <QtCore/QDebug>
+#include <QtCore/QUrl>
#include <QtCore/QtPlugin>
-using namespace Welcome::Internal;
+enum { debug = 0 };
-WelcomePlugin::WelcomePlugin()
- : m_welcomeMode(0)
+using namespace ExtensionSystem;
+
+namespace Welcome {
+namespace Internal {
+
+// Helper class introduced to cache the scaled background image
+// so we avoid re-scaling for every repaint.
+class ImageWidget : public QWidget
{
+public:
+ explicit ImageWidget(QWidget *parent)
+ : QWidget(parent),
+ m_bg(":/welcome/images/welcomebg.png")
+ {}
+
+ void paintEvent(QPaintEvent *e)
+ {
+ if (!m_bg.isNull()) {
+ QPainter painter(this);
+ if (m_stretch.size() != size())
+ m_stretch = QPixmap::fromImage(m_bg.scaled(size(),
+ Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
+ if (!m_stretch.size().isEmpty())
+ painter.drawPixmap(rect(), m_stretch);
+ }
+ QWidget::paintEvent(e);
+ }
+
+private:
+ QImage m_bg;
+ QPixmap m_stretch;
+};
+
+class WelcomeMode : public Core::IMode
+{
+ Q_OBJECT
+
+public:
+ WelcomeMode();
+ ~WelcomeMode();
+
+ void activated();
+ void initPlugins();
+
+private slots:
+ void slotFeedback();
+ void welcomePluginAdded(QObject*);
+ void showClickedPage();
+
+private:
+ void addPageToolButton(Utils::IWelcomePage *plugin, int position = -1);
+
+ typedef QMap<QToolButton *, QWidget *> ToolButtonWidgetMap;
+
+ QScrollArea m_scrollArea;
+ QWidget m_outerWidget;
+ ImageWidget *m_welcomePage;
+ ToolButtonWidgetMap buttonMap;
+ QHBoxLayout *buttonLayout;
+ Ui::WelcomeMode ui;
+};
+
+static const char currentPageSettingsKeyC[] = "General/WelcomeTab";
+
+// --- WelcomeMode
+WelcomeMode::WelcomeMode()
+{
+ setDisplayName(tr("Welcome"));
+ setIcon(QIcon(QLatin1String(Core::Constants::ICON_QTLOGO_32)));
+ setPriority(Core::Constants::P_MODE_WELCOME);
+ setId(QLatin1String(Core::Constants::MODE_WELCOME));
+ setType(QLatin1String(Core::Constants::MODE_WELCOME_TYPE));
+ setContextHelpId(QLatin1String("Qt Creator Manual"));
+ setContext(Core::Context(Core::Constants::C_WELCOME_MODE));
+ setWidget(&m_scrollArea);
+
+ QVBoxLayout *l = new QVBoxLayout(&m_outerWidget);
+ l->setMargin(0);
+ l->setSpacing(0);
+ l->addWidget(new Utils::StyledBar(&m_outerWidget));
+ m_welcomePage = new ImageWidget(&m_outerWidget);
+ ui.setupUi(m_welcomePage);
+ ui.helpUsLabel->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ ui.feedbackButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ l->addWidget(m_welcomePage);
+
+ m_scrollArea.setFrameStyle(QFrame::NoFrame);
+ m_scrollArea.setWidget(&m_outerWidget);
+ m_scrollArea.setWidgetResizable(true);
+
+ PluginManager *pluginManager = PluginManager::instance();
+ connect(pluginManager, SIGNAL(objectAdded(QObject*)), SLOT(welcomePluginAdded(QObject*)));
+
+ connect(ui.feedbackButton, SIGNAL(clicked()), SLOT(slotFeedback()));
}
-WelcomePlugin::~WelcomePlugin()
+WelcomeMode::~WelcomeMode()
+{
+ QSettings *settings = Core::ICore::instance()->settings();
+ settings->setValue(QLatin1String(currentPageSettingsKeyC), ui.stackedWidget->currentIndex());
+}
+
+bool sortFunction(Utils::IWelcomePage *a, Utils::IWelcomePage *b)
+{
+ return a->priority() < b->priority();
+}
+
+// Create a QToolButton for a page
+void WelcomeMode::addPageToolButton(Utils::IWelcomePage *plugin, int position)
+{
+ QToolButton *btn = new QToolButton;
+ btn->setCheckable(true);
+ btn->setText(plugin->title());
+ btn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ btn->setAutoExclusive(true);
+ connect(btn, SIGNAL(clicked()), SLOT(showClickedPage()));
+ buttonMap.insert(btn, plugin->page());
+ if (position >= 0)
+ buttonLayout->insertWidget(position, btn);
+ else
+ buttonLayout->addWidget(btn);
+}
+
+void WelcomeMode::initPlugins()
+{
+ buttonLayout = new QHBoxLayout(ui.navFrame);
+ buttonLayout->setMargin(0);
+ buttonLayout->setSpacing(0);
+ QList<Utils::IWelcomePage*> plugins = PluginManager::instance()->getObjects<Utils::IWelcomePage>();
+ qSort(plugins.begin(), plugins.end(), &sortFunction);
+ foreach (Utils::IWelcomePage *plugin, plugins) {
+ ui.stackedWidget->addWidget(plugin->page());
+ addPageToolButton(plugin);
+ if (debug)
+ qDebug() << "WelcomeMode::initPlugins" << plugin->title();
+ }
+ QSettings *settings = Core::ICore::instance()->settings();
+ const int tabId = settings->value(QLatin1String(currentPageSettingsKeyC), 0).toInt();
+
+ const int pluginCount = ui.stackedWidget->count();
+ if (tabId >= 0 && tabId < pluginCount) {
+ ui.stackedWidget->setCurrentIndex(tabId);
+ if (QToolButton *btn = buttonMap.key(ui.stackedWidget->currentWidget()))
+ btn->setChecked(true);
+ }
+}
+
+void WelcomeMode::welcomePluginAdded(QObject *obj)
+{
+ Utils::IWelcomePage *plugin = qobject_cast<Utils::IWelcomePage*>(obj);
+ if (!plugin)
+ return;
+
+ int insertPos = 0;
+ QList<Utils::IWelcomePage *> pages
+ = PluginManager::instance()->getObjects<Utils::IWelcomePage>();
+ foreach (Utils::IWelcomePage *p, pages) {
+ if (plugin->priority() >= p->priority())
+ break;
+ insertPos++;
+ }
+ ui.stackedWidget->insertWidget(insertPos, plugin->page());
+ addPageToolButton(plugin, insertPos);
+ if (debug)
+ qDebug() << "welcomePluginAdded" << plugin->title() << "at" << insertPos
+ << " of " << buttonMap.size();
+}
+
+void WelcomeMode::showClickedPage()
+{
+ QToolButton *btn = qobject_cast<QToolButton*>(sender());
+ const ToolButtonWidgetMap::const_iterator it = buttonMap.constFind(btn);
+ if (it != buttonMap.constEnd())
+ ui.stackedWidget->setCurrentWidget(it.value());
+}
+
+void WelcomeMode::slotFeedback()
+{
+ QDesktopServices::openUrl(QUrl(QLatin1String(
+ "http://qt.nokia.com/forms/feedback-forms/qt-creator-user-feedback/view")));
+}
+
+
+//
+
+
+
+WelcomePlugin::WelcomePlugin()
+ : m_welcomeMode(0)
{
}
@@ -82,4 +283,10 @@ void WelcomePlugin::extensionsInitialized()
Core::ModeManager::instance()->activateMode(m_welcomeMode->id());
}
-Q_EXPORT_PLUGIN(WelcomePlugin)
+} // namespace Welcome
+} // namespace Internal
+
+
+Q_EXPORT_PLUGIN(Welcome::Internal::WelcomePlugin)
+
+#include "welcomeplugin.moc"
diff --git a/src/plugins/welcome/welcomeplugin.h b/src/plugins/welcome/welcomeplugin.h
index 1a58c8dce4..e2d1dcd028 100644
--- a/src/plugins/welcome/welcomeplugin.h
+++ b/src/plugins/welcome/welcomeplugin.h
@@ -36,19 +36,17 @@
#include <extensionsystem/iplugin.h>
namespace Welcome {
-class WelcomeMode;
-
namespace Internal {
+class WelcomeMode;
+
class WelcomePlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
public:
WelcomePlugin();
- virtual ~WelcomePlugin();
virtual bool initialize(const QStringList &arguments, QString *error_message);
-
virtual void extensionsInitialized();
private: