forked from qt-creator/qt-creator
Debugger: Add CDB symbol cache option.
Change-Id: I9c4ec9bbcc0216271d6e4d10e9f6e925d3569cea Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
This commit is contained in:
@@ -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><html><head/><body><p>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.</p></body></html></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,8 +61,8 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="variousGroupBox">
|
||||
<property name="title">
|
||||
@@ -150,9 +76,42 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="breakCrtDbgReportCheckBox"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="breakpointCorrectionCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>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.</p></body></html></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="symbolPathsGroupBox">
|
||||
<property name="title">
|
||||
<string>Symbol Paths</string>
|
||||
</property>
|
||||
<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>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -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))
|
||||
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));
|
||||
// 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
|
||||
|
||||
@@ -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 server to the path list on debugger startup.
|
||||
static bool promptToAddSymbolServer(const QString &settingsGroup, QStringList *symbolPaths);
|
||||
// Nag user to add a symbol cache and server to the path list on debugger startup.
|
||||
static bool promptToAddSymbolPaths(const QString &settingsGroup, QStringList *symbolPaths);
|
||||
|
||||
private:
|
||||
void addSymbolPath(SymbolPathMode mode);
|
||||
|
||||
private slots:
|
||||
void addSymbolServer();
|
||||
void addSymbolCache();
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
SOURCES += $$PWD/backtrace.cpp \
|
||||
$$PWD/cdbsymbolpathlisteditor.cpp \
|
||||
$$PWD/hostutils.cpp \
|
||||
$$PWD/peutils.cpp
|
||||
$$PWD/peutils.cpp \
|
||||
shared/symbolpathsdialog.cpp
|
||||
|
||||
HEADERS += $$PWD/backtrace.h \
|
||||
$$PWD/cdbsymbolpathlisteditor.h \
|
||||
$$PWD/hostutils.h \
|
||||
$$PWD/peutils.h
|
||||
$$PWD/peutils.h \
|
||||
shared/symbolpathsdialog.h
|
||||
|
||||
INCLUDEPATH += $$PWD
|
||||
|
||||
@@ -14,3 +16,6 @@ win32-msvc* {
|
||||
# For the Privilege manipulation functions in sharedlibraryinjector.cpp.
|
||||
LIBS += -ladvapi32
|
||||
}
|
||||
|
||||
FORMS += \
|
||||
shared/symbolpathsdialog.ui
|
||||
|
||||
104
src/plugins/debugger/shared/symbolpathsdialog.cpp
Normal file
104
src/plugins/debugger/shared/symbolpathsdialog.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "symbolpathsdialog.h"
|
||||
#include "ui_symbolpathsdialog.h"
|
||||
#include "QMessageBox"
|
||||
|
||||
using namespace Debugger;
|
||||
using namespace Internal;
|
||||
|
||||
SymbolPathsDialog::SymbolPathsDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::SymbolPathsDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->pixmapLabel->setPixmap(QMessageBox::standardIcon(QMessageBox::Question));
|
||||
}
|
||||
|
||||
SymbolPathsDialog::~SymbolPathsDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool SymbolPathsDialog::useSymbolCache() const
|
||||
{
|
||||
return ui->useLocalSymbolCache->isChecked();
|
||||
}
|
||||
|
||||
bool SymbolPathsDialog::useSymbolServer() const
|
||||
{
|
||||
return ui->useSymbolServer->isChecked();
|
||||
}
|
||||
|
||||
QString SymbolPathsDialog::path() const
|
||||
{
|
||||
return ui->pathChooser->path();
|
||||
}
|
||||
|
||||
bool SymbolPathsDialog::doNotAskAgain() const
|
||||
{
|
||||
return ui->doNotAskAgain->isChecked();
|
||||
}
|
||||
|
||||
void SymbolPathsDialog::setUseSymbolCache(bool useSymbolCache)
|
||||
{
|
||||
ui->useLocalSymbolCache->setChecked(useSymbolCache);
|
||||
}
|
||||
|
||||
void SymbolPathsDialog::setUseSymbolServer(bool useSymbolServer)
|
||||
{
|
||||
ui->useSymbolServer->setChecked(useSymbolServer);
|
||||
}
|
||||
|
||||
void SymbolPathsDialog::setPath(const QString &path)
|
||||
{
|
||||
ui->pathChooser->setPath(path);
|
||||
}
|
||||
|
||||
void SymbolPathsDialog::setDoNotAskAgain(bool doNotAskAgain) const
|
||||
{
|
||||
ui->doNotAskAgain->setChecked(doNotAskAgain);
|
||||
}
|
||||
|
||||
bool SymbolPathsDialog::useCommonSymbolPaths(bool &useSymbolCache, bool &useSymbolServer,
|
||||
QString &path, bool &doNotAskAgain)
|
||||
{
|
||||
SymbolPathsDialog dialog;
|
||||
dialog.setUseSymbolCache(useSymbolCache);
|
||||
dialog.setUseSymbolServer(useSymbolServer);
|
||||
dialog.setPath(path);
|
||||
dialog.setDoNotAskAgain(doNotAskAgain);
|
||||
int ret = dialog.exec();
|
||||
useSymbolCache = dialog.useSymbolCache();
|
||||
useSymbolServer = dialog.useSymbolServer();
|
||||
path = dialog.path();
|
||||
doNotAskAgain = dialog.doNotAskAgain();
|
||||
return ret == QDialog::Accepted;
|
||||
}
|
||||
70
src/plugins/debugger/shared/symbolpathsdialog.h
Normal file
70
src/plugins/debugger/shared/symbolpathsdialog.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef SYMBOLPATHSDIALOG_H
|
||||
#define SYMBOLPATHSDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QString>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
namespace Ui {
|
||||
class SymbolPathsDialog;
|
||||
}
|
||||
|
||||
class SymbolPathsDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SymbolPathsDialog(QWidget *parent = 0);
|
||||
~SymbolPathsDialog();
|
||||
|
||||
bool useSymbolCache() const;
|
||||
bool useSymbolServer() const;
|
||||
QString path() const;
|
||||
bool doNotAskAgain() const;
|
||||
|
||||
void setUseSymbolCache(bool useSymbolCache);
|
||||
void setUseSymbolServer(bool useSymbolServer);
|
||||
void setPath(const QString &path);
|
||||
void setDoNotAskAgain(bool doNotAskAgain) const;
|
||||
|
||||
static bool useCommonSymbolPaths(bool &useSymbolCache, bool &useSymbolServer, QString &path, bool &doNotAskAgain);
|
||||
|
||||
private:
|
||||
Ui::SymbolPathsDialog *ui;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // SYMBOLPATHSDIALOG_H
|
||||
152
src/plugins/debugger/shared/symbolpathsdialog.ui
Normal file
152
src/plugins/debugger/shared/symbolpathsdialog.ui
Normal file
@@ -0,0 +1,152 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Debugger::Internal::SymbolPathsDialog</class>
|
||||
<widget class="QDialog" name="Debugger::Internal::SymbolPathsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>537</width>
|
||||
<height>245</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="pixmapLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="msgLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body>
|
||||
<p>The debugger is not configured to use the public Microsoft Symbol Server.<br>This is recommended for retrieval of the symbols of the operating system libraries.</p>
|
||||
<p><span style=" font-style:italic;">Note:</span> It is recommended, that if you use the Microsoft Symbol Server, to also use a local symbol cache.<br>Also, a fast internet connection is required for this to work smoothly,<br>and a delay might occur when connecting for the first time, when caching the symbols for the first time.</p>
|
||||
<p>Would you like to set it up?</p>
|
||||
</body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="useLocalSymbolCache">
|
||||
<property name="text">
|
||||
<string>Use Local Symbol Cache</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="useSymbolServer">
|
||||
<property name="text">
|
||||
<string>Use Microsoft Symbol Server</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Utils::PathChooser" name="pathChooser" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="doNotAskAgain">
|
||||
<property name="text">
|
||||
<string>Do not ask again</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Utils::PathChooser</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>utils/pathchooser.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Debugger::Internal::SymbolPathsDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Debugger::Internal::SymbolPathsDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
Reference in New Issue
Block a user