From b6c7c597c2470ec4aae697afe231cdd7a70d48e8 Mon Sep 17 00:00:00 2001
From: Friedemann Kleint <Friedemann.Kleint@nokia.com>
Date: Fri, 5 Feb 2010 10:23:55 +0100
Subject: [PATCH] Debugger: Introduce engine capability flags to enable actions
 correctly. Reviewed-by: hjk

---
 src/plugins/debugger/cdb/cdbdebugengine.cpp |  5 +++++
 src/plugins/debugger/cdb/cdbdebugengine.h   |  1 +
 src/plugins/debugger/debuggerconstants.h    | 13 +++++++++++++
 src/plugins/debugger/debuggermanager.cpp    | 20 ++++++++++++++++----
 src/plugins/debugger/debuggermanager.h      |  1 +
 src/plugins/debugger/gdb/gdbengine.cpp      |  7 +++++++
 src/plugins/debugger/gdb/gdbengine.h        |  4 +---
 src/plugins/debugger/idebuggerengine.h      |  2 +-
 src/plugins/debugger/moduleswindow.cpp      | 14 ++++++++------
 src/plugins/debugger/registerwindow.cpp     |  7 ++++++-
 src/plugins/debugger/stackwindow.cpp        |  3 +++
 src/plugins/debugger/watchwindow.cpp        |  6 ++++--
 12 files changed, 66 insertions(+), 17 deletions(-)

diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp
index e7c7dc49299..f844a2379b3 100644
--- a/src/plugins/debugger/cdb/cdbdebugengine.cpp
+++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp
@@ -1499,6 +1499,11 @@ void CdbDebugEngine::syncDebuggerPaths()
     }
 }
 
+unsigned CdbDebugEngine::debuggerCapabilities() const
+{
+    return DisassemblerCapability | RegisterCapability | ShowMemoryCapability;
+}
+
 // Accessed by DebuggerManager
 IDebuggerEngine *createWinEngine(DebuggerManager *parent,
                                  bool cmdLineEnabled,
diff --git a/src/plugins/debugger/cdb/cdbdebugengine.h b/src/plugins/debugger/cdb/cdbdebugengine.h
index 1085a71de75..9265ce757f2 100644
--- a/src/plugins/debugger/cdb/cdbdebugengine.h
+++ b/src/plugins/debugger/cdb/cdbdebugengine.h
@@ -67,6 +67,7 @@ public:
     virtual void exitDebugger();
     virtual void detachDebugger();
     virtual void updateWatchData(const WatchData &data);
+    virtual unsigned debuggerCapabilities() const;
 
     virtual void stepExec();
     virtual void stepOutExec();
diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h
index 381ea9cf953..2f9b2554434 100644
--- a/src/plugins/debugger/debuggerconstants.h
+++ b/src/plugins/debugger/debuggerconstants.h
@@ -109,6 +109,19 @@ enum DebuggerStartMode
     StartRemote            // Start and attach to a remote process
 };
 
+enum DebuggerCapabilities
+{
+    ReverseSteppingCapability = 0x1,
+    SnapshotCapability = 0x2,
+    AutoDerefPointersCapability = 0x4,
+    DisassemblerCapability = 0x80,
+    RegisterCapability = 0x10,
+    ShowMemoryCapability = 0x20,
+    JumpToLineCapability = 0x40,
+    ReloadModuleCapability = 0x80,
+    ReloadModuleSymbolsCapability = 0x100,
+};
+
 enum LogChannel
 {
     LogInput,               // Used for user input
diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp
index 1586e00b848..4e88a793225 100644
--- a/src/plugins/debugger/debuggermanager.cpp
+++ b/src/plugins/debugger/debuggermanager.cpp
@@ -1051,6 +1051,10 @@ void DebuggerManager::startNewDebugger(const DebuggerStartParametersPtr &sp)
     setState(EngineStarting);
     connect(d->m_engine, SIGNAL(startFailed()), this, SLOT(startFailed()));
     d->m_engine->startDebugger(d->m_startParameters);
+
+    const unsigned engineCapabilities = d->m_engine->debuggerCapabilities();
+    theDebuggerAction(OperateByInstruction)->setEnabled(engineCapabilities & DisassemblerCapability);
+    d->m_actions.reverseDirectionAction->setEnabled(engineCapabilities & ReverseSteppingCapability);
 }
 
 void DebuggerManager::startFailed()
@@ -1717,10 +1721,12 @@ void DebuggerManager::setState(DebuggerState state, bool forced)
     if (stopped)
         QApplication::alert(mainWindow(), 3000);
 
+    const bool actionsEnabled = debuggerActionsEnabled();
+    const unsigned engineCapabilities = debuggerCapabilities();
     d->m_actions.watchAction1->setEnabled(true);
     d->m_actions.watchAction2->setEnabled(true);
     d->m_actions.breakAction->setEnabled(true);
-    d->m_actions.snapshotAction->setEnabled(stopped);
+    d->m_actions.snapshotAction->setEnabled(stopped && (engineCapabilities & SnapshotCapability));
 
     bool interruptIsExit = !running;
     if (interruptIsExit) {
@@ -1740,12 +1746,13 @@ void DebuggerManager::setState(DebuggerState state, bool forced)
     d->m_actions.stepOutAction->setEnabled(stopped);
     d->m_actions.runToLineAction->setEnabled(stopped);
     d->m_actions.runToFunctionAction->setEnabled(stopped);
-    d->m_actions.jumpToLineAction->setEnabled(stopped);
+    d->m_actions.jumpToLineAction->setEnabled(stopped &&
+                                              (engineCapabilities & JumpToLineCapability));
     d->m_actions.nextAction->setEnabled(stopped);
 
-    const bool actionsEnabled = debuggerActionsEnabled();
     theDebuggerAction(RecheckDebuggingHelpers)->setEnabled(actionsEnabled);
-    theDebuggerAction(AutoDerefPointers)->setEnabled(actionsEnabled && d->m_engine->isGdbEngine());
+    theDebuggerAction(AutoDerefPointers)->setEnabled(actionsEnabled &&
+                                                     (engineCapabilities & AutoDerefPointersCapability));
     theDebuggerAction(ExpandStack)->setEnabled(actionsEnabled);
     theDebuggerAction(ExecuteCommand)->setEnabled(d->m_state != DebuggerNotReady);
 
@@ -1787,6 +1794,11 @@ bool DebuggerManager::debuggerActionsEnabled() const
     return false;
 }
 
+unsigned DebuggerManager::debuggerCapabilities() const
+{
+    return d->m_engine ? d->m_engine->debuggerCapabilities() : 0;
+}
+
 bool DebuggerManager::checkDebugConfiguration(int toolChain,
                                               QString *errorMessage,
                                               QString *settingsCategory /* = 0 */,
diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h
index 35b5b9841d4..c8275db6f5a 100644
--- a/src/plugins/debugger/debuggermanager.h
+++ b/src/plugins/debugger/debuggermanager.h
@@ -188,6 +188,7 @@ public:
         int buttons = 0);
 
     bool debuggerActionsEnabled() const;
+    unsigned debuggerCapabilities() const;
 
     bool checkDebugConfiguration(int toolChain,
                                  QString *errorMessage,
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index a616072b318..b74130e61bc 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -1696,6 +1696,13 @@ void GdbEngine::startDebugger(const DebuggerStartParametersPtr &sp)
     m_gdbAdapter->startAdapter();
 }
 
+unsigned GdbEngine::debuggerCapabilities() const
+{
+    return ReverseSteppingCapability | SnapshotCapability | AutoDerefPointersCapability
+           | DisassemblerCapability | RegisterCapability | ShowMemoryCapability
+           | JumpToLineCapability | ReloadModuleCapability | ReloadModuleSymbolsCapability;
+}
+
 void GdbEngine::continueInferiorInternal()
 {
     QTC_ASSERT(state() == InferiorStopped || state() == InferiorStarting,
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 73560d55fa1..7afddca9d99 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -103,10 +103,8 @@ private: ////////// General Interface //////////
     virtual void addOptionPages(QList<Core::IOptionsPage*> *opts) const;
 
     virtual bool checkConfiguration(int toolChain, QString *errorMessage, QString *settingsPage= 0) const;
-
-    virtual bool isGdbEngine() const { return true; }
-
     virtual void startDebugger(const DebuggerStartParametersPtr &sp);
+    virtual unsigned debuggerCapabilities() const;
     virtual void exitDebugger();
     virtual void detachDebugger();
     virtual void shutdown();
diff --git a/src/plugins/debugger/idebuggerengine.h b/src/plugins/debugger/idebuggerengine.h
index cc0a91af282..b60e8c7fb34 100644
--- a/src/plugins/debugger/idebuggerengine.h
+++ b/src/plugins/debugger/idebuggerengine.h
@@ -118,7 +118,7 @@ public:
         { Q_UNUSED(regnr); Q_UNUSED(value); }
 
     virtual void addOptionPages(QList<Core::IOptionsPage*> *) const {}
-    virtual bool isGdbEngine() const { return false; }
+    virtual unsigned debuggerCapabilities() const { return 0; }
     virtual bool checkConfiguration(int /* toolChain */, QString * /* errorMessage */, QString * /* settingsPage */ = 0) const { return true; }
 
     virtual bool isSynchroneous() const { return false; }
diff --git a/src/plugins/debugger/moduleswindow.cpp b/src/plugins/debugger/moduleswindow.cpp
index 95229f10bb5..224319b6ac9 100644
--- a/src/plugins/debugger/moduleswindow.cpp
+++ b/src/plugins/debugger/moduleswindow.cpp
@@ -108,27 +108,29 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev)
 
     QMenu menu;
     const bool enabled = Debugger::DebuggerManager::instance()->debuggerActionsEnabled();
+    const unsigned capabilities = Debugger::DebuggerManager::instance()->debuggerCapabilities();
     QAction *act0 = new QAction(tr("Update module list"), &menu);
-    act0->setEnabled(enabled);
+    act0->setEnabled(enabled && (capabilities & ReloadModuleCapability));
     QAction *act3 = new QAction(tr("Show source files for module \"%1\"").arg(name), &menu);
-    act3->setEnabled(enabled);
+    act3->setEnabled(enabled && (capabilities & ReloadModuleCapability));
     QAction *act4 = new QAction(tr("Load symbols for all modules"), &menu);
-    act4->setEnabled(enabled);
+    act4->setEnabled(enabled && (capabilities & ReloadModuleSymbolsCapability));
     QAction *act5 = 0;
     QAction *act6 = 0;
     QAction *act7 = 0;
     if (name.isEmpty()) {
         act5 = new QAction(tr("Load symbols for module"), &menu);
+        act5->setEnabled(false);
         act6 = new QAction(tr("Edit file"), &menu);
+        act6->setEnabled(false);
         act7 = new QAction(tr("Show symbols"), &menu);
+        act7->setEnabled(false);
     } else {
         act5 = new QAction(tr("Load symbols for module \"%1\"").arg(name), &menu);
+        act5->setEnabled(capabilities & ReloadModuleSymbolsCapability);
         act6 = new QAction(tr("Edit file \"%1\"").arg(name), &menu);
         act7 = new QAction(tr("Show symbols in file \"%1\"").arg(name), &menu);
     }
-    act5->setDisabled(name.isEmpty());
-    act6->setDisabled(name.isEmpty());
-    act7->setDisabled(name.isEmpty());
 
     menu.addAction(act0);
     menu.addAction(act4);
diff --git a/src/plugins/debugger/registerwindow.cpp b/src/plugins/debugger/registerwindow.cpp
index 092efb445e2..6103d9e984d 100644
--- a/src/plugins/debugger/registerwindow.cpp
+++ b/src/plugins/debugger/registerwindow.cpp
@@ -165,7 +165,12 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev)
 {
     QMenu menu;
 
+    const unsigned engineCapabilities = m_manager->debuggerCapabilities();
+    const bool actionsEnabled = m_manager->debuggerActionsEnabled();
+
     QAction *actReload = menu.addAction(tr("Reload register listing"));
+    actReload->setEnabled(engineCapabilities & RegisterCapability);
+
     menu.addSeparator();
 
     QModelIndex idx = indexAt(ev->pos());
@@ -176,8 +181,8 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev)
         actShowMemory->setEnabled(false);
     } else {
         actShowMemory->setText(tr("Open memory editor at %1").arg(address));
+        actShowMemory->setEnabled(actionsEnabled & (engineCapabilities & ShowMemoryCapability));
     }
-    actShowMemory->setEnabled(m_manager->debuggerActionsEnabled());
     menu.addSeparator();
 
     int base = model()->data(QModelIndex(), RegisterNumberBaseRole).toInt();
diff --git a/src/plugins/debugger/stackwindow.cpp b/src/plugins/debugger/stackwindow.cpp
index d39172f1ea9..53595cc3845 100644
--- a/src/plugins/debugger/stackwindow.cpp
+++ b/src/plugins/debugger/stackwindow.cpp
@@ -96,6 +96,7 @@ void StackWindow::contextMenuEvent(QContextMenuEvent *ev)
 
     QMenu menu;
 
+    const unsigned engineCapabilities = m_manager->debuggerCapabilities();
     menu.addAction(theDebuggerAction(ExpandStack));
 
     QAction *actCopyContents = menu.addAction(tr("Copy contents to clipboard"));
@@ -107,6 +108,7 @@ void StackWindow::contextMenuEvent(QContextMenuEvent *ev)
         actShowMemory->setEnabled(false);
     } else {
         actShowMemory->setText(tr("Open memory editor at %1").arg(address));
+        actShowMemory->setEnabled(engineCapabilities & ShowMemoryCapability);
     }
 
     QAction *actShowDisassembler = menu.addAction(QString());
@@ -115,6 +117,7 @@ void StackWindow::contextMenuEvent(QContextMenuEvent *ev)
         actShowDisassembler->setEnabled(false);
     } else {
         actShowDisassembler->setText(tr("Open disassembler at %1").arg(address));
+        actShowDisassembler->setEnabled(engineCapabilities & DisassemblerCapability);
     }
 
     menu.addSeparator();
diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp
index b259c4c22e9..c23eef459b3 100644
--- a/src/plugins/debugger/watchwindow.cpp
+++ b/src/plugins/debugger/watchwindow.cpp
@@ -261,12 +261,14 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
     QAction *actSelectWidgetToWatch = menu.addAction(tr("Select widget to watch"));
 
     const bool actionsEnabled = m_manager->debuggerActionsEnabled();
+    const unsigned engineCapabilities = m_manager->debuggerCapabilities();
     const QString address = model()->data(mi0, AddressRole).toString();
     QAction *actWatchKnownMemory = 0;
     QAction *actWatchUnknownMemory = new QAction(tr("Open memory editor..."), &menu);
-    actWatchUnknownMemory->setEnabled(actionsEnabled);
+    const bool canShowMemory = engineCapabilities & ShowMemoryCapability;
+    actWatchUnknownMemory->setEnabled(actionsEnabled && canShowMemory);
 
-    if (!address.isEmpty())
+    if (canShowMemory && !address.isEmpty())
         actWatchKnownMemory = new QAction(tr("Open memory editor at %1").arg(address), &menu);
     menu.addSeparator();
 
-- 
GitLab