Debugger: Merge debug mode and analyze mode

On the user-visible side, only the 'Analyze' mode button disappears,
and instead a combobox to switch between different tools in appears
in the Debug mode toolbar.

Internally, that's quite some re-organzition: The centralized
'Analyze mode is busy' flag is gone, allowing us to run e.g.
ClangStaticAnalyzer and MemCheck in parallel.

Analyzer tools and debugger now share the same mechanism to
generate/load/save dock widgets.

Analyzer tools now create and handle their own start/stop button
when appropriate. In general, Analyzer tools can create/handle more
than one run control at a time.

Further consolidation is possible, e.g. RunControl state handling
could be merged into the base ProjectExplorer::RunControl to
avoid the still existing duplication in ~15 instances.

Change-Id: I91e5940ebc4211f98056d507cf2f7b5f8efe7f07
Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
This commit is contained in:
hjk
2016-03-02 13:57:37 +01:00
parent c326011feb
commit 92e301a054
79 changed files with 2135 additions and 2642 deletions

View File

@@ -74,7 +74,7 @@ LocalQmlProfilerRunner::LocalQmlProfilerRunner(const Configuration &configuratio
engine, &QmlProfilerRunControl::notifyRemoteFinished);
connect(this, &LocalQmlProfilerRunner::appendMessage,
engine, &QmlProfilerRunControl::logApplicationMessage);
connect(engine, &Analyzer::AnalyzerRunControl::starting,
connect(engine, &Debugger::AnalyzerRunControl::starting,
this, &LocalQmlProfilerRunner::start);
connect(engine, &RunControl::finished,
this, &LocalQmlProfilerRunner::stop);

View File

@@ -34,8 +34,6 @@
#include <QtPlugin>
using namespace Analyzer;
namespace QmlProfiler {
namespace Internal {

View File

@@ -53,7 +53,7 @@ ProjectExplorer::IRunConfigurationAspect *QmlProfilerRunConfigurationAspect::cre
ProjectExplorer::RunConfigWidget *QmlProfilerRunConfigurationAspect::createConfigurationWidget()
{
return new Analyzer::AnalyzerRunConfigWidget(this);
return new Debugger::AnalyzerRunConfigWidget(this);
}
} // Internal

View File

@@ -51,7 +51,7 @@
#include <QMessageBox>
#include <QPushButton>
using namespace Analyzer;
using namespace Debugger;
using namespace Core;
using namespace ProjectExplorer;
@@ -102,16 +102,16 @@ QmlProfilerRunControl::QmlProfilerRunControl(RunConfiguration *runConfiguration,
QmlProfilerRunControl::~QmlProfilerRunControl()
{
if (d->m_profilerState)
stopEngine();
stop();
delete d;
}
bool QmlProfilerRunControl::startEngine()
void QmlProfilerRunControl::start()
{
d->m_tool->finalizeRunControl(this);
QTC_ASSERT(d->m_profilerState, return false);
QTC_ASSERT(d->m_profilerState, finished(); return);
QTC_ASSERT(connection().is<AnalyzerConnection>(), return false);
QTC_ASSERT(connection().is<AnalyzerConnection>(), finished(); return);
auto conn = connection().as<AnalyzerConnection>();
if (conn.analyzerPort != 0)
@@ -120,13 +120,14 @@ bool QmlProfilerRunControl::startEngine()
d->m_noDebugOutputTimer.start();
d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppRunning);
d->m_running = true;
emit starting();
return true;
}
void QmlProfilerRunControl::stopEngine()
RunControl::StopResult QmlProfilerRunControl::stop()
{
QTC_ASSERT(d->m_profilerState, return);
d->m_running = false;
QTC_ASSERT(d->m_profilerState, return RunControl::StoppedSynchronously);
switch (d->m_profilerState->currentState()) {
case QmlProfilerStateManager::AppRunning:
@@ -147,6 +148,13 @@ void QmlProfilerRunControl::stopEngine()
}
break;
}
return RunControl::StoppedSynchronously;
}
bool QmlProfilerRunControl::isRunning() const
{
return d->m_running;
}
void QmlProfilerRunControl::notifyRemoteFinished()
@@ -156,7 +164,6 @@ void QmlProfilerRunControl::notifyRemoteFinished()
switch (d->m_profilerState->currentState()) {
case QmlProfilerStateManager::AppRunning:
d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying);
AnalyzerManager::stopTool();
emit finished();
break;
case QmlProfilerStateManager::Idle:
@@ -215,7 +222,6 @@ void QmlProfilerRunControl::wrongSetupMessageBox(const QString &errorMessage)
// KILL
d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying);
d->m_noDebugOutputTimer.stop();
AnalyzerManager::stopTool();
emit finished();
}
@@ -270,12 +276,4 @@ void QmlProfilerRunControl::profilerStateChanged()
}
}
RunControl::StopResult QmlProfilerRunControl::stop()
{
StopResult result = Analyzer::AnalyzerRunControl::stop();
if (d->m_profilerState->currentState() != QmlProfilerStateManager::Idle)
m_isRunning = true;
return result;
}
} // namespace QmlProfiler

View File

@@ -35,7 +35,7 @@ namespace QmlProfiler {
namespace Internal { class QmlProfilerTool; }
class QmlProfilerRunControl : public Analyzer::AnalyzerRunControl
class QmlProfilerRunControl : public Debugger::AnalyzerRunControl
{
Q_OBJECT
@@ -47,25 +47,22 @@ public:
void registerProfilerStateManager( QmlProfilerStateManager *profilerState );
void notifyRemoteSetupDone(quint16 port) override;
void start() override;
StopResult stop() override;
signals:
void processRunning(quint16 port);
public slots:
bool startEngine() override;
void stopEngine() override;
bool isRunning() const override;
void cancelProcess();
void notifyRemoteFinished() override;
void logApplicationMessage(const QString &msg, Utils::OutputFormat format) override;
private slots:
signals:
void processRunning(quint16 port);
private:
void wrongSetupMessageBox(const QString &errorMessage);
void wrongSetupMessageBoxFinished(int);
void processIsRunning(quint16 port);
void profilerStateChanged();
private:
class QmlProfilerRunControlPrivate;
QmlProfilerRunControlPrivate *d;
};

View File

@@ -45,7 +45,7 @@
#include <utils/qtcassert.h>
using namespace Analyzer;
using namespace Debugger;
using namespace ProjectExplorer;
namespace QmlProfiler {
@@ -94,7 +94,7 @@ RunControl *QmlProfilerRunControlFactory::create(RunConfiguration *runConfigurat
}
auto runControl = qobject_cast<QmlProfilerRunControl *>
(AnalyzerManager::createRunControl(runConfiguration, mode));
(Debugger::createAnalyzerRunControl(runConfiguration, mode));
QTC_ASSERT(runControl, return 0);
runControl->setRunnable(runnable);

View File

@@ -82,8 +82,8 @@
using namespace Core;
using namespace Core::Constants;
using namespace Analyzer;
using namespace Analyzer::Constants;
using namespace Debugger;
using namespace Debugger::Constants;
using namespace QmlProfiler::Constants;
using namespace QmlDebug;
using namespace ProjectExplorer;
@@ -103,6 +103,8 @@ public:
QToolButton *m_recordButton = 0;
QMenu *m_recordFeaturesMenu = 0;
QAction *m_startAction = 0;
QAction *m_stopAction = 0;
QToolButton *m_clearButton = 0;
// elapsed time display
@@ -120,6 +122,8 @@ public:
// save and load actions
QAction *m_saveQmlTrace = 0;
QAction *m_loadQmlTrace = 0;
bool m_toolBusy = false;
};
QmlProfilerTool::QmlProfilerTool(QObject *parent)
@@ -176,8 +180,6 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
d->m_recordingTimer.setInterval(100);
connect(&d->m_recordingTimer, &QTimer::timeout, this, &QmlProfilerTool::updateTimeDisplay);
d->m_viewContainer = new QmlProfilerViewManager(this,
d->m_profilerModelManager,
d->m_profilerState);
@@ -187,14 +189,7 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
//
// Toolbar
//
QWidget *toolbarWidget = new QWidget;
toolbarWidget->setObjectName(QLatin1String("QmlProfilerToolBarWidget"));
QHBoxLayout *layout = new QHBoxLayout;
layout->setMargin(0);
layout->setSpacing(0);
d->m_recordButton = new QToolButton(toolbarWidget);
d->m_recordButton = new QToolButton;
d->m_recordButton->setCheckable(true);
connect(d->m_recordButton,&QAbstractButton::clicked,
@@ -207,9 +202,8 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
this, &QmlProfilerTool::toggleRequestedFeature);
setRecording(d->m_profilerState->clientRecording());
layout->addWidget(d->m_recordButton);
d->m_clearButton = new QToolButton(toolbarWidget);
d->m_clearButton = new QToolButton;
d->m_clearButton->setIcon(Icons::CLEAN_PANE.icon());
d->m_clearButton->setToolTip(tr("Discard data"));
@@ -218,12 +212,9 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
clearData();
});
layout->addWidget(d->m_clearButton);
d->m_searchButton = new QToolButton;
d->m_searchButton->setIcon(Icons::ZOOM.icon());
d->m_searchButton->setToolTip(tr("Search timeline event notes."));
layout->addWidget(d->m_searchButton);
connect(d->m_searchButton, &QToolButton::clicked, this, &QmlProfilerTool::showTimeLineSearch);
@@ -236,7 +227,6 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
d->m_displayFeaturesButton->setMenu(d->m_displayFeaturesMenu);
connect(d->m_displayFeaturesMenu, &QMenu::triggered,
this, &QmlProfilerTool::toggleVisibleFeature);
layout->addWidget(d->m_displayFeaturesButton);
d->m_timeLabel = new QLabel();
QPalette palette;
@@ -244,11 +234,7 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
d->m_timeLabel->setPalette(palette);
d->m_timeLabel->setIndent(10);
updateTimeDisplay();
layout->addWidget(d->m_timeLabel);
layout->addStretch();
toolbarWidget->setLayout(layout);
setAvailableFeatures(d->m_profilerModelManager->availableFeatures());
setRecordedFeatures(0);
@@ -263,6 +249,9 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
QString description = tr("The QML Profiler can be used to find performance "
"bottlenecks in applications using QML.");
d->m_startAction = Debugger::createStartAction();
d->m_stopAction = Debugger::createStopAction();
ActionDescription desc;
desc.setText(tr("QML Profiler"));
desc.setToolTip(description);
@@ -270,8 +259,8 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
desc.setRunControlCreator(runControlCreator);
desc.setToolPreparer([this] { return prepareTool(); });
desc.setRunMode(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_TOOLS);
AnalyzerManager::registerAction(Constants::QmlProfilerLocalActionId, desc);
desc.setMenuGroup(Debugger::Constants::G_ANALYZER_TOOLS);
Debugger::registerAction(Constants::QmlProfilerLocalActionId, desc, d->m_startAction);
desc.setText(tr("QML Profiler (External)"));
desc.setToolTip(description);
@@ -280,10 +269,21 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
desc.setCustomToolStarter([this](RunConfiguration *rc) { startRemoteTool(rc); });
desc.setToolPreparer([this] { return prepareTool(); });
desc.setRunMode(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_REMOTE_TOOLS);
AnalyzerManager::registerAction(Constants::QmlProfilerRemoteActionId, desc);
desc.setMenuGroup(Debugger::Constants::G_ANALYZER_REMOTE_TOOLS);
Debugger::registerAction(Constants::QmlProfilerRemoteActionId, desc);
AnalyzerManager::registerToolbar(Constants::QmlProfilerPerspectiveId, toolbarWidget);
Utils::ToolbarDescription toolbar;
toolbar.addAction(d->m_startAction);
toolbar.addAction(d->m_stopAction);
toolbar.addWidget(d->m_recordButton);
toolbar.addWidget(d->m_clearButton);
toolbar.addWidget(d->m_searchButton);
toolbar.addWidget(d->m_displayFeaturesButton);
toolbar.addWidget(d->m_timeLabel);
Debugger::registerToolbar(Constants::QmlProfilerPerspectiveId, toolbar);
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
this, &QmlProfilerTool::updateRunActions);
}
QmlProfilerTool::~QmlProfilerTool()
@@ -291,6 +291,25 @@ QmlProfilerTool::~QmlProfilerTool()
delete d;
}
void QmlProfilerTool::updateRunActions()
{
if (d->m_toolBusy) {
d->m_startAction->setEnabled(false);
d->m_startAction->setToolTip(tr("A Qml Profiler analysis is still in progress."));
d->m_stopAction->setEnabled(true);
} else {
const bool projectUsable = SessionManager::startupProject() != 0;
d->m_startAction->setToolTip(tr("Start Qml Profiler."));
if (projectUsable) {
d->m_startAction->setEnabled(true);
d->m_stopAction->setEnabled(false);
} else {
d->m_startAction->setEnabled(false);
d->m_stopAction->setEnabled(false);
}
}
}
static QString sysroot(RunConfiguration *runConfig)
{
QTC_ASSERT(runConfig, return QString());
@@ -302,6 +321,7 @@ static QString sysroot(RunConfiguration *runConfig)
AnalyzerRunControl *QmlProfilerTool::createRunControl(RunConfiguration *runConfiguration)
{
d->m_toolBusy = true;
if (runConfiguration) {
QmlProfilerRunConfigurationAspect *aspect = static_cast<QmlProfilerRunConfigurationAspect *>(
runConfiguration->extraAspect(Constants::SETTINGS));
@@ -314,7 +334,16 @@ AnalyzerRunControl *QmlProfilerTool::createRunControl(RunConfiguration *runConfi
}
}
return new QmlProfilerRunControl(runConfiguration, this);
auto runControl = new QmlProfilerRunControl(runConfiguration, this);
connect(runControl, &RunControl::finished, [this, runControl] {
d->m_toolBusy = false;
updateRunActions();
});
connect(d->m_stopAction, &QAction::triggered, runControl, [runControl] { runControl->stop(); });
updateRunActions();
return runControl;
}
void QmlProfilerTool::finalizeRunControl(QmlProfilerRunControl *runControl)
@@ -503,8 +532,6 @@ bool QmlProfilerTool::prepareTool()
void QmlProfilerTool::startRemoteTool(ProjectExplorer::RunConfiguration *rc)
{
AnalyzerManager::showMode();
Id kitId;
quint16 port;
Kit *kit = 0;
@@ -596,7 +623,7 @@ void QmlProfilerTool::showSaveDialog()
if (!filename.endsWith(QLatin1String(TraceFileExtension)))
filename += QLatin1String(TraceFileExtension);
saveLastTraceFile(filename);
AnalyzerManager::enableMainWindow(false);
Debugger::enableMainWindow(false);
d->m_profilerModelManager->save(filename);
}
}
@@ -606,10 +633,7 @@ void QmlProfilerTool::showLoadDialog()
if (!checkForUnsavedNotes())
return;
if (ModeManager::currentMode()->id() != MODE_ANALYZE)
AnalyzerManager::showMode();
AnalyzerManager::selectAction(QmlProfilerRemoteActionId);
Debugger::selectPerspective(QmlProfilerPerspectiveId);
QString filename = QFileDialog::getOpenFileName(
ICore::mainWindow(), tr("Load QML Trace"),
@@ -618,7 +642,7 @@ void QmlProfilerTool::showLoadDialog()
if (!filename.isEmpty()) {
saveLastTraceFile(filename);
AnalyzerManager::enableMainWindow(false);
Debugger::enableMainWindow(false);
connect(d->m_profilerModelManager, &QmlProfilerModelManager::recordedFeaturesChanged,
this, &QmlProfilerTool::setRecordedFeatures);
d->m_profilerModelManager->load(filename);
@@ -629,7 +653,7 @@ void QmlProfilerTool::onLoadSaveFinished()
{
disconnect(d->m_profilerModelManager, &QmlProfilerModelManager::recordedFeaturesChanged,
this, &QmlProfilerTool::setRecordedFeatures);
AnalyzerManager::enableMainWindow(true);
Debugger::enableMainWindow(true);
}
/*!

View File

@@ -51,7 +51,7 @@ public:
explicit QmlProfilerTool(QObject *parent);
~QmlProfilerTool();
Analyzer::AnalyzerRunControl *createRunControl(ProjectExplorer::RunConfiguration *runConfiguration = 0);
Debugger::AnalyzerRunControl *createRunControl(ProjectExplorer::RunConfiguration *runConfiguration = 0);
void finalizeRunControl(QmlProfilerRunControl *runControl);
bool prepareTool();
@@ -96,6 +96,7 @@ private slots:
void toggleVisibleFeature(QAction *action);
private:
void updateRunActions();
void clearDisplay();
void populateFileFinder(QString projectDirectory = QString(), QString activeSysroot = QString());
template<QmlDebug::ProfileFeature feature>

View File

@@ -40,7 +40,8 @@
#include <QDockWidget>
using namespace Analyzer;
using namespace Debugger;
using namespace Utils;
namespace QmlProfiler {
namespace Internal {
@@ -80,7 +81,7 @@ void QmlProfilerViewManager::createViews()
QTC_ASSERT(d->profilerModelManager, return);
QTC_ASSERT(d->profilerState, return);
//Utils::FancyMainWindow *mw = AnalyzerManager::mainWindow();
//Utils::FancyMainWindow *mw = Debugger::mainWindow();
d->traceView = new QmlProfilerTraceView(0, this, d->profilerModelManager);
d->traceView->setWindowTitle(tr("Timeline"));
@@ -90,12 +91,12 @@ void QmlProfilerViewManager::createViews()
this, &QmlProfilerViewManager::typeSelected);
connect(this, &QmlProfilerViewManager::typeSelected,
d->traceView, &QmlProfilerTraceView::selectByTypeId);
AnalyzerManager::registerDockWidget(Constants::QmlProfilerTimelineDockId, d->traceView);
new QmlProfilerStateWidget(d->profilerState, d->profilerModelManager, d->traceView);
Perspective perspective;
perspective.addOperation({Constants::QmlProfilerTimelineDockId, Core::Id(),
Utils::Perspective perspective;
perspective.setName(tr("QML Profiler"));
perspective.addOperation({Constants::QmlProfilerTimelineDockId, d->traceView, {},
Perspective::SplitVertical});
d->eventsViews << new QmlProfilerStatisticsView(0, d->profilerModelManager);
@@ -118,19 +119,17 @@ void QmlProfilerViewManager::createViews()
this, &QmlProfilerViewManager::gotoSourceLocation);
connect(view, &QmlProfilerEventsView::showFullRange,
this, [this](){restrictEventsToRange(-1, -1);});
Core::Id dockId = Core::Id::fromString(view->objectName());
AnalyzerManager::registerDockWidget(dockId, view);
perspective.addOperation({dockId, Constants::QmlProfilerTimelineDockId, Perspective::AddToTab});
QByteArray dockId = view->objectName().toLatin1();
perspective.addOperation({dockId, view, Constants::QmlProfilerTimelineDockId, Perspective::AddToTab});
new QmlProfilerStateWidget(d->profilerState, d->profilerModelManager, view);
if (!settings->contains(view->parent()->objectName())) // parent() is QDockWidget.
settings->remove(QString());
// if (!settings->contains(view->parent()->objectName())) // parent() is QDockWidget.
// settings->remove(QString());
}
AnalyzerManager::registerPerspective(Constants::QmlProfilerPerspectiveId, perspective);
perspective.addOperation({Constants::QmlProfilerTimelineDockId, 0, {}, Perspective::Raise});
Debugger::registerPerspective(Constants::QmlProfilerPerspectiveId, perspective);
settings->endGroup();
QTC_ASSERT(qobject_cast<QDockWidget *>(d->traceView->parentWidget()), return);
d->traceView->parentWidget()->raise();
}
bool QmlProfilerViewManager::hasValidSelection() const