aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhjk <hjk@qt.io>2018-01-31 10:46:57 +0100
committerhjk <hjk@qt.io>2018-02-01 10:20:33 +0000
commit7c417204792fd3c023cf389693d3b3fba8712167 (patch)
tree72f7a4314a164e2bd92bf6eb40a2b4ccd86302f2
parent46ad21a7968b7ef77d5328064522a414363e38ad (diff)
Debugger: Allow disabling individual breakpoint locations
... for breakpoints that resolve to multiple locations, like templates. Toggling is done via the the breakpoint view context menu, for now only available with GDB and not persistent. Change-Id: I098ae13a5518e9f671c647680f8bd4413e7e5ccc Reviewed-by: Christian Stenger <christian.stenger@qt.io>
-rw-r--r--src/plugins/debugger/breakhandler.cpp65
-rw-r--r--src/plugins/debugger/debuggerconstants.h3
-rw-r--r--src/plugins/debugger/debuggerengine.cpp5
-rw-r--r--src/plugins/debugger/debuggerengine.h1
-rw-r--r--src/plugins/debugger/gdb/gdbengine.cpp7
-rw-r--r--src/plugins/debugger/gdb/gdbengine.h1
6 files changed, 68 insertions, 14 deletions
diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp
index 3488be4304..bae65fe320 100644
--- a/src/plugins/debugger/breakhandler.cpp
+++ b/src/plugins/debugger/breakhandler.cpp
@@ -73,11 +73,16 @@ using namespace Utils;
namespace Debugger {
namespace Internal {
-class LocationItem : public TreeItem
+class LocationItem : public TypedTreeItem<TreeItem, BreakpointItem>
{
public:
- QVariant data(int column, int role) const
+ QVariant data(int column, int role) const final
{
+ if (role == Qt::DecorationRole && column == 0) {
+ return params.enabled ? Icons::BREAKPOINT.icon()
+ : Icons::BREAKPOINT_DISABLED.icon();
+ }
+
if (role == Qt::DisplayRole) {
switch (column) {
case BreakpointNumberColumn:
@@ -1951,20 +1956,35 @@ bool BreakHandler::setData(const QModelIndex &idx, const QVariant &value, int ro
bool BreakHandler::contextMenuEvent(const ItemViewEvent &ev)
{
const QModelIndexList selectedIndices = ev.selectedRows();
- const Breakpoints selectedItems = findBreakpointsByIndex(selectedIndices);
- const bool enabled = selectedItems.isEmpty() || selectedItems.at(0).isEnabled();
+
+ const Breakpoints selectedBreakpoints = findBreakpointsByIndex(selectedIndices);
+ const bool breakpointsEnabled = selectedBreakpoints.isEmpty() || selectedBreakpoints.at(0).isEnabled();
+
+ QList<LocationItem *> selectedLocations;
+ bool handlesIndividualLocations = false;
+ for (const QModelIndex &index : selectedIndices) {
+ if (LocationItem *location = itemForIndexAtLevel<2>(index)) {
+ if (selectedLocations.contains(location))
+ continue;
+ selectedLocations.append(location);
+ DebuggerEngine *engine = location->parent()->m_engine;
+ if (engine && engine->hasCapability(BreakIndividualLocationsCapability))
+ handlesIndividualLocations = true;
+ }
+ }
+ const bool locationsEnabled = selectedLocations.isEmpty() || selectedLocations.at(0)->params.enabled;
auto menu = new QMenu;
addAction(menu, tr("Add Breakpoint..."), true, [this] { addBreakpoint(); });
addAction(menu, tr("Delete Selected Breakpoints"),
- !selectedItems.isEmpty(),
- [this, selectedItems] { deleteBreakpoints(selectedItems); });
+ !selectedBreakpoints.isEmpty(),
+ [this, selectedBreakpoints] { deleteBreakpoints(selectedBreakpoints); });
addAction(menu, tr("Edit Selected Breakpoints..."),
- !selectedItems.isEmpty(),
- [this, selectedItems, ev] { editBreakpoints(selectedItems, ev.view()); });
+ !selectedBreakpoints.isEmpty(),
+ [this, selectedBreakpoints, ev] { editBreakpoints(selectedBreakpoints, ev.view()); });
// FIXME BP: m_engine->threadsHandler()->currentThreadId();
@@ -1979,11 +1999,30 @@ bool BreakHandler::contextMenuEvent(const ItemViewEvent &ev)
// });
addAction(menu,
- selectedItems.size() > 1
- ? enabled ? tr("Disable Selected Breakpoints") : tr("Enable Selected Breakpoints")
- : enabled ? tr("Disable Breakpoint") : tr("Enable Breakpoint"),
- !selectedItems.isEmpty(),
- [this, selectedItems, enabled] { setBreakpointsEnabled(selectedItems, !enabled); });
+ selectedBreakpoints.size() > 1
+ ? breakpointsEnabled ? tr("Disable Selected Breakpoints") : tr("Enable Selected Breakpoints")
+ : breakpointsEnabled ? tr("Disable Breakpoint") : tr("Enable Breakpoint"),
+ !selectedBreakpoints.isEmpty(),
+ [this, selectedBreakpoints, breakpointsEnabled] {
+ setBreakpointsEnabled(selectedBreakpoints, !breakpointsEnabled);
+ }
+ );
+
+ addAction(menu,
+ selectedLocations.size() > 1
+ ? locationsEnabled ? tr("Disable Selected Locations") : tr("Enable Selected Locations")
+ : locationsEnabled ? tr("Disable Location") : tr("Enable Location"),
+ !selectedLocations.isEmpty() && handlesIndividualLocations,
+ [this, selectedLocations, locationsEnabled] {
+ for (LocationItem *location : selectedLocations) {
+ location->params.enabled = !locationsEnabled;
+ location->update();
+ BreakpointItem *bp = location->parent();
+ if (bp->m_engine)
+ bp->m_engine->enableSubBreakpoint(location->params.id.toString(), !locationsEnabled);
+ }
+ }
+ );
menu->addSeparator();
diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h
index 9871bcad1a..f688662f65 100644
--- a/src/plugins/debugger/debuggerconstants.h
+++ b/src/plugins/debugger/debuggerconstants.h
@@ -156,7 +156,8 @@ enum DebuggerCapabilities
WatchComplexExpressionsCapability = 1 << 26, // Used to filter out challenges for cdb.
AdditionalQmlStackCapability = 1 << 27, //!< C++ debugger engine is able to retrieve QML stack as well.
ResetInferiorCapability = 1 << 28, //!< restart program while debugging
- NativeMixedCapability = 1 << 29
+ NativeMixedCapability = 1 << 29,
+ BreakIndividualLocationsCapability= 1 << 30 //!< Allows to enable/disable individual location for multi-location bps
};
enum LogChannel
diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp
index df7b79b7f9..a61f5d2da0 100644
--- a/src/plugins/debugger/debuggerengine.cpp
+++ b/src/plugins/debugger/debuggerengine.cpp
@@ -1421,6 +1421,11 @@ void DebuggerEngine::changeBreakpoint(Breakpoint bp)
QTC_CHECK(false);
}
+void DebuggerEngine::enableSubBreakpoint(const QString &, bool)
+{
+ QTC_CHECK(false);
+}
+
void DebuggerEngine::assignValueInDebugger(WatchItem *,
const QString &, const QVariant &)
{
diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h
index 75d87dcedd..ee91ef009c 100644
--- a/src/plugins/debugger/debuggerengine.h
+++ b/src/plugins/debugger/debuggerengine.h
@@ -314,6 +314,7 @@ public:
virtual void insertBreakpoint(Breakpoint bp); // FIXME: make pure
virtual void removeBreakpoint(Breakpoint bp); // FIXME: make pure
virtual void changeBreakpoint(Breakpoint bp); // FIXME: make pure
+ virtual void enableSubBreakpoint(const QString &locid, bool on);
virtual bool acceptsDebuggerCommands() const { return true; }
virtual void executeDebuggerCommand(const QString &command, DebuggerLanguages languages);
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 62837bbf42..7b8ee095ce 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -1835,6 +1835,7 @@ bool GdbEngine::hasCapability(unsigned cap) const
| ReloadModuleSymbolsCapability
| BreakOnThrowAndCatchCapability
| BreakConditionCapability
+ | BreakIndividualLocationsCapability
| TracePointCapability
| ReturnFromFunctionCapability
| CreateFullBacktraceCapability
@@ -2704,6 +2705,12 @@ void GdbEngine::changeBreakpoint(Breakpoint bp)
runCommand(cmd);
}
+void GdbEngine::enableSubBreakpoint(const QString &locId, bool on)
+{
+ DebuggerCommand cmd((on ? "-break-enable " : "-break-disable ") + locId);
+ runCommand(cmd);
+}
+
void GdbEngine::removeBreakpoint(Breakpoint bp)
{
QTC_CHECK(bp.state() == BreakpointRemoveRequested);
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 1768935169..c1901ad400 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -197,6 +197,7 @@ private: ////////// General Interface //////////
void insertBreakpoint(Breakpoint bp) final;
void removeBreakpoint(Breakpoint bp) final;
void changeBreakpoint(Breakpoint bp) final;
+ void enableSubBreakpoint(const QString &locId, bool on) final;
void executeStep() final;
void executeStepOut() final;