forked from qt-creator/qt-creator
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:
@@ -39,7 +39,7 @@
|
||||
#include <QDir>
|
||||
#include <QTcpServer>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
namespace Android {
|
||||
@@ -48,7 +48,7 @@ namespace Internal {
|
||||
RunControl *AndroidAnalyzeSupport::createAnalyzeRunControl(AndroidRunConfiguration *runConfig,
|
||||
Core::Id runMode)
|
||||
{
|
||||
AnalyzerRunControl *runControl = AnalyzerManager::createRunControl(runConfig, runMode);
|
||||
AnalyzerRunControl *runControl = Debugger::createAnalyzerRunControl(runConfig, runMode);
|
||||
QTC_ASSERT(runControl, return 0);
|
||||
AnalyzerConnection connection;
|
||||
if (runMode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) {
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "androidrunconfiguration.h"
|
||||
#include <qmldebug/qmloutputparser.h>
|
||||
|
||||
namespace Analyzer { class AnalyzerRunControl; }
|
||||
namespace Debugger { class AnalyzerRunControl; }
|
||||
namespace ProjectExplorer { class RunControl; }
|
||||
|
||||
namespace Android {
|
||||
@@ -43,7 +43,7 @@ class AndroidAnalyzeSupport : public QObject
|
||||
|
||||
public:
|
||||
AndroidAnalyzeSupport(AndroidRunConfiguration *runConfig,
|
||||
Analyzer::AnalyzerRunControl *runControl);
|
||||
Debugger::AnalyzerRunControl *runControl);
|
||||
|
||||
static ProjectExplorer::RunControl *createAnalyzeRunControl(AndroidRunConfiguration *runConfig,
|
||||
Core::Id runMode);
|
||||
|
||||
@@ -50,7 +50,6 @@
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
|
||||
@@ -44,8 +44,8 @@ public:
|
||||
|
||||
QString message;
|
||||
QString extendedMessage;
|
||||
Analyzer::DiagnosticLocation location;
|
||||
QList<Analyzer::DiagnosticLocation> ranges;
|
||||
Debugger::DiagnosticLocation location;
|
||||
QList<Debugger::DiagnosticLocation> ranges;
|
||||
int depth;
|
||||
};
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
QString type;
|
||||
QString issueContextKind;
|
||||
QString issueContext;
|
||||
Analyzer::DiagnosticLocation location;
|
||||
Debugger::DiagnosticLocation location;
|
||||
QList<ExplainingStep> explainingSteps;
|
||||
};
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ static QString createExplainingStepToolTipString(const ExplainingStep &step)
|
||||
return html;
|
||||
}
|
||||
|
||||
static QString createLocationString(const Analyzer::DiagnosticLocation &location)
|
||||
static QString createLocationString(const Debugger::DiagnosticLocation &location)
|
||||
{
|
||||
const QString filePath = location.filePath;
|
||||
const QString lineNumber = QString::number(location.line);
|
||||
@@ -224,10 +224,10 @@ DiagnosticItem::DiagnosticItem(const Diagnostic &diag) : m_diagnostic(diag)
|
||||
appendChild(new ExplainingStepItem(s));
|
||||
}
|
||||
|
||||
QVariant locationData(int role, const Analyzer::DiagnosticLocation &location)
|
||||
QVariant locationData(int role, const Debugger::DiagnosticLocation &location)
|
||||
{
|
||||
switch (role) {
|
||||
case Analyzer::DetailedErrorView::LocationRole:
|
||||
case Debugger::DetailedErrorView::LocationRole:
|
||||
return QVariant::fromValue(location);
|
||||
case Qt::ToolTipRole:
|
||||
return location.filePath.isEmpty() ? QVariant() : QVariant(location.filePath);
|
||||
@@ -238,12 +238,12 @@ QVariant locationData(int role, const Analyzer::DiagnosticLocation &location)
|
||||
|
||||
QVariant DiagnosticItem::data(int column, int role) const
|
||||
{
|
||||
if (column == Analyzer::DetailedErrorView::LocationColumn)
|
||||
if (column == Debugger::DetailedErrorView::LocationColumn)
|
||||
return locationData(role, m_diagnostic.location);
|
||||
|
||||
// DiagnosticColumn
|
||||
switch (role) {
|
||||
case Analyzer::DetailedErrorView::FullTextRole:
|
||||
case Debugger::DetailedErrorView::FullTextRole:
|
||||
return fullText(m_diagnostic);
|
||||
case ClangStaticAnalyzerDiagnosticModel::DiagnosticRole:
|
||||
return QVariant::fromValue(m_diagnostic);
|
||||
@@ -262,12 +262,12 @@ ExplainingStepItem::ExplainingStepItem(const ExplainingStep &step) : m_step(step
|
||||
|
||||
QVariant ExplainingStepItem::data(int column, int role) const
|
||||
{
|
||||
if (column == Analyzer::DetailedErrorView::LocationColumn)
|
||||
if (column == Debugger::DetailedErrorView::LocationColumn)
|
||||
return locationData(role, m_step.location);
|
||||
|
||||
// DiagnosticColumn
|
||||
switch (role) {
|
||||
case Analyzer::DetailedErrorView::FullTextRole:
|
||||
case Debugger::DetailedErrorView::FullTextRole:
|
||||
return fullText(static_cast<DiagnosticItem *>(parent())->diagnostic());
|
||||
case ClangStaticAnalyzerDiagnosticModel::DiagnosticRole:
|
||||
return QVariant::fromValue(static_cast<DiagnosticItem *>(parent())->diagnostic());
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
QList<Diagnostic> diagnostics() const;
|
||||
|
||||
enum ItemRole {
|
||||
DiagnosticRole = Analyzer::DetailedErrorView::FullTextRole + 1
|
||||
DiagnosticRole = Debugger::DetailedErrorView::FullTextRole + 1
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -36,13 +36,13 @@
|
||||
#include <QAction>
|
||||
#include <QDebug>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
|
||||
namespace ClangStaticAnalyzer {
|
||||
namespace Internal {
|
||||
|
||||
ClangStaticAnalyzerDiagnosticView::ClangStaticAnalyzerDiagnosticView(QWidget *parent)
|
||||
: Analyzer::DetailedErrorView(parent)
|
||||
: Debugger::DetailedErrorView(parent)
|
||||
{
|
||||
m_suppressAction = new QAction(tr("Suppress this diagnostic"), this);
|
||||
connect(m_suppressAction, &QAction::triggered, [this](bool) { suppressCurrentDiagnostic(); });
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
namespace ClangStaticAnalyzer {
|
||||
namespace Internal {
|
||||
|
||||
class ClangStaticAnalyzerDiagnosticView : public Analyzer::DetailedErrorView
|
||||
class ClangStaticAnalyzerDiagnosticView : public Debugger::DetailedErrorView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
@@ -55,8 +55,8 @@ private:
|
||||
void readDiagnosticsDict();
|
||||
QList<ExplainingStep> readPathArray();
|
||||
ExplainingStep readPathDict();
|
||||
Analyzer::DiagnosticLocation readLocationDict(bool elementIsRead = false);
|
||||
QList<Analyzer::DiagnosticLocation> readRangesArray();
|
||||
Debugger::DiagnosticLocation readLocationDict(bool elementIsRead = false);
|
||||
QList<Debugger::DiagnosticLocation> readRangesArray();
|
||||
|
||||
QString readString();
|
||||
QStringList readStringArray();
|
||||
@@ -284,9 +284,9 @@ ExplainingStep ClangStaticAnalyzerLogFileReader::readPathDict()
|
||||
return explainingStep;
|
||||
}
|
||||
|
||||
Analyzer::DiagnosticLocation ClangStaticAnalyzerLogFileReader::readLocationDict(bool elementIsRead)
|
||||
Debugger::DiagnosticLocation ClangStaticAnalyzerLogFileReader::readLocationDict(bool elementIsRead)
|
||||
{
|
||||
Analyzer::DiagnosticLocation location;
|
||||
Debugger::DiagnosticLocation location;
|
||||
if (elementIsRead) {
|
||||
QTC_ASSERT(m_xml.isStartElement() && m_xml.name() == QLatin1String("dict"),
|
||||
return location);
|
||||
@@ -317,14 +317,14 @@ Analyzer::DiagnosticLocation ClangStaticAnalyzerLogFileReader::readLocationDict(
|
||||
|
||||
if (lineOk && columnOk && fileIndexOk) {
|
||||
QTC_ASSERT(fileIndex < m_referencedFiles.size(), return location);
|
||||
location = Analyzer::DiagnosticLocation(m_referencedFiles.at(fileIndex), line, column);
|
||||
location = Debugger::DiagnosticLocation(m_referencedFiles.at(fileIndex), line, column);
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
QList<Analyzer::DiagnosticLocation> ClangStaticAnalyzerLogFileReader::readRangesArray()
|
||||
QList<Debugger::DiagnosticLocation> ClangStaticAnalyzerLogFileReader::readRangesArray()
|
||||
{
|
||||
QList<Analyzer::DiagnosticLocation> result;
|
||||
QList<Debugger::DiagnosticLocation> result;
|
||||
|
||||
// It's an array of arrays...
|
||||
QTC_ASSERT(m_xml.readNextStartElement() && m_xml.name() == QLatin1String("array"),
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
|
||||
#include <QtPlugin>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
|
||||
namespace ClangStaticAnalyzer {
|
||||
namespace Internal {
|
||||
@@ -122,36 +122,10 @@ bool ClangStaticAnalyzerPlugin::initialize(const QStringList &arguments, QString
|
||||
panelFactory->setSimpleCreateWidgetFunction<ProjectSettingsWidget>(QIcon());
|
||||
ProjectExplorer::ProjectPanelFactory::registerFactory(panelFactory);
|
||||
|
||||
auto tool = m_analyzerTool = new ClangStaticAnalyzerTool(this);
|
||||
m_analyzerTool = new ClangStaticAnalyzerTool(this);
|
||||
addAutoReleasedObject(new ClangStaticAnalyzerRunControlFactory(m_analyzerTool));
|
||||
addAutoReleasedObject(new ClangStaticAnalyzerOptionsPage);
|
||||
|
||||
AnalyzerManager::registerToolbar(ClangStaticAnalyzerPerspectiveId, tool->createWidgets());
|
||||
|
||||
auto runControlCreator = [tool](ProjectExplorer::RunConfiguration *runConfiguration,
|
||||
Core::Id runMode) {
|
||||
return tool->createRunControl(runConfiguration, runMode);
|
||||
};
|
||||
|
||||
const QString toolTip = tr("Clang Static Analyzer uses the analyzer from the clang project "
|
||||
"to find bugs.");
|
||||
|
||||
AnalyzerManager::registerPerspective(ClangStaticAnalyzerPerspectiveId, {
|
||||
{ ClangStaticAnalyzerDockId, Core::Id(), Perspective::SplitVertical }
|
||||
});
|
||||
|
||||
ActionDescription desc;
|
||||
desc.setText(tr("Clang Static Analyzer"));
|
||||
desc.setToolTip(toolTip);
|
||||
desc.setRunMode(Constants::CLANGSTATICANALYZER_RUN_MODE);
|
||||
desc.setPerspectiveId(ClangStaticAnalyzerPerspectiveId);
|
||||
desc.setRunControlCreator(runControlCreator);
|
||||
desc.setCustomToolStarter([tool](ProjectExplorer::RunConfiguration *rc) {
|
||||
tool->startTool(rc);
|
||||
});
|
||||
desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_TOOLS);
|
||||
AnalyzerManager::registerAction(ClangStaticAnalyzerActionId, desc);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -304,12 +304,12 @@ static Core::Id toolchainType(ProjectExplorer::RunConfiguration *runConfiguratio
|
||||
return ToolChainKitInformation::toolChain(runConfiguration->target()->kit())->typeId();
|
||||
}
|
||||
|
||||
bool ClangStaticAnalyzerRunControl::startEngine()
|
||||
void ClangStaticAnalyzerRunControl::start()
|
||||
{
|
||||
m_success = false;
|
||||
emit starting();
|
||||
|
||||
QTC_ASSERT(m_projectInfo.isValid(), emit finished(); return false);
|
||||
QTC_ASSERT(m_projectInfo.isValid(), emit finished(); return);
|
||||
const Utils::FileName projectFile = m_projectInfo.project()->projectFilePath();
|
||||
appendMessage(tr("Running Clang Static Analyzer on %1").arg(projectFile.toUserOutput())
|
||||
+ QLatin1Char('\n'), Utils::NormalMessageFormat);
|
||||
@@ -324,7 +324,7 @@ bool ClangStaticAnalyzerRunControl::startEngine()
|
||||
appendMessage(errorMessage + QLatin1Char('\n'), Utils::ErrorMessageFormat);
|
||||
AnalyzerUtils::logToIssuesPane(Task::Error, errorMessage);
|
||||
emit finished();
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
m_clangExecutable = executable;
|
||||
|
||||
@@ -337,7 +337,7 @@ bool ClangStaticAnalyzerRunControl::startEngine()
|
||||
appendMessage(errorMessage + QLatin1Char('\n'), Utils::ErrorMessageFormat);
|
||||
AnalyzerUtils::logToIssuesPane(Task::Error, errorMessage);
|
||||
emit finished();
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
m_clangLogFileDir = temporaryDir.path();
|
||||
|
||||
@@ -364,19 +364,22 @@ bool ClangStaticAnalyzerRunControl::startEngine()
|
||||
qCDebug(LOG) << "Environment:" << m_environment;
|
||||
m_runners.clear();
|
||||
const int parallelRuns = ClangStaticAnalyzerSettings::instance()->simultaneousProcesses();
|
||||
QTC_ASSERT(parallelRuns >= 1, emit finished(); return false);
|
||||
QTC_ASSERT(parallelRuns >= 1, emit finished(); return);
|
||||
m_success = true;
|
||||
m_running = true;
|
||||
|
||||
if (m_unitsToProcess.isEmpty()) {
|
||||
finalize();
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
emit started();
|
||||
|
||||
while (m_runners.size() < parallelRuns && !m_unitsToProcess.isEmpty())
|
||||
analyzeNextFile();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClangStaticAnalyzerRunControl::stopEngine()
|
||||
RunControl::StopResult ClangStaticAnalyzerRunControl::stop()
|
||||
{
|
||||
QSetIterator<ClangStaticAnalyzerRunner *> i(m_runners);
|
||||
while (i.hasNext()) {
|
||||
@@ -389,7 +392,14 @@ void ClangStaticAnalyzerRunControl::stopEngine()
|
||||
appendMessage(tr("Clang Static Analyzer stopped by user.") + QLatin1Char('\n'),
|
||||
Utils::NormalMessageFormat);
|
||||
m_progress.reportFinished();
|
||||
m_running = false;
|
||||
emit finished();
|
||||
return RunControl::StoppedSynchronously;
|
||||
}
|
||||
|
||||
bool ClangStaticAnalyzerRunControl::isRunning() const
|
||||
{
|
||||
return m_running;
|
||||
}
|
||||
|
||||
void ClangStaticAnalyzerRunControl::analyzeNextFile()
|
||||
@@ -479,7 +489,6 @@ void ClangStaticAnalyzerRunControl::handleFinished()
|
||||
|
||||
void ClangStaticAnalyzerRunControl::onProgressCanceled()
|
||||
{
|
||||
Analyzer::AnalyzerManager::stopTool();
|
||||
m_progress.reportCanceled();
|
||||
m_progress.reportFinished();
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ struct AnalyzeUnit {
|
||||
};
|
||||
typedef QList<AnalyzeUnit> AnalyzeUnits;
|
||||
|
||||
class ClangStaticAnalyzerRunControl : public Analyzer::AnalyzerRunControl
|
||||
class ClangStaticAnalyzerRunControl : public Debugger::AnalyzerRunControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -57,8 +57,9 @@ public:
|
||||
Core::Id runMode,
|
||||
const CppTools::ProjectInfo &projectInfo);
|
||||
|
||||
bool startEngine() override;
|
||||
void stopEngine() override;
|
||||
void start() override;
|
||||
StopResult stop() override;
|
||||
bool isRunning() const override;
|
||||
|
||||
bool success() const { return m_success; } // For testing.
|
||||
|
||||
@@ -93,6 +94,7 @@ private:
|
||||
int m_filesAnalyzed;
|
||||
int m_filesNotAnalyzed;
|
||||
bool m_success;
|
||||
bool m_running = false;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
namespace ClangStaticAnalyzer {
|
||||
@@ -115,7 +115,7 @@ RunControl *ClangStaticAnalyzerRunControlFactory::create(RunConfiguration *runCo
|
||||
return 0;
|
||||
}
|
||||
|
||||
return AnalyzerManager::createRunControl(runConfiguration, runMode);
|
||||
return Debugger::createAnalyzerRunControl(runConfiguration, runMode);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -53,8 +53,9 @@
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QToolButton>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
namespace ClangStaticAnalyzer {
|
||||
namespace Internal {
|
||||
@@ -69,14 +70,6 @@ ClangStaticAnalyzerTool::ClangStaticAnalyzerTool(QObject *parent)
|
||||
, m_running(false)
|
||||
{
|
||||
setObjectName(QLatin1String("ClangStaticAnalyzerTool"));
|
||||
}
|
||||
|
||||
QWidget *ClangStaticAnalyzerTool::createWidgets()
|
||||
{
|
||||
QTC_ASSERT(!m_diagnosticView, return 0);
|
||||
QTC_ASSERT(!m_diagnosticModel, return 0);
|
||||
QTC_ASSERT(!m_goBack, return 0);
|
||||
QTC_ASSERT(!m_goNext, return 0);
|
||||
|
||||
//
|
||||
// Diagnostic View
|
||||
@@ -104,27 +97,19 @@ QWidget *ClangStaticAnalyzerTool::createWidgets()
|
||||
this, &ClangStaticAnalyzerTool::handleStateUpdate);
|
||||
}
|
||||
|
||||
AnalyzerManager::registerDockWidget(ClangStaticAnalyzerDockId, m_diagnosticView);
|
||||
|
||||
//
|
||||
// Toolbar widget
|
||||
//
|
||||
QHBoxLayout *layout = new QHBoxLayout;
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
|
||||
QAction *action = 0;
|
||||
QToolButton *button = 0;
|
||||
m_startAction = Debugger::createStartAction();
|
||||
m_stopAction = Debugger::createStopAction();
|
||||
|
||||
// Go to previous diagnostic
|
||||
action = new QAction(this);
|
||||
auto action = new QAction(this);
|
||||
action->setDisabled(true);
|
||||
action->setIcon(Core::Icons::PREV.icon());
|
||||
action->setToolTip(tr("Go to previous bug."));
|
||||
connect(action, &QAction::triggered, m_diagnosticView, &DetailedErrorView::goBack);
|
||||
button = new QToolButton;
|
||||
button->setDefaultAction(action);
|
||||
layout->addWidget(button);
|
||||
m_goBack = action;
|
||||
|
||||
// Go to next diagnostic
|
||||
@@ -133,17 +118,41 @@ QWidget *ClangStaticAnalyzerTool::createWidgets()
|
||||
action->setIcon(Core::Icons::NEXT.icon());
|
||||
action->setToolTip(tr("Go to next bug."));
|
||||
connect(action, &QAction::triggered, m_diagnosticView, &DetailedErrorView::goNext);
|
||||
button = new QToolButton;
|
||||
button->setDefaultAction(action);
|
||||
layout->addWidget(button);
|
||||
m_goNext = action;
|
||||
|
||||
layout->addStretch();
|
||||
const QString toolTip = tr("Clang Static Analyzer uses the analyzer from the clang project "
|
||||
"to find bugs.");
|
||||
|
||||
QWidget *toolbarWidget = new QWidget;
|
||||
toolbarWidget->setObjectName(QLatin1String("ClangStaticAnalyzerToolBarWidget"));
|
||||
toolbarWidget->setLayout(layout);
|
||||
return toolbarWidget;
|
||||
Debugger::registerPerspective(ClangStaticAnalyzerPerspectiveId, {
|
||||
tr("Clang Static Analyzer"),
|
||||
{{ ClangStaticAnalyzerDockId, m_diagnosticView, {}, Perspective::SplitVertical }}
|
||||
});
|
||||
|
||||
ActionDescription desc;
|
||||
desc.setText(tr("Clang Static Analyzer"));
|
||||
desc.setToolTip(toolTip);
|
||||
desc.setRunMode(Constants::CLANGSTATICANALYZER_RUN_MODE);
|
||||
desc.setPerspectiveId(ClangStaticAnalyzerPerspectiveId);
|
||||
desc.setRunControlCreator([this](RunConfiguration *runConfiguration, Core::Id runMode) {
|
||||
return createRunControl(runConfiguration, runMode);
|
||||
});
|
||||
desc.setCustomToolStarter([this](RunConfiguration *runConfiguration) {
|
||||
startTool(runConfiguration);
|
||||
});
|
||||
desc.setMenuGroup(Debugger::Constants::G_ANALYZER_TOOLS);
|
||||
Debugger::registerAction(ClangStaticAnalyzerActionId, desc, m_startAction);
|
||||
|
||||
ToolbarDescription toolbar;
|
||||
toolbar.addAction(m_startAction);
|
||||
toolbar.addAction(m_stopAction);
|
||||
toolbar.addAction(m_goBack);
|
||||
toolbar.addAction(m_goNext);
|
||||
Debugger::registerToolbar(ClangStaticAnalyzerPerspectiveId, toolbar);
|
||||
|
||||
updateRunActions();
|
||||
|
||||
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
|
||||
this, &ClangStaticAnalyzerTool::updateRunActions);
|
||||
}
|
||||
|
||||
AnalyzerRunControl *ClangStaticAnalyzerTool::createRunControl(RunConfiguration *runConfiguration,
|
||||
@@ -171,6 +180,11 @@ AnalyzerRunControl *ClangStaticAnalyzerTool::createRunControl(RunConfiguration *
|
||||
this, &ClangStaticAnalyzerTool::onNewDiagnosticsAvailable);
|
||||
connect(runControl, &ClangStaticAnalyzerRunControl::finished,
|
||||
this, &ClangStaticAnalyzerTool::onEngineFinished);
|
||||
|
||||
connect(m_stopAction, &QAction::triggered, runControl, [runControl] { runControl->stop(); });
|
||||
|
||||
m_toolBusy = true;
|
||||
updateRunActions();
|
||||
return runControl;
|
||||
}
|
||||
|
||||
@@ -208,8 +222,6 @@ static bool dontStartAfterHintForDebugMode(Project *project)
|
||||
|
||||
void ClangStaticAnalyzerTool::startTool(ProjectExplorer::RunConfiguration *runConfiguration)
|
||||
{
|
||||
AnalyzerManager::showMode();
|
||||
|
||||
Project *project = SessionManager::startupProject();
|
||||
QTC_ASSERT(project, emit finished(false); return);
|
||||
|
||||
@@ -261,8 +273,28 @@ void ClangStaticAnalyzerTool::onEngineFinished()
|
||||
m_running = false;
|
||||
handleStateUpdate();
|
||||
emit finished(static_cast<ClangStaticAnalyzerRunControl *>(sender())->success());
|
||||
m_toolBusy = false;
|
||||
updateRunActions();
|
||||
}
|
||||
|
||||
void ClangStaticAnalyzerTool::updateRunActions()
|
||||
{
|
||||
if (m_toolBusy) {
|
||||
m_startAction->setEnabled(false);
|
||||
m_startAction->setToolTip(tr("A Clang analysis is still in progress."));
|
||||
m_stopAction->setEnabled(true);
|
||||
} else {
|
||||
const bool projectUsable = SessionManager::startupProject() != 0;
|
||||
m_startAction->setToolTip(tr("Start Qml Profiler."));
|
||||
if (projectUsable) {
|
||||
m_startAction->setEnabled(true);
|
||||
m_stopAction->setEnabled(false);
|
||||
} else {
|
||||
m_startAction->setEnabled(false);
|
||||
m_stopAction->setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
void ClangStaticAnalyzerTool::setBusyCursor(bool busy)
|
||||
{
|
||||
QTC_ASSERT(m_diagnosticView, return);
|
||||
@@ -291,7 +323,7 @@ void ClangStaticAnalyzerTool::handleStateUpdate()
|
||||
message += tr("%n issues found (%1 suppressed).", 0, issuesFound)
|
||||
.arg(issuesFound - issuesVisible);
|
||||
}
|
||||
AnalyzerManager::showPermanentStatusMessage(message);
|
||||
Debugger::showPermanentStatusMessage(message);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -56,8 +56,7 @@ public:
|
||||
bool isRunning() const { return m_running; }
|
||||
QList<Diagnostic> diagnostics() const;
|
||||
|
||||
QWidget *createWidgets();
|
||||
Analyzer::AnalyzerRunControl *createRunControl(ProjectExplorer::RunConfiguration *runConfiguration,
|
||||
Debugger::AnalyzerRunControl *createRunControl(ProjectExplorer::RunConfiguration *runConfiguration,
|
||||
Core::Id runMode);
|
||||
void startTool(ProjectExplorer::RunConfiguration *rc);
|
||||
|
||||
@@ -71,6 +70,7 @@ private:
|
||||
|
||||
void setBusyCursor(bool busy);
|
||||
void handleStateUpdate();
|
||||
void updateRunActions();
|
||||
|
||||
private:
|
||||
CppTools::ProjectInfo m_projectInfoBeforeBuild;
|
||||
@@ -79,9 +79,12 @@ private:
|
||||
ClangStaticAnalyzerDiagnosticFilterModel *m_diagnosticFilterModel;
|
||||
ClangStaticAnalyzerDiagnosticView *m_diagnosticView;
|
||||
|
||||
QAction *m_startAction = 0;
|
||||
QAction *m_stopAction = 0;
|
||||
QAction *m_goBack;
|
||||
QAction *m_goNext;
|
||||
bool m_running;
|
||||
bool m_toolBusy = false;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
#include <QTimer>
|
||||
#include <QtTest>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
@@ -89,7 +89,7 @@ void ClangStaticAnalyzerUnitTests::testProject()
|
||||
CppTools::Tests::ProjectOpenerAndCloser projectManager;
|
||||
const CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true);
|
||||
QVERIFY(projectInfo.isValid());
|
||||
AnalyzerManager::selectAction(ClangStaticAnalyzerPerspectiveId, /* alsoRunIt = */ true);
|
||||
Debugger::runAction(ClangStaticAnalyzerActionId);
|
||||
QSignalSpy waiter(m_analyzerTool, SIGNAL(finished(bool)));
|
||||
QVERIFY(waiter.wait(30000));
|
||||
const QList<QVariant> arguments = waiter.takeFirst();
|
||||
|
||||
@@ -77,7 +77,7 @@ QString clangExecutable(const QString &fileNameOrPath, bool *isValid)
|
||||
return executable;
|
||||
}
|
||||
|
||||
QString createFullLocationString(const Analyzer::DiagnosticLocation &location)
|
||||
QString createFullLocationString(const Debugger::DiagnosticLocation &location)
|
||||
{
|
||||
const QString filePath = location.filePath;
|
||||
const QString lineNumber = QString::number(location.line);
|
||||
|
||||
@@ -34,7 +34,7 @@ QT_BEGIN_NAMESPACE
|
||||
class QString;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Analyzer { class DiagnosticLocation; }
|
||||
namespace Debugger { class DiagnosticLocation; }
|
||||
|
||||
namespace ClangStaticAnalyzer {
|
||||
namespace Internal {
|
||||
@@ -44,7 +44,7 @@ bool isClangExecutableUsable(const QString &filePath, QString *errorMessage = 0)
|
||||
QString clangExecutable(const QString &fileNameOrPath, bool *isValid);
|
||||
QString clangExecutableFromSettings(Core::Id toolchainType, bool *isValid);
|
||||
|
||||
QString createFullLocationString(const Analyzer::DiagnosticLocation &location);
|
||||
QString createFullLocationString(const Debugger::DiagnosticLocation &location);
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ClangStaticAnalyzer
|
||||
|
||||
@@ -5,7 +5,6 @@ QT += network
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/analyzerruncontrol.cpp \
|
||||
$$PWD/analyzermanager.cpp \
|
||||
$$PWD/analyzerrunconfigwidget.cpp \
|
||||
$$PWD/analyzerutils.cpp \
|
||||
$$PWD/detailederrorview.cpp \
|
||||
@@ -13,7 +12,6 @@ SOURCES += \
|
||||
$$PWD/startremotedialog.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/analyzerbase_global.h \
|
||||
$$PWD/analyzerconstants.h \
|
||||
$$PWD/analyzerruncontrol.h \
|
||||
$$PWD/analyzermanager.h \
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Author: Nicolas Arnaud-Cormos, KDAB (nicolas.arnaud-cormos@kdab.com)
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef ANALYZERBASE_GLOBAL_H
|
||||
#define ANALYZERBASE_GLOBAL_H
|
||||
|
||||
#include "../debugger_global.h"
|
||||
|
||||
#define ANALYZER_EXPORT DEBUGGER_EXPORT
|
||||
|
||||
#endif // ANALYZERBASE_GLOBAL_H
|
||||
@@ -29,16 +29,9 @@
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
namespace Analyzer {
|
||||
namespace Debugger {
|
||||
namespace Constants {
|
||||
|
||||
// Mode and its priority.
|
||||
const char MODE_ANALYZE[] = "Mode.Analyze";
|
||||
const int P_MODE_ANALYZE = 76;
|
||||
|
||||
// Context.
|
||||
const char C_ANALYZEMODE[] = "Analyzer.AnalyzeMode";
|
||||
|
||||
// Menu.
|
||||
const char M_DEBUG_ANALYZER[] = "Analyzer.Menu.StartAnalyzer";
|
||||
const char M_DEBUG_ANALYZER_QML_OPTIONS[] = "Analyzer.Menu.QMLOptions";
|
||||
@@ -51,6 +44,6 @@ const char G_ANALYZER_OPTIONS[] = "Menu.Group.Analyzer.Options";
|
||||
const char ANALYZERTASK_ID[] = "Analyzer.TaskId";
|
||||
|
||||
} // namespace Constants
|
||||
} // namespace Analyzer
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // ANALYZERCONSTANTS_H
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include <utils/icon.h>
|
||||
|
||||
namespace Analyzer {
|
||||
namespace Debugger {
|
||||
namespace Icons {
|
||||
|
||||
const Utils::Icon ANALYZER_CONTROL_START({
|
||||
@@ -42,6 +42,6 @@ const Utils::Icon MODE_ANALYZE_FLAT_ACTIVE({
|
||||
{QLatin1String(":/images/mode_analyze_mask.png"), Utils::Theme::IconsModeAnalyzeActiveColor}});
|
||||
|
||||
} // namespace Icons
|
||||
} // namespace Analyzer
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // ANALYZERICONS_H
|
||||
|
||||
@@ -1,738 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Author: Andreas Hartmetz, KDAB (andreas.hartmetz@kdab.com)
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "analyzermanager.h"
|
||||
|
||||
#include "analyzericons.h"
|
||||
#include "analyzerstartparameters.h"
|
||||
#include "analyzerruncontrol.h"
|
||||
#include "../debuggerplugin.h"
|
||||
|
||||
#include "../debuggermainwindow.h"
|
||||
|
||||
#include <coreplugin/actionmanager/actioncontainer.h>
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
#include <coreplugin/actionmanager/command.h>
|
||||
#include <coreplugin/coreicons.h>
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <coreplugin/findplaceholder.h>
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/imode.h>
|
||||
#include <coreplugin/modemanager.h>
|
||||
#include <coreplugin/modemanager.h>
|
||||
#include <coreplugin/navigationwidget.h>
|
||||
#include <coreplugin/outputpane.h>
|
||||
#include <coreplugin/rightpane.h>
|
||||
|
||||
#include <projectexplorer/buildconfiguration.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/projectexplorericons.h>
|
||||
#include <projectexplorer/session.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <projectexplorer/taskhub.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/fancymainwindow.h>
|
||||
#include <utils/styledbar.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/checkablemessagebox.h>
|
||||
#include <utils/statuslabel.h>
|
||||
|
||||
#include <QAction>
|
||||
#include <QComboBox>
|
||||
#include <QDebug>
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QDockWidget>
|
||||
#include <QHBoxLayout>
|
||||
#include <QMenu>
|
||||
#include <QPointer>
|
||||
#include <QPushButton>
|
||||
#include <QStackedWidget>
|
||||
#include <QSettings>
|
||||
#include <QToolButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <QVariant>
|
||||
|
||||
using namespace Core;
|
||||
using namespace Utils;
|
||||
using namespace Core::Constants;
|
||||
using namespace Analyzer::Constants;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Debugger;
|
||||
using namespace Debugger::Internal;
|
||||
|
||||
namespace Analyzer {
|
||||
|
||||
bool ActionDescription::isRunnable(QString *reason) const
|
||||
{
|
||||
if (m_customToolStarter) // Something special. Pretend we can always run it.
|
||||
return true;
|
||||
|
||||
return ProjectExplorerPlugin::canRun(SessionManager::startupProject(), m_runMode, reason);
|
||||
}
|
||||
|
||||
static bool buildTypeAccepted(QFlags<ToolMode> toolMode, BuildConfiguration::BuildType buildType)
|
||||
{
|
||||
if (buildType == BuildConfiguration::Unknown)
|
||||
return true;
|
||||
if (buildType == BuildConfiguration::Debug && (toolMode & DebugMode))
|
||||
return true;
|
||||
if (buildType == BuildConfiguration::Release && (toolMode & ReleaseMode))
|
||||
return true;
|
||||
if (buildType == BuildConfiguration::Profile && (toolMode & ProfileMode))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ActionDescription::startTool() const
|
||||
{
|
||||
// Make sure mode is shown.
|
||||
AnalyzerManager::showMode();
|
||||
|
||||
TaskHub::clearTasks(Constants::ANALYZERTASK_ID);
|
||||
AnalyzerManager::showPermanentStatusMessage(QString());
|
||||
|
||||
if (m_toolPreparer && !m_toolPreparer())
|
||||
return;
|
||||
|
||||
// ### not sure if we're supposed to check if the RunConFiguration isEnabled
|
||||
Project *pro = SessionManager::startupProject();
|
||||
RunConfiguration *rc = 0;
|
||||
BuildConfiguration::BuildType buildType = BuildConfiguration::Unknown;
|
||||
if (pro) {
|
||||
if (const Target *target = pro->activeTarget()) {
|
||||
// Build configuration is 0 for QML projects.
|
||||
if (const BuildConfiguration *buildConfig = target->activeBuildConfiguration())
|
||||
buildType = buildConfig->buildType();
|
||||
rc = target->activeRunConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
// Custom start.
|
||||
if (m_customToolStarter) {
|
||||
if (rc) {
|
||||
m_customToolStarter(rc);
|
||||
} else {
|
||||
QMessageBox *errorDialog = new QMessageBox(ICore::mainWindow());
|
||||
errorDialog->setIcon(QMessageBox::Warning);
|
||||
errorDialog->setWindowTitle(m_text);
|
||||
errorDialog->setText(tr("Cannot start %1 without a project. Please open the project "
|
||||
"and try again.").arg(m_text));
|
||||
errorDialog->setStandardButtons(QMessageBox::Ok);
|
||||
errorDialog->setDefaultButton(QMessageBox::Ok);
|
||||
errorDialog->show();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 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 (!buildTypeAccepted(m_toolMode, buildType)) {
|
||||
QString currentMode;
|
||||
switch (buildType) {
|
||||
case BuildConfiguration::Debug:
|
||||
currentMode = AnalyzerManager::tr("Debug");
|
||||
break;
|
||||
case BuildConfiguration::Profile:
|
||||
currentMode = AnalyzerManager::tr("Profile");
|
||||
break;
|
||||
case BuildConfiguration::Release:
|
||||
currentMode = AnalyzerManager::tr("Release");
|
||||
break;
|
||||
default:
|
||||
QTC_CHECK(false);
|
||||
}
|
||||
|
||||
QString toolModeString;
|
||||
switch (m_toolMode) {
|
||||
case DebugMode:
|
||||
toolModeString = AnalyzerManager::tr("in Debug mode");
|
||||
break;
|
||||
case ProfileMode:
|
||||
toolModeString = AnalyzerManager::tr("in Profile mode");
|
||||
break;
|
||||
case ReleaseMode:
|
||||
toolModeString = AnalyzerManager::tr("in Release mode");
|
||||
break;
|
||||
case SymbolsMode:
|
||||
toolModeString = AnalyzerManager::tr("with debug symbols (Debug or Profile mode)");
|
||||
break;
|
||||
case OptimizedMode:
|
||||
toolModeString = AnalyzerManager::tr("on optimized code (Profile or Release mode)");
|
||||
break;
|
||||
default:
|
||||
QTC_CHECK(false);
|
||||
}
|
||||
const QString toolName = m_text; // The action text is always the name of the tool
|
||||
const QString title = AnalyzerManager::tr("Run %1 in %2 Mode?").arg(toolName).arg(currentMode);
|
||||
const QString message = AnalyzerManager::tr("<html><head/><body><p>You are trying "
|
||||
"to run the tool \"%1\" on an application in %2 mode. "
|
||||
"The tool is designed to be used %3.</p><p>"
|
||||
"Run-time characteristics differ significantly between "
|
||||
"optimized and non-optimized binaries. Analytical "
|
||||
"findings for one mode may or may not be relevant for "
|
||||
"the other.</p><p>"
|
||||
"Running tools that need debug symbols on binaries that "
|
||||
"don't provide any may lead to missing function names "
|
||||
"or otherwise insufficient output.</p><p>"
|
||||
"Do you want to continue and run the tool in %2 mode?</p></body></html>")
|
||||
.arg(toolName).arg(currentMode).arg(toolModeString);
|
||||
if (Utils::CheckableMessageBox::doNotAskAgainQuestion(ICore::mainWindow(),
|
||||
title, message, ICore::settings(), QLatin1String("AnalyzerCorrectModeWarning"))
|
||||
!= QDialogButtonBox::Yes)
|
||||
return;
|
||||
}
|
||||
|
||||
ProjectExplorerPlugin::runStartupProject(m_runMode);
|
||||
}
|
||||
|
||||
namespace Internal {
|
||||
|
||||
const char LAST_ACTIVE_ACTION[] = "Analyzer.Plugin.LastActiveTool";
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// AnalyzerMode
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
class AnalyzerMode : public IMode
|
||||
{
|
||||
public:
|
||||
AnalyzerMode(QObject *parent = 0)
|
||||
: IMode(parent)
|
||||
{
|
||||
setContext(Context(C_ANALYZEMODE, C_NAVIGATION_PANE));
|
||||
setDisplayName(AnalyzerManager::tr("Analyze"));
|
||||
setIcon(Utils::Icon::modeIcon(Icons::MODE_ANALYZE_CLASSIC,
|
||||
Icons::MODE_ANALYZE_FLAT, Icons::MODE_ANALYZE_FLAT_ACTIVE));
|
||||
setPriority(P_MODE_ANALYZE);
|
||||
setId(MODE_ANALYZE);
|
||||
}
|
||||
|
||||
~AnalyzerMode()
|
||||
{
|
||||
delete m_widget;
|
||||
m_widget = 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// AnalyzerManagerPrivate
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
class AnalyzerManagerPrivate : public QObject
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Analyzer::AnalyzerManager)
|
||||
|
||||
public:
|
||||
AnalyzerManagerPrivate(AnalyzerManager *qq);
|
||||
|
||||
/**
|
||||
* After calling this, a proper instance of IMode is initialized
|
||||
* It is delayed since an analyzer mode makes no sense without analyzer tools
|
||||
*
|
||||
* \note Call this before adding a tool to the manager
|
||||
*/
|
||||
void delayedInit();
|
||||
|
||||
void setupActions();
|
||||
void createModeMainWindow();
|
||||
bool showPromptDialog(const QString &title, const QString &text,
|
||||
const QString &stopButtonText, const QString &cancelButtonText) const;
|
||||
|
||||
void registerAction(Core::Id actionId, const ActionDescription &desc);
|
||||
void selectSavedTool();
|
||||
void selectAction(Id actionId);
|
||||
void handleToolStarted();
|
||||
void handleToolFinished();
|
||||
void modeChanged(IMode *mode);
|
||||
void resetLayout();
|
||||
void updateRunActions();
|
||||
|
||||
public:
|
||||
AnalyzerManager *q;
|
||||
Internal::AnalyzerMode *m_mode = 0;
|
||||
bool m_isRunning = false;
|
||||
Core::Id m_currentActionId;
|
||||
QHash<Id, QAction *> m_actions;
|
||||
QHash<Id, ActionDescription> m_descriptions;
|
||||
QAction *m_startAction = 0;
|
||||
QAction *m_stopAction = 0;
|
||||
ActionContainer *m_menu = 0;
|
||||
MainWindowBase *m_mainWindow;
|
||||
};
|
||||
|
||||
AnalyzerManagerPrivate::AnalyzerManagerPrivate(AnalyzerManager *qq):
|
||||
q(qq), m_mainWindow(new MainWindowBase)
|
||||
{
|
||||
QComboBox *toolBox = m_mainWindow->toolBox();
|
||||
toolBox->setObjectName(QLatin1String("AnalyzerManagerToolBox"));
|
||||
toolBox->insertSeparator(0);
|
||||
connect(toolBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, [this, toolBox](int item) {
|
||||
selectAction(Id::fromSetting(toolBox->itemData(item)));
|
||||
});
|
||||
|
||||
setupActions();
|
||||
|
||||
ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance();
|
||||
connect(pe, &ProjectExplorerPlugin::updateRunActions, this, &AnalyzerManagerPrivate::updateRunActions);
|
||||
}
|
||||
|
||||
void AnalyzerManagerPrivate::setupActions()
|
||||
{
|
||||
Command *command = 0;
|
||||
|
||||
// Menus
|
||||
m_menu = ActionManager::createMenu(M_DEBUG_ANALYZER);
|
||||
m_menu->menu()->setTitle(tr("&Analyze"));
|
||||
m_menu->menu()->setEnabled(true);
|
||||
|
||||
m_menu->appendGroup(G_ANALYZER_CONTROL);
|
||||
m_menu->appendGroup(G_ANALYZER_TOOLS);
|
||||
m_menu->appendGroup(G_ANALYZER_REMOTE_TOOLS);
|
||||
m_menu->appendGroup(G_ANALYZER_OPTIONS);
|
||||
|
||||
ActionContainer *menubar = ActionManager::actionContainer(MENU_BAR);
|
||||
ActionContainer *mtools = ActionManager::actionContainer(M_TOOLS);
|
||||
menubar->addMenu(mtools, m_menu);
|
||||
|
||||
m_startAction = new QAction(tr("Start"), m_menu);
|
||||
m_startAction->setIcon(Analyzer::Icons::ANALYZER_CONTROL_START.icon());
|
||||
ActionManager::registerAction(m_startAction, "Analyzer.Start");
|
||||
connect(m_startAction, &QAction::triggered, this, [this] {
|
||||
QTC_ASSERT(m_descriptions.contains(m_currentActionId), return);
|
||||
m_descriptions.value(m_currentActionId).startTool();
|
||||
});
|
||||
|
||||
m_stopAction = new QAction(tr("Stop"), m_menu);
|
||||
m_stopAction->setEnabled(false);
|
||||
m_stopAction->setIcon(ProjectExplorer::Icons::STOP_SMALL.icon());
|
||||
command = ActionManager::registerAction(m_stopAction, "Analyzer.Stop");
|
||||
m_menu->addAction(command, G_ANALYZER_CONTROL);
|
||||
|
||||
m_menu->addSeparator(G_ANALYZER_TOOLS);
|
||||
m_menu->addSeparator(G_ANALYZER_REMOTE_TOOLS);
|
||||
m_menu->addSeparator(G_ANALYZER_OPTIONS);
|
||||
}
|
||||
|
||||
void AnalyzerManagerPrivate::delayedInit()
|
||||
{
|
||||
if (m_mode)
|
||||
return;
|
||||
|
||||
m_mode = new Internal::AnalyzerMode(q);
|
||||
createModeMainWindow();
|
||||
|
||||
connect(ModeManager::instance(), &ModeManager::currentModeChanged,
|
||||
this, &AnalyzerManagerPrivate::modeChanged);
|
||||
|
||||
// Right-side window with editor, output etc.
|
||||
auto mainWindowSplitter = new MiniSplitter;
|
||||
mainWindowSplitter->addWidget(m_mainWindow);
|
||||
mainWindowSplitter->addWidget(new OutputPanePlaceHolder(m_mode, mainWindowSplitter));
|
||||
mainWindowSplitter->setStretchFactor(0, 10);
|
||||
mainWindowSplitter->setStretchFactor(1, 0);
|
||||
mainWindowSplitter->setOrientation(Qt::Vertical);
|
||||
|
||||
// Navigation + right-side window.
|
||||
auto splitter = new MiniSplitter;
|
||||
splitter->addWidget(new NavigationWidgetPlaceHolder(m_mode));
|
||||
splitter->addWidget(mainWindowSplitter);
|
||||
splitter->setStretchFactor(0, 0);
|
||||
splitter->setStretchFactor(1, 1);
|
||||
|
||||
auto modeContextObject = new IContext(this);
|
||||
modeContextObject->setContext(Context(C_EDITORMANAGER));
|
||||
modeContextObject->setWidget(splitter);
|
||||
ICore::addContextObject(modeContextObject);
|
||||
m_mode->setWidget(splitter);
|
||||
|
||||
Debugger::Internal::DebuggerPlugin::instance()->addAutoReleasedObject(m_mode);
|
||||
|
||||
// Populate Windows->Views menu with standard actions.
|
||||
Context analyzerContext(C_ANALYZEMODE);
|
||||
ActionContainer *viewsMenu = ActionManager::actionContainer(M_WINDOW_VIEWS);
|
||||
Command *cmd = ActionManager::registerAction(m_mainWindow->menuSeparator1(),
|
||||
"Analyzer.Views.Separator1", analyzerContext);
|
||||
cmd->setAttribute(Command::CA_Hide);
|
||||
viewsMenu->addAction(cmd, G_DEFAULT_THREE);
|
||||
cmd = ActionManager::registerAction(m_mainWindow->autoHideTitleBarsAction(),
|
||||
"Analyzer.Views.AutoHideTitleBars", analyzerContext);
|
||||
cmd->setAttribute(Command::CA_Hide);
|
||||
viewsMenu->addAction(cmd, G_DEFAULT_THREE);
|
||||
cmd = ActionManager::registerAction(m_mainWindow->menuSeparator2(),
|
||||
"Analyzer.Views.Separator2", analyzerContext);
|
||||
cmd->setAttribute(Command::CA_Hide);
|
||||
viewsMenu->addAction(cmd, G_DEFAULT_THREE);
|
||||
cmd = ActionManager::registerAction(m_mainWindow->resetLayoutAction(),
|
||||
"Analyzer.Views.ResetSimple", analyzerContext);
|
||||
cmd->setAttribute(Command::CA_Hide);
|
||||
viewsMenu->addAction(cmd, G_DEFAULT_THREE);
|
||||
}
|
||||
|
||||
static QToolButton *toolButton(QAction *action)
|
||||
{
|
||||
auto button = new QToolButton;
|
||||
button->setDefaultAction(action);
|
||||
return button;
|
||||
}
|
||||
|
||||
void AnalyzerManagerPrivate::createModeMainWindow()
|
||||
{
|
||||
m_mainWindow->setObjectName(QLatin1String("AnalyzerManagerMainWindow"));
|
||||
m_mainWindow->setLastSettingsName(QLatin1String(Internal::LAST_ACTIVE_ACTION));
|
||||
|
||||
auto editorHolderLayout = new QVBoxLayout;
|
||||
editorHolderLayout->setMargin(0);
|
||||
editorHolderLayout->setSpacing(0);
|
||||
|
||||
auto editorAndFindWidget = new QWidget;
|
||||
editorAndFindWidget->setLayout(editorHolderLayout);
|
||||
editorHolderLayout->addWidget(new EditorManagerPlaceHolder(m_mode));
|
||||
editorHolderLayout->addWidget(new FindToolBarPlaceHolder(editorAndFindWidget));
|
||||
|
||||
auto documentAndRightPane = new MiniSplitter;
|
||||
documentAndRightPane->addWidget(editorAndFindWidget);
|
||||
documentAndRightPane->addWidget(new RightPanePlaceHolder(m_mode));
|
||||
documentAndRightPane->setStretchFactor(0, 1);
|
||||
documentAndRightPane->setStretchFactor(1, 0);
|
||||
|
||||
auto analyzeToolBar = new StyledBar;
|
||||
analyzeToolBar->setProperty("topBorder", true);
|
||||
|
||||
auto analyzeToolBarLayout = new QHBoxLayout(analyzeToolBar);
|
||||
analyzeToolBarLayout->setMargin(0);
|
||||
analyzeToolBarLayout->setSpacing(0);
|
||||
analyzeToolBarLayout->addWidget(toolButton(m_startAction));
|
||||
analyzeToolBarLayout->addWidget(toolButton(m_stopAction));
|
||||
analyzeToolBarLayout->addWidget(new StyledSeparator);
|
||||
analyzeToolBarLayout->addWidget(m_mainWindow->toolBox());
|
||||
analyzeToolBarLayout->addWidget(m_mainWindow->controlsStack());
|
||||
analyzeToolBarLayout->addWidget(m_mainWindow->statusLabel());
|
||||
analyzeToolBarLayout->addStretch();
|
||||
|
||||
auto 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);
|
||||
|
||||
auto centralWidget = new QWidget;
|
||||
m_mainWindow->setCentralWidget(centralWidget);
|
||||
|
||||
auto centralLayout = new QVBoxLayout(centralWidget);
|
||||
centralWidget->setLayout(centralLayout);
|
||||
centralLayout->setMargin(0);
|
||||
centralLayout->setSpacing(0);
|
||||
centralLayout->addWidget(documentAndRightPane);
|
||||
centralLayout->setStretch(0, 1);
|
||||
centralLayout->setStretch(1, 0);
|
||||
}
|
||||
|
||||
bool AnalyzerManagerPrivate::showPromptDialog(const QString &title, const QString &text,
|
||||
const QString &stopButtonText, const QString &cancelButtonText) const
|
||||
{
|
||||
CheckableMessageBox messageBox(ICore::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 AnalyzerManagerPrivate::modeChanged(IMode *mode)
|
||||
{
|
||||
if (mode && mode == m_mode) {
|
||||
m_mainWindow->setDockActionsVisible(true);
|
||||
static bool firstTime = !m_currentActionId.isValid();
|
||||
if (firstTime)
|
||||
selectSavedTool();
|
||||
firstTime = false;
|
||||
updateRunActions();
|
||||
} else {
|
||||
m_mainWindow->setDockActionsVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerManagerPrivate::selectSavedTool()
|
||||
{
|
||||
const QSettings *settings = ICore::settings();
|
||||
|
||||
if (settings->contains(QLatin1String(Internal::LAST_ACTIVE_ACTION))) {
|
||||
const Id lastAction = Id::fromSetting(settings->value(QLatin1String(Internal::LAST_ACTIVE_ACTION)));
|
||||
selectAction(lastAction);
|
||||
}
|
||||
// fallback to first available tool
|
||||
if (!m_descriptions.isEmpty())
|
||||
selectAction(m_descriptions.begin().key());
|
||||
}
|
||||
|
||||
void AnalyzerManagerPrivate::selectAction(Id actionId)
|
||||
{
|
||||
QTC_ASSERT(m_descriptions.contains(actionId), return);
|
||||
if (m_currentActionId == actionId)
|
||||
return;
|
||||
|
||||
// Now change the tool.
|
||||
m_currentActionId = actionId;
|
||||
ActionDescription desc = m_descriptions.value(actionId);
|
||||
|
||||
m_mainWindow->restorePerspective(desc.perspectiveId());
|
||||
|
||||
const int toolboxIndex = m_mainWindow->toolBox()->findText(desc.text());
|
||||
QTC_ASSERT(toolboxIndex >= 0, return);
|
||||
m_mainWindow->toolBox()->setCurrentIndex(toolboxIndex);
|
||||
|
||||
updateRunActions();
|
||||
}
|
||||
|
||||
void AnalyzerManagerPrivate::registerAction(Id actionId, const ActionDescription &desc)
|
||||
{
|
||||
delayedInit(); // Make sure that there is a valid IMode instance.
|
||||
|
||||
auto action = new QAction(this);
|
||||
action->setText(desc.text());
|
||||
action->setToolTip(desc.toolTip());
|
||||
m_actions.insert(actionId, action);
|
||||
m_descriptions.insert(actionId, desc);
|
||||
|
||||
int index = -1;
|
||||
if (desc.menuGroup() == Constants::G_ANALYZER_REMOTE_TOOLS) {
|
||||
index = m_mainWindow->toolBox()->count();
|
||||
} else if (desc.menuGroup() == Constants::G_ANALYZER_TOOLS) {
|
||||
for (int i = m_mainWindow->toolBox()->count(); --i >= 0; )
|
||||
if (m_mainWindow->toolBox()->itemText(i).isEmpty())
|
||||
index = i;
|
||||
}
|
||||
|
||||
if (index >= 0)
|
||||
m_mainWindow->toolBox()->insertItem(index, desc.text(), actionId.toSetting());
|
||||
|
||||
Id menuGroup = desc.menuGroup();
|
||||
if (menuGroup.isValid()) {
|
||||
Command *command = ActionManager::registerAction(action, actionId);
|
||||
m_menu->addAction(command, menuGroup);
|
||||
}
|
||||
|
||||
connect(action, &QAction::triggered, this, [this, desc, actionId] {
|
||||
selectAction(actionId);
|
||||
desc.startTool();
|
||||
});
|
||||
}
|
||||
|
||||
void AnalyzerManagerPrivate::handleToolStarted()
|
||||
{
|
||||
m_isRunning = true; // FIXME: Make less global.
|
||||
updateRunActions();
|
||||
}
|
||||
|
||||
void AnalyzerManagerPrivate::handleToolFinished()
|
||||
{
|
||||
m_isRunning = false;
|
||||
updateRunActions();
|
||||
}
|
||||
|
||||
void AnalyzerManagerPrivate::updateRunActions()
|
||||
{
|
||||
QString disabledReason;
|
||||
bool enabled = false;
|
||||
if (m_isRunning)
|
||||
disabledReason = tr("An analysis is still in progress.");
|
||||
else if (m_currentActionId.isValid())
|
||||
enabled = m_descriptions.value(m_currentActionId).isRunnable(&disabledReason);
|
||||
else
|
||||
disabledReason = tr("No analyzer tool selected.");
|
||||
|
||||
m_startAction->setEnabled(enabled);
|
||||
m_startAction->setToolTip(disabledReason);
|
||||
m_mainWindow->toolBox()->setEnabled(!m_isRunning);
|
||||
m_stopAction->setEnabled(m_isRunning);
|
||||
|
||||
for (auto it = m_actions.begin(), end = m_actions.end(); it != end; ++it)
|
||||
it.value()->setEnabled(!m_isRunning && m_descriptions.value(it.key()).isRunnable());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// AnalyzerManager
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
static AnalyzerManagerPrivate *d = 0;
|
||||
|
||||
AnalyzerManager::AnalyzerManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
QTC_CHECK(d == 0);
|
||||
d = new AnalyzerManagerPrivate(this);
|
||||
}
|
||||
|
||||
AnalyzerManager::~AnalyzerManager()
|
||||
{
|
||||
QTC_CHECK(d);
|
||||
delete d;
|
||||
d = 0;
|
||||
}
|
||||
|
||||
void AnalyzerManager::shutdown()
|
||||
{
|
||||
d->m_mainWindow->saveCurrentPerspective();
|
||||
}
|
||||
|
||||
void AnalyzerManager::registerAction(Id actionId, const ActionDescription &desc)
|
||||
{
|
||||
d->registerAction(actionId, desc);
|
||||
}
|
||||
|
||||
void AnalyzerManager::registerDockWidget(Id dockId, QWidget *widget)
|
||||
{
|
||||
QTC_ASSERT(!widget->objectName().isEmpty(), return);
|
||||
QDockWidget *dockWidget = d->m_mainWindow->registerDockWidget(dockId, widget);
|
||||
|
||||
QAction *toggleViewAction = dockWidget->toggleViewAction();
|
||||
toggleViewAction->setText(dockWidget->windowTitle());
|
||||
|
||||
Command *cmd = ActionManager::registerAction(toggleViewAction,
|
||||
Id("Analyzer.").withSuffix(dockWidget->objectName()));
|
||||
cmd->setAttribute(Command::CA_Hide);
|
||||
|
||||
ActionContainer *viewsMenu = ActionManager::actionContainer(Id(M_WINDOW_VIEWS));
|
||||
viewsMenu->addAction(cmd);
|
||||
}
|
||||
|
||||
void AnalyzerManager::registerToolbar(Id toolbarId, QWidget *widget)
|
||||
{
|
||||
d->m_mainWindow->registerToolbar(toolbarId, widget);
|
||||
}
|
||||
|
||||
Perspective::Operation::Operation(Id dockId, Id existing, Perspective::OperationType operationType,
|
||||
bool visibleByDefault, Qt::DockWidgetArea area)
|
||||
: dockId(dockId), existing(existing), operationType(operationType),
|
||||
visibleByDefault(visibleByDefault), area(area)
|
||||
{}
|
||||
|
||||
Perspective::Perspective(std::initializer_list<Perspective::Operation> operations)
|
||||
: m_operations(operations)
|
||||
{
|
||||
for (const Operation &operation : operations)
|
||||
m_docks.append(operation.dockId);
|
||||
}
|
||||
|
||||
void Perspective::addOperation(const Operation &operation)
|
||||
{
|
||||
m_docks.append(operation.dockId);
|
||||
m_operations.append(operation);
|
||||
}
|
||||
|
||||
void AnalyzerManager::registerPerspective(Id perspectiveId, const Perspective &perspective)
|
||||
{
|
||||
d->m_mainWindow->registerPerspective(perspectiveId, perspective);
|
||||
}
|
||||
|
||||
void AnalyzerManager::selectAction(Id actionId, bool alsoRunIt)
|
||||
{
|
||||
d->selectAction(actionId);
|
||||
if (alsoRunIt)
|
||||
d->m_descriptions.value(actionId).startTool();
|
||||
}
|
||||
|
||||
void AnalyzerManager::enableMainWindow(bool on)
|
||||
{
|
||||
d->m_mainWindow->setEnabled(on);
|
||||
}
|
||||
|
||||
void AnalyzerManager::showStatusMessage(const QString &message, int timeoutMS)
|
||||
{
|
||||
d->m_mainWindow->showStatusMessage(message, timeoutMS);
|
||||
}
|
||||
|
||||
void AnalyzerManager::showPermanentStatusMessage(const QString &message)
|
||||
{
|
||||
d->m_mainWindow->showStatusMessage(message, -1);
|
||||
}
|
||||
|
||||
void AnalyzerManager::showMode()
|
||||
{
|
||||
if (d->m_mode)
|
||||
ModeManager::activateMode(d->m_mode->id());
|
||||
}
|
||||
|
||||
void AnalyzerManager::stopTool()
|
||||
{
|
||||
stopAction()->trigger();
|
||||
}
|
||||
|
||||
QAction *AnalyzerManager::stopAction()
|
||||
{
|
||||
return d->m_stopAction;
|
||||
}
|
||||
|
||||
void AnalyzerManager::handleToolStarted()
|
||||
{
|
||||
d->handleToolStarted();
|
||||
}
|
||||
|
||||
void AnalyzerManager::handleToolFinished()
|
||||
{
|
||||
d->handleToolFinished();
|
||||
}
|
||||
|
||||
AnalyzerRunControl *AnalyzerManager::createRunControl(RunConfiguration *runConfiguration, Id runMode)
|
||||
{
|
||||
foreach (const ActionDescription &action, d->m_descriptions) {
|
||||
if (action.runMode() == runMode)
|
||||
return action.runControlCreator()(runConfiguration, runMode);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool operator==(const AnalyzerConnection &c1, const AnalyzerConnection &c2)
|
||||
{
|
||||
return c1.connParams == c2.connParams
|
||||
&& c1.analyzerHost == c2.analyzerHost
|
||||
&& c1.analyzerSocket == c2.analyzerSocket
|
||||
&& c1.analyzerPort == c2.analyzerPort;
|
||||
}
|
||||
|
||||
} // namespace Analyzer
|
||||
@@ -27,7 +27,6 @@
|
||||
#ifndef ANALYZERMANAGER_H
|
||||
#define ANALYZERMANAGER_H
|
||||
|
||||
#include "analyzerbase_global.h"
|
||||
#include "analyzerconstants.h"
|
||||
|
||||
#include "../debuggermainwindow.h"
|
||||
@@ -48,7 +47,7 @@ QT_END_NAMESPACE
|
||||
|
||||
namespace ProjectExplorer { class RunConfiguration; }
|
||||
|
||||
namespace Analyzer {
|
||||
namespace Debugger {
|
||||
|
||||
class AnalyzerRunControl;
|
||||
|
||||
@@ -75,9 +74,9 @@ Q_DECLARE_FLAGS(ToolModes, ToolMode)
|
||||
*
|
||||
*/
|
||||
|
||||
class ANALYZER_EXPORT ActionDescription
|
||||
class DEBUGGER_EXPORT ActionDescription
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Analyzer::AnalyzerAction)
|
||||
Q_DECLARE_TR_FUNCTIONS(Debugger::AnalyzerAction)
|
||||
|
||||
public:
|
||||
ActionDescription() {}
|
||||
@@ -85,8 +84,8 @@ public:
|
||||
Core::Id menuGroup() const { return m_menuGroup; }
|
||||
void setMenuGroup(Core::Id menuGroup) { m_menuGroup = menuGroup; }
|
||||
|
||||
Core::Id perspectiveId() const { return m_perspective; }
|
||||
void setPerspectiveId(Core::Id id) { m_perspective = id; }
|
||||
QByteArray perspectiveId() const { return m_perspectiveId; }
|
||||
void setPerspectiveId(const QByteArray &id) { m_perspectiveId = id; }
|
||||
void setToolMode(QFlags<ToolMode> mode) { m_toolMode = mode; }
|
||||
|
||||
Core::Id runMode() const { return m_runMode; }
|
||||
@@ -120,7 +119,7 @@ private:
|
||||
QString m_text;
|
||||
QString m_toolTip;
|
||||
Core::Id m_menuGroup;
|
||||
Core::Id m_perspective;
|
||||
QByteArray m_perspectiveId;
|
||||
QFlags<ToolMode> m_toolMode = AnyMode;
|
||||
Core::Id m_runMode;
|
||||
RunControlCreator m_runControlCreator;
|
||||
@@ -128,41 +127,28 @@ private:
|
||||
ToolPreparer m_toolPreparer;
|
||||
};
|
||||
|
||||
// FIXME: Merge with AnalyzerPlugin.
|
||||
class ANALYZER_EXPORT AnalyzerManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
// FIXME: Merge with something sensible.
|
||||
|
||||
public:
|
||||
explicit AnalyzerManager(QObject *parent);
|
||||
~AnalyzerManager();
|
||||
// Register a tool for a given start mode.
|
||||
DEBUGGER_EXPORT void registerAction(Core::Id actionId, const ActionDescription &desc, QAction *startAction = 0);
|
||||
DEBUGGER_EXPORT void registerPerspective(const QByteArray &perspectiveId, const Utils::Perspective &perspective);
|
||||
DEBUGGER_EXPORT void registerToolbar(const QByteArray &perspectiveId, const Utils::ToolbarDescription &desc);
|
||||
|
||||
static void shutdown();
|
||||
DEBUGGER_EXPORT void enableMainWindow(bool on);
|
||||
|
||||
// Register a tool for a given start mode.
|
||||
static void registerAction(Core::Id actionId, const ActionDescription &desc);
|
||||
static void registerPerspective(Core::Id perspectiveId, const Perspective &perspective);
|
||||
static void registerDockWidget(Core::Id dockId, QWidget *widget);
|
||||
static void registerToolbar(Core::Id toolbarId, QWidget *widget);
|
||||
DEBUGGER_EXPORT void selectPerspective(const QByteArray &perspectiveId);
|
||||
DEBUGGER_EXPORT void runAction(Core::Id actionId);
|
||||
|
||||
static void enableMainWindow(bool on);
|
||||
// Convenience functions.
|
||||
DEBUGGER_EXPORT void showStatusMessage(const QString &message, int timeoutMS = 10000);
|
||||
DEBUGGER_EXPORT void showPermanentStatusMessage(const QString &message);
|
||||
|
||||
static void showMode();
|
||||
static void selectAction(Core::Id actionId, bool alsoRunIt = false);
|
||||
static void stopTool();
|
||||
DEBUGGER_EXPORT QAction *createStartAction();
|
||||
DEBUGGER_EXPORT QAction *createStopAction();
|
||||
|
||||
// Convenience functions.
|
||||
static void showStatusMessage(const QString &message, int timeoutMS = 10000);
|
||||
static void showPermanentStatusMessage(const QString &message);
|
||||
DEBUGGER_EXPORT AnalyzerRunControl *createAnalyzerRunControl(
|
||||
ProjectExplorer::RunConfiguration *runConfiguration, Core::Id runMode);
|
||||
|
||||
static void handleToolStarted();
|
||||
static void handleToolFinished();
|
||||
static QAction *stopAction();
|
||||
|
||||
static AnalyzerRunControl *createRunControl(
|
||||
ProjectExplorer::RunConfiguration *runConfiguration, Core::Id runMode);
|
||||
};
|
||||
|
||||
} // namespace Analyzer
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // ANALYZERMANAGER_H
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#include <QComboBox>
|
||||
#include <QPushButton>
|
||||
|
||||
namespace Analyzer {
|
||||
namespace Debugger {
|
||||
|
||||
AnalyzerRunConfigWidget::AnalyzerRunConfigWidget(ProjectExplorer::IRunConfigurationAspect *aspect)
|
||||
{
|
||||
@@ -105,4 +105,4 @@ void AnalyzerRunConfigWidget::restoreGlobal()
|
||||
m_aspect->resetProjectToGlobalSettings();
|
||||
}
|
||||
|
||||
} // namespace Analyzer
|
||||
} // namespace Debugger
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#ifndef ANALYZERRUNCONFIGWIDGET_H
|
||||
#define ANALYZERRUNCONFIGWIDGET_H
|
||||
|
||||
#include "analyzerbase_global.h"
|
||||
#include <debugger/debugger_global.h>
|
||||
|
||||
#include <projectexplorer/runconfiguration.h>
|
||||
|
||||
@@ -38,9 +38,9 @@ QT_END_NAMESPACE
|
||||
|
||||
namespace Utils { class DetailsWidget; }
|
||||
|
||||
namespace Analyzer {
|
||||
namespace Debugger {
|
||||
|
||||
class ANALYZER_EXPORT AnalyzerRunConfigWidget : public ProjectExplorer::RunConfigWidget
|
||||
class DEBUGGER_EXPORT AnalyzerRunConfigWidget : public ProjectExplorer::RunConfigWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -62,6 +62,6 @@ private:
|
||||
Utils::DetailsWidget *m_details;
|
||||
};
|
||||
|
||||
} // namespace Analyzer
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // ANALYZERRUNCONFIGWIDGET_H
|
||||
|
||||
@@ -37,60 +37,12 @@
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// AnalyzerRunControl
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Analyzer {
|
||||
namespace Debugger {
|
||||
|
||||
AnalyzerRunControl::AnalyzerRunControl(RunConfiguration *runConfiguration, Core::Id runMode)
|
||||
: RunControl(runConfiguration, runMode)
|
||||
{
|
||||
setIcon(Icons::ANALYZER_CONTROL_START);
|
||||
|
||||
connect(this, &AnalyzerRunControl::finished,
|
||||
this, &AnalyzerRunControl::runControlFinished);
|
||||
connect(AnalyzerManager::stopAction(), &QAction::triggered,
|
||||
this, &AnalyzerRunControl::stopIt);
|
||||
}
|
||||
|
||||
void AnalyzerRunControl::stopIt()
|
||||
{
|
||||
if (stop() == RunControl::StoppedSynchronously)
|
||||
AnalyzerManager::handleToolFinished();
|
||||
}
|
||||
|
||||
void AnalyzerRunControl::runControlFinished()
|
||||
{
|
||||
m_isRunning = false;
|
||||
AnalyzerManager::handleToolFinished();
|
||||
}
|
||||
|
||||
void AnalyzerRunControl::start()
|
||||
{
|
||||
AnalyzerManager::handleToolStarted();
|
||||
|
||||
if (startEngine()) {
|
||||
m_isRunning = true;
|
||||
emit started();
|
||||
}
|
||||
}
|
||||
|
||||
RunControl::StopResult AnalyzerRunControl::stop()
|
||||
{
|
||||
if (!m_isRunning)
|
||||
return StoppedSynchronously;
|
||||
|
||||
stopEngine();
|
||||
m_isRunning = false;
|
||||
return AsynchronousStop;
|
||||
}
|
||||
|
||||
bool AnalyzerRunControl::isRunning() const
|
||||
{
|
||||
return m_isRunning;
|
||||
}
|
||||
|
||||
} // namespace Analyzer
|
||||
} // namespace Debugger
|
||||
|
||||
@@ -27,31 +27,26 @@
|
||||
#ifndef ANALYZERRUNCONTROL_H
|
||||
#define ANALYZERRUNCONTROL_H
|
||||
|
||||
#include "analyzerbase_global.h"
|
||||
#include <debugger/debugger_global.h>
|
||||
|
||||
#include <projectexplorer/runconfiguration.h>
|
||||
|
||||
#include <utils/outputformat.h>
|
||||
|
||||
namespace Analyzer {
|
||||
namespace Debugger {
|
||||
|
||||
/**
|
||||
* An AnalyzerRunControl 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 AnalyzerRunControl : public ProjectExplorer::RunControl
|
||||
class DEBUGGER_EXPORT AnalyzerRunControl : public ProjectExplorer::RunControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AnalyzerRunControl(ProjectExplorer::RunConfiguration *runConfiguration, Core::Id runMode);
|
||||
|
||||
/// Start analyzation process.
|
||||
virtual bool startEngine() = 0;
|
||||
/// Trigger async stop of the analyzation process.
|
||||
virtual void stopEngine() = 0;
|
||||
|
||||
/// Controller actions.
|
||||
virtual bool canPause() const { return false; }
|
||||
virtual void pause() {}
|
||||
@@ -60,28 +55,16 @@ public:
|
||||
virtual void notifyRemoteSetupDone(quint16) {}
|
||||
virtual void notifyRemoteFinished() {}
|
||||
|
||||
// ProjectExplorer::RunControl
|
||||
void start() override;
|
||||
StopResult stop() override;
|
||||
bool isRunning() const override;
|
||||
signals:
|
||||
void starting();
|
||||
|
||||
public slots:
|
||||
virtual void logApplicationMessage(const QString &, Utils::OutputFormat) { }
|
||||
|
||||
private slots:
|
||||
void stopIt();
|
||||
void runControlFinished();
|
||||
|
||||
signals:
|
||||
/// Must be emitted when the engine is starting.
|
||||
void starting();
|
||||
|
||||
private:
|
||||
bool supportsReRunning() const override { return false; }
|
||||
|
||||
protected:
|
||||
bool m_isRunning;
|
||||
};
|
||||
} // namespace Analyzer
|
||||
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // ANALYZERRUNCONTROL_H
|
||||
|
||||
@@ -26,16 +26,16 @@
|
||||
#ifndef ANALYZERSTARTPARAMETERS_H
|
||||
#define ANALYZERSTARTPARAMETERS_H
|
||||
|
||||
#include "analyzerbase_global.h"
|
||||
#include <debugger/debugger_global.h>
|
||||
|
||||
#include <projectexplorer/runnables.h>
|
||||
#include <ssh/sshconnection.h>
|
||||
|
||||
#include <QMetaType>
|
||||
|
||||
namespace Analyzer {
|
||||
namespace Debugger {
|
||||
|
||||
class ANALYZER_EXPORT AnalyzerConnection
|
||||
class DEBUGGER_EXPORT AnalyzerConnection
|
||||
{
|
||||
public:
|
||||
QSsh::SshConnectionParameters connParams;
|
||||
@@ -44,8 +44,8 @@ public:
|
||||
quint16 analyzerPort = 0;
|
||||
};
|
||||
|
||||
ANALYZER_EXPORT bool operator==(const AnalyzerConnection &c1, const AnalyzerConnection &c2);
|
||||
DEBUGGER_EXPORT bool operator==(const AnalyzerConnection &c1, const AnalyzerConnection &c2);
|
||||
|
||||
} // namespace Analyzer
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // ANALYZERSTARTPARAMETERS_H
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
#include <QTextCursor>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace Core;
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
@@ -92,7 +92,7 @@ CPlusPlus::Symbol *AnalyzerUtils::findSymbolUnderCursor()
|
||||
|
||||
void AnalyzerUtils::logToIssuesPane(Task::TaskType type, const QString &message)
|
||||
{
|
||||
TaskHub::addTask(type, message, Analyzer::Constants::ANALYZERTASK_ID);
|
||||
TaskHub::addTask(type, message, Debugger::Constants::ANALYZERTASK_ID);
|
||||
if (type == Task::Error)
|
||||
TaskHub::requestPopup();
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#ifndef ANALYZERUTILS_H
|
||||
#define ANALYZERUTILS_H
|
||||
|
||||
#include "analyzerbase_global.h"
|
||||
#include <debugger/debugger_global.h>
|
||||
|
||||
#include <projectexplorer/task.h>
|
||||
|
||||
@@ -34,8 +34,8 @@ namespace CPlusPlus { class Symbol; }
|
||||
|
||||
namespace AnalyzerUtils
|
||||
{
|
||||
ANALYZER_EXPORT CPlusPlus::Symbol *findSymbolUnderCursor();
|
||||
ANALYZER_EXPORT void logToIssuesPane(ProjectExplorer::Task::TaskType type,
|
||||
DEBUGGER_EXPORT CPlusPlus::Symbol *findSymbolUnderCursor();
|
||||
DEBUGGER_EXPORT void logToIssuesPane(ProjectExplorer::Task::TaskType type,
|
||||
const QString &message);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
#include <QSharedPointer>
|
||||
#include <QTextDocument>
|
||||
|
||||
namespace Analyzer {
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class DetailedErrorDelegate : public QStyledItemDelegate
|
||||
@@ -138,8 +138,7 @@ DetailedErrorView::DetailedErrorView(QWidget *parent) :
|
||||
});
|
||||
connect(this, &QAbstractItemView::clicked, [](const QModelIndex &index) {
|
||||
if (index.column() == LocationColumn) {
|
||||
const auto loc = index.model()
|
||||
->data(index, Analyzer::DetailedErrorView::LocationRole)
|
||||
const auto loc = index.model()->data(index, DetailedErrorView::LocationRole)
|
||||
.value<DiagnosticLocation>();
|
||||
if (loc.isValid())
|
||||
Core::EditorManager::openEditorAt(loc.filePath, loc.line, loc.column - 1);
|
||||
@@ -212,6 +211,6 @@ void DetailedErrorView::setCurrentRow(int row)
|
||||
scrollTo(index);
|
||||
}
|
||||
|
||||
} // namespace Analyzer
|
||||
} // namespace Debugger
|
||||
|
||||
#include "detailederrorview.moc"
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
#ifndef DETAILEDERRORVIEW_H
|
||||
#define DETAILEDERRORVIEW_H
|
||||
|
||||
#include "analyzerbase_global.h"
|
||||
#include <debugger/debugger_global.h>
|
||||
|
||||
#include <QTreeView>
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
namespace Analyzer {
|
||||
namespace Debugger {
|
||||
|
||||
class ANALYZER_EXPORT DetailedErrorView : public QTreeView
|
||||
class DEBUGGER_EXPORT DetailedErrorView : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -67,6 +67,6 @@ private:
|
||||
QAction * const m_copyAction;
|
||||
};
|
||||
|
||||
} // namespace Analyzer
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DETAILEDERRORVIEW_H
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#include "diagnosticlocation.h"
|
||||
|
||||
namespace Analyzer {
|
||||
namespace Debugger {
|
||||
|
||||
DiagnosticLocation::DiagnosticLocation() : line(0), column(0)
|
||||
{
|
||||
@@ -56,5 +56,5 @@ QDebug operator<<(QDebug dbg, const DiagnosticLocation &location)
|
||||
return dbg.space();
|
||||
}
|
||||
|
||||
} // namespace Analyzer
|
||||
} // namespace Debugger
|
||||
|
||||
|
||||
@@ -26,15 +26,15 @@
|
||||
#ifndef ANALYZERDIAGNOSTIC_H
|
||||
#define ANALYZERDIAGNOSTIC_H
|
||||
|
||||
#include "analyzerbase_global.h"
|
||||
#include <debugger/debugger_global.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QMetaType>
|
||||
#include <QString>
|
||||
|
||||
namespace Analyzer {
|
||||
namespace Debugger {
|
||||
|
||||
class ANALYZER_EXPORT DiagnosticLocation
|
||||
class DEBUGGER_EXPORT DiagnosticLocation
|
||||
{
|
||||
public:
|
||||
DiagnosticLocation();
|
||||
@@ -49,12 +49,12 @@ public:
|
||||
int column;
|
||||
};
|
||||
|
||||
ANALYZER_EXPORT bool operator==(const DiagnosticLocation &first, const DiagnosticLocation &second);
|
||||
ANALYZER_EXPORT QDebug operator<<(QDebug dbg, const DiagnosticLocation &location);
|
||||
DEBUGGER_EXPORT bool operator==(const DiagnosticLocation &first, const DiagnosticLocation &second);
|
||||
DEBUGGER_EXPORT QDebug operator<<(QDebug dbg, const DiagnosticLocation &location);
|
||||
|
||||
} // namespace Analyzer
|
||||
} // namespace Debugger
|
||||
|
||||
Q_DECLARE_METATYPE(Analyzer::DiagnosticLocation)
|
||||
Q_DECLARE_METATYPE(Debugger::DiagnosticLocation)
|
||||
|
||||
#endif // Include guard.
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
namespace Analyzer {
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class StartRemoteDialogPrivate
|
||||
@@ -146,4 +146,4 @@ StandardRunnable StartRemoteDialog::runnable() const
|
||||
return r;
|
||||
}
|
||||
|
||||
} // namespace Analyzer
|
||||
} // namespace Debugger
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#ifndef STARTREMOTEDIALOG_H
|
||||
#define STARTREMOTEDIALOG_H
|
||||
|
||||
#include "analyzerbase_global.h"
|
||||
#include <debugger/debugger_global.h>
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
@@ -34,29 +34,28 @@ namespace QSsh { class SshConnectionParameters; }
|
||||
|
||||
namespace ProjectExplorer { class StandardRunnable; }
|
||||
|
||||
namespace Analyzer {
|
||||
namespace Debugger {
|
||||
|
||||
namespace Internal { class StartRemoteDialogPrivate; }
|
||||
|
||||
class ANALYZER_EXPORT StartRemoteDialog : public QDialog
|
||||
class DEBUGGER_EXPORT StartRemoteDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit StartRemoteDialog(QWidget *parent = 0);
|
||||
~StartRemoteDialog();
|
||||
~StartRemoteDialog() override;
|
||||
|
||||
QSsh::SshConnectionParameters sshParams() const;
|
||||
ProjectExplorer::StandardRunnable runnable() const;
|
||||
|
||||
private slots:
|
||||
void validate();
|
||||
virtual void accept();
|
||||
|
||||
private:
|
||||
void validate();
|
||||
void accept() override;
|
||||
|
||||
Internal::StartRemoteDialogPrivate *d;
|
||||
};
|
||||
|
||||
} // namespace Analyzer
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // STARTREMOTEDIALOG_H
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <debugger/breakhandler.h>
|
||||
#include <debugger/debuggeractions.h>
|
||||
#include <debugger/debuggercore.h>
|
||||
#include <debugger/debuggerinternalconstants.h>
|
||||
#include <debugger/debuggerprotocol.h>
|
||||
#include <debugger/debuggermainwindow.h>
|
||||
#include <debugger/debuggerstartparameters.h>
|
||||
|
||||
@@ -234,10 +234,8 @@ QtcPlugin {
|
||||
|
||||
files: [
|
||||
"analyzer/analyzerbase.qrc",
|
||||
"analyzer/analyzerbase_global.h",
|
||||
"analyzer/analyzerconstants.h",
|
||||
"analyzer/analyzericons.h",
|
||||
"analyzer/analyzermanager.cpp",
|
||||
"analyzer/analyzermanager.h",
|
||||
"analyzer/analyzerrunconfigwidget.cpp",
|
||||
"analyzer/analyzerrunconfigwidget.h",
|
||||
|
||||
@@ -39,6 +39,9 @@ const char C_DEBUGMODE[] = "Debugger.DebugMode";
|
||||
const char C_CPPDEBUGGER[] = "Gdb Debugger";
|
||||
const char C_QMLDEBUGGER[] = "Qml/JavaScript Debugger";
|
||||
|
||||
const char CppPerspectiveId[] = "Debugger.Perspective.Cpp";
|
||||
const char QmlPerspectiveId[] = "Debugger.Perspective.Qml";
|
||||
|
||||
// Menu Groups
|
||||
const char G_GENERAL[] = "Debugger.Group.General";
|
||||
const char G_SPECIAL[] = "Debugger.Group.Special";
|
||||
|
||||
@@ -74,7 +74,6 @@ bool isReverseDebugging();
|
||||
void runControlStarted(DebuggerEngine *engine);
|
||||
void runControlFinished(DebuggerEngine *engine);
|
||||
void displayDebugger(DebuggerEngine *engine, bool updateEngine);
|
||||
DebuggerLanguages activeLanguages();
|
||||
void synchronizeBreakpoints();
|
||||
|
||||
QWidget *mainWindow();
|
||||
|
||||
@@ -29,6 +29,21 @@
|
||||
#include <QtGlobal>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
// DebuggerMainWindow dock widget names
|
||||
const char DOCKWIDGET_BREAK[] = "Debugger.Docks.Break";
|
||||
const char DOCKWIDGET_MODULES[] = "Debugger.Docks.Modules";
|
||||
const char DOCKWIDGET_REGISTER[] = "Debugger.Docks.Register";
|
||||
const char DOCKWIDGET_OUTPUT[] = "Debugger.Docks.Output";
|
||||
const char DOCKWIDGET_SNAPSHOTS[] = "Debugger.Docks.Snapshots";
|
||||
const char DOCKWIDGET_STACK[] = "Debugger.Docks.Stack";
|
||||
const char DOCKWIDGET_SOURCE_FILES[] = "Debugger.Docks.SourceFiles";
|
||||
const char DOCKWIDGET_THREADS[] = "Debugger.Docks.Threads";
|
||||
const char DOCKWIDGET_WATCHERS[] = "Debugger.Docks.LocalsAndWatchers";
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
namespace Constants {
|
||||
|
||||
const char DEBUGGER_COMMON_SETTINGS_ID[] = "A.Debugger.General";
|
||||
|
||||
@@ -24,37 +24,65 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "debuggermainwindow.h"
|
||||
#include "debuggerconstants.h"
|
||||
#include "debuggerinternalconstants.h"
|
||||
#include "analyzer/analyzericons.h"
|
||||
|
||||
#include <coreplugin/actionmanager/actioncontainer.h>
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
#include <coreplugin/actionmanager/command.h>
|
||||
#include <coreplugin/coreconstants.h>
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <projectexplorer/projectexplorericons.h>
|
||||
|
||||
#include <utils/styledbar.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QAction>
|
||||
#include <QComboBox>
|
||||
#include <QDockWidget>
|
||||
#include <QHBoxLayout>
|
||||
#include <QMenu>
|
||||
#include <QStackedWidget>
|
||||
#include <QToolButton>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace Core;
|
||||
using namespace Utils;
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
namespace Utils {
|
||||
|
||||
MainWindowBase::MainWindowBase()
|
||||
const char LAST_PERSPECTIVE_KEY[] = "LastPerspective";
|
||||
|
||||
DebuggerMainWindow::DebuggerMainWindow()
|
||||
{
|
||||
m_controlsStackWidget = new QStackedWidget;
|
||||
m_statusLabel = new Utils::StatusLabel;
|
||||
m_toolBox = new QComboBox;
|
||||
|
||||
m_perspectiveChooser = new QComboBox;
|
||||
m_perspectiveChooser->setObjectName(QLatin1String("PerspectiveChooser"));
|
||||
connect(m_perspectiveChooser, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
|
||||
this, [this](int item) { restorePerspective(m_perspectiveChooser->itemData(item).toByteArray()); });
|
||||
|
||||
setDockNestingEnabled(true);
|
||||
setDockActionsVisible(false);
|
||||
setDocumentMode(true);
|
||||
|
||||
connect(this, &FancyMainWindow::resetLayout,
|
||||
this, &MainWindowBase::resetCurrentPerspective);
|
||||
this, &DebuggerMainWindow::resetCurrentPerspective);
|
||||
|
||||
auto dock = new QDockWidget(tr("Toolbar"));
|
||||
dock->setObjectName(QLatin1String("Toolbar"));
|
||||
dock->setFeatures(QDockWidget::NoDockWidgetFeatures);
|
||||
dock->setAllowedAreas(Qt::BottomDockWidgetArea);
|
||||
dock->setTitleBarWidget(new QWidget(dock)); // hide title bar
|
||||
dock->setProperty("managed_dockwidget", QLatin1String("true"));
|
||||
|
||||
addDockWidget(Qt::BottomDockWidgetArea, dock);
|
||||
setToolBarDockWidget(dock);
|
||||
}
|
||||
|
||||
MainWindowBase::~MainWindowBase()
|
||||
DebuggerMainWindow::~DebuggerMainWindow()
|
||||
{
|
||||
// as we have to setParent(0) on dock widget that are not selected,
|
||||
// we keep track of all and make sure we don't leak any
|
||||
@@ -64,64 +92,155 @@ MainWindowBase::~MainWindowBase()
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindowBase::registerPerspective(Id perspectiveId, const Perspective &perspective)
|
||||
void DebuggerMainWindow::registerPerspective(const QByteArray &perspectiveId, const Perspective &perspective)
|
||||
{
|
||||
m_perspectiveForPerspectiveId.insert(perspectiveId, perspective);
|
||||
m_perspectiveChooser->addItem(perspective.name(), perspectiveId);
|
||||
}
|
||||
|
||||
void MainWindowBase::registerToolbar(Id perspectiveId, QWidget *widget)
|
||||
void DebuggerMainWindow::registerToolbar(const QByteArray &perspectiveId, QWidget *widget)
|
||||
{
|
||||
m_toolbarForPerspectiveId.insert(perspectiveId, widget);
|
||||
m_controlsStackWidget->addWidget(widget);
|
||||
}
|
||||
|
||||
void MainWindowBase::showStatusMessage(const QString &message, int timeoutMS)
|
||||
void DebuggerMainWindow::showStatusMessage(const QString &message, int timeoutMS)
|
||||
{
|
||||
m_statusLabel->showStatusMessage(message, timeoutMS);
|
||||
}
|
||||
|
||||
void MainWindowBase::resetCurrentPerspective()
|
||||
QDockWidget *DebuggerMainWindow::dockWidget(const QByteArray &dockId) const
|
||||
{
|
||||
return m_dockForDockId.value(dockId);
|
||||
}
|
||||
|
||||
void DebuggerMainWindow::resetCurrentPerspective()
|
||||
{
|
||||
loadPerspectiveHelper(m_currentPerspectiveId, false);
|
||||
}
|
||||
|
||||
void MainWindowBase::restorePerspective(Id perspectiveId)
|
||||
void DebuggerMainWindow::restorePerspective(const QByteArray &perspectiveId)
|
||||
{
|
||||
loadPerspectiveHelper(perspectiveId, true);
|
||||
|
||||
int index = m_perspectiveChooser->findData(perspectiveId);
|
||||
if (index == -1)
|
||||
index = m_perspectiveChooser->findData(m_currentPerspectiveId);
|
||||
if (index != -1)
|
||||
m_perspectiveChooser->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void MainWindowBase::loadPerspectiveHelper(Id perspectiveId, bool fromStoredSettings)
|
||||
void DebuggerMainWindow::finalizeSetup()
|
||||
{
|
||||
QTC_ASSERT(perspectiveId.isValid(), return);
|
||||
auto viewButton = new QToolButton;
|
||||
viewButton->setText(tr("Views"));
|
||||
|
||||
auto toolbar = new Utils::StyledBar;
|
||||
toolbar->setProperty("topBorder", true);
|
||||
auto hbox = new QHBoxLayout(toolbar);
|
||||
hbox->setMargin(0);
|
||||
hbox->setSpacing(0);
|
||||
hbox->addWidget(m_perspectiveChooser);
|
||||
hbox->addWidget(m_controlsStackWidget);
|
||||
hbox->addWidget(m_statusLabel);
|
||||
hbox->addWidget(new Utils::StyledSeparator);
|
||||
hbox->addStretch();
|
||||
hbox->addWidget(viewButton);
|
||||
|
||||
connect(viewButton, &QAbstractButton::clicked, [this, viewButton] {
|
||||
QMenu menu;
|
||||
addDockActionsToMenu(&menu);
|
||||
menu.exec(viewButton->mapToGlobal(QPoint()));
|
||||
});
|
||||
|
||||
toolBarDockWidget()->setWidget(toolbar);
|
||||
|
||||
Context debugcontext(Debugger::Constants::C_DEBUGMODE);
|
||||
|
||||
ActionContainer *viewsMenu = ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS);
|
||||
Command *cmd = ActionManager::registerAction(menuSeparator1(),
|
||||
"Debugger.Views.Separator1", debugcontext);
|
||||
cmd->setAttribute(Command::CA_Hide);
|
||||
viewsMenu->addAction(cmd, Core::Constants::G_DEFAULT_THREE);
|
||||
cmd = ActionManager::registerAction(autoHideTitleBarsAction(),
|
||||
"Debugger.Views.AutoHideTitleBars", debugcontext);
|
||||
cmd->setAttribute(Command::CA_Hide);
|
||||
viewsMenu->addAction(cmd, Core::Constants::G_DEFAULT_THREE);
|
||||
cmd = ActionManager::registerAction(menuSeparator2(),
|
||||
"Debugger.Views.Separator2", debugcontext);
|
||||
cmd->setAttribute(Command::CA_Hide);
|
||||
viewsMenu->addAction(cmd, Core::Constants::G_DEFAULT_THREE);
|
||||
cmd = ActionManager::registerAction(resetLayoutAction(),
|
||||
"Debugger.Views.ResetSimple", debugcontext);
|
||||
cmd->setAttribute(Command::CA_Hide);
|
||||
viewsMenu->addAction(cmd, Core::Constants::G_DEFAULT_THREE);
|
||||
|
||||
addDockActionsToMenu(viewsMenu->menu());
|
||||
}
|
||||
|
||||
void DebuggerMainWindow::loadPerspectiveHelper(const QByteArray &perspectiveId, bool fromStoredSettings)
|
||||
{
|
||||
// Clean up old perspective.
|
||||
closeCurrentPerspective();
|
||||
if (!m_currentPerspectiveId.isEmpty()) {
|
||||
saveCurrentPerspective();
|
||||
foreach (QDockWidget *dockWidget, m_dockForDockId) {
|
||||
QTC_ASSERT(dockWidget, continue);
|
||||
removeDockWidget(dockWidget);
|
||||
dockWidget->hide();
|
||||
// Prevent saveState storing the data of the wrong children.
|
||||
dockWidget->setParent(0);
|
||||
}
|
||||
|
||||
ICore::removeAdditionalContext(Context(Id::fromName(m_currentPerspectiveId)));
|
||||
}
|
||||
|
||||
m_currentPerspectiveId = perspectiveId;
|
||||
|
||||
QTC_ASSERT(m_perspectiveForPerspectiveId.contains(perspectiveId), return);
|
||||
const auto operations = m_perspectiveForPerspectiveId.value(perspectiveId).operations();
|
||||
if (m_currentPerspectiveId.isEmpty()) {
|
||||
const QSettings *settings = ICore::settings();
|
||||
m_currentPerspectiveId = settings->value(QLatin1String(LAST_PERSPECTIVE_KEY)).toByteArray();
|
||||
if (m_currentPerspectiveId.isEmpty())
|
||||
m_currentPerspectiveId = Debugger::Constants::CppPerspectiveId;
|
||||
}
|
||||
|
||||
ICore::addAdditionalContext(Context(Id::fromName(m_currentPerspectiveId)));
|
||||
|
||||
QTC_ASSERT(m_perspectiveForPerspectiveId.contains(m_currentPerspectiveId), return);
|
||||
const auto operations = m_perspectiveForPerspectiveId.value(m_currentPerspectiveId).operations();
|
||||
for (const Perspective::Operation &operation : operations) {
|
||||
QDockWidget *dock = m_dockForDockId.value(operation.dockId);
|
||||
QTC_ASSERT(dock, continue);
|
||||
if (!dock) {
|
||||
QTC_CHECK(!operation.widget->objectName().isEmpty());
|
||||
dock = registerDockWidget(operation.dockId, operation.widget);
|
||||
|
||||
QAction *toggleViewAction = dock->toggleViewAction();
|
||||
toggleViewAction->setText(dock->windowTitle());
|
||||
|
||||
Command *cmd = ActionManager::registerAction(toggleViewAction,
|
||||
Id("Dock.").withSuffix(dock->objectName()),
|
||||
Context(Id::fromName(m_currentPerspectiveId)));
|
||||
cmd->setAttribute(Command::CA_Hide);
|
||||
|
||||
ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS)->addAction(cmd);
|
||||
}
|
||||
if (operation.operationType == Perspective::Raise) {
|
||||
dock->raise();
|
||||
continue;
|
||||
}
|
||||
addDockWidget(operation.area, dock);
|
||||
QDockWidget *existing = m_dockForDockId.value(operation.existing);
|
||||
if (!existing && operation.area == Qt::BottomDockWidgetArea)
|
||||
existing = toolBarDockWidget();
|
||||
if (existing) {
|
||||
QDockWidget *anchor = m_dockForDockId.value(operation.anchorDockId);
|
||||
if (!anchor && operation.area == Qt::BottomDockWidgetArea)
|
||||
anchor = toolBarDockWidget();
|
||||
if (anchor) {
|
||||
switch (operation.operationType) {
|
||||
case Perspective::AddToTab:
|
||||
tabifyDockWidget(existing, dock);
|
||||
tabifyDockWidget(anchor, dock);
|
||||
break;
|
||||
case Perspective::SplitHorizontal:
|
||||
splitDockWidget(existing, dock, Qt::Horizontal);
|
||||
splitDockWidget(anchor, dock, Qt::Horizontal);
|
||||
break;
|
||||
case Perspective::SplitVertical:
|
||||
splitDockWidget(existing, dock, Qt::Vertical);
|
||||
splitDockWidget(anchor, dock, Qt::Vertical);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -135,66 +254,84 @@ void MainWindowBase::loadPerspectiveHelper(Id perspectiveId, bool fromStoredSett
|
||||
|
||||
if (fromStoredSettings) {
|
||||
QSettings *settings = ICore::settings();
|
||||
settings->beginGroup(perspectiveId.toString());
|
||||
settings->beginGroup(QString::fromLatin1(m_currentPerspectiveId));
|
||||
if (settings->value(QLatin1String("ToolSettingsSaved"), false).toBool())
|
||||
restoreSettings(settings);
|
||||
settings->endGroup();
|
||||
}
|
||||
|
||||
QTC_CHECK(m_toolbarForPerspectiveId.contains(perspectiveId));
|
||||
m_controlsStackWidget->setCurrentWidget(m_toolbarForPerspectiveId.value(perspectiveId));
|
||||
QTC_CHECK(m_toolbarForPerspectiveId.contains(m_currentPerspectiveId));
|
||||
m_controlsStackWidget->setCurrentWidget(m_toolbarForPerspectiveId.value(m_currentPerspectiveId));
|
||||
m_statusLabel->clear();
|
||||
}
|
||||
|
||||
void MainWindowBase::closeCurrentPerspective()
|
||||
void DebuggerMainWindow::saveCurrentPerspective()
|
||||
{
|
||||
if (!m_currentPerspectiveId.isValid())
|
||||
return;
|
||||
|
||||
saveCurrentPerspective();
|
||||
foreach (QDockWidget *dockWidget, m_dockForDockId) {
|
||||
QTC_ASSERT(dockWidget, continue);
|
||||
removeDockWidget(dockWidget);
|
||||
dockWidget->hide();
|
||||
// Prevent saveState storing the data of the wrong children.
|
||||
dockWidget->setParent(0);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindowBase::saveCurrentPerspective()
|
||||
{
|
||||
if (!m_currentPerspectiveId.isValid())
|
||||
if (m_currentPerspectiveId.isEmpty())
|
||||
return;
|
||||
QSettings *settings = ICore::settings();
|
||||
settings->beginGroup(m_currentPerspectiveId.toString());
|
||||
settings->beginGroup(QString::fromLatin1(m_currentPerspectiveId));
|
||||
saveSettings(settings);
|
||||
settings->setValue(QLatin1String("ToolSettingsSaved"), true);
|
||||
settings->endGroup();
|
||||
settings->setValue(m_lastSettingsName, m_currentPerspectiveId.toString());
|
||||
settings->setValue(QLatin1String(LAST_PERSPECTIVE_KEY), m_currentPerspectiveId);
|
||||
}
|
||||
|
||||
QDockWidget *MainWindowBase::registerDockWidget(Id dockId, QWidget *widget)
|
||||
QDockWidget *DebuggerMainWindow::registerDockWidget(const QByteArray &dockId, QWidget *widget)
|
||||
{
|
||||
QTC_ASSERT(!widget->objectName().isEmpty(), return 0);
|
||||
QDockWidget *dockWidget = addDockForWidget(widget);
|
||||
m_dockWidgets.append(MainWindowBase::DockPtr(dockWidget));
|
||||
dockWidget->setParent(0);
|
||||
m_dockWidgets.append(DebuggerMainWindow::DockPtr(dockWidget));
|
||||
m_dockForDockId[dockId] = dockWidget;
|
||||
return dockWidget;
|
||||
}
|
||||
|
||||
Core::Id MainWindowBase::currentPerspectiveId() const
|
||||
QString Perspective::name() const
|
||||
{
|
||||
return m_currentPerspectiveId;
|
||||
return m_name;
|
||||
}
|
||||
|
||||
QString MainWindowBase::lastSettingsName() const
|
||||
void Perspective::setName(const QString &name)
|
||||
{
|
||||
return m_lastSettingsName;
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
void MainWindowBase::setLastSettingsName(const QString &lastSettingsName)
|
||||
QList<QWidget *> ToolbarDescription::widgets() const
|
||||
{
|
||||
m_lastSettingsName = lastSettingsName;
|
||||
return m_widgets;
|
||||
}
|
||||
|
||||
} // Internal
|
||||
} // Debugger
|
||||
void ToolbarDescription::addAction(QAction *action)
|
||||
{
|
||||
auto button = new QToolButton;
|
||||
button->setDefaultAction(action);
|
||||
m_widgets.append(button);
|
||||
}
|
||||
|
||||
void ToolbarDescription::addWidget(QWidget *widget)
|
||||
{
|
||||
m_widgets.append(widget);
|
||||
}
|
||||
|
||||
Perspective::Operation::Operation(const QByteArray &dockId, QWidget *widget, const QByteArray &anchorDockId,
|
||||
Perspective::OperationType splitType, bool visibleByDefault,
|
||||
Qt::DockWidgetArea area)
|
||||
: dockId(dockId), widget(widget), anchorDockId(anchorDockId),
|
||||
operationType(splitType), visibleByDefault(visibleByDefault), area(area)
|
||||
{}
|
||||
|
||||
Perspective::Perspective(const QString &name, const QVector<Operation> &splits)
|
||||
: m_name(name), m_operations(splits)
|
||||
{
|
||||
for (const Operation &split : splits)
|
||||
m_docks.append(split.dockId);
|
||||
}
|
||||
|
||||
void Perspective::addOperation(const Operation &operation)
|
||||
{
|
||||
m_docks.append(operation.dockId);
|
||||
m_operations.append(operation);
|
||||
}
|
||||
|
||||
} // Utils
|
||||
|
||||
@@ -27,9 +27,6 @@
|
||||
#define DEBUGGERMAINWINDOW_H
|
||||
|
||||
#include "debugger_global.h"
|
||||
#include "analyzer/analyzerbase_global.h"
|
||||
|
||||
#include <coreplugin/id.h>
|
||||
|
||||
#include <utils/fancymainwindow.h>
|
||||
#include <utils/statuslabel.h>
|
||||
@@ -38,113 +35,108 @@
|
||||
#include <QSet>
|
||||
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QComboBox;
|
||||
class QStackedWidget;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Analyzer {
|
||||
namespace Utils {
|
||||
|
||||
class ANALYZER_EXPORT Perspective
|
||||
class DEBUGGER_EXPORT Perspective
|
||||
{
|
||||
public:
|
||||
enum OperationType { SplitVertical, SplitHorizontal, AddToTab, Raise };
|
||||
|
||||
class ANALYZER_EXPORT Operation
|
||||
class DEBUGGER_EXPORT Operation
|
||||
{
|
||||
public:
|
||||
Operation() = default;
|
||||
Operation(Core::Id dockId, Core::Id existing, OperationType operationType,
|
||||
bool visibleByDefault = true,
|
||||
Qt::DockWidgetArea area = Qt::BottomDockWidgetArea);
|
||||
Operation(const QByteArray &dockId, QWidget *widget,
|
||||
const QByteArray &anchorDockId,
|
||||
OperationType operationType,
|
||||
bool visibleByDefault = true,
|
||||
Qt::DockWidgetArea area = Qt::BottomDockWidgetArea);
|
||||
|
||||
Core::Id dockId;
|
||||
Core::Id existing;
|
||||
QByteArray dockId;
|
||||
QWidget *widget = 0;
|
||||
QByteArray anchorDockId;
|
||||
OperationType operationType;
|
||||
bool visibleByDefault;
|
||||
Qt::DockWidgetArea area;
|
||||
};
|
||||
|
||||
Perspective() = default;
|
||||
Perspective(std::initializer_list<Operation> operations);
|
||||
Perspective(const QString &name, const QVector<Operation> &operations);
|
||||
|
||||
void addOperation(const Operation &operation);
|
||||
|
||||
QVector<Operation> operations() const { return m_operations; }
|
||||
QVector<Core::Id> docks() const { return m_docks; }
|
||||
QVector<QByteArray> docks() const { return m_docks; }
|
||||
|
||||
QString name() const;
|
||||
void setName(const QString &name);
|
||||
|
||||
private:
|
||||
QVector<Core::Id> m_docks;
|
||||
QString m_name;
|
||||
QVector<QByteArray> m_docks;
|
||||
QVector<Operation> m_operations;
|
||||
};
|
||||
|
||||
} // Analyzer
|
||||
class DEBUGGER_EXPORT ToolbarDescription
|
||||
{
|
||||
public:
|
||||
ToolbarDescription() = default;
|
||||
ToolbarDescription(const QList<QWidget *> &widgets) : m_widgets(widgets) {}
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
QList<QWidget *> widgets() const;
|
||||
|
||||
// DebuggerMainWindow dock widget names
|
||||
const char DOCKWIDGET_BREAK[] = "Debugger.Docks.Break";
|
||||
const char DOCKWIDGET_MODULES[] = "Debugger.Docks.Modules";
|
||||
const char DOCKWIDGET_REGISTER[] = "Debugger.Docks.Register";
|
||||
const char DOCKWIDGET_OUTPUT[] = "Debugger.Docks.Output";
|
||||
const char DOCKWIDGET_SNAPSHOTS[] = "Debugger.Docks.Snapshots";
|
||||
const char DOCKWIDGET_STACK[] = "Debugger.Docks.Stack";
|
||||
const char DOCKWIDGET_SOURCE_FILES[] = "Debugger.Docks.SourceFiles";
|
||||
const char DOCKWIDGET_THREADS[] = "Debugger.Docks.Threads";
|
||||
const char DOCKWIDGET_WATCHERS[] = "Debugger.Docks.LocalsAndWatchers";
|
||||
void addAction(QAction *action);
|
||||
void addWidget(QWidget *widget);
|
||||
|
||||
const char CppPerspectiveId[] = "Debugger.Perspective.Cpp";
|
||||
const char QmlPerspectiveId[] = "Debugger.Perspective.Qml";
|
||||
private:
|
||||
QList<QWidget *> m_widgets;
|
||||
};
|
||||
|
||||
class MainWindowBase : public Utils::FancyMainWindow
|
||||
class DebuggerMainWindow : public FancyMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindowBase();
|
||||
~MainWindowBase() override;
|
||||
DebuggerMainWindow();
|
||||
~DebuggerMainWindow() override;
|
||||
|
||||
QComboBox *toolBox() const { return m_toolBox; }
|
||||
QStackedWidget *controlsStack() const { return m_controlsStackWidget; }
|
||||
Utils::StatusLabel *statusLabel() const { return m_statusLabel; }
|
||||
|
||||
void registerPerspective(Core::Id perspectiveId, const Analyzer::Perspective &perspective);
|
||||
void registerToolbar(Core::Id perspectiveId, QWidget *widget);
|
||||
QDockWidget *registerDockWidget(Core::Id dockId, QWidget *widget);
|
||||
void registerPerspective(const QByteArray &perspectiveId, const Perspective &perspective);
|
||||
void registerToolbar(const QByteArray &perspectiveId, QWidget *widget);
|
||||
|
||||
void saveCurrentPerspective();
|
||||
void closeCurrentPerspective();
|
||||
void resetCurrentPerspective();
|
||||
void restorePerspective(Core::Id perspectiveId);
|
||||
void restorePerspective(const QByteArray &perspectiveId);
|
||||
|
||||
void finalizeSetup();
|
||||
|
||||
void showStatusMessage(const QString &message, int timeoutMS);
|
||||
|
||||
QString lastSettingsName() const;
|
||||
void setLastSettingsName(const QString &lastSettingsName);
|
||||
|
||||
Core::Id currentPerspectiveId() const;
|
||||
QDockWidget *dockWidget(const QByteArray &dockId) const;
|
||||
QByteArray currentPerspective() const { return m_currentPerspectiveId; }
|
||||
|
||||
private:
|
||||
void loadPerspectiveHelper(Core::Id perspectiveId, bool fromStoredSettings = true);
|
||||
QDockWidget *registerDockWidget(const QByteArray &dockId, QWidget *widget);
|
||||
void loadPerspectiveHelper(const QByteArray &perspectiveId, bool fromStoredSettings = true);
|
||||
|
||||
Core::Id m_currentPerspectiveId;
|
||||
QString m_lastSettingsName;
|
||||
QComboBox *m_toolBox;
|
||||
QByteArray m_currentPerspectiveId;
|
||||
QComboBox *m_perspectiveChooser;
|
||||
QStackedWidget *m_controlsStackWidget;
|
||||
Utils::StatusLabel *m_statusLabel;
|
||||
QHash<Core::Id, QDockWidget *> m_dockForDockId;
|
||||
QHash<Core::Id, QWidget *> m_toolbarForPerspectiveId;
|
||||
QHash<Core::Id, Analyzer::Perspective> m_perspectiveForPerspectiveId;
|
||||
|
||||
QHash<QByteArray, QDockWidget *> m_dockForDockId;
|
||||
QHash<QByteArray, QWidget *> m_toolbarForPerspectiveId;
|
||||
QHash<QByteArray, Perspective> m_perspectiveForPerspectiveId;
|
||||
|
||||
// list of dock widgets to prevent memory leak
|
||||
typedef QPointer<QDockWidget> DockPtr;
|
||||
QList<DockPtr> m_dockWidgets;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
} // Utils
|
||||
|
||||
#endif // DEBUGGERMAINWINDOW_H
|
||||
|
||||
+1057
-915
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "debuggerruncontrol.h"
|
||||
|
||||
#include "analyzer/analyzermanager.h"
|
||||
#include "debuggeractions.h"
|
||||
#include "debuggercore.h"
|
||||
#include "debuggerengine.h"
|
||||
@@ -140,6 +141,7 @@ QString DebuggerRunControl::displayName() const
|
||||
|
||||
void DebuggerRunControl::start()
|
||||
{
|
||||
Debugger::selectPerspective(Debugger::Constants::CppPerspectiveId);
|
||||
TaskHub::clearTasks(Debugger::Constants::TASK_CATEGORY_DEBUGGER_DEBUGINFO);
|
||||
TaskHub::clearTasks(Debugger::Constants::TASK_CATEGORY_DEBUGGER_RUNTIME);
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
namespace Ios {
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include <QProcess>
|
||||
#include <QObject>
|
||||
|
||||
namespace Analyzer { class AnalyzerRunControl; }
|
||||
namespace Debugger { class AnalyzerRunControl; }
|
||||
|
||||
namespace Ios {
|
||||
namespace Internal {
|
||||
@@ -47,7 +47,7 @@ class IosAnalyzeSupport : public QObject
|
||||
|
||||
public:
|
||||
IosAnalyzeSupport(IosRunConfiguration *runConfig,
|
||||
Analyzer::AnalyzerRunControl *runControl, bool cppDebug, bool qmlDebug);
|
||||
Debugger::AnalyzerRunControl *runControl, bool cppDebug, bool qmlDebug);
|
||||
~IosAnalyzeSupport();
|
||||
|
||||
private:
|
||||
@@ -59,7 +59,7 @@ private:
|
||||
void handleRemoteOutput(const QString &output);
|
||||
void handleRemoteErrorOutput(const QString &output);
|
||||
|
||||
Analyzer::AnalyzerRunControl *m_runControl;
|
||||
Debugger::AnalyzerRunControl *m_runControl;
|
||||
IosRunner * const m_runner;
|
||||
QmlDebug::QmlOutputParser m_outputParser;
|
||||
int m_qmlPort;
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
#include <qtsupport/qtsupportconstants.h>
|
||||
#include <coreplugin/id.h>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace QmakeProjectManager;
|
||||
|
||||
@@ -190,7 +190,7 @@ RunControl *IosRunControlFactory::create(RunConfiguration *runConfig,
|
||||
if (mode == ProjectExplorer::Constants::NORMAL_RUN_MODE)
|
||||
res = new Ios::Internal::IosRunControl(rc);
|
||||
else if (mode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) {
|
||||
AnalyzerRunControl *runControl = AnalyzerManager::createRunControl(runConfig, mode);
|
||||
AnalyzerRunControl *runControl = Debugger::createAnalyzerRunControl(runConfig, mode);
|
||||
QTC_ASSERT(runControl, return 0);
|
||||
IDevice::ConstPtr device = DeviceKitInformation::device(target->kit());
|
||||
if (device.isNull())
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -34,8 +34,6 @@
|
||||
|
||||
#include <QtPlugin>
|
||||
|
||||
using namespace Analyzer;
|
||||
|
||||
namespace QmlProfiler {
|
||||
namespace Internal {
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ ProjectExplorer::IRunConfigurationAspect *QmlProfilerRunConfigurationAspect::cre
|
||||
|
||||
ProjectExplorer::RunConfigWidget *QmlProfilerRunConfigurationAspect::createConfigurationWidget()
|
||||
{
|
||||
return new Analyzer::AnalyzerRunConfigWidget(this);
|
||||
return new Debugger::AnalyzerRunConfigWidget(this);
|
||||
}
|
||||
|
||||
} // Internal
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Qnx {
|
||||
namespace Internal {
|
||||
|
||||
QnxAnalyzeSupport::QnxAnalyzeSupport(QnxRunConfiguration *runConfig,
|
||||
Analyzer::AnalyzerRunControl *runControl)
|
||||
Debugger::AnalyzerRunControl *runControl)
|
||||
: QnxAbstractRunSupport(runConfig, runControl)
|
||||
, m_runnable(runConfig->runnable().as<StandardRunnable>())
|
||||
, m_runControl(runControl)
|
||||
@@ -65,7 +65,7 @@ QnxAnalyzeSupport::QnxAnalyzeSupport(QnxRunConfiguration *runConfig,
|
||||
connect(runner, &DeviceApplicationRunner::remoteStderr,
|
||||
this, &QnxAnalyzeSupport::handleRemoteOutput);
|
||||
|
||||
connect(m_runControl, &Analyzer::AnalyzerRunControl::starting,
|
||||
connect(m_runControl, &Debugger::AnalyzerRunControl::starting,
|
||||
this, &QnxAnalyzeSupport::handleAdapterSetupRequested);
|
||||
connect(&m_outputParser, &QmlDebug::QmlOutputParser::waitingForConnectionOnPort,
|
||||
this, &QnxAnalyzeSupport::remoteIsRunning);
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include <utils/outputformat.h>
|
||||
#include <qmldebug/qmloutputparser.h>
|
||||
|
||||
namespace Analyzer { class AnalyzerRunControl; }
|
||||
namespace Debugger { class AnalyzerRunControl; }
|
||||
|
||||
namespace Qnx {
|
||||
namespace Internal {
|
||||
@@ -44,7 +44,7 @@ class QnxAnalyzeSupport : public QnxAbstractRunSupport
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QnxAnalyzeSupport(QnxRunConfiguration *runConfig, Analyzer::AnalyzerRunControl *engine);
|
||||
QnxAnalyzeSupport(QnxRunConfiguration *runConfig, Debugger::AnalyzerRunControl *engine);
|
||||
|
||||
public slots:
|
||||
void handleProfilingFinished();
|
||||
@@ -66,7 +66,7 @@ private:
|
||||
void startExecution();
|
||||
|
||||
ProjectExplorer::StandardRunnable m_runnable;
|
||||
Analyzer::AnalyzerRunControl *m_runControl;
|
||||
Debugger::AnalyzerRunControl *m_runControl;
|
||||
QmlDebug::QmlOutputParser m_outputParser;
|
||||
int m_qmlPort;
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
#include <qtsupport/qtkitinformation.h>
|
||||
#include <utils/portlist.h>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Qnx;
|
||||
@@ -142,7 +141,7 @@ RunControl *QnxRunControlFactory::create(RunConfiguration *runConfig, Core::Id m
|
||||
const IDevice::ConstPtr device = DeviceKitInformation::device(kit);
|
||||
if (device.isNull())
|
||||
return 0;
|
||||
AnalyzerRunControl *runControl = AnalyzerManager::createRunControl(runConfig, mode);
|
||||
AnalyzerRunControl *runControl = Debugger::createAnalyzerRunControl(runConfig, mode);
|
||||
QTC_ASSERT(runControl, return 0);
|
||||
runControl->setRunnable(runConfig->runnable());
|
||||
AnalyzerConnection connection;
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
#include <QPointer>
|
||||
|
||||
using namespace QSsh;
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#include <utils/outputformat.h>
|
||||
|
||||
namespace Analyzer { class AnalyzerRunControl; }
|
||||
namespace Debugger { class AnalyzerRunControl; }
|
||||
|
||||
namespace RemoteLinux {
|
||||
|
||||
@@ -44,7 +44,7 @@ class REMOTELINUX_EXPORT RemoteLinuxAnalyzeSupport : public AbstractRemoteLinuxR
|
||||
Q_OBJECT
|
||||
public:
|
||||
RemoteLinuxAnalyzeSupport(ProjectExplorer::RunConfiguration *runConfig,
|
||||
Analyzer::AnalyzerRunControl *engine, Core::Id runMode);
|
||||
Debugger::AnalyzerRunControl *engine, Core::Id runMode);
|
||||
~RemoteLinuxAnalyzeSupport();
|
||||
|
||||
protected:
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
#include <utils/portlist.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
@@ -139,7 +138,7 @@ RunControl *RemoteLinuxRunControlFactory::create(RunConfiguration *runConfig, Co
|
||||
}
|
||||
|
||||
if (mode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) {
|
||||
auto runControl = AnalyzerManager::createRunControl(runConfig, mode);
|
||||
auto runControl = Debugger::createAnalyzerRunControl(runConfig, mode);
|
||||
AnalyzerConnection connection;
|
||||
connection.connParams =
|
||||
DeviceKitInformation::device(runConfig->target()->kit())->sshParameters();
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace Valgrind;
|
||||
using namespace Valgrind::Internal;
|
||||
|
||||
@@ -48,7 +48,7 @@ CallgrindRunControl::CallgrindRunControl(ProjectExplorer::RunConfiguration *runC
|
||||
connect(m_runner.parser(), &Callgrind::Parser::parserDataReady,
|
||||
this, &CallgrindRunControl::slotFinished);
|
||||
connect(&m_runner, &Callgrind::CallgrindRunner::statusMessage,
|
||||
this, &AnalyzerManager::showPermanentStatusMessage);
|
||||
this, &Debugger::showPermanentStatusMessage);
|
||||
}
|
||||
|
||||
QStringList CallgrindRunControl::toolArguments() const
|
||||
@@ -89,10 +89,10 @@ ValgrindRunner * CallgrindRunControl::runner()
|
||||
return &m_runner;
|
||||
}
|
||||
|
||||
bool CallgrindRunControl::startEngine()
|
||||
void CallgrindRunControl::start()
|
||||
{
|
||||
appendMessage(tr("Profiling %1").arg(executable()) + QLatin1Char('\n'), Utils::NormalMessageFormat);
|
||||
return ValgrindRunControl::startEngine();
|
||||
return ValgrindRunControl::start();
|
||||
}
|
||||
|
||||
void CallgrindRunControl::dump()
|
||||
|
||||
@@ -41,7 +41,7 @@ class CallgrindRunControl : public ValgrindRunControl
|
||||
public:
|
||||
CallgrindRunControl(ProjectExplorer::RunConfiguration *runConfiguration);
|
||||
|
||||
bool startEngine() override;
|
||||
void start() override;
|
||||
|
||||
Valgrind::Callgrind::ParseData *takeParserData();
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <valgrind/valgrindplugin.h>
|
||||
#include <valgrind/valgrindsettings.h>
|
||||
|
||||
#include <debugger/debuggerconstants.h>
|
||||
#include <debugger/analyzer/analyzerconstants.h>
|
||||
#include <debugger/analyzer/analyzericons.h>
|
||||
#include <debugger/analyzer/analyzermanager.h>
|
||||
@@ -90,11 +91,12 @@
|
||||
#include <QToolBar>
|
||||
#include <QToolButton>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace Core;
|
||||
using namespace Valgrind::Callgrind;
|
||||
using namespace TextEditor;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
@@ -108,7 +110,6 @@ public:
|
||||
~CallgrindTool();
|
||||
|
||||
ValgrindRunControl *createRunControl(RunConfiguration *runConfiguration);
|
||||
void createWidgets();
|
||||
|
||||
void setParseData(ParseData *data);
|
||||
CostDelegate::CostFormat costFormat() const;
|
||||
@@ -164,6 +165,7 @@ public:
|
||||
|
||||
void editorOpened(IEditor *);
|
||||
void requestContextMenu(TextEditorWidget *widget, int line, QMenu *menu);
|
||||
void updateRunActions();
|
||||
|
||||
public:
|
||||
DataModel m_dataModel;
|
||||
@@ -200,15 +202,17 @@ public:
|
||||
|
||||
QVector<CallgrindTextMark *> m_textMarks;
|
||||
|
||||
QAction *m_startAction = 0;
|
||||
QAction *m_stopAction = 0;
|
||||
QAction *m_loadExternalLogFile;
|
||||
QAction *m_dumpAction = 0;
|
||||
QAction *m_resetAction = 0;
|
||||
QAction *m_pauseAction = 0;
|
||||
|
||||
QString m_toggleCollectFunction;
|
||||
bool m_toolBusy = false;
|
||||
};
|
||||
|
||||
|
||||
CallgrindTool::CallgrindTool(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
@@ -231,6 +235,9 @@ CallgrindTool::CallgrindTool(QObject *parent)
|
||||
connect(EditorManager::instance(), &EditorManager::editorOpened,
|
||||
this, &CallgrindTool::editorOpened);
|
||||
|
||||
m_startAction = Debugger::createStartAction();
|
||||
m_stopAction = Debugger::createStopAction();
|
||||
|
||||
ActionDescription desc;
|
||||
desc.setToolTip(tr("Valgrind Function Profile uses the "
|
||||
"Callgrind tool to record function calls when a program runs."));
|
||||
@@ -243,13 +250,13 @@ CallgrindTool::CallgrindTool(QObject *parent)
|
||||
});
|
||||
desc.setToolMode(OptimizedMode);
|
||||
desc.setRunMode(CALLGRIND_RUN_MODE);
|
||||
desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_TOOLS);
|
||||
AnalyzerManager::registerAction(CallgrindLocalActionId, desc);
|
||||
desc.setMenuGroup(Debugger::Constants::G_ANALYZER_TOOLS);
|
||||
Debugger::registerAction(CallgrindLocalActionId, desc, m_startAction);
|
||||
}
|
||||
|
||||
desc.setText(tr("Valgrind Function Profiler (External Application)"));
|
||||
desc.setPerspectiveId(CallgrindPerspectiveId);
|
||||
desc.setCustomToolStarter([this](ProjectExplorer::RunConfiguration *runConfig) {
|
||||
desc.setCustomToolStarter([this](RunConfiguration *runConfig) {
|
||||
StartRemoteDialog dlg;
|
||||
if (dlg.exec() != QDialog::Accepted)
|
||||
return;
|
||||
@@ -263,17 +270,17 @@ CallgrindTool::CallgrindTool(QObject *parent)
|
||||
rc->setDisplayName(runnable.executable);
|
||||
ProjectExplorerPlugin::startRunControl(rc, CALLGRIND_RUN_MODE);
|
||||
});
|
||||
desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_REMOTE_TOOLS);
|
||||
AnalyzerManager::registerAction(CallgrindRemoteActionId, desc);
|
||||
desc.setMenuGroup(Debugger::Constants::G_ANALYZER_REMOTE_TOOLS);
|
||||
Debugger::registerAction(CallgrindRemoteActionId, desc);
|
||||
|
||||
// If there is a CppEditor context menu add our own context menu actions.
|
||||
if (ActionContainer *editorContextMenu =
|
||||
ActionManager::actionContainer(CppEditor::Constants::M_CONTEXT)) {
|
||||
Context analyzerContext = Context(Analyzer::Constants::C_ANALYZEMODE);
|
||||
Context analyzerContext = Context(Debugger::Constants::C_DEBUGMODE);
|
||||
editorContextMenu->addSeparator(analyzerContext);
|
||||
|
||||
auto action = new QAction(tr("Profile Costs of This Function and Its Callees"), this);
|
||||
action->setIcon(Analyzer::Icons::ANALYZER_CONTROL_START.icon());
|
||||
action->setIcon(Debugger::Icons::ANALYZER_CONTROL_START.icon());
|
||||
connect(action, &QAction::triggered, this,
|
||||
&CallgrindTool::handleShowCostsOfFunction);
|
||||
Command *cmd = ActionManager::registerAction(action, "Analyzer.Callgrind.ShowCostsOfFunction",
|
||||
@@ -283,7 +290,214 @@ CallgrindTool::CallgrindTool(QObject *parent)
|
||||
cmd->setAttribute(Command::CA_NonConfigurable);
|
||||
}
|
||||
|
||||
createWidgets();
|
||||
QSettings *coreSettings = ICore::settings();
|
||||
|
||||
//
|
||||
// DockWidgets
|
||||
//
|
||||
m_visualization = new Visualisation;
|
||||
m_visualization->setFrameStyle(QFrame::NoFrame);
|
||||
m_visualization->setObjectName(QLatin1String("Valgrind.CallgrindTool.Visualisation"));
|
||||
m_visualization->setWindowTitle(tr("Visualization"));
|
||||
m_visualization->setModel(&m_dataModel);
|
||||
connect(m_visualization, &Visualisation::functionActivated,
|
||||
this, &CallgrindTool::visualisationFunctionSelected);
|
||||
|
||||
m_callersView = new CostView;
|
||||
m_callersView->setObjectName(QLatin1String("Valgrind.CallgrindTool.CallersView"));
|
||||
m_callersView->setWindowTitle(tr("Callers"));
|
||||
m_callersView->setSettings(coreSettings, "Valgrind.CallgrindTool.CallersView");
|
||||
m_callersView->sortByColumn(CallModel::CostColumn);
|
||||
m_callersView->setFrameStyle(QFrame::NoFrame);
|
||||
// enable sorting
|
||||
m_callersProxy.setSourceModel(&m_callersModel);
|
||||
m_callersView->setModel(&m_callersProxy);
|
||||
m_callersView->hideColumn(CallModel::CalleeColumn);
|
||||
connect(m_callersView, &QAbstractItemView::activated,
|
||||
this, &CallgrindTool::callerFunctionSelected);
|
||||
|
||||
m_calleesView = new CostView;
|
||||
m_calleesView->setObjectName(QLatin1String("Valgrind.CallgrindTool.CalleesView"));
|
||||
m_calleesView->setWindowTitle(tr("Callees"));
|
||||
m_calleesView->setSettings(coreSettings, "Valgrind.CallgrindTool.CalleesView");
|
||||
m_calleesView->sortByColumn(CallModel::CostColumn);
|
||||
m_calleesView->setFrameStyle(QFrame::NoFrame);
|
||||
// enable sorting
|
||||
m_calleesProxy.setSourceModel(&m_calleesModel);
|
||||
m_calleesView->setModel(&m_calleesProxy);
|
||||
m_calleesView->hideColumn(CallModel::CallerColumn);
|
||||
connect(m_calleesView, &QAbstractItemView::activated,
|
||||
this, &CallgrindTool::calleeFunctionSelected);
|
||||
|
||||
m_flatView = new CostView;
|
||||
m_flatView->setObjectName(QLatin1String("Valgrind.CallgrindTool.FlatView"));
|
||||
m_flatView->setWindowTitle(tr("Functions"));
|
||||
m_flatView->setSettings(coreSettings, "Valgrind.CallgrindTool.FlatView");
|
||||
m_flatView->sortByColumn(DataModel::SelfCostColumn);
|
||||
m_flatView->setFrameStyle(QFrame::NoFrame);
|
||||
m_flatView->setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
m_flatView->setModel(&m_proxyModel);
|
||||
connect(m_flatView, &QAbstractItemView::activated,
|
||||
this, &CallgrindTool::dataFunctionSelected);
|
||||
|
||||
updateCostFormat();
|
||||
|
||||
//
|
||||
// Control Widget
|
||||
//
|
||||
|
||||
// load external log file
|
||||
auto action = m_loadExternalLogFile = new QAction(this);
|
||||
action->setIcon(Core::Icons::OPENFILE.icon());
|
||||
action->setToolTip(tr("Load External Log File"));
|
||||
connect(action, &QAction::triggered, this, &CallgrindTool::loadExternalLogFile);
|
||||
|
||||
// dump action
|
||||
m_dumpAction = action = new QAction(this);
|
||||
action->setDisabled(true);
|
||||
action->setIcon(Core::Icons::REDO.icon());
|
||||
//action->setText(tr("Dump"));
|
||||
action->setToolTip(tr("Request the dumping of profile information. This will update the Callgrind visualization."));
|
||||
connect(action, &QAction::triggered, this, &CallgrindTool::slotRequestDump);
|
||||
|
||||
// reset action
|
||||
m_resetAction = action = new QAction(this);
|
||||
action->setDisabled(true);
|
||||
action->setIcon(Core::Icons::RELOAD.icon());
|
||||
//action->setText(tr("Reset"));
|
||||
action->setToolTip(tr("Reset all event counters."));
|
||||
connect(action, &QAction::triggered, this, &CallgrindTool::resetRequested);
|
||||
|
||||
// pause action
|
||||
m_pauseAction = action = new QAction(this);
|
||||
action->setCheckable(true);
|
||||
action->setIcon(ProjectExplorer::Icons::INTERRUPT_SMALL.icon());
|
||||
//action->setText(tr("Ignore"));
|
||||
action->setToolTip(tr("Pause event logging. No events are counted which will speed up program execution during profiling."));
|
||||
connect(action, &QAction::toggled, this, &CallgrindTool::pauseToggled);
|
||||
|
||||
// navigation
|
||||
// go back
|
||||
m_goBack = action = new QAction(this);
|
||||
action->setDisabled(true);
|
||||
action->setIcon(Core::Icons::PREV.icon());
|
||||
action->setToolTip(tr("Go back one step in history. This will select the previously selected item."));
|
||||
connect(action, &QAction::triggered, &m_stackBrowser, &StackBrowser::goBack);
|
||||
|
||||
// go forward
|
||||
m_goNext = action = new QAction(this);
|
||||
action->setDisabled(true);
|
||||
action->setIcon(Core::Icons::NEXT.icon());
|
||||
action->setToolTip(tr("Go forward one step in history."));
|
||||
connect(action, &QAction::triggered, &m_stackBrowser, &StackBrowser::goNext);
|
||||
|
||||
// event selection
|
||||
m_eventCombo = new QComboBox;
|
||||
m_eventCombo->setToolTip(tr("Selects which events from the profiling data are shown and visualized."));
|
||||
connect(m_eventCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this, &CallgrindTool::setCostEvent);
|
||||
updateEventCombo();
|
||||
|
||||
ToolbarDescription toolbar;
|
||||
toolbar.addAction(m_startAction);
|
||||
toolbar.addAction(m_stopAction);
|
||||
toolbar.addAction(m_loadExternalLogFile);
|
||||
toolbar.addAction(m_dumpAction);
|
||||
toolbar.addAction(m_resetAction);
|
||||
toolbar.addAction(m_pauseAction);
|
||||
toolbar.addAction(m_goBack);
|
||||
toolbar.addAction(m_goNext);
|
||||
toolbar.addWidget(new Utils::StyledSeparator);
|
||||
toolbar.addWidget(m_eventCombo);
|
||||
|
||||
// Cost formatting
|
||||
{
|
||||
auto menu = new QMenu;
|
||||
auto group = new QActionGroup(this);
|
||||
|
||||
// Show costs as absolute numbers
|
||||
m_costAbsolute = new QAction(tr("Absolute Costs"), this);
|
||||
m_costAbsolute->setToolTip(tr("Show costs as absolute numbers."));
|
||||
m_costAbsolute->setCheckable(true);
|
||||
m_costAbsolute->setChecked(true);
|
||||
connect(m_costAbsolute, &QAction::toggled, this, &CallgrindTool::updateCostFormat);
|
||||
group->addAction(m_costAbsolute);
|
||||
menu->addAction(m_costAbsolute);
|
||||
|
||||
// Show costs in percentages
|
||||
m_costRelative = new QAction(tr("Relative Costs"), this);
|
||||
m_costRelative->setToolTip(tr("Show costs relative to total inclusive cost."));
|
||||
m_costRelative->setCheckable(true);
|
||||
connect(m_costRelative, &QAction::toggled, this, &CallgrindTool::updateCostFormat);
|
||||
group->addAction(m_costRelative);
|
||||
menu->addAction(m_costRelative);
|
||||
|
||||
// Show costs relative to parent
|
||||
m_costRelativeToParent = new QAction(tr("Relative Costs to Parent"), this);
|
||||
m_costRelativeToParent->setToolTip(tr("Show costs relative to parent functions inclusive cost."));
|
||||
m_costRelativeToParent->setCheckable(true);
|
||||
connect(m_costRelativeToParent, &QAction::toggled, this, &CallgrindTool::updateCostFormat);
|
||||
group->addAction(m_costRelativeToParent);
|
||||
menu->addAction(m_costRelativeToParent);
|
||||
|
||||
auto button = new QToolButton;
|
||||
button->setMenu(menu);
|
||||
button->setPopupMode(QToolButton::InstantPopup);
|
||||
button->setText(QLatin1String("$"));
|
||||
button->setToolTip(tr("Cost Format"));
|
||||
toolbar.addWidget(button);
|
||||
}
|
||||
|
||||
ValgrindGlobalSettings *settings = ValgrindPlugin::globalSettings();
|
||||
|
||||
// Cycle detection
|
||||
//action = new QAction(QLatin1String("Cycle Detection"), this); ///FIXME: icon
|
||||
action = m_cycleDetection = new QAction(QLatin1String("O"), this); ///FIXME: icon
|
||||
action->setToolTip(tr("Enable cycle detection to properly handle recursive or circular function calls."));
|
||||
action->setCheckable(true);
|
||||
connect(action, &QAction::toggled, &m_dataModel, &DataModel::enableCycleDetection);
|
||||
connect(action, &QAction::toggled, settings, &ValgrindGlobalSettings::setDetectCycles);
|
||||
|
||||
// Shorter template signature
|
||||
action = m_shortenTemplates = new QAction(QLatin1String("<>"), this);
|
||||
action->setToolTip(tr("This removes template parameter lists when displaying function names."));
|
||||
action->setCheckable(true);
|
||||
connect(action, &QAction::toggled, &m_dataModel, &DataModel::setShortenTemplates);
|
||||
connect(action, &QAction::toggled, settings, &ValgrindGlobalSettings::setShortenTemplates);
|
||||
|
||||
// Filtering
|
||||
action = m_filterProjectCosts = new QAction(tr("Show Project Costs Only"), this);
|
||||
action->setIcon(Core::Icons::FILTER.icon());
|
||||
action->setToolTip(tr("Show only profiling info that originated from this project source."));
|
||||
action->setCheckable(true);
|
||||
connect(action, &QAction::toggled, this, &CallgrindTool::handleFilterProjectCosts);
|
||||
|
||||
// Filter
|
||||
///FIXME: find workaround for https://bugreports.qt.io/browse/QTCREATORBUG-3247
|
||||
m_searchFilter = new QLineEdit;
|
||||
m_searchFilter->setPlaceholderText(tr("Filter..."));
|
||||
connect(m_searchFilter, &QLineEdit::textChanged,
|
||||
&m_updateTimer, static_cast<void(QTimer::*)()>(&QTimer::start));
|
||||
|
||||
setCostFormat(settings->costFormat());
|
||||
enableCycleDetection(settings->detectCycles());
|
||||
|
||||
toolbar.addAction(m_cycleDetection);
|
||||
toolbar.addAction(m_shortenTemplates);
|
||||
toolbar.addAction(m_filterProjectCosts);
|
||||
toolbar.addWidget(m_searchFilter);
|
||||
Debugger::registerToolbar(CallgrindPerspectiveId, toolbar);
|
||||
|
||||
Debugger::registerPerspective(CallgrindPerspectiveId, { tr("Callgrind"), {
|
||||
{ CallgrindFlatDockId, m_flatView, {}, Perspective::SplitVertical },
|
||||
{ CallgrindCalleesDockId, m_calleesView, {}, Perspective::SplitVertical },
|
||||
{ CallgrindCallersDockId, m_callersView, CallgrindCalleesDockId, Perspective::SplitHorizontal },
|
||||
{ CallgrindVisualizationDockId, m_visualization, {}, Perspective::SplitVertical,
|
||||
false, Qt::RightDockWidgetArea }
|
||||
}});
|
||||
|
||||
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
|
||||
this, &CallgrindTool::updateRunActions);
|
||||
}
|
||||
|
||||
CallgrindTool::~CallgrindTool()
|
||||
@@ -521,34 +735,28 @@ void CallgrindTool::updateEventCombo()
|
||||
m_eventCombo->addItem(ParseData::prettyStringForEvent(event));
|
||||
}
|
||||
|
||||
static QToolButton *createToolButton(QAction *action)
|
||||
{
|
||||
QToolButton *button = new QToolButton;
|
||||
button->setDefaultAction(action);
|
||||
//button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
return button;
|
||||
}
|
||||
|
||||
ValgrindRunControl *CallgrindTool::createRunControl(RunConfiguration *runConfiguration)
|
||||
{
|
||||
auto rc = new CallgrindRunControl(runConfiguration);
|
||||
auto runControl = new CallgrindRunControl(runConfiguration);
|
||||
|
||||
connect(rc, &CallgrindRunControl::parserDataReady, this, &CallgrindTool::takeParserDataFromRunControl);
|
||||
connect(rc, &AnalyzerRunControl::starting, this, &CallgrindTool::engineStarting);
|
||||
connect(rc, &RunControl::finished, this, &CallgrindTool::engineFinished);
|
||||
connect(runControl, &CallgrindRunControl::parserDataReady, this, &CallgrindTool::takeParserDataFromRunControl);
|
||||
connect(runControl, &AnalyzerRunControl::starting, this, &CallgrindTool::engineStarting);
|
||||
connect(runControl, &RunControl::finished, this, &CallgrindTool::engineFinished);
|
||||
|
||||
connect(this, &CallgrindTool::dumpRequested, rc, &CallgrindRunControl::dump);
|
||||
connect(this, &CallgrindTool::resetRequested, rc, &CallgrindRunControl::reset);
|
||||
connect(this, &CallgrindTool::pauseToggled, rc, &CallgrindRunControl::setPaused);
|
||||
connect(this, &CallgrindTool::dumpRequested, runControl, &CallgrindRunControl::dump);
|
||||
connect(this, &CallgrindTool::resetRequested, runControl, &CallgrindRunControl::reset);
|
||||
connect(this, &CallgrindTool::pauseToggled, runControl, &CallgrindRunControl::setPaused);
|
||||
|
||||
connect(m_stopAction, &QAction::triggered, runControl, [runControl] { runControl->stop(); });
|
||||
|
||||
// initialize run control
|
||||
rc->setPaused(m_pauseAction->isChecked());
|
||||
runControl->setPaused(m_pauseAction->isChecked());
|
||||
|
||||
// we may want to toggle collect for one function only in this run
|
||||
rc->setToggleCollectFunction(m_toggleCollectFunction);
|
||||
runControl->setToggleCollectFunction(m_toggleCollectFunction);
|
||||
m_toggleCollectFunction.clear();
|
||||
|
||||
QTC_ASSERT(m_visualization, return rc);
|
||||
QTC_ASSERT(m_visualization, return runControl);
|
||||
|
||||
// apply project settings
|
||||
if (runConfiguration) {
|
||||
@@ -560,241 +768,32 @@ ValgrindRunControl *CallgrindTool::createRunControl(RunConfiguration *runConfigu
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
|
||||
m_toolBusy = true;
|
||||
updateRunActions();
|
||||
|
||||
return runControl;
|
||||
}
|
||||
|
||||
void CallgrindTool::createWidgets()
|
||||
void CallgrindTool::updateRunActions()
|
||||
{
|
||||
QTC_ASSERT(!m_visualization, return);
|
||||
|
||||
QSettings *coreSettings = ICore::settings();
|
||||
|
||||
//
|
||||
// DockWidgets
|
||||
//
|
||||
m_visualization = new Visualisation;
|
||||
m_visualization->setFrameStyle(QFrame::NoFrame);
|
||||
m_visualization->setObjectName(QLatin1String("Valgrind.CallgrindTool.Visualisation"));
|
||||
m_visualization->setWindowTitle(tr("Visualization"));
|
||||
m_visualization->setModel(&m_dataModel);
|
||||
connect(m_visualization, &Visualisation::functionActivated,
|
||||
this, &CallgrindTool::visualisationFunctionSelected);
|
||||
|
||||
m_callersView = new CostView;
|
||||
m_callersView->setObjectName(QLatin1String("Valgrind.CallgrindTool.CallersView"));
|
||||
m_callersView->setWindowTitle(tr("Callers"));
|
||||
m_callersView->setSettings(coreSettings, "Valgrind.CallgrindTool.CallersView");
|
||||
m_callersView->sortByColumn(CallModel::CostColumn);
|
||||
m_callersView->setFrameStyle(QFrame::NoFrame);
|
||||
// enable sorting
|
||||
m_callersProxy.setSourceModel(&m_callersModel);
|
||||
m_callersView->setModel(&m_callersProxy);
|
||||
m_callersView->hideColumn(CallModel::CalleeColumn);
|
||||
connect(m_callersView, &QAbstractItemView::activated,
|
||||
this, &CallgrindTool::callerFunctionSelected);
|
||||
|
||||
m_calleesView = new CostView;
|
||||
m_calleesView->setObjectName(QLatin1String("Valgrind.CallgrindTool.CalleesView"));
|
||||
m_calleesView->setWindowTitle(tr("Callees"));
|
||||
m_calleesView->setSettings(coreSettings, "Valgrind.CallgrindTool.CalleesView");
|
||||
m_calleesView->sortByColumn(CallModel::CostColumn);
|
||||
m_calleesView->setFrameStyle(QFrame::NoFrame);
|
||||
// enable sorting
|
||||
m_calleesProxy.setSourceModel(&m_calleesModel);
|
||||
m_calleesView->setModel(&m_calleesProxy);
|
||||
m_calleesView->hideColumn(CallModel::CallerColumn);
|
||||
connect(m_calleesView, &QAbstractItemView::activated,
|
||||
this, &CallgrindTool::calleeFunctionSelected);
|
||||
|
||||
m_flatView = new CostView;
|
||||
m_flatView->setObjectName(QLatin1String("Valgrind.CallgrindTool.FlatView"));
|
||||
m_flatView->setWindowTitle(tr("Functions"));
|
||||
m_flatView->setSettings(coreSettings, "Valgrind.CallgrindTool.FlatView");
|
||||
m_flatView->sortByColumn(DataModel::SelfCostColumn);
|
||||
m_flatView->setFrameStyle(QFrame::NoFrame);
|
||||
m_flatView->setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
m_flatView->setModel(&m_proxyModel);
|
||||
connect(m_flatView, &QAbstractItemView::activated,
|
||||
this, &CallgrindTool::dataFunctionSelected);
|
||||
|
||||
updateCostFormat();
|
||||
|
||||
//
|
||||
// Control Widget
|
||||
//
|
||||
auto layout = new QHBoxLayout;
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
|
||||
auto widget = new QWidget;
|
||||
widget->setLayout(layout);
|
||||
|
||||
// load external log file
|
||||
auto action = new QAction(this);
|
||||
action->setIcon(Core::Icons::OPENFILE.icon());
|
||||
action->setToolTip(tr("Load External Log File"));
|
||||
connect(action, &QAction::triggered, this, &CallgrindTool::loadExternalLogFile);
|
||||
layout->addWidget(createToolButton(action));
|
||||
m_loadExternalLogFile = action;
|
||||
|
||||
// dump action
|
||||
action = new QAction(this);
|
||||
action->setDisabled(true);
|
||||
action->setIcon(Core::Icons::REDO.icon());
|
||||
//action->setText(tr("Dump"));
|
||||
action->setToolTip(tr("Request the dumping of profile information. This will update the Callgrind visualization."));
|
||||
connect(action, &QAction::triggered, this, &CallgrindTool::slotRequestDump);
|
||||
layout->addWidget(createToolButton(action));
|
||||
m_dumpAction = action;
|
||||
|
||||
// reset action
|
||||
action = new QAction(this);
|
||||
action->setDisabled(true);
|
||||
action->setIcon(Core::Icons::RELOAD.icon());
|
||||
//action->setText(tr("Reset"));
|
||||
action->setToolTip(tr("Reset all event counters."));
|
||||
connect(action, &QAction::triggered, this, &CallgrindTool::resetRequested);
|
||||
layout->addWidget(createToolButton(action));
|
||||
m_resetAction = action;
|
||||
|
||||
// pause action
|
||||
action = new QAction(this);
|
||||
action->setCheckable(true);
|
||||
action->setIcon(ProjectExplorer::Icons::INTERRUPT_SMALL.icon());
|
||||
//action->setText(tr("Ignore"));
|
||||
action->setToolTip(tr("Pause event logging. No events are counted which will speed up program execution during profiling."));
|
||||
connect(action, &QAction::toggled, this, &CallgrindTool::pauseToggled);
|
||||
layout->addWidget(createToolButton(action));
|
||||
m_pauseAction = action;
|
||||
|
||||
// navigation
|
||||
// go back
|
||||
action = new QAction(this);
|
||||
action->setDisabled(true);
|
||||
action->setIcon(Core::Icons::PREV.icon());
|
||||
action->setToolTip(tr("Go back one step in history. This will select the previously selected item."));
|
||||
connect(action, &QAction::triggered, &m_stackBrowser, &StackBrowser::goBack);
|
||||
layout->addWidget(createToolButton(action));
|
||||
m_goBack = action;
|
||||
|
||||
// go forward
|
||||
action = new QAction(this);
|
||||
action->setDisabled(true);
|
||||
action->setIcon(Core::Icons::NEXT.icon());
|
||||
action->setToolTip(tr("Go forward one step in history."));
|
||||
connect(action, &QAction::triggered, &m_stackBrowser, &StackBrowser::goNext);
|
||||
layout->addWidget(createToolButton(action));
|
||||
m_goNext = action;
|
||||
|
||||
layout->addWidget(new Utils::StyledSeparator);
|
||||
|
||||
// event selection
|
||||
m_eventCombo = new QComboBox;
|
||||
m_eventCombo->setToolTip(tr("Selects which events from the profiling data are shown and visualized."));
|
||||
connect(m_eventCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this, &CallgrindTool::setCostEvent);
|
||||
updateEventCombo();
|
||||
layout->addWidget(m_eventCombo);
|
||||
|
||||
// Cost formatting
|
||||
{
|
||||
auto menu = new QMenu(layout->parentWidget());
|
||||
auto group = new QActionGroup(this);
|
||||
|
||||
// Show costs as absolute numbers
|
||||
m_costAbsolute = new QAction(tr("Absolute Costs"), this);
|
||||
m_costAbsolute->setToolTip(tr("Show costs as absolute numbers."));
|
||||
m_costAbsolute->setCheckable(true);
|
||||
m_costAbsolute->setChecked(true);
|
||||
connect(m_costAbsolute, &QAction::toggled, this, &CallgrindTool::updateCostFormat);
|
||||
group->addAction(m_costAbsolute);
|
||||
menu->addAction(m_costAbsolute);
|
||||
|
||||
// Show costs in percentages
|
||||
m_costRelative = new QAction(tr("Relative Costs"), this);
|
||||
m_costRelative->setToolTip(tr("Show costs relative to total inclusive cost."));
|
||||
m_costRelative->setCheckable(true);
|
||||
connect(m_costRelative, &QAction::toggled, this, &CallgrindTool::updateCostFormat);
|
||||
group->addAction(m_costRelative);
|
||||
menu->addAction(m_costRelative);
|
||||
|
||||
// Show costs relative to parent
|
||||
m_costRelativeToParent = new QAction(tr("Relative Costs to Parent"), this);
|
||||
m_costRelativeToParent->setToolTip(tr("Show costs relative to parent functions inclusive cost."));
|
||||
m_costRelativeToParent->setCheckable(true);
|
||||
connect(m_costRelativeToParent, &QAction::toggled, this, &CallgrindTool::updateCostFormat);
|
||||
group->addAction(m_costRelativeToParent);
|
||||
menu->addAction(m_costRelativeToParent);
|
||||
|
||||
auto button = new QToolButton;
|
||||
button->setMenu(menu);
|
||||
button->setPopupMode(QToolButton::InstantPopup);
|
||||
button->setText(QLatin1String("$"));
|
||||
button->setToolTip(tr("Cost Format"));
|
||||
layout->addWidget(button);
|
||||
if (m_toolBusy) {
|
||||
m_startAction->setEnabled(false);
|
||||
m_startAction->setToolTip(tr("A Valgrind Callgrind analysis is still in progress."));
|
||||
m_stopAction->setEnabled(true);
|
||||
} else {
|
||||
const bool projectUsable = SessionManager::startupProject() != 0;
|
||||
if (projectUsable) {
|
||||
m_startAction->setEnabled(true);
|
||||
m_startAction->setToolTip(tr("Start a Valgrind Callgrind analysis."));
|
||||
m_stopAction->setEnabled(false);
|
||||
} else {
|
||||
m_startAction->setEnabled(false);
|
||||
m_startAction->setToolTip(tr("Start a Valgrind Callgrind analysis."));
|
||||
m_stopAction->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
ValgrindGlobalSettings *settings = ValgrindPlugin::globalSettings();
|
||||
|
||||
// Cycle detection
|
||||
//action = new QAction(QLatin1String("Cycle Detection"), this); ///FIXME: icon
|
||||
action = new QAction(QLatin1String("O"), this); ///FIXME: icon
|
||||
action->setToolTip(tr("Enable cycle detection to properly handle recursive or circular function calls."));
|
||||
action->setCheckable(true);
|
||||
connect(action, &QAction::toggled, &m_dataModel, &DataModel::enableCycleDetection);
|
||||
connect(action, &QAction::toggled, settings, &ValgrindGlobalSettings::setDetectCycles);
|
||||
layout->addWidget(createToolButton(action));
|
||||
m_cycleDetection = action;
|
||||
|
||||
// Shorter template signature
|
||||
action = new QAction(QLatin1String("<>"), this);
|
||||
action->setToolTip(tr("This removes template parameter lists when displaying function names."));
|
||||
action->setCheckable(true);
|
||||
connect(action, &QAction::toggled, &m_dataModel, &DataModel::setShortenTemplates);
|
||||
connect(action, &QAction::toggled, settings, &ValgrindGlobalSettings::setShortenTemplates);
|
||||
layout->addWidget(createToolButton(action));
|
||||
m_shortenTemplates = action;
|
||||
|
||||
// Filtering
|
||||
action = new QAction(tr("Show Project Costs Only"), this);
|
||||
action->setIcon(Core::Icons::FILTER.icon());
|
||||
action->setToolTip(tr("Show only profiling info that originated from this project source."));
|
||||
action->setCheckable(true);
|
||||
connect(action, &QAction::toggled, this, &CallgrindTool::handleFilterProjectCosts);
|
||||
layout->addWidget(createToolButton(action));
|
||||
m_filterProjectCosts = action;
|
||||
|
||||
// Filter
|
||||
///FIXME: find workaround for https://bugreports.qt.io/browse/QTCREATORBUG-3247
|
||||
auto filter = new QLineEdit;
|
||||
filter->setPlaceholderText(tr("Filter..."));
|
||||
connect(filter, &QLineEdit::textChanged,
|
||||
&m_updateTimer, static_cast<void(QTimer::*)()>(&QTimer::start));
|
||||
layout->addWidget(filter);
|
||||
m_searchFilter = filter;
|
||||
|
||||
setCostFormat(settings->costFormat());
|
||||
enableCycleDetection(settings->detectCycles());
|
||||
|
||||
layout->addWidget(new Utils::StyledSeparator);
|
||||
layout->addStretch();
|
||||
|
||||
AnalyzerManager::registerDockWidget(CallgrindCallersDockId, m_callersView);
|
||||
AnalyzerManager::registerDockWidget(CallgrindFlatDockId, m_flatView);
|
||||
AnalyzerManager::registerDockWidget(CallgrindCalleesDockId, m_calleesView);
|
||||
AnalyzerManager::registerDockWidget(CallgrindVisualizationDockId, m_visualization);
|
||||
|
||||
AnalyzerManager::registerPerspective(CallgrindPerspectiveId, {
|
||||
{ CallgrindFlatDockId, Id(), Perspective::SplitVertical },
|
||||
{ CallgrindCalleesDockId, Id(), Perspective::SplitVertical },
|
||||
{ CallgrindCallersDockId, CallgrindCalleesDockId, Perspective::SplitHorizontal },
|
||||
{ CallgrindVisualizationDockId, Id(), Perspective::SplitVertical,
|
||||
false, Qt::RightDockWidgetArea }
|
||||
});
|
||||
|
||||
AnalyzerManager::registerToolbar(CallgrindPerspectiveId, widget);
|
||||
}
|
||||
|
||||
void CallgrindTool::clearTextMarks()
|
||||
{
|
||||
qDeleteAll(m_textMarks);
|
||||
@@ -813,6 +812,9 @@ void CallgrindTool::engineStarting()
|
||||
|
||||
void CallgrindTool::engineFinished()
|
||||
{
|
||||
m_toolBusy = false;
|
||||
updateRunActions();
|
||||
|
||||
// Enable/disable actions
|
||||
m_resetAction->setEnabled(false);
|
||||
m_dumpAction->setEnabled(false);
|
||||
@@ -822,7 +824,7 @@ void CallgrindTool::engineFinished()
|
||||
if (data)
|
||||
showParserResults(data);
|
||||
else
|
||||
AnalyzerManager::showPermanentStatusMessage(tr("Profiling aborted."));
|
||||
Debugger::showPermanentStatusMessage(tr("Profiling aborted."));
|
||||
|
||||
setBusyCursor(false);
|
||||
}
|
||||
@@ -841,7 +843,7 @@ void CallgrindTool::showParserResults(const ParseData *data)
|
||||
} else {
|
||||
msg = tr("Parsing failed.");
|
||||
}
|
||||
AnalyzerManager::showPermanentStatusMessage(msg);
|
||||
Debugger::showPermanentStatusMessage(msg);
|
||||
}
|
||||
|
||||
void CallgrindTool::editorOpened(IEditor *editor)
|
||||
@@ -878,8 +880,7 @@ void CallgrindTool::handleShowCostsOfFunction()
|
||||
const QString qualifiedFunctionName = view.prettyName(CPlusPlus::LookupContext::fullyQualifiedName(symbol));
|
||||
|
||||
m_toggleCollectFunction = qualifiedFunctionName + QLatin1String("()");
|
||||
|
||||
AnalyzerManager::selectAction(CallgrindLocalActionId, /* alsoRunIt = */ true);
|
||||
m_startAction->trigger();
|
||||
}
|
||||
|
||||
void CallgrindTool::slotRequestDump()
|
||||
@@ -906,7 +907,7 @@ void CallgrindTool::loadExternalLogFile()
|
||||
return;
|
||||
}
|
||||
|
||||
AnalyzerManager::showPermanentStatusMessage(tr("Parsing Profile Data..."));
|
||||
Debugger::showPermanentStatusMessage(tr("Parsing Profile Data..."));
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
Parser parser;
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Valgrind::XmlProtocol;
|
||||
|
||||
@@ -72,20 +72,20 @@ ValgrindRunner *MemcheckRunControl::runner()
|
||||
return &m_runner;
|
||||
}
|
||||
|
||||
bool MemcheckRunControl::startEngine()
|
||||
void MemcheckRunControl::start()
|
||||
{
|
||||
m_runner.setParser(&m_parser);
|
||||
|
||||
appendMessage(tr("Analyzing memory of %1").arg(executable()) + QLatin1Char('\n'),
|
||||
Utils::NormalMessageFormat);
|
||||
return ValgrindRunControl::startEngine();
|
||||
ValgrindRunControl::start();
|
||||
}
|
||||
|
||||
void MemcheckRunControl::stopEngine()
|
||||
RunControl::StopResult MemcheckRunControl::stop()
|
||||
{
|
||||
disconnect(&m_parser, &ThreadedParser::internalError,
|
||||
this, &MemcheckRunControl::internalParserError);
|
||||
ValgrindRunControl::stopEngine();
|
||||
return ValgrindRunControl::stop();
|
||||
}
|
||||
|
||||
QStringList MemcheckRunControl::toolArguments() const
|
||||
|
||||
@@ -43,8 +43,8 @@ public:
|
||||
MemcheckRunControl(ProjectExplorer::RunConfiguration *runConfiguration,
|
||||
Core::Id runMode);
|
||||
|
||||
bool startEngine() override;
|
||||
void stopEngine() override;
|
||||
void start() override;
|
||||
StopResult stop() override;
|
||||
|
||||
QStringList suppressionFiles() const;
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
MemcheckErrorView::MemcheckErrorView(QWidget *parent)
|
||||
: Analyzer::DetailedErrorView(parent),
|
||||
: Debugger::DetailedErrorView(parent),
|
||||
m_settings(0)
|
||||
{
|
||||
m_suppressAction = new QAction(this);
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Internal {
|
||||
|
||||
class ValgrindBaseSettings;
|
||||
|
||||
class MemcheckErrorView : public Analyzer::DetailedErrorView
|
||||
class MemcheckErrorView : public Debugger::DetailedErrorView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
@@ -85,14 +85,60 @@
|
||||
#include <QString>
|
||||
#include <QToolButton>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
using namespace Valgrind::XmlProtocol;
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
class FrameFinder;
|
||||
class FrameFinder : public ErrorListModel::RelevantFrameFinder
|
||||
{
|
||||
public:
|
||||
Frame findRelevant(const Error &error) const
|
||||
{
|
||||
const QVector<Stack> stacks = error.stacks();
|
||||
if (stacks.isEmpty())
|
||||
return Frame();
|
||||
const Stack &stack = stacks[0];
|
||||
const QVector<Frame> frames = stack.frames();
|
||||
if (frames.isEmpty())
|
||||
return Frame();
|
||||
|
||||
//find the first frame belonging to the project
|
||||
if (!m_projectFiles.isEmpty()) {
|
||||
foreach (const Frame &frame, frames) {
|
||||
if (frame.directory().isEmpty() || frame.fileName().isEmpty())
|
||||
continue;
|
||||
|
||||
//filepaths can contain "..", clean them:
|
||||
const QString f = QFileInfo(frame.filePath()).absoluteFilePath();
|
||||
if (m_projectFiles.contains(f))
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
|
||||
//if no frame belonging to the project was found, return the first one that is not malloc/new
|
||||
foreach (const Frame &frame, frames) {
|
||||
if (!frame.functionName().isEmpty() && frame.functionName() != QLatin1String("malloc")
|
||||
&& !frame.functionName().startsWith(QLatin1String("operator new(")))
|
||||
{
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
|
||||
//else fallback to the first frame
|
||||
return frames.first();
|
||||
}
|
||||
void setFiles(const QStringList &files)
|
||||
{
|
||||
m_projectFiles = files;
|
||||
}
|
||||
private:
|
||||
QStringList m_projectFiles;
|
||||
};
|
||||
|
||||
|
||||
class MemcheckErrorFilterProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
@@ -203,12 +249,13 @@ class MemcheckTool : public QObject
|
||||
public:
|
||||
MemcheckTool(QObject *parent);
|
||||
|
||||
QWidget *createWidgets();
|
||||
void createWidgets();
|
||||
|
||||
MemcheckRunControl *createRunControl(ProjectExplorer::RunConfiguration *runConfiguration,
|
||||
Core::Id runMode);
|
||||
|
||||
private:
|
||||
void updateRunActions();
|
||||
void settingsDestroyed(QObject *settings);
|
||||
void maybeActiveRunConfigurationChanged();
|
||||
|
||||
@@ -240,10 +287,14 @@ private:
|
||||
QList<QAction *> m_errorFilterActions;
|
||||
QAction *m_filterProjectAction;
|
||||
QList<QAction *> m_suppressionActions;
|
||||
QAction *m_startAction;
|
||||
QAction *m_startWithGdbAction;
|
||||
QAction *m_stopAction;
|
||||
QAction *m_suppressionSeparator;
|
||||
QAction *m_loadExternalLogFile;
|
||||
QAction *m_goBack;
|
||||
QAction *m_goNext;
|
||||
bool m_toolBusy = false;
|
||||
};
|
||||
|
||||
MemcheckTool::MemcheckTool(QObject *parent)
|
||||
@@ -288,7 +339,79 @@ MemcheckTool::MemcheckTool(QObject *parent)
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
AnalyzerManager::registerToolbar(MemcheckPerspectiveId, createWidgets());
|
||||
QTC_ASSERT(!m_errorView, return);
|
||||
|
||||
m_errorView = new MemcheckErrorView;
|
||||
m_errorView->setObjectName(QLatin1String("MemcheckErrorView"));
|
||||
m_errorView->setFrameStyle(QFrame::NoFrame);
|
||||
m_errorView->setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
m_errorModel = new ErrorListModel(m_errorView);
|
||||
m_frameFinder = new Internal::FrameFinder;
|
||||
m_errorModel->setRelevantFrameFinder(QSharedPointer<Internal::FrameFinder>(m_frameFinder));
|
||||
m_errorProxyModel = new MemcheckErrorFilterProxyModel(m_errorView);
|
||||
m_errorProxyModel->setSourceModel(m_errorModel);
|
||||
m_errorProxyModel->setDynamicSortFilter(true);
|
||||
m_errorView->setModel(m_errorProxyModel);
|
||||
m_errorView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
// make m_errorView->selectionModel()->selectedRows() return something
|
||||
m_errorView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_errorView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
m_errorView->setAutoScroll(false);
|
||||
m_errorView->setObjectName(QLatin1String("Valgrind.MemcheckTool.ErrorView"));
|
||||
m_errorView->setWindowTitle(tr("Memory Issues"));
|
||||
|
||||
Debugger::registerPerspective(MemcheckPerspectiveId, { tr("Memcheck"), {
|
||||
{ MemcheckErrorDockId, m_errorView, {}, Perspective::SplitVertical }
|
||||
}});
|
||||
|
||||
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
|
||||
this, &MemcheckTool::maybeActiveRunConfigurationChanged);
|
||||
|
||||
//
|
||||
// The Control Widget.
|
||||
//
|
||||
|
||||
m_startAction = Debugger::createStartAction();
|
||||
m_startWithGdbAction = Debugger::createStartAction();
|
||||
m_stopAction = Debugger::createStopAction();
|
||||
|
||||
// Load external XML log file
|
||||
auto action = new QAction(this);
|
||||
action->setIcon(Core::Icons::OPENFILE.icon());
|
||||
action->setToolTip(tr("Load External XML Log File"));
|
||||
connect(action, &QAction::triggered, this, &MemcheckTool::loadExternalXmlLogFile);
|
||||
m_loadExternalLogFile = action;
|
||||
|
||||
// Go to previous leak.
|
||||
action = new QAction(this);
|
||||
action->setDisabled(true);
|
||||
action->setIcon(Core::Icons::PREV.icon());
|
||||
action->setToolTip(tr("Go to previous leak."));
|
||||
connect(action, &QAction::triggered, m_errorView, &MemcheckErrorView::goBack);
|
||||
m_goBack = action;
|
||||
|
||||
// Go to next leak.
|
||||
action = new QAction(this);
|
||||
action->setDisabled(true);
|
||||
action->setIcon(Core::Icons::NEXT.icon());
|
||||
action->setToolTip(tr("Go to next leak."));
|
||||
connect(action, &QAction::triggered, m_errorView, &MemcheckErrorView::goNext);
|
||||
m_goNext = action;
|
||||
|
||||
auto filterButton = new QToolButton;
|
||||
filterButton->setIcon(Core::Icons::FILTER.icon());
|
||||
filterButton->setText(tr("Error Filter"));
|
||||
filterButton->setPopupMode(QToolButton::InstantPopup);
|
||||
filterButton->setProperty("noArrow", true);
|
||||
|
||||
m_filterMenu = new QMenu(filterButton);
|
||||
foreach (QAction *filterAction, m_errorFilterActions)
|
||||
m_filterMenu->addAction(filterAction);
|
||||
m_filterMenu->addSeparator();
|
||||
m_filterMenu->addAction(m_filterProjectAction);
|
||||
m_filterMenu->addAction(m_suppressionSeparator);
|
||||
connect(m_filterMenu, &QMenu::triggered, this, &MemcheckTool::updateErrorFilter);
|
||||
filterButton->setMenu(m_filterMenu);
|
||||
|
||||
ActionDescription desc;
|
||||
desc.setToolTip(tr("Valgrind Analyze Memory uses the "
|
||||
@@ -300,8 +423,8 @@ MemcheckTool::MemcheckTool(QObject *parent)
|
||||
desc.setRunControlCreator(std::bind(&MemcheckTool::createRunControl, this, _1, _2));
|
||||
desc.setToolMode(DebugMode);
|
||||
desc.setRunMode(MEMCHECK_RUN_MODE);
|
||||
desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_TOOLS);
|
||||
AnalyzerManager::registerAction("Memcheck.Local", desc);
|
||||
desc.setMenuGroup(Debugger::Constants::G_ANALYZER_TOOLS);
|
||||
Debugger::registerAction("Memcheck.Local", desc, m_startAction);
|
||||
|
||||
desc.setText(tr("Valgrind Memory Analyzer with GDB"));
|
||||
desc.setToolTip(tr("Valgrind Analyze Memory with GDB uses the "
|
||||
@@ -311,8 +434,8 @@ MemcheckTool::MemcheckTool(QObject *parent)
|
||||
desc.setRunControlCreator(std::bind(&MemcheckTool::createRunControl, this, _1, _2));
|
||||
desc.setToolMode(DebugMode);
|
||||
desc.setRunMode(MEMCHECK_WITH_GDB_RUN_MODE);
|
||||
desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_TOOLS);
|
||||
AnalyzerManager::registerAction("MemcheckWithGdb.Local", desc);
|
||||
desc.setMenuGroup(Debugger::Constants::G_ANALYZER_TOOLS);
|
||||
Debugger::registerAction("MemcheckWithGdb.Local", desc, m_startWithGdbAction);
|
||||
}
|
||||
|
||||
desc.setText(tr("Valgrind Memory Analyzer (External Application)"));
|
||||
@@ -331,8 +454,42 @@ MemcheckTool::MemcheckTool(QObject *parent)
|
||||
rc->setDisplayName(runnable.executable);
|
||||
ProjectExplorerPlugin::startRunControl(rc, MEMCHECK_RUN_MODE);
|
||||
});
|
||||
desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_REMOTE_TOOLS);
|
||||
AnalyzerManager::registerAction("Memcheck.Remote", desc);
|
||||
desc.setMenuGroup(Debugger::Constants::G_ANALYZER_REMOTE_TOOLS);
|
||||
Debugger::registerAction("Memcheck.Remote", desc);
|
||||
|
||||
ToolbarDescription toolbar;
|
||||
toolbar.addAction(m_startAction);
|
||||
//toolbar.addAction(m_startWithGdbAction);
|
||||
toolbar.addAction(m_stopAction);
|
||||
toolbar.addAction(m_loadExternalLogFile);
|
||||
toolbar.addAction(m_goBack);
|
||||
toolbar.addAction(m_goNext);
|
||||
toolbar.addWidget(filterButton);
|
||||
Debugger::registerToolbar(MemcheckPerspectiveId, toolbar);
|
||||
}
|
||||
|
||||
void MemcheckTool::updateRunActions()
|
||||
{
|
||||
if (m_toolBusy) {
|
||||
m_startAction->setEnabled(false);
|
||||
m_startAction->setToolTip(tr("A Valgrind Memcheck analysis is still in progress."));
|
||||
m_startWithGdbAction->setEnabled(false);
|
||||
m_startWithGdbAction->setToolTip(tr("A Valgrind Memcheck analysis is still in progress."));
|
||||
m_stopAction->setEnabled(true);
|
||||
} else {
|
||||
const bool projectUsable = SessionManager::startupProject() != 0;
|
||||
m_startAction->setToolTip(tr("Start a Valgrind Memcheck analysis."));
|
||||
m_startWithGdbAction->setToolTip(tr("Start a Valgrind Memcheck with GDB analysis."));
|
||||
if (projectUsable) {
|
||||
m_startAction->setEnabled(true);
|
||||
m_startWithGdbAction->setEnabled(true);
|
||||
m_stopAction->setEnabled(false);
|
||||
} else {
|
||||
m_startAction->setEnabled(false);
|
||||
m_startWithGdbAction->setEnabled(false);
|
||||
m_stopAction->setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MemcheckTool::settingsDestroyed(QObject *settings)
|
||||
@@ -368,6 +525,8 @@ void MemcheckTool::updateFromSettings()
|
||||
|
||||
void MemcheckTool::maybeActiveRunConfigurationChanged()
|
||||
{
|
||||
updateRunActions();
|
||||
|
||||
ValgrindBaseSettings *settings = 0;
|
||||
if (Project *project = SessionManager::startupProject())
|
||||
if (Target *target = project->activeTarget())
|
||||
@@ -395,150 +554,6 @@ void MemcheckTool::maybeActiveRunConfigurationChanged()
|
||||
updateFromSettings();
|
||||
}
|
||||
|
||||
class FrameFinder : public ErrorListModel::RelevantFrameFinder
|
||||
{
|
||||
public:
|
||||
Frame findRelevant(const Error &error) const
|
||||
{
|
||||
const QVector<Stack> stacks = error.stacks();
|
||||
if (stacks.isEmpty())
|
||||
return Frame();
|
||||
const Stack &stack = stacks[0];
|
||||
const QVector<Frame> frames = stack.frames();
|
||||
if (frames.isEmpty())
|
||||
return Frame();
|
||||
|
||||
//find the first frame belonging to the project
|
||||
if (!m_projectFiles.isEmpty()) {
|
||||
foreach (const Frame &frame, frames) {
|
||||
if (frame.directory().isEmpty() || frame.fileName().isEmpty())
|
||||
continue;
|
||||
|
||||
//filepaths can contain "..", clean them:
|
||||
const QString f = QFileInfo(frame.filePath()).absoluteFilePath();
|
||||
if (m_projectFiles.contains(f))
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
|
||||
//if no frame belonging to the project was found, return the first one that is not malloc/new
|
||||
foreach (const Frame &frame, frames) {
|
||||
if (!frame.functionName().isEmpty() && frame.functionName() != QLatin1String("malloc")
|
||||
&& !frame.functionName().startsWith(QLatin1String("operator new(")))
|
||||
{
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
|
||||
//else fallback to the first frame
|
||||
return frames.first();
|
||||
}
|
||||
void setFiles(const QStringList &files)
|
||||
{
|
||||
m_projectFiles = files;
|
||||
}
|
||||
private:
|
||||
QStringList m_projectFiles;
|
||||
};
|
||||
|
||||
|
||||
QWidget *MemcheckTool::createWidgets()
|
||||
{
|
||||
QTC_ASSERT(!m_errorView, return 0);
|
||||
|
||||
m_errorView = new MemcheckErrorView;
|
||||
m_errorView->setObjectName(QLatin1String("MemcheckErrorView"));
|
||||
m_errorView->setFrameStyle(QFrame::NoFrame);
|
||||
m_errorView->setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
m_errorModel = new ErrorListModel(m_errorView);
|
||||
m_frameFinder = new Internal::FrameFinder;
|
||||
m_errorModel->setRelevantFrameFinder(QSharedPointer<Internal::FrameFinder>(m_frameFinder));
|
||||
m_errorProxyModel = new MemcheckErrorFilterProxyModel(m_errorView);
|
||||
m_errorProxyModel->setSourceModel(m_errorModel);
|
||||
m_errorProxyModel->setDynamicSortFilter(true);
|
||||
m_errorView->setModel(m_errorProxyModel);
|
||||
m_errorView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
// make m_errorView->selectionModel()->selectedRows() return something
|
||||
m_errorView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_errorView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
m_errorView->setAutoScroll(false);
|
||||
m_errorView->setObjectName(QLatin1String("Valgrind.MemcheckTool.ErrorView"));
|
||||
m_errorView->setWindowTitle(tr("Memory Issues"));
|
||||
|
||||
AnalyzerManager::registerDockWidget(MemcheckErrorDockId, m_errorView);
|
||||
|
||||
AnalyzerManager::registerPerspective(MemcheckPerspectiveId, {
|
||||
{ MemcheckErrorDockId, Core::Id(), Perspective::SplitVertical }
|
||||
});
|
||||
|
||||
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
|
||||
this, &MemcheckTool::maybeActiveRunConfigurationChanged);
|
||||
|
||||
//
|
||||
// The Control Widget.
|
||||
//
|
||||
QAction *action = 0;
|
||||
QHBoxLayout *layout = new QHBoxLayout;
|
||||
QToolButton *button = 0;
|
||||
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
|
||||
// Load external XML log file
|
||||
action = new QAction(this);
|
||||
action->setIcon(Core::Icons::OPENFILE.icon());
|
||||
action->setToolTip(tr("Load External XML Log File"));
|
||||
connect(action, &QAction::triggered, this, &MemcheckTool::loadExternalXmlLogFile);
|
||||
button = new QToolButton;
|
||||
button->setDefaultAction(action);
|
||||
layout->addWidget(button);
|
||||
m_loadExternalLogFile = action;
|
||||
|
||||
// Go to previous leak.
|
||||
action = new QAction(this);
|
||||
action->setDisabled(true);
|
||||
action->setIcon(Core::Icons::PREV.icon());
|
||||
action->setToolTip(tr("Go to previous leak."));
|
||||
connect(action, &QAction::triggered, m_errorView, &MemcheckErrorView::goBack);
|
||||
button = new QToolButton;
|
||||
button->setDefaultAction(action);
|
||||
layout->addWidget(button);
|
||||
m_goBack = action;
|
||||
|
||||
// Go to next leak.
|
||||
action = new QAction(this);
|
||||
action->setDisabled(true);
|
||||
action->setIcon(Core::Icons::NEXT.icon());
|
||||
action->setToolTip(tr("Go to next leak."));
|
||||
connect(action, &QAction::triggered, m_errorView, &MemcheckErrorView::goNext);
|
||||
button = new QToolButton;
|
||||
button->setDefaultAction(action);
|
||||
layout->addWidget(button);
|
||||
m_goNext = action;
|
||||
|
||||
QToolButton *filterButton = new QToolButton;
|
||||
filterButton->setIcon(Core::Icons::FILTER.icon());
|
||||
filterButton->setText(tr("Error Filter"));
|
||||
filterButton->setPopupMode(QToolButton::InstantPopup);
|
||||
filterButton->setProperty("noArrow", true);
|
||||
|
||||
m_filterMenu = new QMenu(filterButton);
|
||||
foreach (QAction *filterAction, m_errorFilterActions)
|
||||
m_filterMenu->addAction(filterAction);
|
||||
m_filterMenu->addSeparator();
|
||||
m_filterMenu->addAction(m_filterProjectAction);
|
||||
m_filterMenu->addAction(m_suppressionSeparator);
|
||||
connect(m_filterMenu, &QMenu::triggered, this, &MemcheckTool::updateErrorFilter);
|
||||
filterButton->setMenu(m_filterMenu);
|
||||
layout->addWidget(filterButton);
|
||||
|
||||
layout->addStretch();
|
||||
QWidget *widget = new QWidget;
|
||||
widget->setObjectName(QLatin1String("MemCheckToolBarWidget"));
|
||||
widget->setLayout(layout);
|
||||
return widget;
|
||||
}
|
||||
|
||||
MemcheckRunControl *MemcheckTool::createRunControl(RunConfiguration *runConfiguration,
|
||||
Core::Id runMode)
|
||||
{
|
||||
@@ -555,6 +570,12 @@ MemcheckRunControl *MemcheckTool::createRunControl(RunConfiguration *runConfigur
|
||||
connect(runControl, &MemcheckRunControl::parserError, this, &MemcheckTool::parserError);
|
||||
connect(runControl, &MemcheckRunControl::internalParserError, this, &MemcheckTool::internalParserError);
|
||||
connect(runControl, &MemcheckRunControl::finished, this, &MemcheckTool::engineFinished);
|
||||
|
||||
connect(m_stopAction, &QAction::triggered, runControl, [runControl] { runControl->stop(); });
|
||||
|
||||
m_toolBusy = true;
|
||||
updateRunActions();
|
||||
|
||||
return runControl;
|
||||
}
|
||||
|
||||
@@ -673,18 +694,19 @@ int MemcheckTool::updateUiAfterFinishedHelper()
|
||||
|
||||
void MemcheckTool::engineFinished()
|
||||
{
|
||||
m_toolBusy = false;
|
||||
updateRunActions();
|
||||
|
||||
const int issuesFound = updateUiAfterFinishedHelper();
|
||||
AnalyzerManager::showPermanentStatusMessage(issuesFound > 0
|
||||
? AnalyzerManager::tr("Memory Analyzer Tool finished, %n issues were found.", 0, issuesFound)
|
||||
: AnalyzerManager::tr("Memory Analyzer Tool finished, no issues were found."));
|
||||
Debugger::showPermanentStatusMessage(
|
||||
tr("Memory Analyzer Tool finished, %n issues were found.", 0, issuesFound));
|
||||
}
|
||||
|
||||
void MemcheckTool::loadingExternalXmlLogFileFinished()
|
||||
{
|
||||
const int issuesFound = updateUiAfterFinishedHelper();
|
||||
AnalyzerManager::showPermanentStatusMessage(issuesFound > 0
|
||||
? AnalyzerManager::tr("Log file processed, %n issues were found.", 0, issuesFound)
|
||||
: AnalyzerManager::tr("Log file processed, no issues were found."));
|
||||
Debugger::showPermanentStatusMessage(
|
||||
tr("Log file processed, %n issues were found.", 0, issuesFound));
|
||||
}
|
||||
|
||||
void MemcheckTool::setBusyCursor(bool busy)
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
#define VALGRIND_DEBUG_OUTPUT 0
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace Core;
|
||||
using namespace Utils;
|
||||
using namespace ProjectExplorer;
|
||||
@@ -65,10 +65,8 @@ ValgrindRunControl::ValgrindRunControl(RunConfiguration *runConfiguration, Core:
|
||||
m_settings = ValgrindPlugin::globalSettings();
|
||||
}
|
||||
|
||||
bool ValgrindRunControl::startEngine()
|
||||
void ValgrindRunControl::start()
|
||||
{
|
||||
emit starting();
|
||||
|
||||
FutureProgress *fp = ProgressManager::addTimedTask(m_progress, progressTitle(), "valgrind", 100);
|
||||
fp->setKeepOnFinish(FutureProgress::HideOnFinish);
|
||||
connect(fp, &FutureProgress::canceled,
|
||||
@@ -86,7 +84,6 @@ bool ValgrindRunControl::startEngine()
|
||||
ValgrindRunner *run = runner();
|
||||
run->setValgrindExecutable(m_settings->valgrindExecutable());
|
||||
run->setValgrindArguments(genericToolArguments() + toolArguments());
|
||||
QTC_ASSERT(!device().isNull(), return false);
|
||||
run->setDevice(device());
|
||||
run->setDebuggee(runnable().as<StandardRunnable>());
|
||||
|
||||
@@ -99,15 +96,24 @@ bool ValgrindRunControl::startEngine()
|
||||
|
||||
if (!run->start()) {
|
||||
m_progress.cancel();
|
||||
return false;
|
||||
emit finished();
|
||||
return;
|
||||
}
|
||||
return true;
|
||||
|
||||
m_isRunning = true;
|
||||
emit started();
|
||||
}
|
||||
|
||||
void ValgrindRunControl::stopEngine()
|
||||
RunControl::StopResult ValgrindRunControl::stop()
|
||||
{
|
||||
m_isStopping = true;
|
||||
runner()->stop();
|
||||
return AsynchronousStop;
|
||||
}
|
||||
|
||||
bool ValgrindRunControl::isRunning() const
|
||||
{
|
||||
return m_isRunning;
|
||||
}
|
||||
|
||||
QString ValgrindRunControl::executable() const
|
||||
@@ -139,7 +145,6 @@ QStringList ValgrindRunControl::genericToolArguments() const
|
||||
|
||||
void ValgrindRunControl::handleProgressCanceled()
|
||||
{
|
||||
AnalyzerManager::stopTool();
|
||||
m_progress.reportCanceled();
|
||||
m_progress.reportFinished();
|
||||
}
|
||||
@@ -151,6 +156,8 @@ void ValgrindRunControl::handleProgressFinished()
|
||||
|
||||
void ValgrindRunControl::runnerFinished()
|
||||
{
|
||||
m_isRunning = false;
|
||||
|
||||
appendMessage(tr("Analyzing finished.") + QLatin1Char('\n'), NormalMessageFormat);
|
||||
emit finished();
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
class ValgrindRunControl : public Analyzer::AnalyzerRunControl
|
||||
class ValgrindRunControl : public Debugger::AnalyzerRunControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -46,8 +46,9 @@ public:
|
||||
ValgrindRunControl(ProjectExplorer::RunConfiguration *runConfiguration,
|
||||
Core::Id runMode);
|
||||
|
||||
bool startEngine() override;
|
||||
void stopEngine() override;
|
||||
void start() override;
|
||||
StopResult stop() override;
|
||||
bool isRunning() const override;
|
||||
|
||||
QString executable() const;
|
||||
|
||||
@@ -70,6 +71,7 @@ private:
|
||||
QStringList genericToolArguments() const;
|
||||
|
||||
private:
|
||||
bool m_isRunning = false;
|
||||
bool m_isStopping = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
namespace Valgrind {
|
||||
@@ -56,7 +56,7 @@ bool ValgrindRunControlFactory::canRun(RunConfiguration *runConfiguration, Core:
|
||||
RunControl *ValgrindRunControlFactory::create(RunConfiguration *runConfiguration, Core::Id mode, QString *errorMessage)
|
||||
{
|
||||
Q_UNUSED(errorMessage);
|
||||
return AnalyzerManager::createRunControl(runConfiguration, mode);
|
||||
return Debugger::createAnalyzerRunControl(runConfiguration, mode);
|
||||
}
|
||||
|
||||
class ValgrindRunConfigurationAspect : public IRunConfigurationAspect
|
||||
|
||||
@@ -188,8 +188,8 @@ QString ValgrindRunner::errorString() const
|
||||
|
||||
void ValgrindRunner::stop()
|
||||
{
|
||||
if (d->process)
|
||||
d->process->close();
|
||||
QTC_ASSERT(d->process, finished(); return);
|
||||
d->process->close();
|
||||
}
|
||||
|
||||
ValgrindProcess *ValgrindRunner::valgrindProcess() const
|
||||
|
||||
@@ -191,8 +191,8 @@ ErrorItem::ErrorItem(const ErrorListModelPrivate *modelPrivate, const Error &err
|
||||
static QVariant location(const Frame &frame, int role)
|
||||
{
|
||||
switch (role) {
|
||||
case Analyzer::DetailedErrorView::LocationRole:
|
||||
return QVariant::fromValue(Analyzer::DiagnosticLocation(frame.filePath(), frame.line(), 0));
|
||||
case Debugger::DetailedErrorView::LocationRole:
|
||||
return QVariant::fromValue(Debugger::DiagnosticLocation(frame.filePath(), frame.line(), 0));
|
||||
case Qt::ToolTipRole:
|
||||
return frame.filePath().isEmpty() ? QVariant() : QVariant(frame.filePath());
|
||||
default:
|
||||
@@ -202,14 +202,14 @@ static QVariant location(const Frame &frame, int role)
|
||||
|
||||
QVariant ErrorItem::data(int column, int role) const
|
||||
{
|
||||
if (column == Analyzer::DetailedErrorView::LocationColumn) {
|
||||
if (column == Debugger::DetailedErrorView::LocationColumn) {
|
||||
const Frame frame = m_modelPrivate->findRelevantFrame(m_error);
|
||||
return location(frame, role);
|
||||
}
|
||||
|
||||
// DiagnosticColumn
|
||||
switch (role) {
|
||||
case Analyzer::DetailedErrorView::FullTextRole: {
|
||||
case Debugger::DetailedErrorView::FullTextRole: {
|
||||
QString content;
|
||||
QTextStream stream(&content);
|
||||
|
||||
@@ -257,7 +257,7 @@ StackItem::StackItem(const Stack &stack) : m_stack(stack)
|
||||
QVariant StackItem::data(int column, int role) const
|
||||
{
|
||||
const ErrorItem * const errorItem = getErrorItem();
|
||||
if (column == Analyzer::DetailedErrorView::LocationColumn)
|
||||
if (column == Debugger::DetailedErrorView::LocationColumn)
|
||||
return location(errorItem->modelPrivate()->findRelevantFrame(errorItem->error()), role);
|
||||
|
||||
// DiagnosticColumn
|
||||
@@ -285,7 +285,7 @@ FrameItem::FrameItem(const Frame &frame) : m_frame(frame)
|
||||
|
||||
QVariant FrameItem::data(int column, int role) const
|
||||
{
|
||||
if (column == Analyzer::DetailedErrorView::LocationColumn)
|
||||
if (column == Debugger::DetailedErrorView::LocationColumn)
|
||||
return location(m_frame, role);
|
||||
|
||||
// DiagnosticColumn
|
||||
|
||||
@@ -45,7 +45,7 @@ class ErrorListModel : public Utils::TreeModel
|
||||
|
||||
public:
|
||||
enum Role {
|
||||
ErrorRole = Analyzer::DetailedErrorView::FullTextRole + 1,
|
||||
ErrorRole = Debugger::DetailedErrorView::FullTextRole + 1,
|
||||
};
|
||||
|
||||
class RelevantFrameFinder
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
|
||||
enum { debug = 0 };
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Debugger;
|
||||
using namespace ClangStaticAnalyzer::Internal;
|
||||
|
||||
namespace {
|
||||
|
||||
Reference in New Issue
Block a user