Add analyzer multiple tools, mode & remote support

Merge-request: 284
Reviewed-by: hjk <qtc-committer@nokia.com>
This commit is contained in:
Mike McQuaid
2011-04-04 14:39:28 +02:00
committed by hjk
parent 7554105eee
commit 678d1cc9c9
28 changed files with 1573 additions and 466 deletions

View File

@@ -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

View File

@@ -1,2 +1,3 @@
include(../../plugins/coreplugin/coreplugin.pri)
include(../../libs/cplusplus/cplusplus.pri)
include(../../plugins/projectexplorer/projectexplorer.pri)

View File

@@ -39,6 +39,13 @@
#include <QtCore/QtGlobal>
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

View File

@@ -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 <coreplugin/actionmanager/command.h>
#include <coreplugin/findplaceholder.h>
@@ -72,6 +76,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>
@@ -93,16 +98,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 = 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();
@@ -207,9 +212,11 @@ public:
QList<IAnalyzerTool *> 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<Qt::DockWidgetArea, QDockWidget *> ToolWidgetPair;
@@ -222,6 +229,7 @@ public:
typedef QWeakPointer<QDockWidget> DockPtr;
QList<DockPtr> 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_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("<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();
@@ -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,7 +588,6 @@ 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*)));
ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance();
@@ -541,7 +607,6 @@ bool AnalyzerManager::isInitialized() const
void AnalyzerManager::shutdown()
{
if (useAnalyzeMode)
saveToolSettings(currentTool());
}
@@ -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);
}
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);
}
}
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();
// 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"

View File

@@ -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<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);
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);

View File

@@ -32,8 +32,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>
@@ -46,20 +50,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
@@ -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()) {
popup(false);
setCurrentIndex(index);
}
if (isInitialized())
popup(false);
} 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;
}

View File

@@ -93,6 +93,8 @@ private:
QList<IAnalyzerOutputPaneAdapter *> m_adapters;
QStackedWidget *m_toolbarStackedWidget;
Utils::StyledSeparator *m_toolBarSeparator;
// tracks selected index during !isInitialized() state
int m_delayedCurrentIndex;
};
} // namespace Internal

View File

@@ -37,7 +37,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>
@@ -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;
}

View File

@@ -50,10 +50,11 @@ public:
static AnalyzerPlugin *instance();
AnalyzerPlugin();
~AnalyzerPlugin();
virtual ~AnalyzerPlugin();
bool initialize(const QStringList &arguments, QString *errorString);
void extensionsInitialized();
ShutdownFlag aboutToShutdown();
private:

View File

@@ -41,10 +41,6 @@
QT_BEGIN_NAMESPACE
class QStandardItemModel;
namespace Ui {
class AnalyzerConfigWidget;
}
QT_END_NAMESPACE
namespace Utils {

View File

@@ -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 <extensionsystem/pluginmanager.h>
#include <projectexplorer/applicationrunconfiguration.h>
@@ -50,88 +48,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 ///////////////////////////////////////////
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<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;
}
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<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 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<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

View File

@@ -36,54 +36,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
@@ -103,12 +75,10 @@ private slots:
void engineFinished();
private:
bool m_isRunning;
IAnalyzerEngine *m_engine;
class Private;
QScopedPointer<Private> d;
};
} // namespace Internal
} // namespace Analyzer
#endif // ANALYZERRUNCONTROL_H

View File

@@ -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;
}

View File

@@ -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

View File

@@ -59,6 +59,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
{
@@ -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<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>
@@ -155,6 +168,11 @@ protected:
// differently.
/**
* Global settings
*
* To access your custom configuration use:
* @code
* AnalyzerGlobalSettings::instance()->subConfig<YourGlobalConfig>()->...
* @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<AnalyzerProjectSettings>()->subConfig<YourProjectConfig>()->...
* @endcode
*/
class ANALYZER_EXPORT AnalyzerProjectSettings : public AnalyzerSettings, public ProjectExplorer::IRunConfigurationAspect
{

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -37,8 +37,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>
@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -34,163 +34,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)
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

View File

@@ -40,9 +40,6 @@
#include <QtCore/QObject>
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

View File

@@ -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();
}
}

View File

@@ -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

View File

@@ -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>