DAP: Add engine chooser

The Engine Chooser empowers users to select the desired
debugging engine when initiating DAP debugging sessions.

Change-Id: I070ff2620b318494ee715c5ac369765d4a9dc616
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
Artem Sokolovskii
2023-08-18 15:17:11 +02:00
parent b80cef815e
commit d304e82e63
15 changed files with 300 additions and 95 deletions

View File

@@ -93,7 +93,8 @@ CMakeDapEngine::CMakeDapEngine()
: DapEngine() : DapEngine()
{ {
setObjectName("CmakeDapEngine"); setObjectName("CmakeDapEngine");
setDebuggerName("CmakeDAP"); setDebuggerName("Cmake");
setDebuggerType("DAP");
} }
void CMakeDapEngine::setupEngine() void CMakeDapEngine::setupEngine()

View File

@@ -5,6 +5,8 @@
#include "dapclient.h" #include "dapclient.h"
#include <coreplugin/messagemanager.h>
#include <debugger/debuggermainwindow.h> #include <debugger/debuggermainwindow.h>
#include <utils/temporarydirectory.h> #include <utils/temporarydirectory.h>
@@ -16,6 +18,7 @@
#include <QDebug> #include <QDebug>
#include <QLocalSocket> #include <QLocalSocket>
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QVersionNumber>
using namespace Core; using namespace Core;
using namespace Utils; using namespace Utils;
@@ -82,7 +85,8 @@ GdbDapEngine::GdbDapEngine()
: DapEngine() : DapEngine()
{ {
setObjectName("GdbDapEngine"); setObjectName("GdbDapEngine");
setDebuggerName("GdbDAP"); setDebuggerName("Gdb");
setDebuggerType("DAP");
} }
void GdbDapEngine::setupEngine() void GdbDapEngine::setupEngine()
@@ -92,6 +96,16 @@ void GdbDapEngine::setupEngine()
const DebuggerRunParameters &rp = runParameters(); const DebuggerRunParameters &rp = runParameters();
const CommandLine cmd{rp.debugger.command.executable(), {"-i", "dap"}}; const CommandLine cmd{rp.debugger.command.executable(), {"-i", "dap"}};
QVersionNumber oldestVersion(14, 0, 50);
QVersionNumber version = QVersionNumber::fromString(rp.version);
if (version < oldestVersion) {
notifyEngineSetupFailed();
MessageManager::writeDisrupting("Debugger version " + rp.version
+ " is too old. Please upgrade to at least "
+ oldestVersion.toString());
return;
}
IDataProvider *dataProvider = new ProcessDataProvider(rp, cmd, this); IDataProvider *dataProvider = new ProcessDataProvider(rp, cmd, this);
m_dapClient = new DapClient(dataProvider, this); m_dapClient = new DapClient(dataProvider, this);

View File

@@ -99,7 +99,6 @@ enum DebuggerEngineType
CdbEngineType = 0x004, CdbEngineType = 0x004,
PdbEngineType = 0x008, PdbEngineType = 0x008,
LldbEngineType = 0x100, LldbEngineType = 0x100,
DapEngineType = 0x200,
UvscEngineType = 0x1000 UvscEngineType = 0x1000
}; };

View File

@@ -440,6 +440,7 @@ public:
DebuggerEngine *m_engine = nullptr; // Not owned. DebuggerEngine *m_engine = nullptr; // Not owned.
QString m_runId; QString m_runId;
QString m_debuggerName; QString m_debuggerName;
QString m_debuggerType;
QPointer<Perspective> m_perspective; QPointer<Perspective> m_perspective;
DebuggerRunParameters m_runParameters; DebuggerRunParameters m_runParameters;
IDevice::ConstPtr m_device; IDevice::ConstPtr m_device;
@@ -728,6 +729,8 @@ void DebuggerEnginePrivate::setupViews()
if (!currentPerspective || currentPerspective->id() == Constants::PRESET_PERSPECTIVE_ID) if (!currentPerspective || currentPerspective->id() == Constants::PRESET_PERSPECTIVE_ID)
m_perspective->useSubPerspectiveSwitcher(EngineManager::engineChooser()); m_perspective->useSubPerspectiveSwitcher(EngineManager::engineChooser());
else
m_perspective->useSubPerspectiveSwitcher(EngineManager::dapEngineChooser());
m_perspective->addToolBarAction(&m_continueAction); m_perspective->addToolBarAction(&m_continueAction);
m_perspective->addToolBarAction(&m_interruptAction); m_perspective->addToolBarAction(&m_interruptAction);
@@ -872,6 +875,16 @@ QString DebuggerEngine::debuggerName() const
return d->m_debuggerName; return d->m_debuggerName;
} }
void DebuggerEngine::setDebuggerType(const QString &type)
{
d->m_debuggerType = type;
}
QString DebuggerEngine::debuggerType() const
{
return d->m_debuggerType;
}
QString DebuggerEngine::stateName(int s) QString DebuggerEngine::stateName(int s)
{ {
# define SN(x) case x: return QLatin1String(#x); # define SN(x) case x: return QLatin1String(#x);
@@ -2590,7 +2603,6 @@ bool DebuggerRunParameters::isCppDebugging() const
return cppEngineType == GdbEngineType return cppEngineType == GdbEngineType
|| cppEngineType == LldbEngineType || cppEngineType == LldbEngineType
|| cppEngineType == CdbEngineType || cppEngineType == CdbEngineType
|| cppEngineType == DapEngineType
|| cppEngineType == UvscEngineType; || cppEngineType == UvscEngineType;
} }

View File

@@ -146,6 +146,7 @@ public:
QString additionalStartupCommands; QString additionalStartupCommands;
DebuggerEngineType cppEngineType = NoEngineType; DebuggerEngineType cppEngineType = NoEngineType;
QString version;
bool isQmlDebugging = false; bool isQmlDebugging = false;
bool breakOnMain = false; bool breakOnMain = false;
@@ -451,6 +452,7 @@ public:
void updateLocalsWindow(bool showReturn); void updateLocalsWindow(bool showReturn);
void raiseWatchersWindow(); void raiseWatchersWindow();
QString debuggerName() const; QString debuggerName() const;
QString debuggerType() const;
bool isRegistersWindowVisible() const; bool isRegistersWindowVisible() const;
bool isPeripheralRegistersWindowVisible() const; bool isPeripheralRegistersWindowVisible() const;
@@ -493,6 +495,7 @@ public:
protected: protected:
void setDebuggerName(const QString &name); void setDebuggerName(const QString &name);
void setDebuggerType(const QString &type);
void notifyDebuggerProcessFinished(const Utils::ProcessResultData &resultData, void notifyDebuggerProcessFinished(const Utils::ProcessResultData &resultData,
const QString &backendName); const QString &backendName);

View File

@@ -41,7 +41,7 @@ const char C_QMLDEBUGGER[] = "Qml/JavaScript Debugger";
const char C_DEBUGGER_NOTRUNNING[] = "Debugger.NotRunning"; const char C_DEBUGGER_NOTRUNNING[] = "Debugger.NotRunning";
const char PRESET_PERSPECTIVE_ID[] = "Debugger.Perspective.Preset"; const char PRESET_PERSPECTIVE_ID[] = "Debugger.Perspective.Preset";
const char CMAKE_PERSPECTIVE_ID[] = "CMakeDebugger"; const char DAP_PERSPECTIVE_ID[] = "DAPDebugger";
const char TASK_CATEGORY_DEBUGGER_RUNTIME[] = "DebugRuntime"; const char TASK_CATEGORY_DEBUGGER_RUNTIME[] = "DebugRuntime";

View File

@@ -177,9 +177,6 @@ void DebuggerItem::reinitializeFromFile(QString *error, Utils::Environment *cust
if (output.contains("gdb")) { if (output.contains("gdb")) {
m_engineType = GdbEngineType; m_engineType = GdbEngineType;
// FIXME: HACK while introducing DAP support
if (m_command.fileName().endsWith("-dap"))
m_engineType = DapEngineType;
// Version // Version
bool isMacGdb, isQnxGdb; bool isMacGdb, isQnxGdb;
@@ -283,8 +280,6 @@ QString DebuggerItem::engineTypeName() const
return QLatin1String("CDB"); return QLatin1String("CDB");
case LldbEngineType: case LldbEngineType:
return QLatin1String("LLDB"); return QLatin1String("LLDB");
case DapEngineType:
return QLatin1String("DAP");
case UvscEngineType: case UvscEngineType:
return QLatin1String("UVSC"); return QLatin1String("UVSC");
default: default:

View File

@@ -665,14 +665,6 @@ void DebuggerItemModel::autoDetectGdbOrLldbDebuggers(const FilePaths &searchPath
item.setUnexpandedDisplayName(name.arg(item.engineTypeName()).arg(command.toUserOutput())); item.setUnexpandedDisplayName(name.arg(item.engineTypeName()).arg(command.toUserOutput()));
addDebuggerItem(item); addDebuggerItem(item);
logMessages.append(Tr::tr("Found: \"%1\"").arg(command.toUserOutput())); logMessages.append(Tr::tr("Found: \"%1\"").arg(command.toUserOutput()));
if (item.engineType() == GdbEngineType) {
if (item.version().startsWith("GNU gdb (GDB) 14.0.50.2023")) {
// FIXME: Use something more robust
item.setEngineType(DapEngineType);
addDebuggerItem(item);
}
}
} }
if (logMessage) if (logMessage)
*logMessage = logMessages.join('\n'); *logMessage = logMessages.join('\n');

View File

@@ -248,6 +248,13 @@ QString DebuggerKitAspect::displayString(const Kit *k)
return binary.isEmpty() ? Tr::tr("%1 <None>").arg(name) : Tr::tr("%1 using \"%2\"").arg(name, binary); return binary.isEmpty() ? Tr::tr("%1 <None>").arg(name) : Tr::tr("%1 using \"%2\"").arg(name, binary);
} }
QString DebuggerKitAspect::version(const Kit *k)
{
const DebuggerItem *item = debugger(k);
QTC_ASSERT(item, return {});
return item->version();
}
void DebuggerKitAspect::setDebugger(Kit *k, const QVariant &id) void DebuggerKitAspect::setDebugger(Kit *k, const QVariant &id)
{ {
// Only register reasonably complete debuggers. // Only register reasonably complete debuggers.

View File

@@ -33,6 +33,7 @@ public:
static void setDebugger(ProjectExplorer::Kit *k, const QVariant &id); static void setDebugger(ProjectExplorer::Kit *k, const QVariant &id);
static DebuggerEngineType engineType(const ProjectExplorer::Kit *k); static DebuggerEngineType engineType(const ProjectExplorer::Kit *k);
static QString displayString(const ProjectExplorer::Kit *k); static QString displayString(const ProjectExplorer::Kit *k);
static QString version(const ProjectExplorer::Kit *k);
static Utils::Id id(); static Utils::Id id();
}; };

View File

@@ -105,20 +105,21 @@
#include <QFileDialog> #include <QFileDialog>
#include <QHeaderView> #include <QHeaderView>
#include <QInputDialog> #include <QInputDialog>
#include <QJsonDocument>
#include <QJsonObject>
#include <QMenu> #include <QMenu>
#include <QMessageBox> #include <QMessageBox>
#include <QPointer> #include <QPointer>
#include <QPushButton> #include <QPushButton>
#include <QScopeGuard> #include <QScopeGuard>
#include <QSettings> #include <QSettings>
#include <QSortFilterProxyModel>
#include <QStackedWidget> #include <QStackedWidget>
#include <QTextBlock> #include <QTextBlock>
#include <QToolButton> #include <QToolButton>
#include <QTreeWidget> #include <QTreeWidget>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QVariant> #include <QVariant>
#include <QJsonDocument>
#include <QJsonObject>
#ifdef WITH_TESTS #ifdef WITH_TESTS
@@ -509,6 +510,7 @@ public:
splitter->setObjectName("DebugModeWidget"); splitter->setObjectName("DebugModeWidget");
mainWindow->addSubPerspectiveSwitcher(EngineManager::engineChooser()); mainWindow->addSubPerspectiveSwitcher(EngineManager::engineChooser());
mainWindow->addSubPerspectiveSwitcher(EngineManager::dapEngineChooser());
setWidget(splitter); setWidget(splitter);
@@ -616,12 +618,14 @@ public:
const QString &title, const QString &title,
const QString &objectName); const QString &objectName);
BaseTreeView *createEngineManagerView(const QString &title, const QByteArray &settingsKey); BaseTreeView *createEngineManagerView(QAbstractItemModel *model,
const QString &title,
const QByteArray &settingsKey);
QWidget *createEngineManagerWindow(BaseTreeView *engineManagerView, QWidget *createEngineManagerWindow(BaseTreeView *engineManagerView,
const QString &title, const QString &title,
const QString &objectName); const QString &objectName);
void createCMakeDebuggerPerspective(QWidget *globalLogWindow); void createDapDebuggerPerspective(QWidget *globalLogWindow);
void editorOpened(IEditor *editor); void editorOpened(IEditor *editor);
void updateBreakMenuItem(IEditor *editor); void updateBreakMenuItem(IEditor *editor);
@@ -668,7 +672,7 @@ public:
ProxyAction m_hiddenStopAction; ProxyAction m_hiddenStopAction;
QAction m_undisturbableAction; QAction m_undisturbableAction;
OptionalAction m_startAction; OptionalAction m_startAction;
OptionalAction m_startCmakeAction; OptionalAction m_startDapAction;
QAction m_debugWithoutDeployAction{Tr::tr("Start Debugging Without Deployment")}; QAction m_debugWithoutDeployAction{Tr::tr("Start Debugging Without Deployment")};
QAction m_startAndDebugApplicationAction{Tr::tr("Start and Debug External Application...")}; QAction m_startAndDebugApplicationAction{Tr::tr("Start and Debug External Application...")};
QAction m_attachToRunningApplication{Tr::tr("Attach to Running Application...")}; QAction m_attachToRunningApplication{Tr::tr("Attach to Running Application...")};
@@ -699,7 +703,7 @@ public:
IContext m_debugModeContext; IContext m_debugModeContext;
Perspective m_perspective{Constants::PRESET_PERSPECTIVE_ID, Tr::tr("Debugger")}; Perspective m_perspective{Constants::PRESET_PERSPECTIVE_ID, Tr::tr("Debugger")};
std::unique_ptr<Perspective> m_perspectiveCmake; Perspective m_perspectiveDap{Constants::DAP_PERSPECTIVE_ID, Tr::tr("DAP")};
DebuggerRunWorkerFactory debuggerWorkerFactory; DebuggerRunWorkerFactory debuggerWorkerFactory;
@@ -761,13 +765,15 @@ QWidget *DebuggerPluginPrivate::createBreakpointManagerWindow(BaseTreeView *brea
return breakpointManagerWindow; return breakpointManagerWindow;
} }
BaseTreeView *DebuggerPluginPrivate::createEngineManagerView(const QString &title, const QByteArray &settingsKey) BaseTreeView *DebuggerPluginPrivate::createEngineManagerView(QAbstractItemModel *model,
const QString &title,
const QByteArray &settingsKey)
{ {
auto engineManagerView = new BaseTreeView; auto engineManagerView = new BaseTreeView;
engineManagerView->setWindowTitle(title); engineManagerView->setWindowTitle(title);
engineManagerView->setSettings(ICore::settings(), settingsKey); engineManagerView->setSettings(ICore::settings(), settingsKey);
engineManagerView->setIconSize(QSize(10, 10)); engineManagerView->setIconSize(QSize(10, 10));
engineManagerView->setModel(EngineManager::model()); engineManagerView->setModel(model);
engineManagerView->setSelectionMode(QAbstractItemView::SingleSelection); engineManagerView->setSelectionMode(QAbstractItemView::SingleSelection);
engineManagerView->enableColumnHiding(); engineManagerView->enableColumnHiding();
return engineManagerView; return engineManagerView;
@@ -858,7 +864,8 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(const QStringList &arguments)
"Debugger.Docks.BreakpointManager"); "Debugger.Docks.BreakpointManager");
// Snapshot // Snapshot
auto engineManagerView = createEngineManagerView(Tr::tr("Running Debuggers"), auto engineManagerView = createEngineManagerView(EngineManager::model(),
Tr::tr("Running Debuggers"),
"Debugger.SnapshotView"); "Debugger.SnapshotView");
auto engineManagerWindow = createEngineManagerWindow(engineManagerView, auto engineManagerWindow = createEngineManagerWindow(engineManagerView,
Tr::tr("Debugger Perspectives"), Tr::tr("Debugger Perspectives"),
@@ -877,11 +884,6 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(const QStringList &arguments)
ProjectExplorerPlugin::runStartupProject(ProjectExplorer::Constants::DEBUG_RUN_MODE, false); ProjectExplorerPlugin::runStartupProject(ProjectExplorer::Constants::DEBUG_RUN_MODE, false);
}); });
connect(&m_startCmakeAction, &QAction::triggered, this, [] {
ProjectExplorerPlugin::runStartupProject(ProjectExplorer::Constants::CMAKE_DEBUG_RUN_MODE,
true);
});
connect(&m_debugWithoutDeployAction, &QAction::triggered, this, [] { connect(&m_debugWithoutDeployAction, &QAction::triggered, this, [] {
ProjectExplorerPlugin::runStartupProject(ProjectExplorer::Constants::DEBUG_RUN_MODE, true); ProjectExplorerPlugin::runStartupProject(ProjectExplorer::Constants::DEBUG_RUN_MODE, true);
}); });
@@ -1214,6 +1216,10 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(const QStringList &arguments)
connect(settings().settingsDialog.action(), &QAction::triggered, this, connect(settings().settingsDialog.action(), &QAction::triggered, this,
[] { ICore::showOptionsDialog(DEBUGGER_COMMON_SETTINGS_ID); }, Qt::QueuedConnection); [] { ICore::showOptionsDialog(DEBUGGER_COMMON_SETTINGS_ID); }, Qt::QueuedConnection);
EngineManager::registerDefaultPerspective(Tr::tr("Debugger Preset"),
{},
Constants::PRESET_PERSPECTIVE_ID);
m_perspective.useSubPerspectiveSwitcher(EngineManager::engineChooser()); m_perspective.useSubPerspectiveSwitcher(EngineManager::engineChooser());
m_perspective.addToolBarAction(&m_startAction); m_perspective.addToolBarAction(&m_startAction);
@@ -1221,7 +1227,7 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(const QStringList &arguments)
m_perspective.addWindow(breakpointManagerWindow, Perspective::SplitHorizontal, engineManagerWindow); m_perspective.addWindow(breakpointManagerWindow, Perspective::SplitHorizontal, engineManagerWindow);
m_perspective.addWindow(globalLogWindow, Perspective::AddToTab, nullptr, false, Qt::TopDockWidgetArea); m_perspective.addWindow(globalLogWindow, Perspective::AddToTab, nullptr, false, Qt::TopDockWidgetArea);
createCMakeDebuggerPerspective(globalLogWindow); createDapDebuggerPerspective(globalLogWindow);
setInitialState(); setInitialState();
connect(ProjectManager::instance(), &ProjectManager::startupProjectChanged, connect(ProjectManager::instance(), &ProjectManager::startupProjectChanged,
@@ -1232,42 +1238,62 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(const QStringList &arguments)
this, &DebuggerPluginPrivate::updatePresetState); this, &DebuggerPluginPrivate::updatePresetState);
} }
void DebuggerPluginPrivate::createCMakeDebuggerPerspective(QWidget *globalLogWindow) void DebuggerPluginPrivate::createDapDebuggerPerspective(QWidget *globalLogWindow)
{ {
auto breakpointManagerView = createBreakpointManagerView("CMake.BreakWindow"); EngineManager::registerDefaultPerspective(Tr::tr("CMake Preset"),
"DAP",
ProjectExplorer::Constants::CMAKE_DEBUG_RUN_MODE);
EngineManager::registerDefaultPerspective(Tr::tr("GDB Preset"),
"DAP",
ProjectExplorer::Constants::DAP_GDB_DEBUG_RUN_MODE);
auto breakpointManagerView = createBreakpointManagerView("DAPDebugger.BreakWindow");
auto breakpointManagerWindow auto breakpointManagerWindow
= createBreakpointManagerWindow(breakpointManagerView, = createBreakpointManagerWindow(breakpointManagerView,
Tr::tr("CMake Breakpoint Preset"), Tr::tr("DAP Breakpoint Preset"),
"CMake.Docks.BreakpointManager"); "DAPDebugger.Docks.BreakpointManager");
// Snapshot // Snapshot
auto engineManagerView = createEngineManagerView(Tr::tr("Running Debuggers"), auto engineManagerView = createEngineManagerView(EngineManager::dapModel(),
"CMake.SnapshotView"); Tr::tr("Running Debuggers"),
"DAPDebugger.SnapshotView");
auto engineManagerWindow = createEngineManagerWindow(engineManagerView, auto engineManagerWindow = createEngineManagerWindow(engineManagerView,
Tr::tr("CMake Debugger Perspectives"), Tr::tr("DAP Debugger Perspectives"),
"CMake.Docks.Snapshots"); "DAPDebugger.Docks.Snapshots");
m_perspectiveCmake = std::make_unique<Perspective>(Constants::CMAKE_PERSPECTIVE_ID, connect(&m_startDapAction, &QAction::triggered, this, [] {
Tr::tr("CMake")); QComboBox *combo = qobject_cast<QComboBox *>(EngineManager::dapEngineChooser());
m_startCmakeAction.setText(Tr::tr("Start CMake Debugging")); if (combo->currentText() == "CMake Preset") {
m_startCmakeAction.setEnabled(true); ProjectExplorerPlugin::runStartupProject(ProjectExplorer::Constants::CMAKE_DEBUG_RUN_MODE,
m_startCmakeAction.setIcon(startIcon(true)); true);
m_startCmakeAction.setVisible(true); } else {
ProjectExplorerPlugin::runStartupProject(
ProjectExplorer::Constants::DAP_GDB_DEBUG_RUN_MODE, true);
}
});
m_perspectiveCmake->addToolBarAction(&m_startCmakeAction); m_startDapAction.setToolTip(Tr::tr("Start DAP Debugging"));
m_startDapAction.setText(Tr::tr("Start DAP Debugging"));
m_startDapAction.setEnabled(true);
m_startDapAction.setIcon(startIcon(true));
m_startDapAction.setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
m_startDapAction.setVisible(true);
m_perspectiveCmake->addWindow(engineManagerWindow, Perspective::SplitVertical, nullptr); m_perspectiveDap.useSubPerspectiveSwitcher(EngineManager::dapEngineChooser());
m_perspectiveCmake->addWindow(breakpointManagerWindow, m_perspectiveDap.addToolBarAction(&m_startDapAction);
m_perspectiveDap.addWindow(engineManagerWindow, Perspective::SplitVertical, nullptr);
m_perspectiveDap.addWindow(breakpointManagerWindow,
Perspective::SplitHorizontal, Perspective::SplitHorizontal,
engineManagerWindow); engineManagerWindow);
m_perspectiveCmake->addWindow(globalLogWindow, m_perspectiveDap.addWindow(globalLogWindow,
Perspective::AddToTab, Perspective::AddToTab,
nullptr, nullptr,
false, false,
Qt::TopDockWidgetArea); Qt::TopDockWidgetArea);
} }
DebuggerPluginPrivate::~DebuggerPluginPrivate() DebuggerPluginPrivate::~DebuggerPluginPrivate()
{ {
qDeleteAll(m_optionPages); qDeleteAll(m_optionPages);

View File

@@ -484,6 +484,8 @@ void DebuggerRunTool::start()
if (!m_engine) { if (!m_engine) {
if (runControl()->runMode() == ProjectExplorer::Constants::CMAKE_DEBUG_RUN_MODE) if (runControl()->runMode() == ProjectExplorer::Constants::CMAKE_DEBUG_RUN_MODE)
m_engine = createDapEngine(runControl()->runMode()); m_engine = createDapEngine(runControl()->runMode());
else if (runControl()->runMode() == ProjectExplorer::Constants::DAP_GDB_DEBUG_RUN_MODE)
m_engine = createDapEngine();
else if (m_runParameters.isCppDebugging()) { else if (m_runParameters.isCppDebugging()) {
switch (m_runParameters.cppEngineType) { switch (m_runParameters.cppEngineType) {
case GdbEngineType: case GdbEngineType:
@@ -506,9 +508,6 @@ void DebuggerRunTool::start()
case UvscEngineType: case UvscEngineType:
m_engine = createUvscEngine(); m_engine = createUvscEngine();
break; break;
case DapEngineType:
m_engine = createDapEngine();
break;
default: default:
if (!m_runParameters.isQmlDebugging) { if (!m_runParameters.isQmlDebugging) {
reportFailure(noEngineMessage() + '\n' + reportFailure(noEngineMessage() + '\n' +
@@ -856,6 +855,7 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, AllowTerminal allowTerm
m_runParameters.macroExpander = runControl->macroExpander(); m_runParameters.macroExpander = runControl->macroExpander();
m_runParameters.debugger = DebuggerKitAspect::runnable(kit); m_runParameters.debugger = DebuggerKitAspect::runnable(kit);
m_runParameters.cppEngineType = DebuggerKitAspect::engineType(kit); m_runParameters.cppEngineType = DebuggerKitAspect::engineType(kit);
m_runParameters.version = DebuggerKitAspect::version(kit);
if (QtSupport::QtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(kit)) { if (QtSupport::QtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(kit)) {
m_runParameters.qtPackageSourceLocation = qtVersion->qtPackageSourcePath().toString(); m_runParameters.qtPackageSourceLocation = qtVersion->qtPackageSourcePath().toString();
@@ -1121,6 +1121,7 @@ DebuggerRunWorkerFactory::DebuggerRunWorkerFactory()
setProduct<DebuggerRunTool>(); setProduct<DebuggerRunTool>();
addSupportedRunMode(ProjectExplorer::Constants::DEBUG_RUN_MODE); addSupportedRunMode(ProjectExplorer::Constants::DEBUG_RUN_MODE);
addSupportedRunMode(ProjectExplorer::Constants::CMAKE_DEBUG_RUN_MODE); addSupportedRunMode(ProjectExplorer::Constants::CMAKE_DEBUG_RUN_MODE);
addSupportedRunMode(ProjectExplorer::Constants::DAP_GDB_DEBUG_RUN_MODE);
addSupportedDeviceType(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE); addSupportedDeviceType(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE);
addSupportedDeviceType("DockerDeviceType"); addSupportedDeviceType("DockerDeviceType");
} }

View File

@@ -17,9 +17,11 @@
#include <utils/treemodel.h> #include <utils/treemodel.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QAbstractProxyModel>
#include <QComboBox> #include <QComboBox>
#include <QDebug> #include <QDebug>
#include <QMenu> #include <QMenu>
#include <QSortFilterProxyModel>
#include <QTimer> #include <QTimer>
using namespace Core; using namespace Core;
@@ -93,6 +95,108 @@ QDebug operator<<(QDebug d, const SnapshotData &f)
} }
#endif #endif
class EngineTypeFilterProxyModel : public QSortFilterProxyModel
{
public:
explicit EngineTypeFilterProxyModel(const QString &type, QObject *parent = nullptr)
: QSortFilterProxyModel(parent)
, m_type(type)
{
}
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
{
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
if (index.isValid()) {
QVariant data = sourceModel()->data(index, Qt::UserRole);
if (data.isValid() && data.toString() == m_type) {
return true; // Display only DapEngines
}
}
return false;
}
private:
QString m_type;
};
class ModelChooser : public QObject
{
Q_OBJECT
public:
ModelChooser(QAbstractItemModel *sourceModel,
const QString &enginType,
QObject *parent = nullptr)
: QObject(parent)
, m_engineChooser(new QComboBox())
, m_proxyModel(new EngineTypeFilterProxyModel(enginType))
, m_sourceModel(sourceModel)
, m_enginType(enginType)
{
m_proxyModel->setSourceModel(sourceModel);
m_engineChooser->setModel(m_proxyModel);
m_engineChooser->setIconSize(QSize(0, 0));
if (hideSwitcherUnlessNeeded)
m_engineChooser->hide();
connect(m_engineChooser, &QComboBox::activated, this, [this](int index) {
QModelIndex sourceIndex = m_proxyModel->mapToSource(m_proxyModel->index(index, 0));
emit activated(sourceIndex.row());
});
}
~ModelChooser()
{
delete m_engineChooser;
delete m_proxyModel;
}
QComboBox *comboBox() const { return m_engineChooser; }
QAbstractItemModel *model() const { return m_proxyModel; }
const QString &engineType() const { return m_enginType; }
void setCurrentIndex(int index)
{
const QModelIndex sourceIndex = m_proxyModel->mapFromSource(m_sourceModel->index(index, 0));
if (sourceIndex.isValid())
m_engineChooser->setCurrentIndex(sourceIndex.row());
else
m_engineChooser->setCurrentIndex(0);
}
void adjustUiForEngine(int row)
{
setCurrentIndex(row);
const int contentWidth = m_engineChooser->fontMetrics().horizontalAdvance(
m_engineChooser->currentText() + "xx");
QStyleOptionComboBox option;
option.initFrom(m_engineChooser);
const QSize sz(contentWidth, 1);
const int width = m_engineChooser->style()
->sizeFromContents(QStyle::CT_ComboBox, &option, sz)
.width();
m_engineChooser->setFixedWidth(width);
}
signals:
void activated(int index);
private:
QPointer<QComboBox> m_engineChooser;
QPointer<EngineTypeFilterProxyModel> m_proxyModel;
QAbstractItemModel *m_sourceModel;
QString m_enginType;
};
struct PerspectiveItem
{
QString name;
QString type;
QString id;
};
class EngineItem : public QObject, public TreeItem class EngineItem : public QObject, public TreeItem
{ {
public: public:
@@ -101,6 +205,8 @@ public:
const bool m_isPreset = false; const bool m_isPreset = false;
QPointer<DebuggerEngine> m_engine; QPointer<DebuggerEngine> m_engine;
PerspectiveItem m_perspective;
}; };
class EngineManagerPrivate : public QObject class EngineManagerPrivate : public QObject
@@ -110,25 +216,19 @@ public:
{ {
m_engineModel.setHeader({Tr::tr("Perspective"), Tr::tr("Debugged Application")}); m_engineModel.setHeader({Tr::tr("Perspective"), Tr::tr("Debugged Application")});
// The preset case: m_engineChooser = new ModelChooser(&m_engineModel, "", this);
auto preset = new EngineItem; m_engineDAPChooser = new ModelChooser(&m_engineModel, "DAP", this);
m_engineModel.rootItem()->appendChild(preset);
m_currentItem = preset;
m_engineChooser = new QComboBox; connect(m_engineChooser, &ModelChooser::activated, this, [this](int index) {
m_engineChooser->setModel(&m_engineModel); activateEngineByIndex(index);
m_engineChooser->setIconSize(QSize(0, 0)); });
if (hideSwitcherUnlessNeeded)
m_engineChooser->hide();
connect(m_engineChooser, &QComboBox::activated, connect(m_engineDAPChooser, &ModelChooser::activated, this, [this](int index) {
this, &EngineManagerPrivate::activateEngineByIndex); activateEngineByIndex(index);
});
} }
~EngineManagerPrivate() ~EngineManagerPrivate() = default;
{
delete m_engineChooser;
}
EngineItem *findEngineItem(DebuggerEngine *engine); EngineItem *findEngineItem(DebuggerEngine *engine);
void activateEngineItem(EngineItem *engineItem); void activateEngineItem(EngineItem *engineItem);
@@ -140,7 +240,11 @@ public:
TreeModel<TypedTreeItem<EngineItem>, EngineItem> m_engineModel; TreeModel<TypedTreeItem<EngineItem>, EngineItem> m_engineModel;
QPointer<EngineItem> m_currentItem; // The primary information is DebuggerMainWindow::d->m_currentPerspective QPointer<EngineItem> m_currentItem; // The primary information is DebuggerMainWindow::d->m_currentPerspective
Utils::Id m_previousMode; Utils::Id m_previousMode;
QPointer<QComboBox> m_engineChooser;
QPointer<ModelChooser> m_engineChooser;
QPointer<ModelChooser> m_engineDAPChooser;
QList<PerspectiveItem> m_perspectives;
bool m_shuttingDown = false; bool m_shuttingDown = false;
// This contains the contexts that need to be removed when switching // This contains the contexts that need to be removed when switching
@@ -173,7 +277,12 @@ EngineManager::EngineManager()
QWidget *EngineManager::engineChooser() QWidget *EngineManager::engineChooser()
{ {
return d->m_engineChooser; return d->m_engineChooser->comboBox();
}
QWidget *EngineManager::dapEngineChooser()
{
return d->m_engineDAPChooser->comboBox();
} }
void EngineManager::updatePerspectives() void EngineManager::updatePerspectives()
@@ -194,7 +303,12 @@ EngineManager *EngineManager::instance()
QAbstractItemModel *EngineManager::model() QAbstractItemModel *EngineManager::model()
{ {
return &d->m_engineModel; return d->m_engineChooser->model();
}
QAbstractItemModel *EngineManager::dapModel()
{
return d->m_engineDAPChooser->model();
} }
QVariant EngineItem::data(int column, int role) const QVariant EngineItem::data(int column, int role) const
@@ -232,7 +346,9 @@ QVariant EngineItem::data(int column, int role) const
// Return icon that indicates whether this is the active engine // Return icon that indicates whether this is the active engine
if (column == 0) if (column == 0)
return d->m_currentItem == this ? Icons::LOCATION.icon() : Icons::EMPTY.icon(); return d->m_currentItem == this ? Icons::LOCATION.icon() : Icons::EMPTY.icon();
break;
case Qt::UserRole:
return QVariant::fromValue(m_engine->debuggerType());
default: default:
break; break;
} }
@@ -240,8 +356,10 @@ QVariant EngineItem::data(int column, int role) const
switch (role) { switch (role) {
case Qt::DisplayRole: case Qt::DisplayRole:
if (column == 0) if (column == 0)
return Tr::tr("Debugger Preset"); return m_perspective.name;
return QString("-"); return QString("-");
case Qt::UserRole:
return m_perspective.type;
default: default:
break; break;
} }
@@ -302,10 +420,11 @@ void EngineManagerPrivate::activateEngineByIndex(int index)
{ {
// The actual activation is triggered indirectly via the perspective change. // The actual activation is triggered indirectly via the perspective change.
Perspective *perspective = nullptr; Perspective *perspective = nullptr;
if (index == 0) {
perspective = Perspective::findPerspective(Debugger::Constants::PRESET_PERSPECTIVE_ID);
} else {
EngineItem *engineItem = m_engineModel.rootItem()->childAt(index); EngineItem *engineItem = m_engineModel.rootItem()->childAt(index);
if (engineItem && !engineItem->m_engine) {
perspective = Perspective::findPerspective(engineItem->m_perspective.id);
} else {
QTC_ASSERT(engineItem, return); QTC_ASSERT(engineItem, return);
QTC_ASSERT(engineItem->m_engine, return); QTC_ASSERT(engineItem->m_engine, return);
perspective = engineItem->m_engine->perspective(); perspective = engineItem->m_engine->perspective();
@@ -338,6 +457,13 @@ void EngineManagerPrivate::activateEngineItem(EngineItem *engineItem)
// In case this was triggered externally by some Perspective::select() call. // In case this was triggered externally by some Perspective::select() call.
const int idx = engineItem->indexInParent(); const int idx = engineItem->indexInParent();
if ((engineItem->m_engine
&& engineItem->m_engine->debuggerType() == m_engineDAPChooser->engineType())
|| (engineItem->m_engine
&& engineItem->m_perspective.type == m_engineDAPChooser->engineType()))
m_engineDAPChooser->setCurrentIndex(idx);
else
m_engineChooser->setCurrentIndex(idx); m_engineChooser->setCurrentIndex(idx);
selectUiForCurrentEngine(); selectUiForCurrentEngine();
@@ -352,15 +478,13 @@ void EngineManagerPrivate::selectUiForCurrentEngine()
if (m_currentItem) if (m_currentItem)
row = m_engineModel.rootItem()->indexOf(m_currentItem); row = m_engineModel.rootItem()->indexOf(m_currentItem);
m_engineChooser->setCurrentIndex(row); if ((m_currentItem->m_engine
const int contentWidth = && m_currentItem->m_engine->debuggerType() == m_engineDAPChooser->engineType())
m_engineChooser->fontMetrics().horizontalAdvance(m_engineChooser->currentText() + "xx"); || (m_currentItem->m_engine
QStyleOptionComboBox option; && m_currentItem->m_perspective.type == m_engineDAPChooser->engineType()))
option.initFrom(m_engineChooser); m_engineDAPChooser->adjustUiForEngine(row);
const QSize sz(contentWidth, 1); else
const int width = m_engineChooser->style()->sizeFromContents( m_engineChooser->adjustUiForEngine(row);
QStyle::CT_ComboBox, &option, sz).width();
m_engineChooser->setFixedWidth(width);
m_engineModel.rootItem()->forFirstLevelChildren([this](EngineItem *engineItem) { m_engineModel.rootItem()->forFirstLevelChildren([this](EngineItem *engineItem) {
if (engineItem && engineItem->m_engine) if (engineItem && engineItem->m_engine)
@@ -382,7 +506,8 @@ void EngineManagerPrivate::updateEngineChooserVisibility()
// Show it if there's more than one option (i.e. not the preset engine only) // Show it if there's more than one option (i.e. not the preset engine only)
if (hideSwitcherUnlessNeeded) { if (hideSwitcherUnlessNeeded) {
const int count = m_engineModel.rootItem()->childCount(); const int count = m_engineModel.rootItem()->childCount();
m_engineChooser->setVisible(count >= 2); m_engineChooser->comboBox()->setVisible(count >= 2);
m_engineDAPChooser->comboBox()->setVisible(count >= 2);
} }
} }
@@ -430,6 +555,18 @@ void EngineManager::unregisterEngine(DebuggerEngine *engine)
d->updateEngineChooserVisibility(); d->updateEngineChooserVisibility();
} }
QString EngineManager::registerDefaultPerspective(const QString &name,
const QString &type,
const QString &id)
{
auto engineItem = new EngineItem;
engineItem->m_perspective.name = name;
engineItem->m_perspective.type = type;
engineItem->m_perspective.id = id;
d->m_engineModel.rootItem()->appendChild(engineItem);
return QString::number(d->m_engineModel.rootItem()->childCount());
}
void EngineManager::activateDebugMode() void EngineManager::activateDebugMode()
{ {
if (ModeManager::currentModeId() != Constants::MODE_DEBUG) { if (ModeManager::currentModeId() != Constants::MODE_DEBUG) {
@@ -438,6 +575,11 @@ void EngineManager::activateDebugMode()
} }
} }
void EngineManager::activateByIndex(int index)
{
d->activateEngineByIndex(index);
}
void EngineManager::deactivateDebugMode() void EngineManager::deactivateDebugMode()
{ {
if (ModeManager::currentModeId() == Constants::MODE_DEBUG && d->m_previousMode.isValid()) { if (ModeManager::currentModeId() == Constants::MODE_DEBUG && d->m_previousMode.isValid()) {
@@ -479,3 +621,5 @@ bool EngineManager::shutDown()
} }
} // Debugger::Internal } // Debugger::Internal
#include "enginemanager.moc"

View File

@@ -10,6 +10,7 @@
namespace Debugger::Internal { namespace Debugger::Internal {
class DebuggerEngine; class DebuggerEngine;
struct PerspectiveItem;
class EngineManager final : public QObject class EngineManager final : public QObject
{ {
@@ -21,17 +22,25 @@ public:
static EngineManager *instance(); static EngineManager *instance();
static QAbstractItemModel *model(); static QAbstractItemModel *model();
static QAbstractItemModel *dapModel();
static QString registerEngine(DebuggerEngine *engine); static QString registerEngine(DebuggerEngine *engine);
static void unregisterEngine(DebuggerEngine *engine); static void unregisterEngine(DebuggerEngine *engine);
static QString registerDefaultPerspective(const QString &name,
const QString &type,
const QString &id);
static void activateDebugMode(); static void activateDebugMode();
static void deactivateDebugMode(); static void deactivateDebugMode();
static void activateByIndex(int index);
static QList<QPointer<DebuggerEngine> > engines(); static QList<QPointer<DebuggerEngine> > engines();
static QPointer<DebuggerEngine> currentEngine(); static QPointer<DebuggerEngine> currentEngine();
static QWidget *engineChooser(); static QWidget *engineChooser();
static QWidget *dapEngineChooser();
static void updatePerspectives(); static void updatePerspectives();
static bool shutDown(); // Return true if some engine is being forced to shut down. static bool shutDown(); // Return true if some engine is being forced to shut down.

View File

@@ -179,6 +179,7 @@ const char NO_RUN_MODE[]="RunConfiguration.NoRunMode";
const char NORMAL_RUN_MODE[]="RunConfiguration.NormalRunMode"; const char NORMAL_RUN_MODE[]="RunConfiguration.NormalRunMode";
const char DEBUG_RUN_MODE[]="RunConfiguration.DebugRunMode"; const char DEBUG_RUN_MODE[]="RunConfiguration.DebugRunMode";
const char CMAKE_DEBUG_RUN_MODE[]="RunConfiguration.CmakeDebugRunMode"; const char CMAKE_DEBUG_RUN_MODE[]="RunConfiguration.CmakeDebugRunMode";
const char DAP_GDB_DEBUG_RUN_MODE[]="RunConfiguration.DapGdbDebugRunMode";
const char QML_PROFILER_RUN_MODE[]="RunConfiguration.QmlProfilerRunMode"; const char QML_PROFILER_RUN_MODE[]="RunConfiguration.QmlProfilerRunMode";
const char QML_PROFILER_RUNNER[]="RunConfiguration.QmlProfilerRunner"; const char QML_PROFILER_RUNNER[]="RunConfiguration.QmlProfilerRunner";
const char QML_PREVIEW_RUN_MODE[]="RunConfiguration.QmlPreviewRunMode"; const char QML_PREVIEW_RUN_MODE[]="RunConfiguration.QmlPreviewRunMode";