From fc46406fc8b58c970b9b44f66aef82f39f37f25f Mon Sep 17 00:00:00 2001
From: hjk <hjk121@nokiamail.com>
Date: Mon, 23 Jun 2014 16:33:19 +0200
Subject: [PATCH] Debugger: Allow loading dumpers from a file directly

Instead of requiring the user to add the required python
code to load them manually let him specify a file directly.
This also makes the feature accessible to LLDB which needs
a slightly different syntax.

Task-number: QTCREATORBUG-12492
Change-Id: I12621b1cea2429476b0865bcbcb739a238dcf6af
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
---
 src/plugins/debugger/debuggeractions.cpp    |  8 +++++++-
 src/plugins/debugger/debuggeractions.h      |  3 ++-
 src/plugins/debugger/gdb/gdbengine.cpp      | 17 +++++++++++++++--
 src/plugins/debugger/gdb/gdboptionspage.cpp | 18 +++++++++++++-----
 src/plugins/debugger/lldb/lldbengine.cpp    | 20 ++++++++++++++++++++
 5 files changed, 57 insertions(+), 9 deletions(-)

diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp
index 89901af73e..976453e5d2 100644
--- a/src/plugins/debugger/debuggeractions.cpp
+++ b/src/plugins/debugger/debuggeractions.cpp
@@ -404,7 +404,13 @@ DebuggerSettings::DebuggerSettings()
     item = new SavedAction(this);
     item->setSettingsKey(debugModeGroup, QLatin1String("GdbCustomDumperCommands"));
     item->setDefaultValue(QString());
-    insertItem(GdbCustomDumperCommands, item);
+    insertItem(ExtraDumperCommands, item);
+    item = new SavedAction(this);
+
+    item = new SavedAction(this);
+    item->setSettingsKey(debugModeGroup, QLatin1String("ExtraDumperFile"));
+    item->setDefaultValue(QString());
+    insertItem(ExtraDumperFile, item);
     item = new SavedAction(this);
 
     item->setSettingsKey(debugModeGroup, QLatin1String("GdbPostAttachCommands"));
diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h
index 5cf9a71550..23156f7b52 100644
--- a/src/plugins/debugger/debuggeractions.h
+++ b/src/plugins/debugger/debuggeractions.h
@@ -110,6 +110,8 @@ enum DebuggerActionCode
     RegisterForPostMortem,
     AlwaysAdjustColumnWidths,
 
+    ExtraDumperFile,     // For loading a file. Recommended.
+    ExtraDumperCommands, // To modify an existing setup.
 
     // Cdb
     CdbAdditionalArguments,
@@ -126,7 +128,6 @@ enum DebuggerActionCode
     LoadGdbDumpers,
     AttemptQuickStart,
     GdbStartupCommands,
-    GdbCustomDumperCommands,
     GdbPostAttachCommands,
     GdbWatchdogTimeout,
     AutoEnrichParameters,
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 02c142415a..b201a1ec66 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -1735,12 +1735,25 @@ void GdbEngine::handlePythonSetup(const GdbResponse &response)
 {
     QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
     if (response.resultClass == GdbResultDone) {
-        const QString commands = debuggerCore()->stringSetting(GdbCustomDumperCommands);
+        bool needSetup = false;
+
+        const QString path = debuggerCore()->stringSetting(ExtraDumperFile);
+        if (!path.isEmpty()) {
+            QFileInfo fi(path);
+            postCommand("python sys.path.insert(1, '" + fi.absolutePath().toUtf8() + "')");
+            postCommand("python from " + fi.baseName().toUtf8() + " import *");
+            needSetup = true;
+        }
+
+        const QString commands = debuggerCore()->stringSetting(ExtraDumperCommands);
         if (!commands.isEmpty()) {
             postCommand(commands.toLocal8Bit());
-            postCommand("bbsetup");
+            needSetup = true;
         }
 
+        if (needSetup)
+            postCommand("bbsetup");
+
         GdbMi data;
         data.fromStringMultiple(response.consoleStreamOutput);
         const GdbMi dumpers = data["dumpers"];
diff --git a/src/plugins/debugger/gdb/gdboptionspage.cpp b/src/plugins/debugger/gdb/gdboptionspage.cpp
index 91a77399b8..e8d914d34a 100644
--- a/src/plugins/debugger/gdb/gdboptionspage.cpp
+++ b/src/plugins/debugger/gdb/gdboptionspage.cpp
@@ -41,6 +41,7 @@
 #include <QDebug>
 #include <QFormLayout>
 #include <QLabel>
+#include <QLineEdit>
 #include <QSpinBox>
 #include <QTextEdit>
 
@@ -63,7 +64,6 @@ public:
     explicit GdbOptionsPageWidget(QWidget *parent = 0);
 
     QGroupBox *groupBoxGeneral;
-    QLabel *labelGdbWatchdogTimeout;
     QSpinBox *spinBoxGdbWatchdogTimeout;
     QCheckBox *checkBoxSkipKnownFrames;
     QCheckBox *checkBoxUseMessageBoxForSignals;
@@ -80,6 +80,7 @@ public:
     QTextEdit *textEditPostAttachCommands;
     QGroupBox *groupBoxCustomDumperCommands;
     QTextEdit *textEditCustomDumperCommands;
+    QLineEdit *extraDumperFile;
 
     //QGroupBox *groupBoxPluginDebugging;
     //QRadioButton *radioButtonAllPluginBreakpoints;
@@ -99,7 +100,7 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent)
     groupBoxGeneral = new QGroupBox(this);
     groupBoxGeneral->setTitle(GdbOptionsPage::tr("General"));
 
-    labelGdbWatchdogTimeout = new QLabel(groupBoxGeneral);
+    QLabel *labelGdbWatchdogTimeout = new QLabel(groupBoxGeneral);
     labelGdbWatchdogTimeout->setText(GdbOptionsPage::tr("GDB timeout:"));
     labelGdbWatchdogTimeout->setToolTip(GdbOptionsPage::tr(
         "The number of seconds Qt Creator will wait before it terminates\n"
@@ -221,6 +222,10 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent)
     textEditCustomDumperCommands->setAcceptRichText(false);
     textEditCustomDumperCommands->setToolTip(groupBoxCustomDumperCommands->toolTip());
 
+    extraDumperFile = new QLineEdit(groupBoxCustomDumperCommands);
+    extraDumperFile->setToolTip(GdbOptionsPage::tr(
+        "Path to a Python file containing additional data dumpers."));
+
     /*
     groupBoxPluginDebugging = new QGroupBox(q);
     groupBoxPluginDebugging->setTitle(GdbOptionsPage::tr(
@@ -250,6 +255,7 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent)
     VariableChooser::addVariableSupport(textEditCustomDumperCommands);
     VariableChooser::addVariableSupport(textEditPostAttachCommands);
     VariableChooser::addVariableSupport(textEditStartupCommands);
+    VariableChooser::addVariableSupport(extraDumperFile);
 
     QFormLayout *formLayout = new QFormLayout(groupBoxGeneral);
     formLayout->addRow(labelGdbWatchdogTimeout, spinBoxGdbWatchdogTimeout);
@@ -268,8 +274,9 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent)
     QGridLayout *postAttachLayout = new QGridLayout(groupBoxPostAttachCommands);
     postAttachLayout->addWidget(textEditPostAttachCommands, 0, 0, 1, 1);
 
-    QGridLayout *customDumperLayout = new QGridLayout(groupBoxCustomDumperCommands);
-    customDumperLayout->addWidget(textEditCustomDumperCommands, 0, 0, 1, 1);
+    QFormLayout *customDumperLayout = new QFormLayout(groupBoxCustomDumperCommands);
+    customDumperLayout->addRow(GdbOptionsPage::tr("Additional file:"), extraDumperFile);
+    customDumperLayout->addRow(textEditCustomDumperCommands);
 
     //QHBoxLayout *horizontalLayout = new QHBoxLayout();
     //horizontalLayout->addItem(new QSpacerItem(10, 10, QSizePolicy::Preferred, QSizePolicy::Minimum));
@@ -292,7 +299,8 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent)
 
     DebuggerCore *dc = debuggerCore();
     group.insert(dc->action(GdbStartupCommands), textEditStartupCommands);
-    group.insert(dc->action(GdbCustomDumperCommands), textEditCustomDumperCommands);
+    group.insert(dc->action(ExtraDumperFile), extraDumperFile);
+    group.insert(dc->action(ExtraDumperCommands), textEditCustomDumperCommands);
     group.insert(dc->action(GdbPostAttachCommands), textEditPostAttachCommands);
     group.insert(dc->action(LoadGdbInit), checkBoxLoadGdbInit);
     group.insert(dc->action(LoadGdbDumpers), checkBoxLoadGdbDumpers);
diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp
index 24c791f2fb..90f18d631f 100644
--- a/src/plugins/debugger/lldb/lldbengine.cpp
+++ b/src/plugins/debugger/lldb/lldbengine.cpp
@@ -275,6 +275,26 @@ void LldbEngine::setupInferior()
 {
     const DebuggerStartParameters &sp = startParameters();
 
+    const QString path = debuggerCore()->stringSetting(ExtraDumperFile);
+    if (!path.isEmpty()) {
+        QFileInfo fi(path);
+
+        Command cmd1("executeDebuggerCommand");
+        cmd1.arg("command", "python sys.path.insert(1, '" + fi.absolutePath().toUtf8() + "')");
+        runCommand(cmd1);
+
+        Command cmd2("executeDebuggerCommand");
+        cmd2.arg("python from " + fi.baseName().toUtf8() + " import *");
+        runCommand(cmd2);
+    }
+
+    const QString commands = debuggerCore()->stringSetting(ExtraDumperCommands);
+    if (!commands.isEmpty()) {
+        Command cmd("executeDebuggerCommand");
+        cmd.arg(commands.toUtf8());
+        runCommand(cmd);
+    }
+
     QString executable;
     Utils::QtcProcess::Arguments args;
     Utils::QtcProcess::prepareCommand(QFileInfo(sp.executable).absoluteFilePath(),
-- 
GitLab