Commit 7d41e048 authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

Split apart debugger options pages, allow specifying a path to CDB.

Modify engine creation funcs to populate a list of option pages
to be able to handle engine enabling independently of the
actual engine creation.
parent bc89f5dc
......@@ -44,15 +44,17 @@
#include <QtGui/QToolButton>
#include <QtGui/QPushButton>
namespace Core {
namespace Utils {
#ifdef Q_OS_MAC
/*static*/ const char * const PathChooser::browseButtonLabel = "Choose...";
/*static*/ const char * const Core::Utils::PathChooser::browseButtonLabel =
QT_TRANSLATE_NOOP("Core::Utils::PathChooser", "Choose...");
#else
/*static*/ const char * const PathChooser::browseButtonLabel = "Browse...";
/*static*/ const char * const Core::Utils::PathChooser::browseButtonLabel =
QT_TRANSLATE_NOOP("Core::Utils::PathChooser", "Browse...");
#endif
namespace Core {
namespace Utils {
// ------------------ PathValidatingLineEdit
class PathValidatingLineEdit : public BaseValidatingLineEdit
{
......@@ -83,6 +85,7 @@ struct PathChooserPrivate
{
PathChooserPrivate(PathChooser *chooser);
QHBoxLayout *m_hLayout;
PathValidatingLineEdit *m_lineEdit;
PathChooser::Kind m_acceptingKind;
QString m_dialogTitleOverride;
......@@ -90,6 +93,7 @@ struct PathChooserPrivate
};
PathChooserPrivate::PathChooserPrivate(PathChooser *chooser) :
m_hLayout(new QHBoxLayout),
m_lineEdit(new PathValidatingLineEdit(chooser)),
m_acceptingKind(PathChooser::Directory)
{
......@@ -99,8 +103,8 @@ PathChooser::PathChooser(QWidget *parent) :
QWidget(parent),
m_d(new PathChooserPrivate(this))
{
QHBoxLayout *hLayout = new QHBoxLayout;
hLayout->setContentsMargins(0, 0, 0, 0);
m_d->m_hLayout->setContentsMargins(0, 0, 0, 0);
connect(m_d->m_lineEdit, SIGNAL(validReturnPressed()), this, SIGNAL(returnPressed()));
connect(m_d->m_lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(changed()));
......@@ -108,19 +112,12 @@ PathChooser::PathChooser(QWidget *parent) :
connect(m_d->m_lineEdit, SIGNAL(editingFinished()), this, SIGNAL(editingFinished()));
m_d->m_lineEdit->setMinimumWidth(200);
hLayout->addWidget(m_d->m_lineEdit);
hLayout->setSizeConstraint(QLayout::SetMinimumSize);
m_d->m_hLayout->addWidget(m_d->m_lineEdit);
m_d->m_hLayout->setSizeConstraint(QLayout::SetMinimumSize);
#ifdef Q_OS_MAC
QPushButton *browseButton = new QPushButton;
#else
QToolButton *browseButton = new QToolButton;
#endif
browseButton->setText(tr(browseButtonLabel));
connect(browseButton, SIGNAL(clicked()), this, SLOT(slotBrowse()));
addButton(tr(browseButtonLabel), this, SLOT(slotBrowse()));
hLayout->addWidget(browseButton);
setLayout(hLayout);
setLayout(m_d->m_hLayout);
setFocusProxy(m_d->m_lineEdit);
}
......@@ -129,6 +126,18 @@ PathChooser::~PathChooser()
delete m_d;
}
void PathChooser::addButton(const QString &text, QObject *receiver, const char *slotFunc)
{
#ifdef Q_OS_MAC
QPushButton *button = new QPushButton;
#else
QToolButton *button = new QToolButton;
#endif
button->setText(text);
connect(button, SIGNAL(clicked()), receiver, slotFunc);
m_d->m_hLayout->addWidget(button);
}
QString PathChooser::path() const
{
return m_d->m_lineEdit->text();
......
......@@ -82,6 +82,8 @@ public:
/** Return the home directory, which needs some fixing under Windows. */
static QString homePath();
void addButton(const QString &text, QObject *receiver, const char *slotFunc);
private:
// Returns overridden title or the one from <title>
QString makeDialogTitle(const QString &title);
......
......@@ -25,6 +25,6 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.</license>
<dependency name="Find" version="1.1.80"/>
</dependencyList>
<argumentList>
<argument name="-enable-cdb"/>
<argument name="-disable-cdb">Disable CDB debugger engine</argument>
</argumentList>
</plugin>
......@@ -10,6 +10,10 @@ CDB_PATH="$$(ProgramFiles)/Debugging Tools For Windows/sdk"
CDB_PATH="$$(ProgramFiles)/Debugging Tools For Windows (x86)/sdk"
}
!exists ($$CDB_PATH) {
CDB_PATH="$$(ProgramFiles)/Debugging Tools For Windows (x64)/sdk"
}
exists ($$CDB_PATH) {
message("Experimental: Adding support for $$CDB_PATH")
......@@ -31,7 +35,9 @@ HEADERS += \
$$PWD/cdbstacktracecontext.h \
$$PWD/cdbbreakpoint.h \
$$PWD/cdbmodules.h \
$$PWD/cdbassembler.h
$$PWD/cdbassembler.h \
$$PWD/cdboptions.h \
$$PWD/cdboptionspage.h
SOURCES += \
$$PWD/cdbdebugengine.cpp \
......@@ -41,7 +47,11 @@ SOURCES += \
$$PWD/cdbstacktracecontext.cpp \
$$PWD/cdbbreakpoint.cpp \
$$PWD/cdbmodules.cpp \
$$PWD/cdbassembler.cpp
$$PWD/cdbassembler.cpp \
$$PWD/cdboptions.cpp \
$$PWD/cdboptionspage.cpp
FORMS += $$PWD/cdboptionspagewidget.ui
} else {
message("Debugging Tools for Windows could not be found in $$CDB_PATH")
......
......@@ -34,6 +34,8 @@
#include "cdbbreakpoint.h"
#include "cdbmodules.h"
#include "cdbassembler.h"
#include "cdboptionspage.h"
#include "cdboptions.h"
#include "debuggeractions.h"
#include "debuggermanager.h"
......@@ -45,6 +47,7 @@
#include "disassemblerhandler.h"
#include "watchutils.h"
#include <coreplugin/icore.h>
#include <utils/qtcassert.h>
#include <utils/winutils.h>
#include <utils/consoleprocess.h>
......@@ -140,10 +143,15 @@ DebuggerEngineLibrary::DebuggerEngineLibrary() :
{
}
bool DebuggerEngineLibrary::init(QString *errorMessage)
bool DebuggerEngineLibrary::init(const QString &path, QString *errorMessage)
{
// Load
QLibrary lib(QLatin1String(dbgEngineDllC), 0);
// Load from path
QString dllPath = path;
if (!dllPath.isEmpty())
dllPath += QDir::separator();
dllPath += QLatin1String(dbgEngineDllC);
QLibrary lib(dllPath, 0);
if (!lib.isLoaded() && !lib.load()) {
*errorMessage = CdbDebugEngine::tr("Unable to load the debugger engine library '%1': %2").
......@@ -191,7 +199,10 @@ SyntaxSetter::~SyntaxSetter()
// --- CdbDebugEnginePrivate
CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *parent, CdbDebugEngine* engine) :
CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *parent,
const QSharedPointer<CdbOptions> &options,
CdbDebugEngine* engine) :
m_options(options),
m_hDebuggeeProcess(0),
m_hDebuggeeThread(0),
m_breakEventMode(BreakEventHandle),
......@@ -215,7 +226,7 @@ bool CdbDebugEnginePrivate::init(QString *errorMessage)
{
// Load the DLL
DebuggerEngineLibrary lib;
if (!lib.init(errorMessage))
if (!lib.init(m_options->path, errorMessage))
return false;
// Initialize the COM interfaces
......@@ -259,18 +270,15 @@ bool CdbDebugEnginePrivate::init(QString *errorMessage)
return true;
}
IDebuggerEngine *CdbDebugEngine::create(DebuggerManager *parent)
IDebuggerEngine *CdbDebugEngine::create(DebuggerManager *parent,
const QSharedPointer<CdbOptions> &options,
QString *errorMessage)
{
QString errorMessage;
IDebuggerEngine *rc = 0;
CdbDebugEngine *e = new CdbDebugEngine(parent);
if (e->m_d->init(&errorMessage)) {
rc = e;
} else {
delete e;
qWarning("%s", qPrintable(errorMessage));
}
return rc;
CdbDebugEngine *rc = new CdbDebugEngine(parent, options);
if (rc->m_d->init(errorMessage))
return rc;
delete rc;
return 0;
}
CdbDebugEnginePrivate::~CdbDebugEnginePrivate()
......@@ -306,9 +314,9 @@ void CdbDebugEnginePrivate::cleanStackTrace()
}
}
CdbDebugEngine::CdbDebugEngine(DebuggerManager *parent) :
CdbDebugEngine::CdbDebugEngine(DebuggerManager *parent, const QSharedPointer<CdbOptions> &options) :
IDebuggerEngine(parent),
m_d(new CdbDebugEnginePrivate(parent, this))
m_d(new CdbDebugEnginePrivate(parent, options, this))
{
// m_d->m_consoleStubProc.setDebug(true);
connect(&m_d->m_consoleStubProc, SIGNAL(processError(QString)), this, SLOT(slotConsoleStubError(QString)));
......@@ -1327,8 +1335,24 @@ void CdbDebugEngine::reloadSourceFiles()
} // namespace Debugger
// Accessed by DebuggerManager
Debugger::Internal::IDebuggerEngine *createWinEngine(Debugger::Internal::DebuggerManager *parent)
{
return Debugger::Internal::CdbDebugEngine::create(parent);
Debugger::Internal::IDebuggerEngine *createWinEngine(Debugger::Internal::DebuggerManager *parent,
bool cmdLineDisabled,
QList<Core::IOptionsPage*> *opts)
{
// Create options page
QSharedPointer<Debugger::Internal::CdbOptions> options(new Debugger::Internal::CdbOptions);
options->fromSettings(Core::ICore::instance()->settings());
Debugger::Internal::CdbOptionsPage *optionsPage = new Debugger::Internal::CdbOptionsPage(options);
opts->push_back(optionsPage);
if (cmdLineDisabled || !options->enabled)
return 0;
// Create engine
QString errorMessage;
Debugger::Internal::IDebuggerEngine *engine =
Debugger::Internal::CdbDebugEngine::create(parent, options, &errorMessage);
if (!engine) {
optionsPage->setFailureMessage(errorMessage);
qWarning("%s", qPrintable(errorMessage));
}
return engine;
}
......@@ -33,6 +33,8 @@
#include "idebuggerengine.h"
#include "debuggermanager.h"
#include <QtCore/QSharedPointer>
namespace Debugger {
namespace Internal {
......@@ -40,18 +42,22 @@ class DebuggerManager;
class CdbDebugEventCallback;
class CdbDebugOutput;
struct CdbDebugEnginePrivate;
struct CdbOptions;
class CdbDebugEngine : public IDebuggerEngine
{
Q_DISABLE_COPY(CdbDebugEngine)
Q_OBJECT
explicit CdbDebugEngine(DebuggerManager *parent);
explicit CdbDebugEngine(DebuggerManager *parent,
const QSharedPointer<CdbOptions> &options);
public:
~CdbDebugEngine();
// Factory function that returns 0 if the debug engine library cannot be found.
static IDebuggerEngine *create(DebuggerManager *parent);
static IDebuggerEngine *create(DebuggerManager *parent,
const QSharedPointer<CdbOptions> &options,
QString *errorMessage);
virtual void shutdown();
virtual void setToolTipExpression(const QPoint &pos, const QString &exp);
......
......@@ -32,9 +32,12 @@
#include "cdbdebugeventcallback.h"
#include "cdbdebugoutput.h"
#include "cdboptions.h"
#include "stackhandler.h"
#include "debuggermanager.h"
#include <utils/consoleprocess.h>
#include <QtCore/QSharedPointer>
namespace Debugger {
namespace Internal {
......@@ -52,7 +55,7 @@ class DebuggerEngineLibrary
{
public:
DebuggerEngineLibrary();
bool init(QString *errorMessage);
bool init(const QString &path, QString *errorMessage);
inline HRESULT debugCreate(REFIID interfaceId, PVOID *interfaceHandle) const
{ return m_debugCreate(interfaceId, interfaceHandle); }
......@@ -72,7 +75,9 @@ struct CdbDebugEnginePrivate
BreakEventSyncBreakPoints,
};
explicit CdbDebugEnginePrivate(DebuggerManager *parent, CdbDebugEngine* engine);
explicit CdbDebugEnginePrivate(DebuggerManager *parent,
const QSharedPointer<CdbOptions> &options,
CdbDebugEngine* engine);
bool init(QString *errorMessage);
~CdbDebugEnginePrivate();
......@@ -98,6 +103,7 @@ struct CdbDebugEnginePrivate
bool attemptBreakpointSynchronization(QString *errorMessage);
const QSharedPointer<CdbOptions> m_options;
HANDLE m_hDebuggeeProcess;
HANDLE m_hDebuggeeThread;
int m_currentThreadId;
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/
#include "cdboptions.h"
#include <QtCore/QSettings>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
static const char *settingsGroupC = "CDB";
static const char *enabledKeyC = "enabled";
static const char *pathKeyC = "path";
namespace Debugger {
namespace Internal {
CdbOptions::CdbOptions() :
enabled(false)
{
}
void CdbOptions::clear()
{
enabled = false;
path.clear();
}
void CdbOptions::fromSettings(const QSettings *s)
{
clear();
// Is this the first time we are called ->
// try to find automatically
const QString keyRoot = QLatin1String(settingsGroupC) + QLatin1Char('/');
const QString enabledKey = keyRoot + QLatin1String(enabledKeyC);
const bool firstTime = !s->contains(enabledKey);
if (firstTime) {
enabled = autoDetectPath(&path);
return;
}
enabled = s->value(enabledKey, false).toBool();
path = s->value(keyRoot + QLatin1String(pathKeyC), QString()).toString();
}
void CdbOptions::toSettings(QSettings *s) const
{
s->beginGroup(QLatin1String(settingsGroupC));
s->setValue(QLatin1String(enabledKeyC), enabled);
s->setValue(QLatin1String(pathKeyC), path);
s->endGroup();
}
bool CdbOptions::autoDetectPath(QString *outPath)
{
// Look for $ProgramFiles/"Debugging Tools For Windows" and its
// :" (x86)", " (x64)" variations
static const char *postFixes[] = { " (x86)", " (x64)" };
outPath->clear();
const QByteArray programDirB = qgetenv("ProgramFiles");
if (programDirB.isEmpty())
return false;
const QString programDir = QString::fromLocal8Bit(programDirB) + QDir::separator();
const QString installDir = QLatin1String("Debugging Tools For Windows");
QString path = programDir + installDir;
if (QFileInfo(path).isDir()) {
*outPath = QDir::toNativeSeparators(path);
return true;
}
const int rootLength = path.size();
for (int i = 0; i < sizeof(postFixes)/sizeof(const char*); i++) {
path.truncate(rootLength);
path += QLatin1String(postFixes[i]);
if (QFileInfo(path).isDir()) {
*outPath = QDir::toNativeSeparators(path);
return true;
}
}
return false;
}
bool CdbOptions::equals(const CdbOptions &rhs) const
{
return enabled == rhs.enabled && path == rhs.path;
}
} // namespace Internal
} // namespace Debugger
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/
#ifndef CDBSETTINGS_H
#define CDBSETTINGS_H
#include <QtCore/QString>
QT_BEGIN_NAMESPACE
class QSettings;
QT_END_NAMESPACE
namespace Debugger {
namespace Internal {
struct CdbOptions
{
public:
CdbOptions();
void clear();
void fromSettings(const QSettings *s);
void toSettings(QSettings *s) const;
bool equals(const CdbOptions &s) const;
// Locate the debugging tools
static bool autoDetectPath(QString *path);
bool enabled;
QString path;
};
inline bool operator==(const CdbOptions &s1, const CdbOptions &s2)
{ return s1.equals(s2); }
inline bool operator!=(const CdbOptions &s1, const CdbOptions &s2)
{ return !s1.equals(s2); }
} // namespace Internal
} // namespace Debugger
#endif // CDBSETTINGS_H
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/
#include "cdboptionspage.h"
#include "cdboptions.h"
#include "debuggerconstants.h"
#include <coreplugin/icore.h>
#include <QtCore/QCoreApplication>
const char * const CDB_SETTINGS_ID = QT_TRANSLATE_NOOP("Debugger::Internal::CdbOptionsPageWidget", "CDB");
namespace Debugger {
namespace Internal {
CdbOptionsPageWidget::CdbOptionsPageWidget(QWidget *parent) :
QWidget(parent)
{
m_ui.setupUi(this);
m_ui.pathChooser->setExpectedKind(Core::Utils::PathChooser::Directory);
m_ui.pathChooser->addButton(tr("Autodetect"), this, SLOT(autoDetect()));
m_ui.failureLabel->setVisible(false);
}
void CdbOptionsPageWidget::setOptions(CdbOptions &o)
{
m_ui.pathChooser->setPath(o.path);
m_ui.cdbOptionsGroupBox->setChecked(o.enabled);
}
CdbOptions CdbOptionsPageWidget::options() const
{
CdbOptions rc;
rc.path = m_ui.pathChooser->path();
rc.enabled = m_ui.cdbOptionsGroupBox->isChecked();
return rc;
}
void CdbOptionsPageWidget::autoDetect()
{
QString path;
const bool ok = CdbOptions::autoDetectPath(&path);
m_ui.cdbOptionsGroupBox->setChecked(ok);
if (ok)
m_ui.pathChooser->setPath(path);
}
void CdbOptionsPageWidget::setFailureMessage(const QString &msg)
{
m_ui.failureLabel->setText(msg);
m_ui.failureLabel->setVisible(!msg.isEmpty());
}
// ---------- CdbOptionsPage
CdbOptionsPage::CdbOptionsPage(const QSharedPointer<CdbOptions> &options) :
m_options(options)
{