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