From 90657a496bb83377c01662a434d6edc19a059033 Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Wed, 24 Nov 2010 11:44:43 +0100
Subject: [PATCH] debugger: small usability fixes for dissassembler, breakpoint
 view, location

---
 src/plugins/debugger/breakhandler.cpp   |  24 ++++--
 src/plugins/debugger/breakpoint.cpp     |  26 +++---
 src/plugins/debugger/breakwindow.cpp    | 110 ++++++++++--------------
 src/plugins/debugger/breakwindow.h      |   9 +-
 src/plugins/debugger/debuggeragents.cpp |  18 ++--
 src/plugins/debugger/debuggeragents.h   |   2 +-
 src/plugins/debugger/debuggerengine.cpp |  14 +--
 src/plugins/debugger/debuggerplugin.cpp |  69 +++++++--------
 src/plugins/debugger/gdb/gdbengine.cpp  |  34 +++++---
 src/plugins/debugger/stackwindow.cpp    |   2 +-
 10 files changed, 155 insertions(+), 153 deletions(-)

diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp
index f6e4fc6d148..103598715bf 100644
--- a/src/plugins/debugger/breakhandler.cpp
+++ b/src/plugins/debugger/breakhandler.cpp
@@ -34,6 +34,7 @@
 #include "debuggercore.h"
 #include "debuggerengine.h"
 #include "debuggerstringutils.h"
+#include "stackframe.h"
 
 #include <utils/qtcassert.h>
 
@@ -140,7 +141,7 @@ BreakpointId BreakHandler::findSimilarBreakpoint(const BreakpointResponse &needl
         const BreakpointId id = it.key();
         const BreakpointParameters &data = it->data;
         const BreakpointResponse &response = it->response;
-        qDebug() << "COMPARING " << data.toString() << " WITH " << needle.toString();
+        //qDebug() << "COMPARING " << data.toString() << " WITH " << needle.toString();
         if (response.number && response.number == needle.number)
             return id;
 
@@ -353,10 +354,10 @@ BreakpointId BreakHandler::findBreakpointByIndex(const QModelIndex &index) const
 
 BreakpointIds BreakHandler::findBreakpointsByIndex(const QList<QModelIndex> &list) const
 {
-    BreakpointIds ids;
+    QSet<BreakpointId> ids;
     foreach (const QModelIndex &index, list)
-        ids.append(findBreakpointByIndex(index));
-    return ids;
+        ids.insert(findBreakpointByIndex(index));
+    return ids.toList();
 }
 
 Qt::ItemFlags BreakHandler::flags(const QModelIndex &index) const
@@ -467,7 +468,7 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
             if (role == Qt::DisplayRole) {
                 QString displayValue;
                 const quint64 address =
-                    data.isWatchpoint() ? data.address : response.address;
+                    it->isPending() ? data.address : response.address;
                 if (address)
                     displayValue += QString::fromAscii("0x%1").arg(address, 0, 16);
                 if (!response.extra.isEmpty()) {
@@ -842,8 +843,17 @@ void BreakHandler::gotoLocation(BreakpointId id) const
 {
     ConstIterator it = m_storage.find(id);
     QTC_ASSERT(it != m_storage.end(), return);
-    debuggerCore()->gotoLocation(
-        it->data.fileName, it->data.lineNumber, false);
+    if (it->data.type == BreakpointByAddress) {
+        StackFrame frame;
+        frame.address = it->data.address;
+        DebuggerEngine *engine = debuggerCore()->currentEngine();
+        if (engine)
+            engine->gotoLocation(frame, false);
+    } else {
+        const QString fileName = it->markerFileName();
+        const int lineNumber = it->markerLineNumber();
+        debuggerCore()->gotoLocation(fileName, lineNumber, false);
+    }
 }
 
 void BreakHandler::updateLineNumberFromMarker(BreakpointId id, int lineNumber)
diff --git a/src/plugins/debugger/breakpoint.cpp b/src/plugins/debugger/breakpoint.cpp
index 0215d975ec3..7ad027e2b83 100644
--- a/src/plugins/debugger/breakpoint.cpp
+++ b/src/plugins/debugger/breakpoint.cpp
@@ -74,13 +74,13 @@ QString BreakpointParameters::toString() const
 {
     QString result;
     QTextStream ts(&result);
-    ts << fileName;
-    ts << condition;
-    ts << ignoreCount;
-    ts << lineNumber;
-    ts << address;
-    ts << functionName;
-    ts << useFullPath;
+    ts << " FileName: " << fileName;
+    ts << " Condition: " << condition;
+    ts << " IgnoreCount: " << ignoreCount;
+    ts << " LineNumber: " << lineNumber;
+    ts << " Address: " << address;
+    ts << " FunctionName: " << functionName;
+    ts << " UseFullPath: " << useFullPath;
     return result;
 }
 
@@ -99,12 +99,12 @@ QString BreakpointResponse::toString() const
 {
     QString result;
     QTextStream ts(&result);
-    ts << number;
-    ts << pending;
-    ts << fullName;
-    ts << multiple;
-    ts << extra;
-    ts << correctedLineNumber;
+    ts << " Number: " << number;
+    ts << " Pending: " << pending;
+    ts << " FullName: " << fullName;
+    ts << " Multiple: " << multiple;
+    ts << " Extra: " << extra;
+    ts << " CorrectedLineNumber: " << correctedLineNumber;
     return result + BreakpointParameters::toString();
 }
 
diff --git a/src/plugins/debugger/breakwindow.cpp b/src/plugins/debugger/breakwindow.cpp
index 7e7bccdbc26..f775ddddebb 100644
--- a/src/plugins/debugger/breakwindow.cpp
+++ b/src/plugins/debugger/breakwindow.cpp
@@ -335,15 +335,6 @@ void BreakWindow::showAddressColumn(bool on)
     setColumnHidden(7, !on);
 }
 
-static QModelIndexList normalizeIndexes(const QModelIndexList &list)
-{
-    QModelIndexList res;
-    foreach (const QModelIndex &index, list)
-        if (index.column() == 0)
-            res.append(index);
-    return res;
-}
-
 void BreakWindow::keyPressEvent(QKeyEvent *ev)
 {
     if (ev->key() == Qt::Key_Delete) {
@@ -351,8 +342,11 @@ void BreakWindow::keyPressEvent(QKeyEvent *ev)
         QTC_ASSERT(sm, return);
         QModelIndexList si = sm->selectedIndexes();
         if (si.isEmpty())
-            si.append(currentIndex().sibling(currentIndex().row(), 0));
-        deleteBreakpoints(normalizeIndexes(si));
+            si.append(currentIndex());
+        const BreakpointIds ids = breakHandler()->findBreakpointsByIndex(si);
+        int row = qMin(model()->rowCount() - ids.size() - 1, currentIndex().row());
+        deleteBreakpoints(ids);
+        setCurrentIndex(si.at(0).sibling(row, 0));
     }
     QTreeView::keyPressEvent(ev);
 }
@@ -365,8 +359,10 @@ void BreakWindow::resizeEvent(QResizeEvent *ev)
 void BreakWindow::mouseDoubleClickEvent(QMouseEvent *ev)
 {
     QModelIndex indexUnderMouse = indexAt(ev->pos());
-    if (indexUnderMouse.isValid() && indexUnderMouse.column() >= 4)
-        editBreakpoints(QModelIndexList() << indexUnderMouse);
+    if (indexUnderMouse.isValid() && indexUnderMouse.column() >= 4) {
+        BreakpointId id = breakHandler()->findBreakpointByIndex(indexUnderMouse);
+        editBreakpoints(BreakpointIds() << id);
+    }
     QTreeView::mouseDoubleClickEvent(ev);
 }
 
@@ -375,34 +371,35 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
     QMenu menu;
     QItemSelectionModel *sm = selectionModel();
     QTC_ASSERT(sm, return);
-    QModelIndexList si = sm->selectedIndexes();
+    QModelIndexList selectedIndices = sm->selectedIndexes();
     QModelIndex indexUnderMouse = indexAt(ev->pos());
-    if (si.isEmpty() && indexUnderMouse.isValid())
-        si.append(indexUnderMouse.sibling(indexUnderMouse.row(), 0));
-    si = normalizeIndexes(si);
+    if (selectedIndices.isEmpty() && indexUnderMouse.isValid())
+        selectedIndices.append(indexUnderMouse);
+
+    BreakHandler *handler = breakHandler();
+    BreakpointIds selectedIds = handler->findBreakpointsByIndex(selectedIndices);
 
     const int rowCount = model()->rowCount();
     const unsigned engineCapabilities = BreakOnThrowAndCatchCapability;
-    BreakHandler *handler = breakHandler();
     // FIXME BP:    model()->data(QModelIndex(), EngineCapabilitiesRole).toUInt();
 
     QAction *deleteAction = new QAction(tr("Delete Breakpoint"), &menu);
-    deleteAction->setEnabled(si.size() > 0);
+    deleteAction->setEnabled(!selectedIds.isEmpty());
 
     QAction *deleteAllAction = new QAction(tr("Delete All Breakpoints"), &menu);
     deleteAllAction->setEnabled(model()->rowCount() > 0);
 
     // Delete by file: Find indices of breakpoints of the same file.
     QAction *deleteByFileAction = 0;
-    QList<QModelIndex> breakPointsOfFile;
+    BreakpointIds breakpointsInFile;
     if (indexUnderMouse.isValid()) {
         const QModelIndex index = indexUnderMouse.sibling(indexUnderMouse.row(), 2);
-        const QString file = model()->data(index).toString();
+        const QString file = index.data().toString();
         if (!file.isEmpty()) {
             for (int i = 0; i < rowCount; i++)
-                if (model()->data(model()->index(i, 2)).toString() == file)
-                    breakPointsOfFile.push_back(model()->index(i, 2));
-            if (breakPointsOfFile.size() > 1) {
+                if (index.data().toString() == file)
+                    breakpointsInFile.append(handler->findBreakpointByIndex(index));
+            if (breakpointsInFile.size() > 1) {
                 deleteByFileAction =
                     new QAction(tr("Delete Breakpoints of \"%1\"").arg(file), &menu);
                 deleteByFileAction->setEnabled(true);
@@ -425,7 +422,7 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
 
     QAction *editBreakpointAction =
         new QAction(tr("Edit Breakpoint..."), &menu);
-    editBreakpointAction->setEnabled(si.size() > 0);
+    editBreakpointAction->setEnabled(!selectedIds.isEmpty());
 
     int threadId = 0;
     // FIXME BP: m_engine->threadsHandler()->currentThreadId();
@@ -433,18 +430,15 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
         ?  tr("Associate Breakpoint With All Threads")
         :  tr("Associate Breakpoint With Thread %1").arg(threadId);
     QAction *associateBreakpointAction = new QAction(associateTitle, &menu);
-    associateBreakpointAction->setEnabled(si.size() > 0);
+    associateBreakpointAction->setEnabled(!selectedIds.isEmpty());
 
     QAction *synchronizeAction =
         new QAction(tr("Synchronize Breakpoints"), &menu);
     synchronizeAction->setEnabled(debuggerCore()->hasSnapshots());
 
-    QModelIndex idx0 = (si.size() ? si.front() : QModelIndex());
-    const BreakpointId id = handler->findBreakpointByIndex(idx0);
+    bool enabled = selectedIds.isEmpty() || handler->isEnabled(selectedIds.at(0));
 
-    bool enabled = si.isEmpty() || handler->isEnabled(id);
-
-    const QString str5 = si.size() > 1
+    const QString str5 = selectedIds.size() > 1
         ? enabled
             ? tr("Disable Selected Breakpoints")
             : tr("Enable Selected Breakpoints")
@@ -452,7 +446,7 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
             ? tr("Disable Breakpoint")
             : tr("Enable Breakpoint");
     QAction *toggleEnabledAction = new QAction(str5, &menu);
-    toggleEnabledAction->setEnabled(si.size() > 0);
+    toggleEnabledAction->setEnabled(!selectedIds.isEmpty());
 
     QAction *addBreakpointAction =
         new QAction(tr("Add Breakpoint..."), this);
@@ -486,27 +480,24 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
 
     QAction *act = menu.exec(ev->globalPos());
 
-    if (act == deleteAction) {
-        deleteBreakpoints(si);
-    } else if (act == deleteAllAction) {
-        QList<QModelIndex> allRows;
-        for (int i = 0; i < rowCount; i++)
-            allRows.push_back(model()->index(i, 0));
-        deleteBreakpoints(allRows);
-    }  else if (act == deleteByFileAction)
-        deleteBreakpoints(breakPointsOfFile);
+    if (act == deleteAction)
+        deleteBreakpoints(selectedIds);
+    else if (act == deleteAllAction)
+        deleteBreakpoints(handler->allBreakpointIds());
+    else if (act == deleteByFileAction)
+        deleteBreakpoints(breakpointsInFile);
     else if (act == adjustColumnAction)
         resizeColumnsToContents();
     else if (act == alwaysAdjustAction)
         setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
     else if (act == editBreakpointAction)
-        editBreakpoints(si);
+        editBreakpoints(selectedIds);
     else if (act == associateBreakpointAction)
-        associateBreakpoint(si, threadId);
+        associateBreakpoint(selectedIds, threadId);
     else if (act == synchronizeAction)
         ; //synchronizeBreakpoints();
     else if (act == toggleEnabledAction)
-        setBreakpointsEnabled(si, !enabled);
+        setBreakpointsEnabled(selectedIds, !enabled);
     else if (act == addBreakpointAction)
         addBreakpoint();
     else if (act == breakAtThrowAction)
@@ -515,24 +506,17 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
         handler->appendBreakpoint(BreakpointParameters(BreakpointAtCatch));
 }
 
-void BreakWindow::setBreakpointsEnabled(const QModelIndexList &list, bool enabled)
+void BreakWindow::setBreakpointsEnabled(const BreakpointIds &ids, bool enabled)
 {
     BreakHandler *handler = breakHandler();
-    foreach (const BreakpointId id, handler->findBreakpointsByIndex(list))
+    foreach (const BreakpointId id, ids)
         handler->setEnabled(id, enabled);
 }
 
-void BreakWindow::setBreakpointsFullPath(const QModelIndexList &list, bool fullpath)
+void BreakWindow::deleteBreakpoints(const BreakpointIds &ids)
 {
     BreakHandler *handler = breakHandler();
-    foreach (const BreakpointId id, handler->findBreakpointsByIndex(list))
-       handler->setUseFullPath(id, fullpath);
-}
-
-void BreakWindow::deleteBreakpoints(const QModelIndexList &list)
-{
-    BreakHandler *handler = breakHandler();
-    foreach (const BreakpointId id, handler->findBreakpointsByIndex(list))
+    foreach (const BreakpointId id, ids)
        handler->removeBreakpoint(id);
 }
 
@@ -552,15 +536,13 @@ void BreakWindow::addBreakpoint()
         breakHandler()->appendBreakpoint(data);
 }
 
-void BreakWindow::editBreakpoints(const QModelIndexList &list)
+void BreakWindow::editBreakpoints(const BreakpointIds &ids)
 {
-    QTC_ASSERT(!list.isEmpty(), return);
+    QTC_ASSERT(!ids.isEmpty(), return);
 
-    BreakHandler *handler = breakHandler();
-    const BreakpointIds ids = handler->findBreakpointsByIndex(list);
     const BreakpointId id = ids.at(0);
 
-    if (list.size() == 1) {
+    if (ids.size() == 1) {
         editBreakpoint(id, this);
         return;
     }
@@ -573,6 +555,7 @@ void BreakWindow::editBreakpoints(const QModelIndexList &list)
     ui.lineEditIgnoreCount->setValidator(
         new QIntValidator(0, 2147483647, ui.lineEditIgnoreCount));
 
+    BreakHandler *handler = breakHandler();
     const QString oldCondition = QString::fromLatin1(handler->condition(id));
     const QString oldIgnoreCount = QString::number(handler->ignoreCount(id));
     const QString oldThreadSpec = QString::fromLatin1(handler->threadSpec(id));
@@ -588,23 +571,22 @@ void BreakWindow::editBreakpoints(const QModelIndexList &list)
     const QString newIgnoreCount = ui.lineEditIgnoreCount->text();
     const QString newThreadSpec = ui.lineEditThreadSpec->text();
 
-    // Unchanged -> cancel
     if (newCondition == oldCondition && newIgnoreCount == oldIgnoreCount
             && newThreadSpec == oldThreadSpec)
         return;
 
-    foreach (const BreakpointId id, handler->findBreakpointsByIndex(list)) {
+    foreach (const BreakpointId id, ids) {
         handler->setCondition(id, newCondition.toLatin1());
         handler->setIgnoreCount(id, newIgnoreCount.toInt());
         handler->setThreadSpec(id, newThreadSpec.toLatin1());
     }
 }
 
-void BreakWindow::associateBreakpoint(const QModelIndexList &list, int threadId)
+void BreakWindow::associateBreakpoint(const BreakpointIds &ids, int threadId)
 {
     BreakHandler *handler = breakHandler();
     QByteArray spec = QByteArray::number(threadId);
-    foreach (const BreakpointId id, handler->findBreakpointsByIndex(list))
+    foreach (const BreakpointId id, ids)
         handler->setThreadSpec(id, spec);
 }
 
diff --git a/src/plugins/debugger/breakwindow.h b/src/plugins/debugger/breakwindow.h
index 8973729e597..043ef8c6883 100644
--- a/src/plugins/debugger/breakwindow.h
+++ b/src/plugins/debugger/breakwindow.h
@@ -61,12 +61,11 @@ private:
     void keyPressEvent(QKeyEvent *ev);
     void mouseDoubleClickEvent(QMouseEvent *ev);
 
-    void deleteBreakpoints(const QModelIndexList &list);
+    void deleteBreakpoints(const BreakpointIds &ids);
     void addBreakpoint();
-    void editBreakpoints(const QModelIndexList &list);
-    void associateBreakpoint(const QModelIndexList &list, int thread);
-    void setBreakpointsEnabled(const QModelIndexList &list, bool enabled);
-    void setBreakpointsFullPath(const QModelIndexList &list, bool fullpath);
+    void editBreakpoints(const BreakpointIds &ids);
+    void associateBreakpoint(const BreakpointIds &ids, int thread);
+    void setBreakpointsEnabled(const BreakpointIds &ids, bool enabled);
 
     bool m_alwaysResizeColumnsToContents;
 };
diff --git a/src/plugins/debugger/debuggeragents.cpp b/src/plugins/debugger/debuggeragents.cpp
index 6d83added11..e16178416ad 100644
--- a/src/plugins/debugger/debuggeragents.cpp
+++ b/src/plugins/debugger/debuggeragents.cpp
@@ -210,6 +210,7 @@ struct DisassemblerViewAgentPrivate
     QPointer<TextEditor::ITextEditor> editor;
     StackFrame frame;
     bool tryMixed;
+    bool setMarker;
     QPointer<DebuggerEngine> engine;
     LocationMark2 *locationMark;
     QHash<QString, QString> cache;
@@ -219,6 +220,7 @@ struct DisassemblerViewAgentPrivate
 DisassemblerViewAgentPrivate::DisassemblerViewAgentPrivate() :
     editor(0),
     tryMixed(true),
+    setMarker(true),
     locationMark(new LocationMark2),
     mimeType(_("text/x-qtcreator-generic-asm"))
 {
@@ -279,9 +281,11 @@ bool DisassemblerViewAgent::isMixed() const
         && d->frame.function != _("??");
 }
 
-void DisassemblerViewAgent::setFrame(const StackFrame &frame, bool tryMixed)
+void DisassemblerViewAgent::setFrame(const StackFrame &frame, bool tryMixed,
+    bool setMarker)
 {
     d->frame = frame;
+    d->setMarker = setMarker;
     d->tryMixed = tryMixed;
     if (isMixed()) {
         QHash<QString, QString>::ConstIterator it = d->cache.find(frameKey(frame));
@@ -342,7 +346,7 @@ static QPair<int, int> lineNumberOfAddress(const QString &disassembly, quint64 a
 
     const int size = disassembly.size();
     for (int lineNumber = 1; pos < size; lineNumber++) {
-        int endOfLinePos = disassembly.indexOf(newLine, pos + 1);
+        int endOfLinePos = disassembly.indexOf(newLine, pos);
         if (endOfLinePos == -1)
             endOfLinePos = size;
         const QString line = disassembly.mid(pos, endOfLinePos - pos);
@@ -382,12 +386,15 @@ void DisassemblerViewAgent::setContents(const QString &contents)
         plainTextEdit->setReadOnly(true);
     }
 
-    d->editor->markableInterface()->removeMark(d->locationMark);
+    if (d->setMarker)
+        d->editor->markableInterface()->removeMark(d->locationMark);
     d->editor->setDisplayName(_("Disassembler (%1)").arg(d->frame.function));
 
-    const QPair<int, int> lineNumberPos = lineNumberOfAddress(contents, d->frame.address);
+    const QPair<int, int> lineNumberPos =
+        lineNumberOfAddress(contents, d->frame.address);
     if (lineNumberPos.first > 0) {
-        d->editor->markableInterface()->addMark(d->locationMark, lineNumberPos.first);
+        if (d->setMarker)
+            d->editor->markableInterface()->addMark(d->locationMark, lineNumberPos.first);
         if (plainTextEdit) {
             QTextCursor tc = plainTextEdit->textCursor();
             tc.setPosition(lineNumberPos.second);
@@ -399,7 +406,6 @@ void DisassemblerViewAgent::setContents(const QString &contents)
 bool DisassemblerViewAgent::contentsCoversAddress(const QString &contents) const
 {
     QTC_ASSERT(d, return false);
-
     return lineNumberOfAddress(contents, d->frame.address).first > 0;
 }
 
diff --git a/src/plugins/debugger/debuggeragents.h b/src/plugins/debugger/debuggeragents.h
index da972707186..3db89008101 100644
--- a/src/plugins/debugger/debuggeragents.h
+++ b/src/plugins/debugger/debuggeragents.h
@@ -83,7 +83,7 @@ public:
     explicit DisassemblerViewAgent(Debugger::DebuggerEngine *engine);
     ~DisassemblerViewAgent();
 
-    void setFrame(const StackFrame &frame, bool tryMixed = true);
+    void setFrame(const StackFrame &frame, bool tryMixed, bool setMarker);
     const StackFrame &frame() const;
     void resetLocation();
     Q_SLOT void setContents(const QString &contents);
diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp
index 7aa5d935c51..de35125f4ea 100644
--- a/src/plugins/debugger/debuggerengine.cpp
+++ b/src/plugins/debugger/debuggerengine.cpp
@@ -516,21 +516,15 @@ void DebuggerEngine::resetLocation()
 
 void DebuggerEngine::gotoLocation(const QString &fileName, int lineNumber, bool setMarker)
 {
-    StackFrame frame;
-    frame.file = fileName;
-    frame.line = lineNumber;
-    gotoLocation(frame, setMarker);
+    debuggerCore()->gotoLocation(fileName, lineNumber, setMarker);
 }
 
 void DebuggerEngine::gotoLocation(const StackFrame &frame, bool setMarker)
 {
-    if (debuggerCore()->boolSetting(OperateByInstruction) || !frame.isUsable()) {
-        if (setMarker)
-            resetLocation();
-        d->m_disassemblerViewAgent.setFrame(frame);
-    } else {
+    if (debuggerCore()->boolSetting(OperateByInstruction) || !frame.isUsable())
+        d->m_disassemblerViewAgent.setFrame(frame, true, setMarker);
+    else
         debuggerCore()->gotoLocation(frame.file, frame.line, setMarker);
-    }
 }
 
 // Called from RunControl.
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index dec5a279757..7ccbabe6388 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -395,46 +395,13 @@ const char * const SNAPSHOT_KEY             = "Ctrl+D,Ctrl+S";
 #endif
 
 } // namespace Constants
-} // namespace Debugger
-
-
 
-static SessionManager *sessionManager()
-{
-    return ProjectExplorerPlugin::instance()->session();
-}
 
-static QToolButton *toolButton(QAction *action)
-{
-    QToolButton *button = new QToolButton;
-    button->setDefaultAction(action);
-    return button;
-}
-
-// Retrieve file name and line and optionally address
-// from the data set on the text editor context menu action.
-static bool positionFromContextActionData(const QObject *sender,
-                                          QString *fileName,
-                                          int *lineNumber,
-                                          quint64 *address = 0)
-{
-    if (const QAction *action = qobject_cast<const QAction *>(sender)) {
-        const QVariantList data = action->data().toList();
-        if (data.size() >= (address ? 3 : 2)) {
-            *fileName = data.front().toString();
-            *lineNumber = data.at(1).toInt();
-            if (address)
-                *address = data.at(2).toULongLong();
-            return true;
-        }
-    }
-    return false;
-}
-
-namespace Debugger {
 namespace Cdb {
 void addCdb2OptionPages(QList<Core::IOptionsPage*> *);
 } // namespace Cdb
+
+
 namespace Internal {
 
 // FIXME: Outdated?
@@ -450,6 +417,34 @@ void addTcfOptionPages(QList<IOptionsPage*> *opts);
 void addCdbOptionPages(QList<IOptionsPage*> *opts);
 #endif
 
+static SessionManager *sessionManager()
+{
+    return ProjectExplorerPlugin::instance()->session();
+}
+
+static QToolButton *toolButton(QAction *action)
+{
+    QToolButton *button = new QToolButton;
+    button->setDefaultAction(action);
+    return button;
+}
+
+// Retrieve file name and line and optionally address
+// from the data set on the text editor context menu action.
+static bool positionFromContextActionData(const QObject *sender,
+    QString *fileName, int *lineNumber, quint64 *address = 0)
+{
+    const QAction *action = qobject_cast<const QAction *>(sender);
+    QTC_ASSERT(action, return false);
+    const QVariantList data = action->data().toList();
+    QTC_ASSERT(data.size() == 3, return false);
+    *fileName = data.front().toString();
+    *lineNumber = data.at(1).toInt();
+    if (address)
+        *address = data.at(2).toULongLong();
+    return true;
+}
+
 struct AttachRemoteParameters
 {
     AttachRemoteParameters() : attachPid(0), winCrashEvent(0) {}
@@ -917,7 +912,7 @@ public slots:
         quint64 address;
         if (positionFromContextActionData(sender(), &fileName, &lineNumber, &address))
             m_breakHandler->toggleBreakpoint(fileName, lineNumber, address);
-     }
+    }
 
     void breakpointRemoveMarginActionTriggered()
     {
@@ -2391,7 +2386,9 @@ void DebuggerPluginPrivate::requestContextMenu(TextEditor::ITextEditor *editor,
         QString line = editor->contents()
             .section('\n', lineNumber - 1, lineNumber - 1);
         BreakpointResponse needle;
+        needle.type = BreakpointByAddress;
         needle.address = DisassemblerViewAgent::addressFromDisassemblyLine(line);
+        address = needle.address;
         needle.lineNumber = -1;
         id = breakHandler()->findSimilarBreakpoint(needle);
     } else {
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 965bb8a8eb3..4e93dfb5c1b 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -1186,8 +1186,9 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
     }
 
     // Quickly set the location marker.
-    if (lineNumber && QFileInfo(fullName).exists())
-        debuggerCore()->gotoLocation(fullName, lineNumber, true);
+    if (lineNumber && !debuggerCore()->boolSetting(OperateByInstruction)
+            && QFileInfo(fullName).exists())
+        gotoLocation(fullName, lineNumber, true);
 
     if (!m_commandsToRunOnTemporaryBreak.isEmpty()) {
         QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state())
@@ -1443,7 +1444,7 @@ void GdbEngine::handleStop1(const GdbMi &data)
     //
     // Stack
     //
-    reloadStack(false);
+    reloadStack(false); // Will trigger register reload.
 
     if (supportsThreads()) {
         int currentId = data.findChild("thread-id").data().toInt();
@@ -1458,11 +1459,6 @@ void GdbEngine::handleStop1(const GdbMi &data)
                 CB(handleThreadInfo), currentId);
         }
     }
-
-    //
-    // Registers
-    //
-    reloadRegisters();
 }
 
 void GdbEngine::handleInfoProc(const GdbResponse &response)
@@ -2886,8 +2882,7 @@ void GdbEngine::handleStackSelectThread(const GdbResponse &)
 {
     QTC_ASSERT(state() == InferiorUnrunnable || state() == InferiorStopOk, /**/);
     showStatusMessage(tr("Retrieving data for stack view..."), 3000);
-    reloadRegisters();
-    reloadStack(true);
+    reloadStack(true); // Will reload registers.
     updateLocals();
 }
 
@@ -2943,6 +2938,7 @@ void GdbEngine::handleStackListFrames(const GdbResponse &response)
         // ^error,data={msg="Previous frame identical to this frame (corrupt stack?)"
         // logstreamoutput="Previous frame identical to this frame (corrupt stack?)\n"
         //qDebug() << "LISTING STACK FAILED: " << response.toString();
+        reloadRegisters();
         return;
     }
 
@@ -4039,17 +4035,35 @@ void GdbEngine::handleFetchDisassemblerByCli(const GdbResponse &response)
             // "Dump of assembler code from 0xb7ff598f to 0xb7ff5a07:"
             GdbMi output = response.data.findChild("consolestreamoutput");
             QByteArray res;
+            QByteArray lastFunction;
             foreach (const QByteArray &line0, output.data().split('\n')) {
                 QByteArray line = line0.trimmed();
                 if (line.startsWith("=> "))
                     line = line.mid(3);
+                if (line.isEmpty())
+                    continue;
                 if (line.startsWith("Current language:"))
                     continue;
+                if (line.startsWith("Dump of assembler"))
+                    continue;
                 if (line.startsWith("The current source"))
                     continue;
                 if (line.startsWith("End of assembler"))
                     continue;
                 if (line.startsWith("0x")) {
+                    int pos1 = line.indexOf('<') + 1;
+                    int pos2 = line.indexOf('+', pos1);
+                    int pos3 = line.indexOf('>', pos1);
+                    if (pos1 < pos2 && pos2 < pos3) {
+                        QByteArray function = line.mid(pos1, pos2 - pos1);
+                        if (function != lastFunction) {
+                            res.append("\nFunction: ");
+                            res.append(function);
+                            res.append('\n');
+                            lastFunction = function;
+                        }
+                        line.replace(pos1, pos2 - pos1, "");
+                    }
                     res.append(line);
                     res.append('\n');
                     continue;
diff --git a/src/plugins/debugger/stackwindow.cpp b/src/plugins/debugger/stackwindow.cpp
index 25f5cae841e..d5bda5594bd 100644
--- a/src/plugins/debugger/stackwindow.cpp
+++ b/src/plugins/debugger/stackwindow.cpp
@@ -162,7 +162,7 @@ void StackWindow::contextMenuEvent(QContextMenuEvent *ev)
         (void) new MemoryViewAgent(currentEngine(), address);
     else if (act == actShowDisassembler) {
         DisassemblerViewAgent *agent = new DisassemblerViewAgent(engine);
-        agent->setFrame(frame);
+        agent->setFrame(frame, true, false);
     }
 }
 
-- 
GitLab