Debugger: Merge debug mode and analyze mode

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

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

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

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

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

Change-Id: I91e5940ebc4211f98056d507cf2f7b5f8efe7f07
Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
This commit is contained in:
hjk
2016-03-02 13:57:37 +01:00
parent c326011feb
commit 92e301a054
79 changed files with 2135 additions and 2642 deletions
@@ -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) {
+2 -2
View File
@@ -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;
}
while (m_runners.size() < parallelRuns && !m_unitsToProcess.isEmpty())
analyzeNextFile();
return true;
return;
}
void ClangStaticAnalyzerRunControl::stopEngine()
emit started();
while (m_runners.size() < parallelRuns && !m_unitsToProcess.isEmpty())
analyzeNextFile();
}
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
+19 -33
View File
@@ -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
public:
explicit AnalyzerManager(QObject *parent);
~AnalyzerManager();
static void shutdown();
// FIXME: Merge with something sensible.
// 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 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 enableMainWindow(bool on);
DEBUGGER_EXPORT void enableMainWindow(bool on);
static void showMode();
static void selectAction(Core::Id actionId, bool alsoRunIt = false);
static void stopTool();
DEBUGGER_EXPORT void selectPerspective(const QByteArray &perspectiveId);
DEBUGGER_EXPORT void runAction(Core::Id actionId);
// Convenience functions.
static void showStatusMessage(const QString &message, int timeoutMS = 10000);
static void showPermanentStatusMessage(const QString &message);
DEBUGGER_EXPORT void showStatusMessage(const QString &message, int timeoutMS = 10000);
DEBUGGER_EXPORT void showPermanentStatusMessage(const QString &message);
static void handleToolStarted();
static void handleToolFinished();
static QAction *stopAction();
DEBUGGER_EXPORT QAction *createStartAction();
DEBUGGER_EXPORT QAction *createStopAction();
static AnalyzerRunControl *createRunControl(
DEBUGGER_EXPORT AnalyzerRunControl *createAnalyzerRunControl(
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
+1
View File
@@ -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>
-2
View File
@@ -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",
+3
View File
@@ -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";
-1
View File
@@ -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";
+195 -58
View File
@@ -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
+46 -54
View File
@@ -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,
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
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);
+1 -1
View File
@@ -56,7 +56,7 @@
#include <io.h>
#endif
using namespace Analyzer;
using namespace Debugger;
using namespace ProjectExplorer;
namespace Ios {
+3 -3
View File
@@ -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;
+2 -2
View File
@@ -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);
+61 -37
View File
@@ -82,8 +82,8 @@
using namespace Core;
using namespace Core::Constants;
using namespace Analyzer;
using namespace Analyzer::Constants;
using namespace Debugger;
using namespace Debugger::Constants;
using namespace QmlProfiler::Constants;
using namespace QmlDebug;
using namespace ProjectExplorer;
@@ -103,6 +103,8 @@ public:
QToolButton *m_recordButton = 0;
QMenu *m_recordFeaturesMenu = 0;
QAction *m_startAction = 0;
QAction *m_stopAction = 0;
QToolButton *m_clearButton = 0;
// elapsed time display
@@ -120,6 +122,8 @@ public:
// save and load actions
QAction *m_saveQmlTrace = 0;
QAction *m_loadQmlTrace = 0;
bool m_toolBusy = false;
};
QmlProfilerTool::QmlProfilerTool(QObject *parent)
@@ -176,8 +180,6 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
d->m_recordingTimer.setInterval(100);
connect(&d->m_recordingTimer, &QTimer::timeout, this, &QmlProfilerTool::updateTimeDisplay);
d->m_viewContainer = new QmlProfilerViewManager(this,
d->m_profilerModelManager,
d->m_profilerState);
@@ -187,14 +189,7 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
//
// Toolbar
//
QWidget *toolbarWidget = new QWidget;
toolbarWidget->setObjectName(QLatin1String("QmlProfilerToolBarWidget"));
QHBoxLayout *layout = new QHBoxLayout;
layout->setMargin(0);
layout->setSpacing(0);
d->m_recordButton = new QToolButton(toolbarWidget);
d->m_recordButton = new QToolButton;
d->m_recordButton->setCheckable(true);
connect(d->m_recordButton,&QAbstractButton::clicked,
@@ -207,9 +202,8 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
this, &QmlProfilerTool::toggleRequestedFeature);
setRecording(d->m_profilerState->clientRecording());
layout->addWidget(d->m_recordButton);
d->m_clearButton = new QToolButton(toolbarWidget);
d->m_clearButton = new QToolButton;
d->m_clearButton->setIcon(Icons::CLEAN_PANE.icon());
d->m_clearButton->setToolTip(tr("Discard data"));
@@ -218,12 +212,9 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
clearData();
});
layout->addWidget(d->m_clearButton);
d->m_searchButton = new QToolButton;
d->m_searchButton->setIcon(Icons::ZOOM.icon());
d->m_searchButton->setToolTip(tr("Search timeline event notes."));
layout->addWidget(d->m_searchButton);
connect(d->m_searchButton, &QToolButton::clicked, this, &QmlProfilerTool::showTimeLineSearch);
@@ -236,7 +227,6 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
d->m_displayFeaturesButton->setMenu(d->m_displayFeaturesMenu);
connect(d->m_displayFeaturesMenu, &QMenu::triggered,
this, &QmlProfilerTool::toggleVisibleFeature);
layout->addWidget(d->m_displayFeaturesButton);
d->m_timeLabel = new QLabel();
QPalette palette;
@@ -244,11 +234,7 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
d->m_timeLabel->setPalette(palette);
d->m_timeLabel->setIndent(10);
updateTimeDisplay();
layout->addWidget(d->m_timeLabel);
layout->addStretch();
toolbarWidget->setLayout(layout);
setAvailableFeatures(d->m_profilerModelManager->availableFeatures());
setRecordedFeatures(0);
@@ -263,6 +249,9 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
QString description = tr("The QML Profiler can be used to find performance "
"bottlenecks in applications using QML.");
d->m_startAction = Debugger::createStartAction();
d->m_stopAction = Debugger::createStopAction();
ActionDescription desc;
desc.setText(tr("QML Profiler"));
desc.setToolTip(description);
@@ -270,8 +259,8 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
desc.setRunControlCreator(runControlCreator);
desc.setToolPreparer([this] { return prepareTool(); });
desc.setRunMode(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_TOOLS);
AnalyzerManager::registerAction(Constants::QmlProfilerLocalActionId, desc);
desc.setMenuGroup(Debugger::Constants::G_ANALYZER_TOOLS);
Debugger::registerAction(Constants::QmlProfilerLocalActionId, desc, d->m_startAction);
desc.setText(tr("QML Profiler (External)"));
desc.setToolTip(description);
@@ -280,10 +269,21 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
desc.setCustomToolStarter([this](RunConfiguration *rc) { startRemoteTool(rc); });
desc.setToolPreparer([this] { return prepareTool(); });
desc.setRunMode(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_REMOTE_TOOLS);
AnalyzerManager::registerAction(Constants::QmlProfilerRemoteActionId, desc);
desc.setMenuGroup(Debugger::Constants::G_ANALYZER_REMOTE_TOOLS);
Debugger::registerAction(Constants::QmlProfilerRemoteActionId, desc);
AnalyzerManager::registerToolbar(Constants::QmlProfilerPerspectiveId, toolbarWidget);
Utils::ToolbarDescription toolbar;
toolbar.addAction(d->m_startAction);
toolbar.addAction(d->m_stopAction);
toolbar.addWidget(d->m_recordButton);
toolbar.addWidget(d->m_clearButton);
toolbar.addWidget(d->m_searchButton);
toolbar.addWidget(d->m_displayFeaturesButton);
toolbar.addWidget(d->m_timeLabel);
Debugger::registerToolbar(Constants::QmlProfilerPerspectiveId, toolbar);
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
this, &QmlProfilerTool::updateRunActions);
}
QmlProfilerTool::~QmlProfilerTool()
@@ -291,6 +291,25 @@ QmlProfilerTool::~QmlProfilerTool()
delete d;
}
void QmlProfilerTool::updateRunActions()
{
if (d->m_toolBusy) {
d->m_startAction->setEnabled(false);
d->m_startAction->setToolTip(tr("A Qml Profiler analysis is still in progress."));
d->m_stopAction->setEnabled(true);
} else {
const bool projectUsable = SessionManager::startupProject() != 0;
d->m_startAction->setToolTip(tr("Start Qml Profiler."));
if (projectUsable) {
d->m_startAction->setEnabled(true);
d->m_stopAction->setEnabled(false);
} else {
d->m_startAction->setEnabled(false);
d->m_stopAction->setEnabled(false);
}
}
}
static QString sysroot(RunConfiguration *runConfig)
{
QTC_ASSERT(runConfig, return QString());
@@ -302,6 +321,7 @@ static QString sysroot(RunConfiguration *runConfig)
AnalyzerRunControl *QmlProfilerTool::createRunControl(RunConfiguration *runConfiguration)
{
d->m_toolBusy = true;
if (runConfiguration) {
QmlProfilerRunConfigurationAspect *aspect = static_cast<QmlProfilerRunConfigurationAspect *>(
runConfiguration->extraAspect(Constants::SETTINGS));
@@ -314,7 +334,16 @@ AnalyzerRunControl *QmlProfilerTool::createRunControl(RunConfiguration *runConfi
}
}
return new QmlProfilerRunControl(runConfiguration, this);
auto runControl = new QmlProfilerRunControl(runConfiguration, this);
connect(runControl, &RunControl::finished, [this, runControl] {
d->m_toolBusy = false;
updateRunActions();
});
connect(d->m_stopAction, &QAction::triggered, runControl, [runControl] { runControl->stop(); });
updateRunActions();
return runControl;
}
void QmlProfilerTool::finalizeRunControl(QmlProfilerRunControl *runControl)
@@ -503,8 +532,6 @@ bool QmlProfilerTool::prepareTool()
void QmlProfilerTool::startRemoteTool(ProjectExplorer::RunConfiguration *rc)
{
AnalyzerManager::showMode();
Id kitId;
quint16 port;
Kit *kit = 0;
@@ -596,7 +623,7 @@ void QmlProfilerTool::showSaveDialog()
if (!filename.endsWith(QLatin1String(TraceFileExtension)))
filename += QLatin1String(TraceFileExtension);
saveLastTraceFile(filename);
AnalyzerManager::enableMainWindow(false);
Debugger::enableMainWindow(false);
d->m_profilerModelManager->save(filename);
}
}
@@ -606,10 +633,7 @@ void QmlProfilerTool::showLoadDialog()
if (!checkForUnsavedNotes())
return;
if (ModeManager::currentMode()->id() != MODE_ANALYZE)
AnalyzerManager::showMode();
AnalyzerManager::selectAction(QmlProfilerRemoteActionId);
Debugger::selectPerspective(QmlProfilerPerspectiveId);
QString filename = QFileDialog::getOpenFileName(
ICore::mainWindow(), tr("Load QML Trace"),
@@ -618,7 +642,7 @@ void QmlProfilerTool::showLoadDialog()
if (!filename.isEmpty()) {
saveLastTraceFile(filename);
AnalyzerManager::enableMainWindow(false);
Debugger::enableMainWindow(false);
connect(d->m_profilerModelManager, &QmlProfilerModelManager::recordedFeaturesChanged,
this, &QmlProfilerTool::setRecordedFeatures);
d->m_profilerModelManager->load(filename);
@@ -629,7 +653,7 @@ void QmlProfilerTool::onLoadSaveFinished()
{
disconnect(d->m_profilerModelManager, &QmlProfilerModelManager::recordedFeaturesChanged,
this, &QmlProfilerTool::setRecordedFeatures);
AnalyzerManager::enableMainWindow(true);
Debugger::enableMainWindow(true);
}
/*!
+2 -1
View File
@@ -51,7 +51,7 @@ public:
explicit QmlProfilerTool(QObject *parent);
~QmlProfilerTool();
Analyzer::AnalyzerRunControl *createRunControl(ProjectExplorer::RunConfiguration *runConfiguration = 0);
Debugger::AnalyzerRunControl *createRunControl(ProjectExplorer::RunConfiguration *runConfiguration = 0);
void finalizeRunControl(QmlProfilerRunControl *runControl);
bool prepareTool();
@@ -96,6 +96,7 @@ private slots:
void toggleVisibleFeature(QAction *action);
private:
void updateRunActions();
void clearDisplay();
void populateFileFinder(QString projectDirectory = QString(), QString activeSysroot = QString());
template<QmlDebug::ProfileFeature feature>
@@ -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
+2 -2
View File
@@ -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);
+3 -3
View File
@@ -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;
+1 -2
View File
@@ -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();
+4 -4
View File
@@ -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()
+1 -1
View File
@@ -41,7 +41,7 @@ class CallgrindRunControl : public ValgrindRunControl
public:
CallgrindRunControl(ProjectExplorer::RunConfiguration *runConfiguration);
bool startEngine() override;
void start() override;
Valgrind::Callgrind::ParseData *takeParserData();
+265 -264
View File
@@ -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;
+5 -5
View File
@@ -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
+2 -2
View File
@@ -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;
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -36,7 +36,7 @@ namespace Internal {
class ValgrindBaseSettings;
class MemcheckErrorView : public Analyzer::DetailedErrorView
class MemcheckErrorView : public Debugger::DetailedErrorView
{
Q_OBJECT
+182 -160
View File
@@ -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)
+17 -10
View File
@@ -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;
}
return true;
emit finished();
return;
}
void ValgrindRunControl::stopEngine()
m_isRunning = true;
emit started();
}
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();
+5 -3
View File
@@ -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
+1 -1
View File
@@ -188,7 +188,7 @@ QString ValgrindRunner::errorString() const
void ValgrindRunner::stop()
{
if (d->process)
QTC_ASSERT(d->process, finished(); return);
d->process->close();
}
@@ -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
@@ -31,7 +31,7 @@
enum { debug = 0 };
using namespace Analyzer;
using namespace Debugger;
using namespace ClangStaticAnalyzer::Internal;
namespace {