diff --git a/src/plugins/analyzerbase/analyzerbase.pro b/src/plugins/analyzerbase/analyzerbase.pro index d224a2518bf..e34290af953 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 a3a44bbdaae..010452d61f7 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 ee40095ef97..bb7c874c042 100644 --- a/src/plugins/analyzerbase/analyzerconstants.h +++ b/src/plugins/analyzerbase/analyzerconstants.h @@ -39,6 +39,13 @@ #include namespace Analyzer { + +enum AnalyzerStartMode +{ + StartLocal, + StartRemote +}; + namespace Constants { // modes and their priorities @@ -49,9 +56,10 @@ 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 START = "Analyzer.Start"; +const char * const STARTREMOTE = "Analyzer.StartRemote"; const char * const STOP = "Analyzer.Stop"; // options dialog @@ -61,8 +69,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 8dd1629e4e7..d05d0862ab3 100644 --- a/src/plugins/analyzerbase/analyzermanager.cpp +++ b/src/plugins/analyzerbase/analyzermanager.cpp @@ -34,13 +34,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 #include @@ -72,6 +76,7 @@ #include #include #include +#include #include #include @@ -93,16 +98,12 @@ #include #include #include +#include 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 = 1 }; - namespace Analyzer { namespace Internal { @@ -194,6 +195,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(); @@ -204,17 +209,19 @@ public: AnalyzerRunControlFactory *m_runControlFactory; ProjectExplorer::RunControl *m_currentRunControl; Utils::FancyMainWindow *m_mainWindow; - QList m_tools; + QList m_tools; QActionGroup *m_toolGroup; QAction *m_startAction; + QAction *m_startRemoteAction; QAction *m_stopAction; QMenu *m_menu; QComboBox *m_toolBox; + QStackedWidget *m_controlsWidget; ActionContainer *m_viewsMenu; Utils::StatusLabel *m_statusLabel; - typedef QPair ToolWidgetPair; + typedef QPair ToolWidgetPair; typedef QList ToolWidgetPairList; - QMap m_toolWidgets; + QMap m_toolWidgets; DockWidgetEventFilter *m_resizeEventFilter; QMap m_defaultSettings; @@ -222,6 +229,7 @@ public: typedef QWeakPointer DockPtr; QList m_dockWidgets; + bool m_restartOnStop; bool m_initialized; }; @@ -234,19 +242,22 @@ 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 *))); + connect(m_runControlFactory, SIGNAL(runControlCreated(Analyzer::AnalyzerRunControl *)), + q, SLOT(runControlCreated(Analyzer::AnalyzerRunControl *))); connect(m_toolBox, SIGNAL(currentIndexChanged(int)), q, SLOT(toolSelected(int))); @@ -269,7 +280,16 @@ 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); + Core::ActionContainer *mAnalyzermenu = 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(); @@ -281,18 +301,24 @@ void AnalyzerManager::AnalyzerManagerPrivate::setupActions() 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); 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); + mAnalyzermenu->addAction(command); + 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); connect(m_stopAction, SIGNAL(triggered()), q, SLOT(stopTool())); @@ -307,17 +333,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()); @@ -342,18 +366,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()), @@ -378,6 +392,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); @@ -396,7 +438,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); @@ -411,22 +453,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) @@ -443,9 +476,29 @@ 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); + QTC_ASSERT(q->currentTool(), return); + // make sure our mode is shown m_outputpane->popup(); if (m_mode) @@ -468,14 +521,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("
%1 is still running. You have to quit the Analyzer before being able to run another instance.
" + "
Force it to quit?
").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(); @@ -506,11 +575,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; @@ -521,9 +588,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())); @@ -541,8 +607,7 @@ bool AnalyzerManager::isInitialized() const void AnalyzerManager::shutdown() { - if (useAnalyzeMode) - saveToolSettings(currentTool()); + saveToolSettings(currentTool()); } AnalyzerManager * AnalyzerManager::instance() @@ -575,7 +640,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(); @@ -595,17 +660,17 @@ 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; } @@ -627,23 +692,27 @@ void AnalyzerManager::addTool(IAnalyzerTool *tool) 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); @@ -676,6 +745,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()); @@ -688,20 +776,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 @@ -745,6 +834,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) @@ -769,4 +864,10 @@ 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); +} + #include "analyzermanager.moc" diff --git a/src/plugins/analyzerbase/analyzermanager.h b/src/plugins/analyzerbase/analyzermanager.h index 8f9b8af2931..d18e32564d5 100644 --- a/src/plugins/analyzerbase/analyzermanager.h +++ b/src/plugins/analyzerbase/analyzermanager.h @@ -53,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 @@ -88,23 +94,27 @@ public: void selectTool(IAnalyzerTool *tool); - void addOutputPaneToolBarWidgets(QList *) 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); + public slots: + void startTool(); + void startToolRemote(); + void stopTool(); + void showStatusMessage(const QString &message, int timeoutMS = 10000); void showPermanentStatusMessage(const QString &message); - void startTool(); - void stopTool(); private slots: 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); diff --git a/src/plugins/analyzerbase/analyzeroutputpane.cpp b/src/plugins/analyzerbase/analyzeroutputpane.cpp index 8698160c479..c1263d37f30 100644 --- a/src/plugins/analyzerbase/analyzeroutputpane.cpp +++ b/src/plugins/analyzerbase/analyzeroutputpane.cpp @@ -32,8 +32,12 @@ **************************************************************************/ #include "analyzeroutputpane.h" + +#include "analyzerconstants.h" #include "analyzermanager.h" +#include "analyzerutils.h" #include "ianalyzertool.h" +#include "ianalyzeroutputpaneadapter.h" #include #include @@ -46,20 +50,13 @@ #include #include -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 @@ -97,7 +94,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")); } @@ -106,8 +104,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(); @@ -115,27 +113,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(); @@ -160,7 +158,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) @@ -174,13 +172,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(); } @@ -208,17 +205,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); } @@ -230,7 +229,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 8773d5205c1..90150240fad 100644 --- a/src/plugins/analyzerbase/analyzeroutputpane.h +++ b/src/plugins/analyzerbase/analyzeroutputpane.h @@ -57,7 +57,7 @@ public: void setTool(IAnalyzerTool *t); // IOutputPane virtual QWidget *outputWidget(QWidget *parent); - virtual QList toolBarWidgets() const; + virtual QList toolBarWidgets() const; virtual QString displayName() const; virtual int priorityInStatusBar() const; @@ -93,6 +93,8 @@ private: QList 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 62d8f7b1270..0aaf8e38445 100644 --- a/src/plugins/analyzerbase/analyzerplugin.cpp +++ b/src/plugins/analyzerbase/analyzerplugin.cpp @@ -37,7 +37,9 @@ #include "analyzerconstants.h" #include "analyzermanager.h" #include "analyzeroutputpane.h" +#include "ianalyzertool.h" +#include #include #include #include @@ -54,6 +56,7 @@ using namespace Analyzer; using namespace Analyzer::Internal; +static const QLatin1String lastActiveToolC("Analyzer.Plugin.LastActiveTool"); AnalyzerPlugin *AnalyzerPlugin::m_instance = 0; @@ -117,9 +120,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; } @@ -128,14 +128,33 @@ 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) + + QSettings *settings = Core::ICore::instance()->settings(); + settings->setValue(lastActiveToolC, d->m_manager->currentTool()->id()); + + d->m_manager->shutdown(); return SynchronousShutdown; } diff --git a/src/plugins/analyzerbase/analyzerplugin.h b/src/plugins/analyzerbase/analyzerplugin.h index cbeb1ab1e67..82011f3e4c0 100644 --- a/src/plugins/analyzerbase/analyzerplugin.h +++ b/src/plugins/analyzerbase/analyzerplugin.h @@ -50,10 +50,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 794b6107da1..1097e1324a8 100644 --- a/src/plugins/analyzerbase/analyzerrunconfigwidget.cpp +++ b/src/plugins/analyzerbase/analyzerrunconfigwidget.cpp @@ -50,7 +50,7 @@ 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); @@ -79,11 +79,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 969d4687d3d..e99b40e0c3e 100644 --- a/src/plugins/analyzerbase/analyzerrunconfigwidget.h +++ b/src/plugins/analyzerbase/analyzerrunconfigwidget.h @@ -41,10 +41,6 @@ QT_BEGIN_NAMESPACE class QStandardItemModel; - -namespace Ui { -class AnalyzerConfigWidget; -} QT_END_NAMESPACE namespace Utils { diff --git a/src/plugins/analyzerbase/analyzerruncontrol.cpp b/src/plugins/analyzerbase/analyzerruncontrol.cpp index 55058f13ebf..926267a90b8 100644 --- a/src/plugins/analyzerbase/analyzerruncontrol.cpp +++ b/src/plugins/analyzerbase/analyzerruncontrol.cpp @@ -37,10 +37,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 #include @@ -50,88 +48,54 @@ #include #include -#include -#include -#include using namespace Analyzer; using namespace Analyzer::Internal; -// AnalyzerRunControlFactory //////////////////////////////////////////////////// -AnalyzerRunControlFactory::AnalyzerRunControlFactory(QObject *parent) - : IRunControlFactory(parent) +// AnalyzerRunControl::Private /////////////////////////////////////////// + +class AnalyzerRunControl::Private { +public: + Private(); + + bool m_isRunning; + IAnalyzerEngine *m_engine; +}; + +AnalyzerRunControl::Private::Private() +: m_isRunning(false) +, m_engine(0) { + } -bool AnalyzerRunControlFactory::canRun(RunConfiguration *runConfiguration, const QString &mode) const -{ - if (!qobject_cast(runConfiguration)) - return false; - return mode == Constants::MODE_ANALYZE; -} - -ProjectExplorer::RunControl *AnalyzerRunControlFactory::create(RunConfiguration *runConfiguration, - const QString &mode) -{ - if (!qobject_cast(runConfiguration) || - mode != Constants::MODE_ANALYZE) { - return 0; - } - AnalyzerRunControl *rc = new AnalyzerRunControl(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(runConfiguration); - if (!localRc) - return 0; - AnalyzerProjectSettings *settings = runConfiguration->extraAspect(); - 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 m_engine; + + delete d->m_engine; + d->m_engine = 0; } void AnalyzerRunControl::start() @@ -141,32 +105,35 @@ void AnalyzerRunControl::start() ProjectExplorer::TaskHub *hub = pm->getObject(); 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 diff --git a/src/plugins/analyzerbase/analyzerruncontrol.h b/src/plugins/analyzerbase/analyzerruncontrol.h index 03333d06a58..c9567f11ced 100644 --- a/src/plugins/analyzerbase/analyzerruncontrol.h +++ b/src/plugins/analyzerbase/analyzerruncontrol.h @@ -36,54 +36,26 @@ #ifndef ANALYZERRUNCONTROL_H #define ANALYZERRUNCONTROL_H -#include "analyzerconstants.h" +#include "analyzerbase_global.h" -#include +#include #include #include -#include - 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 @@ -103,12 +75,10 @@ private slots: void engineFinished(); private: - bool m_isRunning; - IAnalyzerEngine *m_engine; + class Private; + QScopedPointer 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 00000000000..e919c82f62b --- /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 + +#include + +#include + +using namespace Analyzer; +using namespace Analyzer::Internal; + +AnalyzerStartParameters localStartParameters(ProjectExplorer::RunConfiguration *runConfiguration) +{ + AnalyzerStartParameters sp; + QTC_ASSERT(runConfiguration, return sp); + ProjectExplorer::LocalApplicationRunConfiguration *rc = + qobject_cast(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(runConfiguration)) + return false; + return mode == Constants::MODE_ANALYZE; +} + +ProjectExplorer::RunControl *AnalyzerRunControlFactory::create(RunConfiguration *runConfiguration, + const QString &mode) +{ + if (!qobject_cast(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(runConfiguration); + if (!localRc) + return 0; + AnalyzerProjectSettings *settings = runConfiguration->extraAspect(); + 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 00000000000..02da795d305 --- /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 + +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 de2fce9e9d9..fae468d7512 100644 --- a/src/plugins/analyzerbase/analyzersettings.h +++ b/src/plugins/analyzerbase/analyzersettings.h @@ -59,6 +59,9 @@ template 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 { @@ -67,12 +70,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; }; @@ -84,17 +93,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); + * bool MemcheckPlugin::initialize(const QStringList &arguments, QString *errorString) + * { + * typedef AnalyzerSubConfigFactory YourConfigFactory; + * AnalyzerGlobalSettings::instance()->registerSubConfigFactory(new YourConfigFactory); + * } * @endcode */ template @@ -126,7 +139,7 @@ public: virtual ~AnalyzerSettings(); template - T* subConfig() const + T *subConfig() const { return findChild(); } @@ -155,6 +168,11 @@ protected: // differently. /** * Global settings + * + * To access your custom configuration use: + * @code + * AnalyzerGlobalSettings::instance()->subConfig()->... + * @endcode */ class ANALYZER_EXPORT AnalyzerGlobalSettings : public AnalyzerSettings { @@ -177,6 +195,12 @@ private: /** * Settings associated with a single project/run configuration + * + * To access your custom configuration use: + * @code + * ProjectExplorer::RunConfiguration *rc = ...; + * rc->extraAspect()->subConfig()->... + * @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 00000000000..59bab574274 --- /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 + +#include +#include + +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 00000000000..3cf8c8b1d7f --- /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 +#include +#include +#include +#include + +#include +#include +#include +#include + +// shared/cplusplus includes +#include +#include + +#include +#include +#include + +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(editor); + if (!textEditor) + return 0; + TextEditor::BaseTextEditorWidget *editorWidget = qobject_cast(editor->widget()); + if (!editorWidget) + return 0; + + QPlainTextEdit *ptEdit = qobject_cast(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 &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 00000000000..38b5bb3c680 --- /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 c68eac8d213..b55e1a595c2 100644 --- a/src/plugins/analyzerbase/ianalyzerengine.cpp +++ b/src/plugins/analyzerbase/ianalyzerengine.cpp @@ -37,9 +37,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() { } @@ -47,3 +52,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 75b06dff179..00ae2e67087 100644 --- a/src/plugins/analyzerbase/ianalyzerengine.h +++ b/src/plugins/analyzerbase/ianalyzerengine.h @@ -37,8 +37,10 @@ #define IANALYZERENGINE_H #include "analyzerbase_global.h" +#include "analyzerstartparameters.h" #include +#include #include #include @@ -49,28 +51,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); +public: + 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 00000000000..bf3119a04a6 --- /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 + +#include +#include +#include +#include + +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 00000000000..8ed6d76baf5 --- /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 + +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 99d929218fa..7e8d25e9428 100644 --- a/src/plugins/analyzerbase/ianalyzertool.cpp +++ b/src/plugins/analyzerbase/ianalyzertool.cpp @@ -34,163 +34,12 @@ **************************************************************************/ #include "ianalyzertool.h" -#include "analyzeroutputpane.h" - -#include - -#include -#include -#include -#include namespace Analyzer { -IAnalyzerTool::IAnalyzerTool(QObject *parent) : - QObject(parent) +QString IAnalyzerTool::modeString(ToolMode mode) { -} - -/*! - \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; -} - -// -------------IAnalyzerTool -QString IAnalyzerTool::modeString() -{ - switch (mode()) { + switch (mode) { case IAnalyzerTool::DebugMode: return tr("Debug"); case IAnalyzerTool::ReleaseMode: @@ -206,4 +55,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 849abde0568..b4f083637b5 100644 --- a/src/plugins/analyzerbase/ianalyzertool.h +++ b/src/plugins/analyzerbase/ianalyzertool.h @@ -40,9 +40,6 @@ #include -QT_FORWARD_DECLARE_CLASS(QAbstractItemView) -QT_FORWARD_DECLARE_CLASS(QAbstractItemModel) - namespace ProjectExplorer { class RunConfiguration; } @@ -52,79 +49,36 @@ class IPlugin; } namespace Analyzer { + +class AnalyzerStartParameters; +class IAnalyzerOutputPaneAdapter; 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; -}; - +/** + * 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 { @@ -134,13 +88,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(); - virtual IAnalyzerEngine *createEngine(ProjectExplorer::RunConfiguration *runConfiguration) = 0; + /// @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; + + /// @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 00000000000..3c51231fbc6 --- /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 + +#include + +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 00000000000..ad92857f922 --- /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 + +#include + +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 00000000000..dad3f4adf6e --- /dev/null +++ b/src/plugins/analyzerbase/startremotedialog.ui @@ -0,0 +1,178 @@ + + + Analyzer::StartRemoteDialog + + + + 0 + 0 + 446 + 296 + + + + Start Debugger + + + + + + Remote + + + + QFormLayout::ExpandingFieldsGrow + + + + + Host: + + + host + + + + + + + + + + User: + + + user + + + + + + + + + + You need to pass either a password or a SSH Key. + + + Password: + + + password + + + + + + + QLineEdit::Password + + + + + + + Port + + + port + + + + + + + 65535 + + + 1 + + + 22 + + + + + + + You need to pass either a password or a SSH Key. + + + Private Key: + + + + + + + + + + + + + Target + + + + + + Executable: + + + + + + + + + + Arguments: + + + + + + + + + + Working Directory: + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + Utils::PathChooser + QWidget +
utils/pathchooser.h
+ 1 +
+
+ + host + user + password + buttonBox + + + +