Commit 70336e30 authored by David Schulz's avatar David Schulz

Debugger: Add CDB symbol cache option.

Change-Id: I9c4ec9bbcc0216271d6e4d10e9f6e925d3569cea
Reviewed-by: default avatarFriedemann Kleint <Friedemann.Kleint@digia.com>
parent 1bf0343a
......@@ -582,8 +582,8 @@ void CdbEngine::setupEngine()
{
if (debug)
qDebug(">setupEngine");
// Nag to add symbol server
if (CdbSymbolPathListEditor::promptToAddSymbolServer(CdbOptions::settingsGroup(),
// Nag to add symbol server and cache
if (CdbSymbolPathListEditor::promptToAddSymbolPaths(CdbOptions::settingsGroup(),
&(m_options->symbolPaths)))
m_options->toSettings(Core::ICore::settings());
......
......@@ -154,48 +154,11 @@ QStringList CdbBreakEventWidget::breakEvents() const
return rc;
}
CdbPathDialog::CdbPathDialog(QWidget *parent, Mode mode)
: QDialog(parent)
, m_pathListEditor(0)
{
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setMinimumWidth(700);
switch (mode) {
case SymbolPaths:
setWindowTitle(tr("CDB Symbol Paths"));
m_pathListEditor = new CdbSymbolPathListEditor(this);
break;
case SourcePaths:
setWindowTitle(tr("CDB Source Paths"));
m_pathListEditor = new Utils::PathListEditor(this);
break;
}
QVBoxLayout *layout = new QVBoxLayout(this);
QGroupBox *groupBox = new QGroupBox(this);
(new QVBoxLayout(groupBox))->addWidget(m_pathListEditor);
layout->addWidget(groupBox);
QDialogButtonBox *buttonBox =
new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
Qt::Horizontal, this);
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
layout->addWidget(buttonBox);
}
QStringList CdbPathDialog::paths() const
{
return m_pathListEditor->pathList();
}
void CdbPathDialog::setPaths(const QStringList &paths)
{
m_pathListEditor->setPathList(paths);
}
CdbOptionsPageWidget::CdbOptionsPageWidget(QWidget *parent) :
QWidget(parent), m_breakEventWidget(new CdbBreakEventWidget)
CdbOptionsPageWidget::CdbOptionsPageWidget(QWidget *parent)
: QWidget(parent)
, m_breakEventWidget(new CdbBreakEventWidget)
, m_symbolPathListEditor(new CdbSymbolPathListEditor)
, m_sourcePathListEditor(new Utils::PathListEditor)
{
m_ui.setupUi(this);
// Squeeze the groupbox layouts vertically to
......@@ -206,8 +169,6 @@ CdbOptionsPageWidget::CdbOptionsPageWidget(QWidget *parent) :
const QMargins margins(margin, margin / 3, margin, margin / 3);
m_ui.startupFormLayout->setContentsMargins(margins);
m_ui.pathGroupBox->layout()->setContentsMargins(margins);
m_ui.breakpointLayout->setContentsMargins(margins);
QVBoxLayout *eventLayout = new QVBoxLayout;
eventLayout->setContentsMargins(margins);
......@@ -219,33 +180,15 @@ CdbOptionsPageWidget::CdbOptionsPageWidget(QWidget *parent) :
m_ui.breakCrtDbgReportCheckBox
->setToolTip(CommonOptionsPage::msgSetBreakpointAtFunctionToolTip(CdbOptions::crtDbgReport, hint));
connect(m_ui.symbolPathButton, SIGNAL(clicked()), this, SLOT(showSymbolPathDialog()));
connect(m_ui.sourcePathButton, SIGNAL(clicked()), this, SLOT(showSourcePathDialog()));
}
void CdbOptionsPageWidget::setSymbolPaths(const QStringList &s)
{
m_symbolPaths = s;
const QString summary =
tr("Symbol paths: %1").arg(m_symbolPaths.isEmpty() ?
tr("<none>") : QString::number(m_symbolPaths.size()));
m_ui.symbolPathLabel->setText(summary);
}
void CdbOptionsPageWidget::setSourcePaths(const QStringList &s)
{
m_sourcePaths = s;
const QString summary =
tr("Source paths: %1").arg(m_sourcePaths.isEmpty() ?
tr("<none>") : QString::number(m_sourcePaths.size()));
m_ui.sourcePathLabel->setText(summary);
m_ui.symbolPathsGroupBox->layout()->addWidget(m_symbolPathListEditor);
m_ui.sourcePathsGroupBox->layout()->addWidget(m_sourcePathListEditor);
}
void CdbOptionsPageWidget::setOptions(CdbOptions &o)
{
m_ui.additionalArgumentsLineEdit->setText(o.additionalArguments);
setSymbolPaths(o.symbolPaths);
setSourcePaths(o.sourcePaths);
m_symbolPathListEditor->setPathList(o.symbolPaths);
m_sourcePathListEditor->setPathList(o.sourcePaths);
m_ui.ignoreFirstChanceAccessViolationCheckBox->setChecked(o.ignoreFirstChanceAccessViolation);
m_breakEventWidget->setBreakEvents(o.breakEvents);
m_ui.consoleCheckBox->setChecked(o.cdbConsole);
......@@ -257,8 +200,8 @@ CdbOptions CdbOptionsPageWidget::options() const
{
CdbOptions rc;
rc.additionalArguments = m_ui.additionalArgumentsLineEdit->text().trimmed();
rc.symbolPaths = m_symbolPaths;
rc.sourcePaths = m_sourcePaths;
rc.symbolPaths = m_symbolPathListEditor->pathList();
rc.sourcePaths = m_sourcePathListEditor->pathList();
rc.ignoreFirstChanceAccessViolation = m_ui.ignoreFirstChanceAccessViolationCheckBox->isChecked();
rc.breakEvents = m_breakEventWidget->breakEvents();
rc.cdbConsole = m_ui.consoleCheckBox->isChecked();
......@@ -268,22 +211,6 @@ CdbOptions CdbOptionsPageWidget::options() const
return rc;
}
void CdbOptionsPageWidget::showSymbolPathDialog()
{
CdbPathDialog pathDialog(this, CdbPathDialog::SymbolPaths);
pathDialog.setPaths(m_symbolPaths);
if (pathDialog.exec() == QDialog::Accepted)
setSymbolPaths(pathDialog.paths());
}
void CdbOptionsPageWidget::showSourcePathDialog()
{
CdbPathDialog pathDialog(this, CdbPathDialog::SourcePaths);
pathDialog.setPaths(m_sourcePaths);
if (pathDialog.exec() == QDialog::Accepted)
setSourcePaths(pathDialog.paths());
}
static QString stripColon(QString s)
{
const int lastColon = s.lastIndexOf(QLatin1Char(':'));
......@@ -297,10 +224,8 @@ QString CdbOptionsPageWidget::searchKeywords() const
QString rc;
QTextStream(&rc)
<< stripColon(m_ui.additionalArgumentsLabel->text()) << ' '
<< stripColon(m_ui.breakFunctionGroupBox->title()) << ' '
<< m_ui.breakpointsGroupBox->title() << ' '
<< stripColon(m_ui.symbolPathLabel->text()) << ' '
<< stripColon(m_ui.sourcePathLabel->text());
<< m_ui.symbolPathsGroupBox->title() << ' '
<< m_ui.sourcePathsGroupBox->title();
rc.remove(QLatin1Char('&'));
return rc;
}
......
......@@ -72,24 +72,6 @@ private:
QList<QLineEdit*> m_lineEdits;
};
class CdbPathDialog : public QDialog
{
Q_OBJECT
public:
enum Mode {
SymbolPaths,
SourcePaths
};
explicit CdbPathDialog(QWidget *parent, Mode mode);
QStringList paths() const;
void setPaths(const QStringList &paths);
private:
Utils::PathListEditor *m_pathListEditor;
};
class CdbOptionsPageWidget : public QWidget
{
Q_OBJECT
......@@ -102,20 +84,13 @@ public:
QString searchKeywords() const;
private slots:
void showSymbolPathDialog();
void showSourcePathDialog();
private:
void setSymbolPaths(const QStringList &);
void setSourcePaths(const QStringList &);
inline QString path() const;
Ui::CdbOptionsPageWidget m_ui;
CdbBreakEventWidget *m_breakEventWidget;
QStringList m_symbolPaths;
QStringList m_sourcePaths;
CdbSymbolPathListEditor *m_symbolPathListEditor;
Utils::PathListEditor *m_sourcePathListEditor;
};
class CdbOptionsPage : public Core::IOptionsPage
......
......@@ -54,80 +54,6 @@
</layout>
</widget>
</item>
<item row="0" column="1">
<widget class="QGroupBox" name="pathGroupBox">
<property name="title">
<string>Paths</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="symbolPathLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="symbolPathButton">
<property name="text">
<string>Edit...</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="sourcePathLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="sourcePathButton">
<property name="text">
<string>Edit...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="breakpointsGroupBox">
<property name="title">
<string>Breakpoints</string>
</property>
<layout class="QVBoxLayout" name="breakpointLayout">
<item>
<widget class="QCheckBox" name="breakpointCorrectionCheckBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Attempt to correct the location of a breakpoint based on file and line number should it be in a comment or in a line for which no code is generated. The correction is based on the code model.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Correct breakpoint location</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="1">
<widget class="QGroupBox" name="breakFunctionGroupBox">
<property name="title">
<string>Break on functions:</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="breakCrtDbgReportCheckBox"/>
</item>
</layout>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QGroupBox" name="eventGroupBox">
<property name="title">
......@@ -135,22 +61,55 @@
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QGroupBox" name="variousGroupBox">
<property name="title">
<string>Various</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="ignoreFirstChanceAccessViolationCheckBox">
<property name="text">
<string>Ignore first chance access violations</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="breakCrtDbgReportCheckBox"/>
</item>
<item>
<widget class="QCheckBox" name="breakpointCorrectionCheckBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Attempt to correct the location of a breakpoint based on file and line number should it be in a comment or in a line for which no code is generated. The correction is based on the code model.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Correct breakpoint location</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="variousGroupBox">
<widget class="QGroupBox" name="symbolPathsGroupBox">
<property name="title">
<string>Various</string>
<string>Symbol Paths</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="ignoreFirstChanceAccessViolationCheckBox">
<property name="text">
<string>Ignore first chance access violations</string>
</property>
</widget>
</item>
</layout>
<layout class="QGridLayout" name="gridLayout_3"/>
</widget>
</item>
<item>
<widget class="QGroupBox" name="sourcePathsGroupBox">
<property name="title">
<string>Source Paths</string>
</property>
<layout class="QGridLayout" name="gridLayout_4"/>
</widget>
</item>
<item>
......
......@@ -263,6 +263,9 @@ QtcPlugin {
"shared/hostutils.h",
"shared/peutils.cpp",
"shared/peutils.h",
"shared/symbolpathsdialog.ui",
"shared/symbolpathsdialog.cpp",
"shared/symbolpathsdialog.h",
]
Group {
......
......@@ -34,10 +34,14 @@
#include <utils/pathchooser.h>
#include <utils/checkablemessagebox.h>
#include <symbolpathsdialog.h>
#include <QCheckBox>
#include <QDir>
#include <QDebug>
#include <QAction>
#include <QFormLayout>
#include <QLabel>
namespace Debugger {
namespace Internal {
......@@ -77,10 +81,13 @@ QString CacheDirectoryDialog::path() const
void CacheDirectoryDialog::accept()
{
// Ensure path exists
QString cache = path();
if (cache.isEmpty())
// if cache is empty a default is used by the cdb
if (cache.isEmpty()) {
QDialog::accept();
return;
}
// Ensure path exists
QFileInfo fi(cache);
// Folder exists - all happy.
if (fi.isDir()) {
......@@ -105,8 +112,9 @@ void CacheDirectoryDialog::accept()
// ---------------- CdbSymbolPathListEditor
const char *CdbSymbolPathListEditor::symbolServerPrefixC = "symsrv*symsrv.dll*";
const char *CdbSymbolPathListEditor::symbolServerPostfixC = "*http://msdl.microsoft.com/download/symbols";
const char *CdbSymbolPathListEditor::symbolServerPrefixC = "srv*";
const char *CdbSymbolPathListEditor::symbolServerPostfixC = "http://msdl.microsoft.com/download/symbols";
const char *CdbSymbolPathListEditor::symbolCachePrefixC = "cache*";
CdbSymbolPathListEditor::CdbSymbolPathListEditor(QWidget *parent) :
Utils::PathListEditor(parent)
......@@ -115,86 +123,146 @@ CdbSymbolPathListEditor::CdbSymbolPathListEditor(QWidget *parent) :
QAction *action = insertAction(lastAddActionIndex() + 1, tr("Symbol Server..."), this, SLOT(addSymbolServer()));
action->setToolTip(tr("Adds the Microsoft symbol server providing symbols for operating system libraries."
"Requires specifying a local cache directory."));
action = insertAction(lastAddActionIndex() + 1, tr("Symbol Cache..."), this, SLOT(addSymbolCache()));
action->setToolTip(tr("Uses a directory to cache symbols used by the debugger."));
}
QString CdbSymbolPathListEditor::promptCacheDirectory(QWidget *parent)
bool CdbSymbolPathListEditor::promptCacheDirectory(QWidget *parent, QString *cacheDirectory)
{
CacheDirectoryDialog dialog(parent);
dialog.setPath(QDir::tempPath() + QDir::separator() + QLatin1String("symbolcache"));
if (dialog.exec() != QDialog::Accepted)
return QString();
return dialog.path();
return false;
*cacheDirectory = dialog.path();
return true;
}
void CdbSymbolPathListEditor::addSymbolServer()
{
const QString cacheDir = promptCacheDirectory(this);
if (!cacheDir.isEmpty())
insertPathAtCursor(CdbSymbolPathListEditor::symbolServerPath(cacheDir));
addSymbolPath(SymbolServerPath);
}
QString CdbSymbolPathListEditor::symbolServerPath(const QString &cacheDir)
void CdbSymbolPathListEditor::addSymbolCache()
{
addSymbolPath(SymbolCachePath);
}
void CdbSymbolPathListEditor::addSymbolPath(CdbSymbolPathListEditor::SymbolPathMode mode)
{
QString cacheDir;
if (promptCacheDirectory(this, &cacheDir))
insertPathAtCursor(CdbSymbolPathListEditor::symbolPath(cacheDir, mode));
}
QString CdbSymbolPathListEditor::symbolPath(const QString &cacheDir,
CdbSymbolPathListEditor::SymbolPathMode mode)
{
if (mode == SymbolCachePath)
return QLatin1String(symbolCachePrefixC) + QDir::toNativeSeparators(cacheDir);
QString s = QLatin1String(symbolServerPrefixC);
s += QDir::toNativeSeparators(cacheDir);
if (!cacheDir.isEmpty())
s += QDir::toNativeSeparators(cacheDir) + QLatin1String("*");
s += QLatin1String(symbolServerPostfixC);
return s;
}
bool CdbSymbolPathListEditor::isSymbolServerPath(const QString &path, QString *cacheDir /* = 0 */)
{
// Split apart symbol server post/prefixes
if (!path.startsWith(QLatin1String(symbolServerPrefixC)) || !path.endsWith(QLatin1String(symbolServerPostfixC)))
return false;
if (cacheDir) {
const unsigned prefixLength = qstrlen(symbolServerPrefixC);
*cacheDir = path.mid(prefixLength, path.size() - prefixLength - qstrlen(symbolServerPostfixC));
static const unsigned prefixLength = qstrlen(symbolServerPrefixC);
static const unsigned postfixLength = qstrlen(symbolServerPostfixC);
if (path.length() == prefixLength + postfixLength)
return true;
// Split apart symbol server post/prefixes
*cacheDir = path.mid(prefixLength, path.size() - prefixLength - qstrlen(symbolServerPostfixC) + 1);
}
return true;
}
int CdbSymbolPathListEditor::indexOfSymbolServerPath(const QStringList &paths, QString *cacheDir /* = 0 */)
bool CdbSymbolPathListEditor::isSymbolCachePath(const QString &path, QString *cacheDir)
{
if (!path.startsWith(QLatin1String(symbolCachePrefixC)))
return false;
if (cacheDir) {
static const unsigned prefixLength = qstrlen(symbolCachePrefixC);
// Split apart symbol cach prefixes
*cacheDir = path.mid(prefixLength);
}
return true;
}
int CdbSymbolPathListEditor::indexOfSymbolPath(const QStringList &paths,
CdbSymbolPathListEditor::SymbolPathMode mode,
QString *cacheDir /* = 0 */)
{
const int count = paths.size();
for (int i = 0; i < count; i++)
if (CdbSymbolPathListEditor::isSymbolServerPath(paths.at(i), cacheDir))
return i;
for (int i = 0; i < count; i++) {
if (mode == SymbolServerPath
? CdbSymbolPathListEditor::isSymbolServerPath(paths.at(i), cacheDir)
: CdbSymbolPathListEditor::isSymbolCachePath(paths.at(i), cacheDir)) {
return i;
}
}
return -1;
}
bool CdbSymbolPathListEditor::promptToAddSymbolServer(const QString &settingsGroup, QStringList *symbolPaths)
bool CdbSymbolPathListEditor::promptToAddSymbolPaths(const QString &settingsGroup,
QStringList *symbolPaths)
{
// Check symbol server unless the user has an external/internal setup
const int indexOfSymbolServer =
CdbSymbolPathListEditor::indexOfSymbolPath(*symbolPaths, SymbolServerPath);
const int indexOfSymbolCache =
CdbSymbolPathListEditor::indexOfSymbolPath(*symbolPaths, SymbolCachePath);
if (!qgetenv("_NT_SYMBOL_PATH").isEmpty()
|| CdbSymbolPathListEditor::indexOfSymbolServerPath(*symbolPaths) != -1)
|| (indexOfSymbolServer != -1 && indexOfSymbolCache != -1))
return false;
// Prompt to use Symbol server unless the user checked "No nagging".
const QString nagSymbolServerKey = settingsGroup + QLatin1String("/NoPromptSymbolServer");
const QString nagSymbolServerKey = settingsGroup + QLatin1String("/NoPromptSymbolCache");
bool noFurtherNagging = Core::ICore::settings()->value(nagSymbolServerKey, false).toBool();
if (noFurtherNagging)
return false;
const QString symServUrl = QLatin1String("http://support.microsoft.com/kb/311503");
const QString msg = tr("<html><head/><body><p>The debugger is not configured to use the public "
"<a href=\"%1\">Microsoft Symbol Server</a>. This is recommended "
"for retrieval of the symbols of the operating system libraries.</p>"
"<p><i>Note:</i> A fast internet connection is required for this to work smoothly. Also, a delay "
"might occur when connecting for the first time.</p>"
"<p>Would you like to set it up?</p>"
"</body></html>").arg(symServUrl);
const QDialogButtonBox::StandardButton answer =
Utils::CheckableMessageBox::question(Core::ICore::mainWindow(), tr("Symbol Server"), msg,
tr("Do not ask again"), &noFurtherNagging);
QString path;
if (indexOfSymbolServer != -1)
path = symbolPaths->at(indexOfSymbolServer);
if (path.isEmpty() && indexOfSymbolCache != -1)
path = symbolPaths->at(indexOfSymbolCache);
if (path.isEmpty())
path = QDir::tempPath() + QDir::separator() + QLatin1String("symbolcache");
bool useSymbolServer = true;
bool useSymbolCache = true;
bool addSymbolPaths = SymbolPathsDialog::useCommonSymbolPaths(useSymbolCache,
useSymbolServer,
path, noFurtherNagging);
Core::ICore::settings()->setValue(nagSymbolServerKey, noFurtherNagging);
if (answer == QDialogButtonBox::No)
return false;
// Prompt for path and add it. Synchronize QSetting and debugger.
const QString cacheDir = CdbSymbolPathListEditor::promptCacheDirectory(Core::ICore::mainWindow());
if (cacheDir.isEmpty())
if (!addSymbolPaths)
return false;
symbolPaths->push_back(CdbSymbolPathListEditor::symbolServerPath(cacheDir));
return true;
// remove old entries
if (indexOfSymbolServer > indexOfSymbolCache) {
symbolPaths->removeAt(indexOfSymbolServer);
if (indexOfSymbolCache != -1)
symbolPaths->removeAt(indexOfSymbolCache);
} else if (indexOfSymbolCache > indexOfSymbolServer) {
symbolPaths->removeAt(indexOfSymbolCache);
if (indexOfSymbolServer != -1)
symbolPaths->removeAt(indexOfSymbolServer);
}
if (useSymbolCache) {
symbolPaths->push_back(CdbSymbolPathListEditor::symbolPath(path, SymbolCachePath));
if (useSymbolServer)
symbolPaths->push_back(CdbSymbolPathListEditor::symbolPath(QString(), SymbolServerPath));
return true;
} else if (useSymbolServer) {
symbolPaths->push_back(CdbSymbolPathListEditor::symbolPath(path, SymbolServerPath));
return true;
}
return false;
}
} // namespace Internal
......
......@@ -52,7 +52,7 @@ namespace Internal {
// created. This is done here (suggest $TEMP\symbolcache
// regardless of its existence).
class CacheDirectoryDialog : public QDialog {
class CacheDirectoryDialog : public QDialog {
Q_OBJECT
public:
explicit CacheDirectoryDialog(QWidget *parent = 0);
......@@ -71,26 +71,38 @@ class CdbSymbolPathListEditor : public Utils::PathListEditor
{
Q_OBJECT
public:
enum SymbolPathMode{
SymbolServerPath,
SymbolCachePath
};
explicit CdbSymbolPathListEditor(QWidget *parent = 0);
static QString promptCacheDirectory(QWidget *parent);
static bool promptCacheDirectory(QWidget *parent, QString *cacheDirectory);
// Pre- and Postfix used to build a symbol server path specification
static const char *symbolServerPrefixC;
static const char *symbolServerPostfixC;
static const char *symbolCachePrefixC;
// Format a symbol server specification with a local cache directory
static QString symbolServerPath(const QString &cacheDir);
// Format a symbol path specification
static QString symbolPath(const QString &cacheDir, SymbolPathMode mode);
// Check for a symbol server path and extract local cache directory
static bool isSymbolServerPath(const QString &path, QString *cacheDir = 0);
// Check for a symbol cache path and extract local cache directory
static bool isSymbolCachePath(const QString &path, QString *cacheDir = 0);
// Check for symbol server in list of paths.
static int indexOfSymbolServerPath(const QStringList &paths, QString *cacheDir = 0);
static int indexOfSymbolPath(const QStringList &paths, SymbolPathMode mode, QString *cacheDir = 0);
// Nag user to add a symbol cache and server to the path list on debugger startup.
static bool promptToAddSymbolPaths(const QString &settingsGroup, QStringList *symbolPaths);
// Nag user to add a symbol server to the path list on debugger startup.
static bool promptToAddSymbolServer(const QString &settingsGroup, QStringList *symbolPaths);
private:
void addSymbolPath(SymbolPathMode mode);
private slots:
void addSymbolServer();
void addSymbolCache();
};
} // namespace Internal
......
SOURCES += $$PWD/backtrace.cpp \
$$PWD/cdbsymbolpathlisteditor.cpp \
$$PWD/hostutils.cpp \
$$PWD/peutils.cpp