From 7100d29f66c1ec540882912e1535247dfae6ee15 Mon Sep 17 00:00:00 2001
From: Christiaan Janssen <christiaan.janssen@nokia.com>
Date: Mon, 28 Feb 2011 10:58:21 +0100
Subject: [PATCH] QmlDebugger: user input on watches

Reviewed-by: hjk
---
 src/plugins/debugger/debuggerengine.cpp   | 10 ++++++++++
 src/plugins/debugger/debuggerengine.h     |  2 ++
 src/plugins/debugger/debuggerplugin.cpp   |  2 +-
 src/plugins/debugger/gdb/gdbengine.cpp    |  5 +++++
 src/plugins/debugger/gdb/gdbengine.h      |  1 +
 src/plugins/debugger/qml/qmlcppengine.cpp | 10 ++++++++++
 src/plugins/debugger/qml/qmlcppengine.h   |  2 ++
 src/plugins/debugger/qml/qmlengine.cpp    |  5 +++++
 src/plugins/debugger/qml/qmlengine.h      |  1 +
 src/plugins/debugger/watchhandler.cpp     |  6 +++++-
 src/plugins/debugger/watchwindow.cpp      | 17 ++++++++++++-----
 11 files changed, 54 insertions(+), 7 deletions(-)

diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp
index 754a8ade091..c6c1666b9e3 100644
--- a/src/plugins/debugger/debuggerengine.cpp
+++ b/src/plugins/debugger/debuggerengine.cpp
@@ -1311,6 +1311,16 @@ unsigned DebuggerEngine::debuggerCapabilities() const
     return 0;
 }
 
+bool DebuggerEngine::canWatchWidgets() const
+{
+    return false;
+}
+
+bool DebuggerEngine::acceptsWatchesWhileRunning() const
+{
+    return false;
+}
+
 bool DebuggerEngine::isSynchronous() const
 {
     return false;
diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h
index 60cffe51aa5..eff8ce1f269 100644
--- a/src/plugins/debugger/debuggerengine.h
+++ b/src/plugins/debugger/debuggerengine.h
@@ -180,6 +180,8 @@ public:
     virtual void setRegisterValue(int regnr, const QString &value);
     virtual void addOptionPages(QList<Core::IOptionsPage*> *) const;
     virtual unsigned debuggerCapabilities() const;
+    virtual bool canWatchWidgets() const;
+    virtual bool acceptsWatchesWhileRunning() const;
 
     virtual bool isSynchronous() const;
     virtual QByteArray qtNamespace() const;
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index 0558a5644c8..4e265350df6 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -482,7 +482,7 @@ public:
     void runEngine() {}
     void shutdownEngine() {}
     void shutdownInferior() {}
-    unsigned debuggerCapabilities() const { return 0; }
+    unsigned debuggerCapabilities() const { return AddWatcherCapability; }
     bool acceptsBreakpoint(BreakpointId) const { return false; }
     bool acceptsDebuggerCommands() const { return false; }
 };
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 606cadfc2fb..9fad46fdd76 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -1895,6 +1895,11 @@ unsigned GdbEngine::debuggerCapabilities() const
     return caps | SnapshotCapability;
 }
 
+bool GdbEngine::canWatchWidgets() const
+{
+    return true;
+}
+
 void GdbEngine::continueInferiorInternal()
 {
     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state());
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 55df525f6b4..a1613aec43d 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -110,6 +110,7 @@ private: ////////// General Interface //////////
     virtual void runEngine();
 
     virtual unsigned debuggerCapabilities() const;
+    virtual bool canWatchWidgets() const;
     virtual void detachDebugger();
     virtual void shutdownEngine();
     virtual void shutdownInferior();
diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp
index 205bc88323f..96ce6a2d4d4 100644
--- a/src/plugins/debugger/qml/qmlcppengine.cpp
+++ b/src/plugins/debugger/qml/qmlcppengine.cpp
@@ -248,6 +248,16 @@ unsigned QmlCppEngine::debuggerCapabilities() const
     return d->m_cppEngine->debuggerCapabilities();
 }
 
+bool QmlCppEngine::canWatchWidgets() const
+{
+    return d->m_activeEngine->canWatchWidgets();
+}
+
+bool QmlCppEngine::acceptsWatchesWhileRunning() const
+{
+    return d->m_activeEngine->acceptsWatchesWhileRunning();
+}
+
 bool QmlCppEngine::isSynchronous() const
 {
     return d->m_activeEngine->isSynchronous();
diff --git a/src/plugins/debugger/qml/qmlcppengine.h b/src/plugins/debugger/qml/qmlcppengine.h
index 822787b51fc..77473d1ade2 100644
--- a/src/plugins/debugger/qml/qmlcppengine.h
+++ b/src/plugins/debugger/qml/qmlcppengine.h
@@ -75,6 +75,8 @@ public:
 
     void setRegisterValue(int regnr, const QString &value);
     unsigned debuggerCapabilities() const;
+    virtual bool canWatchWidgets() const;
+    virtual bool acceptsWatchesWhileRunning() const;
 
     bool isSynchronous() const;
     QByteArray qtNamespace() const;
diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp
index b4479733a8d..176761bd8db 100644
--- a/src/plugins/debugger/qml/qmlengine.cpp
+++ b/src/plugins/debugger/qml/qmlengine.cpp
@@ -353,6 +353,11 @@ void QmlEngine::showMessage(const QString &msg, int channel, int timeout) const
     DebuggerEngine::showMessage(msg, channel, timeout);
 }
 
+bool QmlEngine::acceptsWatchesWhileRunning() const
+{
+    return true;
+}
+
 void QmlEngine::closeConnection()
 {
     disconnect(&d->m_adapter, SIGNAL(connectionStartupFailed()),
diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h
index db03bfbb27e..6c6158f86ee 100644
--- a/src/plugins/debugger/qml/qmlengine.h
+++ b/src/plugins/debugger/qml/qmlengine.h
@@ -63,6 +63,7 @@ public:
     void showMessage(const QString &msg, int channel = LogDebug,
                      int timeout = -1) const;
     void filterApplicationMessage(const QString &msg, int channel);
+    virtual bool acceptsWatchesWhileRunning() const;
 
 public slots:
     void messageReceived(const QByteArray &message);
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index 68597a20b3f..776a82dfa5d 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -811,7 +811,7 @@ Qt::ItemFlags WatchModel::flags(const QModelIndex &idx) const
 
     // Disable editing if debuggee is positively running.
     const bool isRunning = engine() && engine()->state() == InferiorRunOk;
-    if (isRunning)
+    if (isRunning && engine() && !engine()->acceptsWatchesWhileRunning())
         return notEditable;
 
     const WatchData &data = *watchItem(idx);
@@ -1186,6 +1186,10 @@ void WatchHandler::insertData(const WatchData &data)
     if (data.isSomethingNeeded() && data.iname.contains('.')) {
         MODEL_DEBUG("SOMETHING NEEDED: " << data.toString());
         if (!m_engine->isSynchronous()) {
+            WatchModel *model = modelForIName(data.iname);
+            QTC_ASSERT(model, return);
+            model->insertData(data);
+
             m_engine->updateWatchData(data);
         } else {
             m_engine->showMessage(QLatin1String("ENDLESS LOOP: SOMETHING NEEDED: ")
diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp
index 1632e655635..a2820c59535 100644
--- a/src/plugins/debugger/watchwindow.cpp
+++ b/src/plugins/debugger/watchwindow.cpp
@@ -59,6 +59,7 @@
 #include <QtGui/QMenu>
 #include <QtGui/QPainter>
 #include <QtGui/QResizeEvent>
+#include <QtGui/QInputDialog>
 
 /////////////////////////////////////////////////////////////////////
 //
@@ -361,15 +362,15 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
 
     const bool actionsEnabled = engine->debuggerActionsEnabled();
     const unsigned engineCapabilities = engine->debuggerCapabilities();
-    const bool canHandleWatches =
-        actionsEnabled && (engineCapabilities & AddWatcherCapability);
+    const bool canHandleWatches = engineCapabilities & AddWatcherCapability;
     const DebuggerState state = engine->state();
+    const bool canInsertWatches = (state==InferiorStopOk) || ((state==InferiorRunOk) && engine->acceptsWatchesWhileRunning());
 
     QMenu menu;
     QAction *actInsertNewWatchItem = menu.addAction(tr("Insert New Watch Item"));
-    actInsertNewWatchItem->setEnabled(canHandleWatches);
+    actInsertNewWatchItem->setEnabled(canHandleWatches && canInsertWatches);
     QAction *actSelectWidgetToWatch = menu.addAction(tr("Select Widget to Watch"));
-    actSelectWidgetToWatch->setEnabled(canHandleWatches);
+    actSelectWidgetToWatch->setEnabled(canHandleWatches && (engine->canWatchWidgets()));
 
     // Offer to open address pointed to or variable address.
     const bool createPointerActions = pointerValue && pointerValue != address;
@@ -497,7 +498,13 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
     if (act == actAdjustColumnWidths) {
         resizeColumnsToContents();
     } else if (act == actInsertNewWatchItem) {
-        watchExpression(QString());
+        bool ok;
+        QString newExp = QInputDialog::getText(this, tr("Enter watch expression"),
+                                   tr("Expression:"), QLineEdit::Normal,
+                                   QString(), &ok);
+        if (ok && !newExp.isEmpty()) {
+            watchExpression(newExp);
+        }
     } else if (act == actOpenMemoryEditAtVariableAddress) {
         currentEngine()->openMemoryView(address);
     } else if (act == actOpenMemoryEditAtPointerValue) {
-- 
GitLab