diff options
author | hjk <hjk@qt.io> | 2018-01-31 10:46:57 +0100 |
---|---|---|
committer | hjk <hjk@qt.io> | 2018-02-01 10:20:33 +0000 |
commit | 7c417204792fd3c023cf389693d3b3fba8712167 (patch) | |
tree | 72f7a4314a164e2bd92bf6eb40a2b4ccd86302f2 | |
parent | 46ad21a7968b7ef77d5328064522a414363e38ad (diff) | |
download | qt-creator-7c417204792fd3c023cf389693d3b3fba8712167.tar.gz |
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.cpp | 65 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerconstants.h | 3 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerengine.cpp | 5 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerengine.h | 1 | ||||
-rw-r--r-- | src/plugins/debugger/gdb/gdbengine.cpp | 7 | ||||
-rw-r--r-- | src/plugins/debugger/gdb/gdbengine.h | 1 |
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; |