OSDN Git Service

Debugger[New CDB]: Add more fine-grained settings for events/break.
authorFriedemann Kleint <Friedemann.Kleint@nokia.com>
Fri, 17 Dec 2010 11:00:44 +0000 (12:00 +0100)
committerFriedemann Kleint <Friedemann.Kleint@nokia.com>
Fri, 17 Dec 2010 11:02:13 +0000 (12:02 +0100)
Add options to break on Cpp Exceptions, thread creation, etc.

src/plugins/debugger/cdb2/cdbengine2.cpp
src/plugins/debugger/cdb2/cdboptions2.cpp
src/plugins/debugger/cdb2/cdboptions2.h
src/plugins/debugger/cdb2/cdboptionspage2.cpp
src/plugins/debugger/cdb2/cdboptionspage2.h
src/plugins/debugger/cdb2/cdboptionspagewidget2.ui

index 91ba92c..43439c3 100644 (file)
@@ -520,6 +520,8 @@ void CdbEngine::runEngine()
 {
     if (debug)
         qDebug("runEngine");
+    foreach (const QString &breakEvent, m_options->breakEvents)
+            postCommand(QByteArray("sxe ") + breakEvent.toAscii(), 0);
     postCommand("g", 0);
 }
 
index bd44e5f..57a364f 100644 (file)
@@ -44,6 +44,7 @@ static const char enabledKeyC[] = "Enabled";
 static const char pathKeyC[] = "Path";
 static const char symbolPathsKeyC[] = "SymbolPaths";
 static const char sourcePathsKeyC[] = "SourcePaths";
+static const char breakEventKeyC[] = "BreakEvent";
 static const char is64bitKeyC[] = "64bit";
 
 namespace Debugger {
@@ -145,6 +146,7 @@ void CdbOptions::fromSettings(QSettings *s)
     executable = s->value(keyRoot + QLatin1String(pathKeyC), executable).toString();
     symbolPaths = s->value(keyRoot + QLatin1String(symbolPathsKeyC), QStringList()).toStringList();
     sourcePaths = s->value(keyRoot + QLatin1String(sourcePathsKeyC), QStringList()).toStringList();
+    breakEvents = s->value(keyRoot + QLatin1String(breakEventKeyC), QStringList()).toStringList();
 }
 
 void CdbOptions::toSettings(QSettings *s) const
@@ -155,6 +157,7 @@ void CdbOptions::toSettings(QSettings *s) const
     s->setValue(QLatin1String(is64bitKeyC), is64bit);
     s->setValue(QLatin1String(symbolPathsKeyC), symbolPaths);
     s->setValue(QLatin1String(sourcePathsKeyC), sourcePaths);
+    s->setValue(QLatin1String(breakEventKeyC), breakEvents);
     s->endGroup();
 }
 
@@ -163,7 +166,8 @@ bool CdbOptions::equals(const CdbOptions &rhs) const
     return enabled == rhs.enabled && is64bit == rhs.is64bit
             && executable == rhs.executable
             && symbolPaths == rhs.symbolPaths
-            && sourcePaths == rhs.sourcePaths;
+            && sourcePaths == rhs.sourcePaths
+            && breakEvents == rhs.breakEvents;
 }
 
 bool CdbOptions::autoDetectExecutable(QString *outPath, bool *is64bitIn  /* = 0 */,
index 0161cd0..ebec5a3 100644 (file)
@@ -63,6 +63,8 @@ public:
     QString executable;
     QStringList symbolPaths;
     QStringList sourcePaths;
+    // Events to break on (Command 'sxe' with abbreviation and optional parameter)
+    QStringList breakEvents;
 };
 
 inline bool operator==(const CdbOptions &s1, const CdbOptions &s2)
index 3b75e34..b60a6c5 100644 (file)
@@ -48,6 +48,7 @@
 #include <QtCore/QTimer>
 #include <QtCore/QProcess>
 #include <QtGui/QMessageBox>
+#include <QtGui/QLineEdit>
 #include <QtGui/QDesktopServices>
 
 static const char *dgbToolsDownloadLink32C = "http://www.microsoft.com/whdc/devtools/debugging/installx86.Mspx";
@@ -56,6 +57,118 @@ static const char *dgbToolsDownloadLink64C = "http://www.microsoft.com/whdc/devt
 namespace Debugger {
 namespace Cdb {
 
+struct EventsDescription {
+    const char *abbreviation;
+    bool hasParameter;
+    const char *description;
+};
+
+// Parameters of the "sxe" command
+const EventsDescription eventDescriptions[] =
+{
+    {"eh", false, QT_TRANSLATE_NOOP("Debugger::Cdb::CdbBreakEventWidget",
+                                    "C++ exception")},
+    {"ct", false, QT_TRANSLATE_NOOP("Debugger::Cdb::CdbBreakEventWidget",
+                                    "Thread creation")},
+    {"et", false, QT_TRANSLATE_NOOP("Debugger::Cdb::CdbBreakEventWidget",
+                                    "Thread exit")},
+    {"ld", true,  QT_TRANSLATE_NOOP("Debugger::Cdb::CdbBreakEventWidget",
+                                    "Load Module:")},
+    {"ud", true,  QT_TRANSLATE_NOOP("Debugger::Cdb::CdbBreakEventWidget",
+                                    "Unload Module:")},
+    {"out", true, QT_TRANSLATE_NOOP("Debugger::Cdb::CdbBreakEventWidget",
+                                    "Output:")}
+};
+
+static inline int indexOfEvent(const QString &abbrev)
+{
+    const size_t eventCount = sizeof(eventDescriptions) / sizeof(EventsDescription);
+    for (size_t e = 0; e < eventCount; e++)
+        if (abbrev == QLatin1String(eventDescriptions[e].abbreviation))
+                return int(e);
+    return -1;
+}
+
+CdbBreakEventWidget::CdbBreakEventWidget(QWidget *parent) : QWidget(parent)
+{
+    // 1 column with checkboxes only,
+    // further columns with checkbox + parameter
+    QHBoxLayout *mainLayout = new QHBoxLayout;
+    QVBoxLayout *leftLayout = new QVBoxLayout;
+    QFormLayout *parameterLayout = 0;
+    mainLayout->addLayout(leftLayout);
+    const size_t eventCount = sizeof(eventDescriptions) / sizeof(EventsDescription);
+    for (size_t e = 0; e < eventCount; e++) {
+        QCheckBox *cb = new QCheckBox(tr(eventDescriptions[e].description));
+        QLineEdit *le = 0;
+        if (eventDescriptions[e].hasParameter) {
+            if (!parameterLayout) {
+                parameterLayout = new QFormLayout;
+                mainLayout->addSpacerItem(new QSpacerItem(20, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
+                mainLayout->addLayout(parameterLayout);
+            }
+            le = new QLineEdit;
+            parameterLayout->addRow(cb, le);
+            if (parameterLayout->count() >= 4) // New column
+                parameterLayout = 0;
+        } else {
+            leftLayout->addWidget(cb);
+        }
+        m_checkBoxes.push_back(cb);
+        m_lineEdits.push_back(le);
+    }
+    setLayout(mainLayout);
+}
+
+void CdbBreakEventWidget::clear()
+{
+    foreach (QLineEdit *l, m_lineEdits) {
+        if (l)
+            l->clear();
+    }
+    foreach (QCheckBox *c, m_checkBoxes)
+        c->setChecked(false);
+}
+
+void CdbBreakEventWidget::setBreakEvents(const QStringList &l)
+{
+    clear();
+    // Split the list of ("eh", "out:MyOutput")
+    foreach (const QString &evt, l) {
+        const int colonPos = evt.indexOf(QLatin1Char(':'));
+        const QString abbrev = colonPos != -1 ? evt.mid(0, colonPos) : evt;
+        const int index = indexOfEvent(abbrev);
+        if (index != -1)
+            m_checkBoxes.at(index)->setChecked(true);
+        if (colonPos != -1 && m_lineEdits.at(index))
+            m_lineEdits.at(index)->setText(evt.mid(colonPos + 1));
+    }
+}
+
+QString CdbBreakEventWidget::filterText(int i) const
+{
+    return m_lineEdits.at(i) ? m_lineEdits.at(i)->text() : QString();
+}
+
+QStringList CdbBreakEventWidget::breakEvents() const
+{
+    // Compile a list of ("eh", "out:MyOutput")
+    QStringList rc;
+    const int eventCount = sizeof(eventDescriptions) / sizeof(EventsDescription);
+    for (int e = 0; e < eventCount; e++) {
+        if (m_checkBoxes.at(e)->isChecked()) {
+            const QString filter = filterText(e);
+            QString s = QLatin1String(eventDescriptions[e].abbreviation);
+            if (!filter.isEmpty()) {
+                s += QLatin1Char(':');
+                s += filter;
+            }
+            rc.push_back(s);
+        }
+    }
+    return rc;
+}
+
 static inline QString msgPathConfigNote()
 {
 #ifdef Q_OS_WIN
@@ -74,7 +187,8 @@ static inline QString msgPathConfigNote()
 }
 
 CdbOptionsPageWidget::CdbOptionsPageWidget(QWidget *parent) :
-    QWidget(parent), m_reportTimer(0)
+    QWidget(parent), m_breakEventWidget(new CdbBreakEventWidget),
+    m_reportTimer(0)
 {
     m_ui.setupUi(this);
     m_ui.noteLabel->setText(msgPathConfigNote());
@@ -84,6 +198,9 @@ CdbOptionsPageWidget::CdbOptionsPageWidget(QWidget *parent) :
     m_ui.pathChooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
     m_ui.pathChooser->addButton(tr("Autodetect"), this, SLOT(autoDetect()));
     m_ui.cdbPathGroupBox->installEventFilter(this);
+    QVBoxLayout *eventLayout = new QVBoxLayout;
+    eventLayout->addWidget(m_breakEventWidget);
+    m_ui.eventGroupBox->setLayout(eventLayout);
 }
 
 void CdbOptionsPageWidget::setOptions(CdbOptions &o)
@@ -93,6 +210,7 @@ void CdbOptionsPageWidget::setOptions(CdbOptions &o)
     m_ui.cdbPathGroupBox->setChecked(o.enabled);
     setSymbolPaths(o.symbolPaths);
     m_ui.sourcePathListEditor->setPathList(o.sourcePaths);
+    m_breakEventWidget->setBreakEvents(o.breakEvents);
 }
 
 bool CdbOptionsPageWidget::is64Bit() const
@@ -113,6 +231,7 @@ CdbOptions CdbOptionsPageWidget::options() const
     rc.is64bit = is64Bit();
     rc.symbolPaths = symbolPaths();
     rc.sourcePaths = m_ui.sourcePathListEditor->pathList();
+    rc.breakEvents = m_breakEventWidget->breakEvents();
     return rc;
 }
 
index e8c868d..b441cdc 100644 (file)
 #include <QtCore/QPointer>
 #include <QtCore/QSharedPointer>
 
-QT_FORWARD_DECLARE_CLASS(QTimer)
+QT_BEGIN_NAMESPACE
+class QTimer;
+QT_END_NAMESPACE
 
 namespace Debugger {
 namespace Cdb {
 
+// Widget displaying a list of break events for the 'sxe' command
+// with a checkbox to enable 'break' and optionally a QLineEdit for
+// events with parameters (like 'out:Needle').
+class CdbBreakEventWidget : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit CdbBreakEventWidget(QWidget *parent = 0);
+
+    void setBreakEvents(const QStringList &l);
+    QStringList breakEvents() const;
+
+private:
+    QString filterText(int i) const;
+    void clear();
+
+    QList<QCheckBox*> m_checkBoxes;
+    QList<QLineEdit*> m_lineEdits;
+};
+
 class CdbOptionsPageWidget : public QWidget
 {
     Q_OBJECT
@@ -73,6 +95,7 @@ private:
                                   QString *message);
 
     Ui::CdbOptionsPageWidget2 m_ui;
+    CdbBreakEventWidget *m_breakEventWidget;
     QTimer *m_reportTimer;
 };
 
index 9904bb5..f15d09d 100644 (file)
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>135</width>
-    <height>246</height>
+    <width>347</width>
+    <height>358</height>
    </rect>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
     </widget>
    </item>
    <item>
+    <widget class="QGroupBox" name="eventGroupBox">
+     <property name="title">
+      <string>Break on:</string>
+     </property>
+    </widget>
+   </item>
+   <item>
     <spacer name="verticalSpacer">
      <property name="orientation">
       <enum>Qt::Vertical</enum>