From 047ee5522c203276e0c6a53acdd1862277fb8a7c Mon Sep 17 00:00:00 2001
From: Friedemann Kleint <Friedemann.Kleint@nokia.com>
Date: Fri, 25 Feb 2011 09:34:31 +0100
Subject: [PATCH] Debugger: Improve configuration error reporting.

- Make showWarningWithOptions actually show the details.
- Show errors from multiple engines as separate messages.
- Remove 'enabled' option from CDB (handled by toolchain config now).
- Show ABI as tooltip in debbugger toolchain chooser.
---
 src/plugins/coreplugin/mainwindow.cpp         |  2 +-
 src/plugins/debugger/cdb/cdbengine.cpp        | 14 +++----
 src/plugins/debugger/cdb/cdboptions.cpp       | 10 +----
 src/plugins/debugger/cdb/cdboptions.h         |  5 +--
 src/plugins/debugger/cdb/cdboptionspage.cpp   |  2 -
 .../debugger/cdb/cdboptionspagewidget.ui      |  9 +++--
 src/plugins/debugger/debuggerplugin.cpp       | 12 +++++-
 src/plugins/debugger/debuggerrunner.cpp       | 40 ++++++++++++++++---
 src/plugins/debugger/debuggerrunner.h         |  3 ++
 .../debugger/debuggertoolchaincombobox.cpp    | 11 +++++
 .../debugger/debuggertoolchaincombobox.h      |  4 ++
 .../qt-s60/s60devicerunconfiguration.cpp      |  2 +-
 12 files changed, 82 insertions(+), 32 deletions(-)

diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp
index ad10e914982..ac9ce6d3110 100644
--- a/src/plugins/coreplugin/mainwindow.cpp
+++ b/src/plugins/coreplugin/mainwindow.cpp
@@ -1386,7 +1386,7 @@ bool MainWindow::showWarningWithOptions(const QString &title,
         parent = this;
     QMessageBox msgBox(QMessageBox::Warning, title, text,
                        QMessageBox::Ok, parent);
-    if (details.isEmpty())
+    if (!details.isEmpty())
         msgBox.setDetailedText(details);
     QAbstractButton *settingsButton = 0;
     if (!settingsId.isEmpty() || !settingsCategory.isEmpty())
diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp
index 771bf6f65c2..2a8ed5ebf03 100644
--- a/src/plugins/debugger/cdb/cdbengine.cpp
+++ b/src/plugins/debugger/cdb/cdbengine.cpp
@@ -337,34 +337,34 @@ bool checkCdbConfiguration(const DebuggerStartParameters &sp, ConfigurationCheck
 {
 #ifdef Q_OS_WIN
     if (!isCdbEngineEnabled()) {
-        check->errorMessage = CdbEngine::tr("The CDB debug engine required for %1 is currently disabled.").
-                              arg(sp.toolChainAbi.toString());
+        check->errorDetails.push_back(CdbEngine::tr("The CDB debug engine required for %1 is currently disabled.").
+                           arg(sp.toolChainAbi.toString()));
         check->settingsCategory = QLatin1String(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY);
         check->settingsPage = CdbOptionsPage::settingsId();
         return false;
     }
 
     if (debuggerCore()->debuggerForAbi(sp.toolChainAbi, CdbEngineType).isEmpty()) {
-        check->errorMessage = msgNoCdbBinaryForToolChain(sp.toolChainAbi);
+        check->errorDetails.push_back(msgNoCdbBinaryForToolChain(sp.toolChainAbi));
         check->settingsCategory = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
         check->settingsPage = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
         return false;
     }
 
     if (!validMode(sp.startMode)) {
-        check->errorMessage = CdbEngine::tr("The CDB engine does not support start mode %1.").arg(sp.startMode);
+        check->errorDetails.push_back(CdbEngine::tr("The CDB engine does not support start mode %1.").arg(sp.startMode));
         return false;
     }
 
     if (sp.toolChainAbi.binaryFormat() != Abi::PEFormat || sp.toolChainAbi.os() != Abi::WindowsOS) {
-        check->errorMessage = CdbEngine::tr("The CDB debug engine does not support the %1 ABI.").
-                                            arg(sp.toolChainAbi.toString());
+        check->errorDetails.push_back(CdbEngine::tr("The CDB debug engine does not support the %1 ABI.").
+                                      arg(sp.toolChainAbi.toString()));
         return false;
     }
     return true;
 #else
     Q_UNUSED(sp);
-    check->errorMessage = QString::fromLatin1("Unsupported debug mode");
+    check->errorDetails.push_back(QString::fromLatin1("Unsupported debug mode"));
     return false;
 #endif
 }
diff --git a/src/plugins/debugger/cdb/cdboptions.cpp b/src/plugins/debugger/cdb/cdboptions.cpp
index fe91471d998..4c00d042724 100644
--- a/src/plugins/debugger/cdb/cdboptions.cpp
+++ b/src/plugins/debugger/cdb/cdboptions.cpp
@@ -36,7 +36,6 @@
 #include <QtCore/QSettings>
 
 static const char settingsGroupC[] = "CDB2";
-static const char enabledKeyC[] = "Enabled";
 static const char symbolPathsKeyC[] = "SymbolPaths";
 static const char sourcePathsKeyC[] = "SourcePaths";
 static const char breakEventKeyC[] = "BreakEvent";
@@ -45,7 +44,7 @@ static const char additionalArgumentsKeyC[] = "AdditionalArguments";
 namespace Debugger {
 namespace Internal {
 
-CdbOptions::CdbOptions() : enabled(false)
+CdbOptions::CdbOptions()
 {
 }
 
@@ -56,7 +55,6 @@ QString CdbOptions::settingsGroup()
 
 void CdbOptions::clear()
 {
-    enabled = false;
     symbolPaths.clear();
     sourcePaths.clear();
 }
@@ -70,7 +68,6 @@ void CdbOptions::fromSettings(QSettings *s)
 {
     clear();
     const QString keyRoot = QLatin1String(settingsGroupC) + QLatin1Char('/');
-    enabled = s->value(keyRoot + QLatin1String(enabledKeyC), QVariant(false)).toBool();
     additionalArguments = s->value(keyRoot + QLatin1String(additionalArgumentsKeyC), QString()).toString();
     symbolPaths = s->value(keyRoot + QLatin1String(symbolPathsKeyC), QStringList()).toStringList();
     sourcePaths = s->value(keyRoot + QLatin1String(sourcePathsKeyC), QStringList()).toStringList();
@@ -80,7 +77,6 @@ void CdbOptions::fromSettings(QSettings *s)
 void CdbOptions::toSettings(QSettings *s) const
 {
     s->beginGroup(QLatin1String(settingsGroupC));
-    s->setValue(QLatin1String(enabledKeyC), enabled);
     s->setValue(QLatin1String(symbolPathsKeyC), symbolPaths);
     s->setValue(QLatin1String(sourcePathsKeyC), sourcePaths);
     s->setValue(QLatin1String(breakEventKeyC), breakEvents);
@@ -90,13 +86,11 @@ void CdbOptions::toSettings(QSettings *s) const
 
 bool CdbOptions::equals(const CdbOptions &rhs) const
 {
-    return enabled == rhs.enabled
-            && additionalArguments == rhs.additionalArguments
+    return additionalArguments == rhs.additionalArguments
             && symbolPaths == rhs.symbolPaths
             && sourcePaths == rhs.sourcePaths
             && breakEvents == rhs.breakEvents;
 }
 
-
 } // namespace Internal
 } // namespace Debugger
diff --git a/src/plugins/debugger/cdb/cdboptions.h b/src/plugins/debugger/cdb/cdboptions.h
index 5ebd85fd426..8bc8bece187 100644
--- a/src/plugins/debugger/cdb/cdboptions.h
+++ b/src/plugins/debugger/cdb/cdboptions.h
@@ -48,10 +48,10 @@ struct CdbOptions
 public:
     CdbOptions();
 
-    bool isValid() const { return enabled; }
-
     void clear();
 
+    bool isValid() { return true; }
+
     void fromSettings(QSettings *s); // Writes parameters on first-time autodetect
     void toSettings(QSettings *s) const;
 
@@ -60,7 +60,6 @@ public:
     static QString settingsGroup();
     static QStringList oldEngineSymbolPaths(const QSettings *s);
 
-    bool enabled;
     QString additionalArguments;
     QStringList symbolPaths;
     QStringList sourcePaths;
diff --git a/src/plugins/debugger/cdb/cdboptionspage.cpp b/src/plugins/debugger/cdb/cdboptionspage.cpp
index 015bae61f8f..18caf5ac842 100644
--- a/src/plugins/debugger/cdb/cdboptionspage.cpp
+++ b/src/plugins/debugger/cdb/cdboptionspage.cpp
@@ -172,7 +172,6 @@ CdbOptionsPageWidget::CdbOptionsPageWidget(QWidget *parent) :
 void CdbOptionsPageWidget::setOptions(CdbOptions &o)
 {
     m_ui.additionalArgumentsLineEdit->setText(o.additionalArguments);
-    m_ui.cdbPathGroupBox->setChecked(o.enabled);
     setSymbolPaths(o.symbolPaths);
     m_ui.sourcePathListEditor->setPathList(o.sourcePaths);
     m_breakEventWidget->setBreakEvents(o.breakEvents);
@@ -182,7 +181,6 @@ CdbOptions CdbOptionsPageWidget::options() const
 {
     CdbOptions  rc;
     rc.additionalArguments = m_ui.additionalArgumentsLineEdit->text().trimmed();
-    rc.enabled = m_ui.cdbPathGroupBox->isChecked();
     rc.symbolPaths = symbolPaths();
     rc.sourcePaths = m_ui.sourcePathListEditor->pathList();
     rc.breakEvents = m_breakEventWidget->breakEvents();
diff --git a/src/plugins/debugger/cdb/cdboptionspagewidget.ui b/src/plugins/debugger/cdb/cdboptionspagewidget.ui
index 7a74d5ac039..c3a29266ee7 100644
--- a/src/plugins/debugger/cdb/cdboptionspagewidget.ui
+++ b/src/plugins/debugger/cdb/cdboptionspagewidget.ui
@@ -16,10 +16,13 @@
      <item>
       <widget class="QGroupBox" name="cdbPathGroupBox">
        <property name="title">
-        <string extracomment="Placeholder">CDB</string>
+        <string extracomment="Placeholder">Startup</string>
        </property>
        <property name="checkable">
-        <bool>true</bool>
+        <bool>false</bool>
+       </property>
+       <property name="checked">
+        <bool>false</bool>
        </property>
        <layout class="QFormLayout" name="formLayout">
         <property name="fieldGrowthPolicy">
@@ -44,7 +47,7 @@
     </layout>
    </item>
    <item>
-    <widget class="QGroupBox" name="pathGroupBox">
+    <widget class="QGroupBox" name="startupGroupBox">
      <property name="title">
       <string>Debugger Paths</string>
      </property>
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index 9371f8f6593..6a6968db288 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -2394,6 +2394,7 @@ void DebuggerPluginPrivate::remoteCommand(const QStringList &options,
 
 QString DebuggerPluginPrivate::debuggerForAbi(const Abi &abi, DebuggerEngineType et) const
 {
+    enum { debug = 0 };
     Abi searchAbi = abi;
     // Pick the right toolchain in case cdb/gdb were started with other toolchains.
     // Also, lldb should be preferred over gdb.
@@ -2411,8 +2412,15 @@ QString DebuggerPluginPrivate::debuggerForAbi(const Abi &abi, DebuggerEngineType
             break;
         }
     }
-    foreach (const ToolChain *tc, ToolChainManager::instance()->findToolChains(searchAbi)) {
-        const QString debugger = tc->debuggerCommand();
+    if (debug)
+        qDebug() << "debuggerForAbi" << abi.toString() << searchAbi.toString() << et;
+
+    const QList<ToolChain *> toolchains = ToolChainManager::instance()->findToolChains(searchAbi);
+    // Find manually configured ones first
+    for (int i = toolchains.size() - 1; i >= 0; i--) {
+        const QString debugger = toolchains.at(i)->debuggerCommand();
+        if (debug)
+            qDebug() << i << toolchains.at(i)->displayName() << debugger;
         if (!debugger.isEmpty())
             return debugger;
     }
diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp
index 27919378834..9eb243c4a0d 100644
--- a/src/plugins/debugger/debuggerrunner.cpp
+++ b/src/plugins/debugger/debuggerrunner.cpp
@@ -65,11 +65,14 @@
 #include <coreplugin/icore.h>
 
 #include <QtCore/QDir>
+#include <QtCore/QDebug>
 #include <QtGui/QMessageBox>
 
 using namespace ProjectExplorer;
 using namespace Debugger::Internal;
 
+enum { debug = 0 };
+
 namespace Debugger {
 namespace Internal {
 
@@ -118,6 +121,17 @@ static const char *engineTypeName(DebuggerEngineType et)
     return "No engine";
 }
 
+static inline QString engineTypeNames(const QList<DebuggerEngineType> &l)
+{
+    QString rc;
+    foreach (DebuggerEngineType et, l) {
+        if (!rc.isEmpty())
+            rc.append(QLatin1Char(','));
+        rc += QLatin1String(engineTypeName(et));
+    }
+    return rc;
+}
+
 static QString msgEngineNotAvailable(const char *engine)
 {
     return DebuggerPlugin::tr("The application requires the debugger engine '%1', "
@@ -479,7 +493,7 @@ static inline bool engineConfigurationCheck(const DebuggerStartParameters &sp,
         return checkCdbConfiguration(sp, check);
     case Debugger::GdbEngineType:
         if (debuggerCore()->debuggerForAbi(sp.toolChainAbi, et).isEmpty()) {
-            check->errorMessage = msgNoBinaryForToolChain(sp.toolChainAbi, et);
+            check->errorDetails.push_back(msgNoBinaryForToolChain(sp.toolChainAbi, et));
             check->settingsCategory = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
             check->settingsPage = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
             return false;
@@ -498,7 +512,12 @@ ConfigurationCheck::ConfigurationCheck() :
 
 ConfigurationCheck::operator bool() const
 {
-    return errorMessage.isEmpty() &&  masterSlaveEngineTypes.first != NoEngineType;
+    return errorMessage.isEmpty() &&  errorDetails.isEmpty() && masterSlaveEngineTypes.first != NoEngineType;
+}
+
+QString ConfigurationCheck::errorDetailsString() const
+{
+    return errorDetails.join(QLatin1String("\n\n"));
 }
 
 /*!
@@ -516,6 +535,10 @@ DEBUGGER_EXPORT ConfigurationCheck checkDebugConfiguration(const DebuggerStartPa
     const unsigned activeLangs = debuggerCore()->activeLanguages();
     const bool qmlLanguage = activeLangs & QmlLanguage;
     const bool cppLanguage = activeLangs & CppLanguage;
+    if (debug)
+        qDebug().nospace() << "checkDebugConfiguration " << sp.toolChainAbi.toString()
+                           << " Start mode=" << sp.startMode << " Executable=" << sp.executable
+                           << " Debugger command=" << sp.debuggerCommand;
     // Get all applicable types.
     QList<DebuggerEngineType> requiredTypes;
     if (qmlLanguage && !cppLanguage) {
@@ -527,6 +550,8 @@ DEBUGGER_EXPORT ConfigurationCheck checkDebugConfiguration(const DebuggerStartPa
         result.errorMessage = DebuggerPlugin::tr("Internal error: Unable to determine debugger engine type for this configuration");
         return result;
     }
+    if (debug)
+        qDebug() << " Required: " << engineTypeNames(requiredTypes);
     // Filter out disables types, command line + current settings.
     unsigned cmdLineEnabledEngines = debuggerCore()->enabledEngines();
 #ifdef CDB_ENABLED
@@ -548,12 +573,15 @@ DEBUGGER_EXPORT ConfigurationCheck checkDebugConfiguration(const DebuggerStartPa
                 arg(QLatin1String(engineTypeName(usableTypes.front())));
         return result;
     }
+    if (debug)
+        qDebug() << " Usable engines: " << engineTypeNames(usableTypes);
     // Configuration check: Strip off non-configured engines.
     while (!usableTypes.isEmpty() && !engineConfigurationCheck(sp, usableTypes.front(), &result))
         usableTypes.pop_front();
+    if (debug)
+        qDebug() << "Configured engines: " << engineTypeNames(usableTypes);
     if (usableTypes.isEmpty()) {
-        result.errorMessage = DebuggerPlugin::tr("The debugger engine required for this configuration is not correctly configured:\n%1")
-                .arg(result.errorMessage);
+        result.errorMessage = DebuggerPlugin::tr("The debugger engine required for this configuration is not correctly configured.");
         return result;
     }
     // Anything left: Happy.
@@ -563,6 +591,8 @@ DEBUGGER_EXPORT ConfigurationCheck checkDebugConfiguration(const DebuggerStartPa
     } else {
         result.masterSlaveEngineTypes.first = usableTypes.front();
     }
+    if (debug)
+        qDebug() << engineTypeName(result.masterSlaveEngineTypes.first) << engineTypeName(result.masterSlaveEngineTypes.second);
     return result;
 }
 
@@ -690,7 +720,7 @@ DebuggerRunControl *DebuggerRunControlFactory::create
     if (!check) {
         //appendMessage(errorMessage, true);
         Core::ICore::instance()->showWarningWithOptions(DebuggerRunControl::tr("Debugger"),
-            check.errorMessage, QString(), check.settingsCategory, check.settingsPage);
+            check.errorMessage, check.errorDetailsString(), check.settingsCategory, check.settingsPage);
         return 0;
     }
 
diff --git a/src/plugins/debugger/debuggerrunner.h b/src/plugins/debugger/debuggerrunner.h
index 0a864a1ad67..70991889ff7 100644
--- a/src/plugins/debugger/debuggerrunner.h
+++ b/src/plugins/debugger/debuggerrunner.h
@@ -42,6 +42,7 @@
 
 #include <QtCore/QScopedPointer>
 #include <QtCore/QPair>
+#include <QtCore/QStringList>
 
 namespace Utils {
 class Environment;
@@ -63,8 +64,10 @@ class DEBUGGER_EXPORT ConfigurationCheck
 public:
     ConfigurationCheck();
     operator bool() const;
+    QString errorDetailsString() const;
 
     QString errorMessage;
+    QStringList errorDetails;
     QString settingsCategory;
     QString settingsPage;
     QPair<DebuggerEngineType, DebuggerEngineType> masterSlaveEngineTypes;
diff --git a/src/plugins/debugger/debuggertoolchaincombobox.cpp b/src/plugins/debugger/debuggertoolchaincombobox.cpp
index 1f2acfe370d..b11125d1a07 100644
--- a/src/plugins/debugger/debuggertoolchaincombobox.cpp
+++ b/src/plugins/debugger/debuggertoolchaincombobox.cpp
@@ -38,6 +38,8 @@
 
 #include <QtCore/QFileInfo>
 
+#include <QtGui/QtEvents>
+
 Q_DECLARE_METATYPE(ProjectExplorer::Abi)
 
 namespace Debugger {
@@ -86,5 +88,14 @@ ProjectExplorer::Abi DebuggerToolChainComboBox::abiAt(int index) const
                         ProjectExplorer::Abi();
 }
 
+bool DebuggerToolChainComboBox::event(QEvent *event)
+{
+    if (event->type() == QEvent::ToolTip) {
+        const ProjectExplorer::Abi current = abi();
+        setToolTip(current.isValid() ? current.toString() : QString());
+    }
+    return QComboBox::event(event);
+}
+
 } // namespace Debugger
 } // namespace Internal
diff --git a/src/plugins/debugger/debuggertoolchaincombobox.h b/src/plugins/debugger/debuggertoolchaincombobox.h
index bf198da3039..f853092dec5 100644
--- a/src/plugins/debugger/debuggertoolchaincombobox.h
+++ b/src/plugins/debugger/debuggertoolchaincombobox.h
@@ -55,7 +55,11 @@ public:
     void setAbi(const ProjectExplorer::Abi &abi);
     ProjectExplorer::Abi abi() const;
 
+protected:
+    virtual bool event(QEvent *event);
+
 private:
+
     ProjectExplorer::Abi abiAt(int index) const;
 };
 
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
index 44c7c564d24..4bd7ea0c60d 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
@@ -530,7 +530,7 @@ ProjectExplorer::RunControl* S60DeviceDebugRunControlFactory::create(ProjectExpl
     const Debugger::ConfigurationCheck check = Debugger::checkDebugConfiguration(startParameters);
     if (!check) {
         Core::ICore::instance()->showWarningWithOptions(tr("Debugger for Symbian Platform"),
-            check.errorMessage, QString(), check.settingsCategory, check.settingsPage);
+            check.errorMessage, check.errorDetailsString(), check.settingsCategory, check.settingsPage);
         return 0;
     }
     return new S60DeviceDebugRunControl(rc, startParameters, check.masterSlaveEngineTypes);
-- 
GitLab