forked from qt-creator/qt-creator
ToolChain: Refactor toolchain support
Refactor ToolChains in Qt Creator: * Allow for several toolchains of the same type * Be smarter wrt. guessing what kind of output a toolchain produces. This allows us to eventually handle e.g. embedded linux setups way better than before. * Be smarter wrt. guessing what kind of environment a Qt version needs. * Improve auto-detection of toolchains a bit * Decide on which debugger to use based on the kind of output produced by the compiler. * Add options page to configure toolchains * Remove toolchain related options from the Qt version dialog Reviewed-by: dt
This commit is contained in:
@@ -52,51 +52,15 @@
|
||||
#include <QtGui/QIcon>
|
||||
#include <QtGui/QGroupBox>
|
||||
#include <QtGui/QCheckBox>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QSet>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QProcess>
|
||||
|
||||
enum { binaryRole = Qt::UserRole + 1, toolChainRole = Qt::UserRole + 2 };
|
||||
enum Columns { binaryColumn, toolChainColumn, ColumnCount };
|
||||
enum Columns { abiColumn, binaryColumn, ColumnCount };
|
||||
|
||||
typedef QList<QStandardItem *> StandardItemList;
|
||||
|
||||
Q_DECLARE_METATYPE(QList<int>)
|
||||
|
||||
static QList<int> allGdbToolChains()
|
||||
{
|
||||
QList<int> rc;
|
||||
rc
|
||||
#ifdef Q_OS_UNIX
|
||||
<< ProjectExplorer::ToolChain_GCC
|
||||
<< ProjectExplorer::ToolChain_LINUX_ICC
|
||||
#endif
|
||||
#ifdef Q_OS_WIN
|
||||
<< ProjectExplorer::ToolChain_MinGW
|
||||
<< ProjectExplorer::ToolChain_WINSCW
|
||||
<< ProjectExplorer::ToolChain_GCCE
|
||||
<< ProjectExplorer::ToolChain_RVCT2_ARMV5
|
||||
<< ProjectExplorer::ToolChain_RVCT2_ARMV6
|
||||
#endif
|
||||
<< ProjectExplorer::ToolChain_GCC_MAEMO5
|
||||
<< ProjectExplorer::ToolChain_GCC_HARMATTAN
|
||||
<< ProjectExplorer::ToolChain_GCC_MEEGO
|
||||
#ifdef Q_OS_UNIX
|
||||
<< ProjectExplorer::ToolChain_GCCE_GNUPOC
|
||||
<< ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC
|
||||
#endif
|
||||
<< ProjectExplorer::ToolChain_OTHER
|
||||
<< ProjectExplorer::ToolChain_UNKNOWN;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline QString toolChainName(int tc)
|
||||
{
|
||||
return ProjectExplorer::ToolChain::toolChainName(static_cast<ProjectExplorer::ToolChainType>(tc));
|
||||
}
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
@@ -105,6 +69,10 @@ namespace Internal {
|
||||
// Obtain a tooltip for a gdb binary by running --version
|
||||
static inline QString gdbToolTip(const QString &binary)
|
||||
{
|
||||
if (binary.isEmpty())
|
||||
return QString();
|
||||
if (!QFileInfo(binary).exists())
|
||||
return GdbChooserWidget::tr("File not found.");
|
||||
QProcess process;
|
||||
process.start(binary, QStringList(QLatin1String("--version")));
|
||||
process.closeWriteChannel();
|
||||
@@ -122,37 +90,32 @@ static inline QString gdbToolTip(const QString &binary)
|
||||
// Provides a delayed tooltip listing the gdb version as
|
||||
// obtained by running it. Provides conveniences for getting/setting the maps and
|
||||
// for listing the toolchains used and the ones still available.
|
||||
|
||||
class GdbBinaryModel : public QStandardItemModel {
|
||||
public:
|
||||
typedef GdbChooserWidget::BinaryToolChainMap BinaryToolChainMap;
|
||||
|
||||
explicit GdbBinaryModel(QObject * parent = 0);
|
||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||
|
||||
// get / set data as map.
|
||||
BinaryToolChainMap gdbBinaries() const;
|
||||
void setGdbBinaries(const BinaryToolChainMap &m);
|
||||
QMap<QString, QString> gdbMapping() const;
|
||||
void setGdbMapping(const QMap<QString, QString> &m);
|
||||
|
||||
QString binary(int row) const;
|
||||
QList<int> toolChains(int row) const;
|
||||
QString abi(int row) const;
|
||||
|
||||
QStringList binaries() const;
|
||||
QList<int> usedToolChains() const;
|
||||
QSet<int> unusedToolChainSet() const;
|
||||
QList<int> unusedToolChains() const;
|
||||
void append(const QString &abi, const QString &binary);
|
||||
|
||||
void append(const QString &binary, const QList<int> &toolChains);
|
||||
bool isDirty() const;
|
||||
|
||||
static void setAbiItem(QStandardItem *item, const QString &abi);
|
||||
static void setBinaryItem(QStandardItem *item, const QString &binary);
|
||||
static void setToolChainItem(QStandardItem *item, const QList<int> &toolChain);
|
||||
};
|
||||
|
||||
GdbBinaryModel::GdbBinaryModel(QObject *parent) :
|
||||
QStandardItemModel(0, ColumnCount, parent)
|
||||
{
|
||||
QStringList headers;
|
||||
headers << GdbChooserWidget::tr("Binary") << GdbChooserWidget::tr("Toolchains");
|
||||
headers << GdbChooserWidget::tr("ABI") << GdbChooserWidget::tr("Debugger");
|
||||
setHorizontalHeaderLabels(headers);
|
||||
}
|
||||
|
||||
@@ -166,455 +129,119 @@ QVariant GdbBinaryModel::data(const QModelIndex &index, int role) const
|
||||
// Run the gdb and obtain the tooltip
|
||||
const QString tooltip = gdbToolTip(binary(index.row()));
|
||||
// Set on the whole row
|
||||
item(index.row(), abiColumn)->setToolTip(tooltip);
|
||||
item(index.row(), binaryColumn)->setToolTip(tooltip);
|
||||
item(index.row(), toolChainColumn)->setToolTip(tooltip);
|
||||
return QVariant(tooltip);
|
||||
}
|
||||
return QStandardItemModel::data(index, role);
|
||||
}
|
||||
|
||||
QStringList GdbBinaryModel::binaries() const
|
||||
bool GdbBinaryModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
QStringList rc;
|
||||
const int binaryCount = rowCount();
|
||||
for (int b = 0; b < binaryCount; b++)
|
||||
rc.push_back(binary(b));
|
||||
return rc;
|
||||
}
|
||||
|
||||
QList<int> GdbBinaryModel::usedToolChains() const
|
||||
{
|
||||
// Loop over model and collect all toolchains.
|
||||
QList<int> rc;
|
||||
const int binaryCount = rowCount();
|
||||
for (int b = 0; b < binaryCount; b++)
|
||||
foreach(int tc, toolChains(b))
|
||||
rc.push_back(tc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
QSet<int> GdbBinaryModel::unusedToolChainSet() const
|
||||
{
|
||||
const QSet<int> used = usedToolChains().toSet();
|
||||
QSet<int> all = allGdbToolChains().toSet();
|
||||
return all.subtract(used);
|
||||
}
|
||||
|
||||
QList<int> GdbBinaryModel::unusedToolChains() const
|
||||
{
|
||||
QList<int> unused = unusedToolChainSet().toList();
|
||||
qSort(unused);
|
||||
return unused;
|
||||
}
|
||||
|
||||
GdbBinaryModel::BinaryToolChainMap GdbBinaryModel::gdbBinaries() const
|
||||
{
|
||||
BinaryToolChainMap rc;
|
||||
const int binaryCount = rowCount();
|
||||
for (int r = 0; r < binaryCount; r++) {
|
||||
const QString bin = binary(r);
|
||||
foreach(int tc, toolChains(r))
|
||||
rc.insert(bin, tc);
|
||||
if (index.isValid() && role == Qt::EditRole) {
|
||||
Q_ASSERT(index.column() == binaryColumn);
|
||||
item(index.row(), abiColumn)->setToolTip(QString());
|
||||
item(index.row(), binaryColumn)->setToolTip(QString());
|
||||
item(index.row(), binaryColumn)->setData(true);
|
||||
QFont f(item(index.row(), binaryColumn)->font());
|
||||
f.setBold(true);
|
||||
item(index.row(), binaryColumn)->setFont(f);
|
||||
}
|
||||
return QStandardItemModel::setData(index, value, role);
|
||||
}
|
||||
|
||||
QMap<QString, QString> GdbBinaryModel::gdbMapping() const
|
||||
{
|
||||
QMap<QString, QString> rc;
|
||||
const int binaryCount = rowCount();
|
||||
for (int r = 0; r < binaryCount; ++r)
|
||||
rc.insert(abi(r), binary(r));
|
||||
return rc;
|
||||
}
|
||||
|
||||
void GdbBinaryModel::setGdbBinaries(const BinaryToolChainMap &m)
|
||||
void GdbBinaryModel::setGdbMapping(const QMap<QString, QString> &m)
|
||||
{
|
||||
removeRows(0, rowCount());
|
||||
foreach(const QString &binary, m.uniqueKeys())
|
||||
append(binary, m.values(binary));
|
||||
for (QMap<QString, QString>::const_iterator i = m.constBegin(); i != m.constEnd(); ++i)
|
||||
append(i.key(), i.value());
|
||||
}
|
||||
|
||||
QString GdbBinaryModel::binary(int row) const
|
||||
{
|
||||
return item(row, binaryColumn)->data(binaryRole).toString();
|
||||
return QDir::fromNativeSeparators(item(row, binaryColumn)->data(Qt::DisplayRole).toString());
|
||||
}
|
||||
|
||||
QList<int> GdbBinaryModel::toolChains(int row) const
|
||||
QString GdbBinaryModel::abi(int row) const
|
||||
{
|
||||
const QVariant data = item(row, toolChainColumn)->data(toolChainRole);
|
||||
return qVariantValue<QList<int> >(data);
|
||||
return item(row, abiColumn)->data(Qt::DisplayRole).toString();
|
||||
}
|
||||
|
||||
void GdbBinaryModel::setBinaryItem(QStandardItem *item, const QString &binary)
|
||||
{
|
||||
const QFileInfo fi(binary);
|
||||
item->setText(fi.isAbsolute() ? fi.fileName() : QDir::toNativeSeparators(binary));
|
||||
item->setText(binary.isEmpty() ? QString() : QDir::toNativeSeparators(binary));
|
||||
item->setToolTip(QString());; // clean out delayed tooltip
|
||||
item->setData(QVariant(binary), binaryRole);
|
||||
item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable);
|
||||
item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsEditable);
|
||||
item->setData(false);
|
||||
}
|
||||
|
||||
void GdbBinaryModel::setToolChainItem(QStandardItem *item, const QList<int> &toolChains)
|
||||
void GdbBinaryModel::setAbiItem(QStandardItem *item, const QString &abi)
|
||||
{
|
||||
// Format comma-separated list
|
||||
const QString toolChainSeparator = QLatin1String(", ");
|
||||
QString toolChainDesc;
|
||||
const int count = toolChains.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (i)
|
||||
toolChainDesc += toolChainSeparator;
|
||||
toolChainDesc += toolChainName(toolChains.at(i));
|
||||
}
|
||||
|
||||
item->setText(toolChainDesc);
|
||||
item->setToolTip(QString());; // clean out delayed tooltip
|
||||
item->setData(qVariantFromValue(toolChains), toolChainRole);
|
||||
item->setText(abi);
|
||||
item->setToolTip(QString()); // clean out delayed tooltip
|
||||
item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable);
|
||||
}
|
||||
|
||||
void GdbBinaryModel::append(const QString &binary, const QList<int> &toolChains)
|
||||
void GdbBinaryModel::append(const QString &abi, const QString &binary)
|
||||
{
|
||||
QStandardItem *binaryItem = new QStandardItem;
|
||||
QStandardItem *toolChainItem = new QStandardItem;
|
||||
QStandardItem *abiItem = new QStandardItem;
|
||||
GdbBinaryModel::setAbiItem(abiItem, abi);
|
||||
GdbBinaryModel::setBinaryItem(binaryItem, binary);
|
||||
GdbBinaryModel::setToolChainItem(toolChainItem, toolChains);
|
||||
|
||||
StandardItemList row;
|
||||
row << binaryItem << toolChainItem;
|
||||
row << abiItem << binaryItem;
|
||||
appendRow(row);
|
||||
}
|
||||
|
||||
bool GdbBinaryModel::isDirty() const
|
||||
{
|
||||
for (int i = 0; i < rowCount(); ++i) {
|
||||
if (item(i, binaryColumn)->data().toBool())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------- GdbChooserWidget
|
||||
GdbChooserWidget::GdbChooserWidget(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
m_treeView(new QTreeView),
|
||||
m_model(new GdbBinaryModel(m_treeView)),
|
||||
m_addButton(new QToolButton),
|
||||
m_deleteButton(new QToolButton),
|
||||
m_dirty(false)
|
||||
m_model(new GdbBinaryModel(m_treeView))
|
||||
{
|
||||
QHBoxLayout *mainHLayout = new QHBoxLayout;
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
m_treeView->setRootIsDecorated(false);
|
||||
m_treeView->setModel(m_model);
|
||||
m_treeView->setUniformRowHeights(true);
|
||||
m_treeView->setAllColumnsShowFocus(true);
|
||||
m_treeView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
connect(m_treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
|
||||
this, SLOT(slotCurrentChanged(QModelIndex,QModelIndex)));
|
||||
connect(m_treeView, SIGNAL(doubleClicked(QModelIndex)),
|
||||
this, SLOT(slotDoubleClicked(QModelIndex)));
|
||||
mainHLayout->addWidget(m_treeView);
|
||||
|
||||
m_addButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_PLUS)));
|
||||
connect(m_addButton, SIGNAL(clicked()), this, SLOT(slotAdd()));
|
||||
|
||||
m_deleteButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_MINUS)));
|
||||
m_deleteButton->setEnabled(false);
|
||||
connect(m_deleteButton, SIGNAL(clicked()), this, SLOT(slotRemove()));
|
||||
|
||||
QVBoxLayout *vButtonLayout = new QVBoxLayout;
|
||||
vButtonLayout->addWidget(m_addButton);
|
||||
vButtonLayout->addWidget(m_deleteButton);
|
||||
vButtonLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));
|
||||
|
||||
mainHLayout->addLayout(vButtonLayout);
|
||||
setLayout(mainHLayout);
|
||||
layout->addWidget(m_treeView);
|
||||
}
|
||||
|
||||
QStandardItem *GdbChooserWidget::currentItem() const
|
||||
QMap<QString, QString> GdbChooserWidget::gdbMapping() const
|
||||
{
|
||||
// Return the column-0-item
|
||||
QModelIndex currentIndex = m_treeView->currentIndex();
|
||||
if (!currentIndex.isValid())
|
||||
return 0;
|
||||
if (currentIndex.column() != binaryColumn)
|
||||
currentIndex = currentIndex.sibling(currentIndex.row(), binaryColumn);
|
||||
return m_model->itemFromIndex(currentIndex);
|
||||
return m_model->gdbMapping();
|
||||
}
|
||||
|
||||
void GdbChooserWidget::slotAdd()
|
||||
void GdbChooserWidget::setGdbMapping(const QMap<QString, QString> &m)
|
||||
{
|
||||
// Any toolchains left?
|
||||
const QList<int> unusedToolChains = m_model->unusedToolChains();
|
||||
if (unusedToolChains.isEmpty())
|
||||
return;
|
||||
|
||||
// On a binary or no current item: Add binary + toolchain
|
||||
BinaryToolChainDialog binaryDialog(this);
|
||||
binaryDialog.setToolChainChoices(unusedToolChains);
|
||||
if (binaryDialog.exec() != QDialog::Accepted)
|
||||
return;
|
||||
// Refuse binaries that already exist
|
||||
const QString path = binaryDialog.path();
|
||||
if (m_model->binaries().contains(path)) {
|
||||
QMessageBox::warning(this, tr("Duplicate binary"),
|
||||
tr("The binary '%1' already exists.").arg(path));
|
||||
return;
|
||||
}
|
||||
// Add binary + toolchain to model
|
||||
m_model->append(path, binaryDialog.toolChains());
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
void GdbChooserWidget::slotRemove()
|
||||
{
|
||||
if (QStandardItem *item = currentItem())
|
||||
removeItem(item);
|
||||
}
|
||||
|
||||
void GdbChooserWidget::removeItem(QStandardItem *item)
|
||||
{
|
||||
m_model->removeRow(item->row());
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
void GdbChooserWidget::slotCurrentChanged(const QModelIndex ¤t, const QModelIndex &)
|
||||
{
|
||||
const bool hasItem = current.isValid() && m_model->itemFromIndex(current);
|
||||
m_deleteButton->setEnabled(hasItem);
|
||||
}
|
||||
|
||||
void GdbChooserWidget::slotDoubleClicked(const QModelIndex ¤t)
|
||||
{
|
||||
QTC_ASSERT(current.isValid(), return)
|
||||
// Show dialog to edit. Make all unused toolchains including the ones
|
||||
// previously assigned to that binary available.
|
||||
const int row = current.row();
|
||||
const QString oldBinary = m_model->binary(row);
|
||||
const QList<int> oldToolChains = m_model->toolChains(row);
|
||||
const QSet<int> toolChainChoices = m_model->unusedToolChainSet().unite(oldToolChains.toSet());
|
||||
|
||||
BinaryToolChainDialog dialog(this);
|
||||
dialog.setPath(oldBinary);
|
||||
const BinaryToolChainMap map = gdbBinaries();
|
||||
dialog.setToolChainChoices(toolChainChoices.toList(), &map);
|
||||
dialog.setToolChains(oldToolChains);
|
||||
if (dialog.exec() != QDialog::Accepted)
|
||||
return;
|
||||
// Check if anything changed.
|
||||
const QString newBinary = dialog.path();
|
||||
const QList<int> newToolChains = dialog.toolChains();
|
||||
if (newBinary == oldBinary && newToolChains == oldToolChains)
|
||||
return;
|
||||
|
||||
GdbBinaryModel::setBinaryItem(m_model->item(row, binaryColumn), newBinary);
|
||||
GdbBinaryModel::setToolChainItem(m_model->item(row, toolChainColumn), newToolChains);
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
GdbChooserWidget::BinaryToolChainMap GdbChooserWidget::gdbBinaries() const
|
||||
{
|
||||
return m_model->gdbBinaries();
|
||||
}
|
||||
|
||||
void GdbChooserWidget::setGdbBinaries(const BinaryToolChainMap &m)
|
||||
{
|
||||
m_model->setGdbBinaries(m);
|
||||
m_model->setGdbMapping(m);
|
||||
for (int c = 0; c < ColumnCount; c++)
|
||||
m_treeView->resizeColumnToContents(c);
|
||||
m_dirty = false;
|
||||
}
|
||||
|
||||
bool GdbChooserWidget::isDirty() const
|
||||
{
|
||||
return m_dirty;
|
||||
}
|
||||
|
||||
void GdbChooserWidget::clearDirty()
|
||||
{
|
||||
m_dirty = false;
|
||||
}
|
||||
|
||||
// -------------- ToolChainSelectorWidget
|
||||
static const char *toolChainPropertyC = "toolChain";
|
||||
|
||||
static inline int toolChainOfCheckBox(const QCheckBox *c)
|
||||
{
|
||||
return c->property(toolChainPropertyC).toInt();
|
||||
}
|
||||
|
||||
static inline QVBoxLayout *createGroupBox(const QString &title, QVBoxLayout *lt)
|
||||
{
|
||||
QGroupBox *gb = new QGroupBox(title);
|
||||
QVBoxLayout *gbLayout = new QVBoxLayout;
|
||||
gb->setLayout(gbLayout);
|
||||
lt->addWidget(gb);
|
||||
return gbLayout;
|
||||
}
|
||||
|
||||
ToolChainSelectorWidget::ToolChainSelectorWidget(QWidget *parent) :
|
||||
QWidget(parent), m_valid(false)
|
||||
{
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
QVBoxLayout *desktopLayout = createGroupBox(tr("Desktop/General"), mainLayout);
|
||||
QVBoxLayout *symbianLayout = createGroupBox(tr("Symbian"), mainLayout);
|
||||
QVBoxLayout *maemoLayout = createGroupBox(tr("Maemo"), mainLayout);
|
||||
|
||||
// Group checkboxes into categories
|
||||
foreach(int tc, allGdbToolChains()) {
|
||||
switch (tc) {
|
||||
case ProjectExplorer::ToolChain_GCC:
|
||||
case ProjectExplorer::ToolChain_LINUX_ICC:
|
||||
case ProjectExplorer::ToolChain_MinGW:
|
||||
case ProjectExplorer::ToolChain_OTHER:
|
||||
case ProjectExplorer::ToolChain_UNKNOWN:
|
||||
desktopLayout->addWidget(createToolChainCheckBox(tc));
|
||||
break;
|
||||
case ProjectExplorer::ToolChain_MSVC:
|
||||
case ProjectExplorer::ToolChain_WINCE:
|
||||
break;
|
||||
case ProjectExplorer::ToolChain_WINSCW:
|
||||
case ProjectExplorer::ToolChain_GCCE:
|
||||
case ProjectExplorer::ToolChain_RVCT2_ARMV5:
|
||||
case ProjectExplorer::ToolChain_RVCT2_ARMV6:
|
||||
case ProjectExplorer::ToolChain_GCCE_GNUPOC:
|
||||
case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC:
|
||||
symbianLayout->addWidget(createToolChainCheckBox(tc));
|
||||
break;
|
||||
case ProjectExplorer::ToolChain_GCC_MAEMO5:
|
||||
case ProjectExplorer::ToolChain_GCC_HARMATTAN:
|
||||
case ProjectExplorer::ToolChain_GCC_MEEGO:
|
||||
maemoLayout->addWidget(createToolChainCheckBox(tc));
|
||||
break;
|
||||
case ProjectExplorer::ToolChain_INVALID:
|
||||
break;
|
||||
}
|
||||
}
|
||||
setLayout(mainLayout);
|
||||
}
|
||||
|
||||
QCheckBox *ToolChainSelectorWidget::createToolChainCheckBox(int tc)
|
||||
{
|
||||
// Add checkbox
|
||||
QCheckBox *cb = new QCheckBox(toolChainName(tc));
|
||||
cb->setProperty(toolChainPropertyC, QVariant(tc));
|
||||
connect(cb, SIGNAL(stateChanged(int)), this, SLOT(slotCheckStateChanged(int)));
|
||||
m_checkBoxes.push_back(cb);
|
||||
return cb;
|
||||
}
|
||||
|
||||
static inline QString msgDisabledToolChainToolTip(const QString &binary, int toolChain)
|
||||
{
|
||||
return ToolChainSelectorWidget::tr(
|
||||
"<html><head/><body><p>Another gdb binary (<i>%1</i>) is currently configured "
|
||||
"to handle the toolchain <i>%2</i>.</p></body></html>").
|
||||
arg(QFileInfo(binary).fileName(), toolChainName(toolChain));
|
||||
}
|
||||
|
||||
void ToolChainSelectorWidget::setEnabledToolChains(const QList<int> &enabled,
|
||||
const BinaryToolChainMap *binaryToolChainMap)
|
||||
{
|
||||
foreach(QCheckBox *cb, m_checkBoxes) {
|
||||
const int toolChain = toolChainOfCheckBox(cb);
|
||||
if (enabled.contains(toolChain)) {
|
||||
cb->setToolTip(QString());
|
||||
} else {
|
||||
// Toolchain is handled by a different binary, hint to user.
|
||||
cb->setEnabled(false);
|
||||
const QString binary = binaryToolChainMap ? binaryToolChainMap->key(toolChain) : QString();
|
||||
if (!binary.isEmpty())
|
||||
cb->setToolTip(msgDisabledToolChainToolTip(binary, toolChain));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ToolChainSelectorWidget::setCheckedToolChains(const QList<int> &checked)
|
||||
{
|
||||
foreach(QCheckBox *cb, m_checkBoxes)
|
||||
if (checked.contains(toolChainOfCheckBox(cb)))
|
||||
cb->setChecked(true);
|
||||
// Trigger 'valid changed'
|
||||
slotCheckStateChanged(checked.isEmpty() ? Qt::Unchecked : Qt::Checked);
|
||||
}
|
||||
|
||||
QList<int> ToolChainSelectorWidget::checkedToolChains() const
|
||||
{
|
||||
QList<int> rc;
|
||||
foreach(const QCheckBox *cb, m_checkBoxes)
|
||||
if (cb->isChecked())
|
||||
rc.push_back(toolChainOfCheckBox(cb));
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool ToolChainSelectorWidget::isValid() const
|
||||
{
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
void ToolChainSelectorWidget::slotCheckStateChanged(int state)
|
||||
{
|
||||
// Emit signal if valid state changed
|
||||
const bool newValid = state == Qt::Checked || hasCheckedToolChain();
|
||||
if (newValid != m_valid) {
|
||||
m_valid = newValid;
|
||||
emit validChanged(m_valid);
|
||||
}
|
||||
}
|
||||
|
||||
bool ToolChainSelectorWidget::hasCheckedToolChain() const
|
||||
{
|
||||
foreach(const QCheckBox *cb, m_checkBoxes)
|
||||
if (cb->isChecked())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// -------------- ToolChainDialog
|
||||
BinaryToolChainDialog::BinaryToolChainDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
m_toolChainSelector(new ToolChainSelectorWidget),
|
||||
m_mainLayout(new QFormLayout),
|
||||
m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel)),
|
||||
m_pathChooser(new Utils::PathChooser)
|
||||
{
|
||||
|
||||
setModal(true);
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
setWindowTitle(tr("Select binary and toolchains"));
|
||||
|
||||
m_pathChooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
|
||||
m_pathChooser->setPromptDialogTitle(tr("Gdb binary"));
|
||||
connect(m_pathChooser, SIGNAL(validChanged()), this, SLOT(slotValidChanged()));
|
||||
m_mainLayout->addRow(tr("Path:"), m_pathChooser);
|
||||
|
||||
connect(m_toolChainSelector, SIGNAL(validChanged(bool)), this, SLOT(slotValidChanged()));
|
||||
m_mainLayout->addRow(m_toolChainSelector);
|
||||
|
||||
connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
m_mainLayout->addRow(m_buttonBox);
|
||||
setLayout(m_mainLayout);
|
||||
|
||||
setOkButtonEnabled(false);
|
||||
m_pathChooser->setFocus();
|
||||
}
|
||||
|
||||
void BinaryToolChainDialog::setToolChainChoices(const QList<int> &tcs,
|
||||
const BinaryToolChainMap *binaryToolChainMap)
|
||||
{
|
||||
m_toolChainSelector->setEnabledToolChains(tcs, binaryToolChainMap);
|
||||
}
|
||||
|
||||
void BinaryToolChainDialog::setToolChains(const QList<int> &tcs)
|
||||
{
|
||||
m_toolChainSelector->setCheckedToolChains(tcs);
|
||||
}
|
||||
|
||||
QList<int> BinaryToolChainDialog::toolChains() const
|
||||
{
|
||||
return m_toolChainSelector->checkedToolChains();
|
||||
}
|
||||
|
||||
void BinaryToolChainDialog::setOkButtonEnabled(bool v)
|
||||
{
|
||||
m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(v);
|
||||
}
|
||||
|
||||
void BinaryToolChainDialog::setPath(const QString &p)
|
||||
{
|
||||
m_pathChooser->setPath(p);
|
||||
}
|
||||
|
||||
QString BinaryToolChainDialog::path() const
|
||||
{
|
||||
return m_pathChooser->rawPath();
|
||||
}
|
||||
|
||||
void BinaryToolChainDialog::slotValidChanged()
|
||||
{
|
||||
setOkButtonEnabled(m_pathChooser->isValid() && m_toolChainSelector->isValid());
|
||||
return m_model->isDirty();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -67,96 +67,17 @@ class GdbChooserWidget : public QWidget
|
||||
public:
|
||||
explicit GdbChooserWidget(QWidget *parent = 0);
|
||||
|
||||
typedef QMultiMap<QString, int> BinaryToolChainMap;
|
||||
|
||||
BinaryToolChainMap gdbBinaries() const;
|
||||
void setGdbBinaries(const BinaryToolChainMap &m);
|
||||
QMap<QString, QString> gdbMapping() const;
|
||||
void setGdbMapping(const QMap<QString, QString> &m);
|
||||
|
||||
bool isDirty() const;
|
||||
|
||||
public slots:
|
||||
void clearDirty();
|
||||
|
||||
private slots:
|
||||
void slotAdd();
|
||||
void slotRemove();
|
||||
void slotCurrentChanged(const QModelIndex ¤t, const QModelIndex & previous);
|
||||
void slotDoubleClicked(const QModelIndex ¤t);
|
||||
|
||||
private:
|
||||
void removeItem(QStandardItem *item);
|
||||
QToolButton *createAddToolMenuButton();
|
||||
QStandardItem *currentItem() const;
|
||||
|
||||
QTreeView *m_treeView;
|
||||
GdbBinaryModel *m_model;
|
||||
QToolButton *m_addButton;
|
||||
QToolButton *m_deleteButton;
|
||||
bool m_dirty;
|
||||
};
|
||||
|
||||
// Present toolchains with checkboxes grouped in QGroupBox panes
|
||||
// and provide valid-handling. Unavailabe toolchains can be grayed
|
||||
// out using setEnabledToolChains().
|
||||
class ToolChainSelectorWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
typedef GdbChooserWidget::BinaryToolChainMap BinaryToolChainMap;
|
||||
|
||||
explicit ToolChainSelectorWidget(QWidget *parent = 0);
|
||||
|
||||
void setEnabledToolChains(const QList<int> &enabled,
|
||||
// Optionally used for generating a tooltip for the disabled check boxes
|
||||
const BinaryToolChainMap *binaryToolChainMap = 0);
|
||||
|
||||
void setCheckedToolChains(const QList<int> &);
|
||||
QList<int> checkedToolChains() const;
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
signals:
|
||||
void validChanged(bool);
|
||||
|
||||
private slots:
|
||||
void slotCheckStateChanged(int);
|
||||
|
||||
private:
|
||||
bool hasCheckedToolChain() const;
|
||||
QCheckBox *createToolChainCheckBox(int tc);
|
||||
|
||||
QList<QCheckBox*> m_checkBoxes;
|
||||
bool m_valid;
|
||||
};
|
||||
|
||||
// Internal helper dialog for selecting a binary and its
|
||||
// associated toolchains.
|
||||
class BinaryToolChainDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
typedef GdbChooserWidget::BinaryToolChainMap BinaryToolChainMap;
|
||||
|
||||
explicit BinaryToolChainDialog(QWidget *parent);
|
||||
|
||||
void setToolChainChoices(const QList<int> &,
|
||||
// Optionally used for generating a tooltip for the disabled check boxes
|
||||
const BinaryToolChainMap *binaryToolChainMap = 0);
|
||||
|
||||
void setToolChains(const QList<int> &);
|
||||
QList<int> toolChains() const;
|
||||
|
||||
void setPath(const QString &);
|
||||
QString path() const;
|
||||
|
||||
private slots:
|
||||
void slotValidChanged();
|
||||
|
||||
private:
|
||||
void setOkButtonEnabled(bool e);
|
||||
|
||||
ToolChainSelectorWidget *m_toolChainSelector;
|
||||
QFormLayout *m_mainLayout;
|
||||
QDialogButtonBox *m_buttonBox;
|
||||
Utils::PathChooser *m_pathChooser;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -1795,36 +1795,29 @@ int GdbEngine::currentFrame() const
|
||||
return stackHandler()->currentIndex();
|
||||
}
|
||||
|
||||
QString msgNoBinaryForToolChain(int tc)
|
||||
QString msgNoBinaryForToolChain(const ProjectExplorer::Abi &tc)
|
||||
{
|
||||
using namespace ProjectExplorer;
|
||||
return GdbEngine::tr("There is no gdb binary available for '%1'.")
|
||||
.arg(ToolChain::toolChainName(ToolChainType(tc)));
|
||||
return GdbEngine::tr("There is no gdb binary available for binaries in format '%1'")
|
||||
.arg(tc.toString());
|
||||
}
|
||||
|
||||
AbstractGdbAdapter *GdbEngine::createAdapter()
|
||||
{
|
||||
const DebuggerStartParameters &sp = startParameters();
|
||||
switch (sp.toolChainType) {
|
||||
case ProjectExplorer::ToolChain_WINSCW: // S60
|
||||
case ProjectExplorer::ToolChain_GCCE:
|
||||
case ProjectExplorer::ToolChain_RVCT2_ARMV5:
|
||||
case ProjectExplorer::ToolChain_RVCT2_ARMV6:
|
||||
case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC:
|
||||
case ProjectExplorer::ToolChain_GCCE_GNUPOC:
|
||||
if (sp.toolChainAbi.os() == ProjectExplorer::Abi::Symbian) {
|
||||
// FIXME: 1 of 3 testing hacks.
|
||||
if (sp.debugClient == DebuggerStartParameters::DebugClientCoda)
|
||||
return new CodaGdbAdapter(this);
|
||||
else
|
||||
return new TrkGdbAdapter(this);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (sp.startMode) {
|
||||
case AttachCore:
|
||||
return new CoreGdbAdapter(this);
|
||||
case AttachToRemote:
|
||||
return new RemoteGdbServerAdapter(this, sp.toolChainType);
|
||||
return new RemoteGdbServerAdapter(this, sp.toolChainAbi);
|
||||
case StartRemoteGdb:
|
||||
return new RemotePlainGdbAdapter(this);
|
||||
case AttachExternal:
|
||||
@@ -4220,12 +4213,12 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb,
|
||||
const DebuggerStartParameters &sp = startParameters();
|
||||
m_gdb = QString::fromLocal8Bit(qgetenv("QTC_DEBUGGER_PATH"));
|
||||
if (m_gdb.isEmpty() && sp.startMode != StartRemoteGdb)
|
||||
m_gdb = debuggerCore()->gdbBinaryForToolChain(sp.toolChainType);
|
||||
m_gdb = debuggerCore()->gdbBinaryForAbi(startParameters().toolChainAbi);
|
||||
if (m_gdb.isEmpty())
|
||||
m_gdb = gdb;
|
||||
if (m_gdb.isEmpty()) {
|
||||
handleAdapterStartFailed(
|
||||
msgNoBinaryForToolChain(sp.toolChainType),
|
||||
msgNoBinaryForToolChain(sp.toolChainAbi),
|
||||
GdbOptionsPage::settingsId());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/toolchain.h>
|
||||
#include <projectexplorer/toolchaintype.h>
|
||||
#include <projectexplorer/toolchainmanager.h>
|
||||
#include <projectexplorer/abi.h>
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QTextStream>
|
||||
@@ -47,22 +47,37 @@
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
const char gdbBinariesSettingsGroupC[] = "GdbBinaries";
|
||||
const char debugModeGdbBinaryKeyC[] = "GdbBinary";
|
||||
static const char *GDB_MAPPING_ARRAY = "GdbMapping";
|
||||
static const char *GDB_ABI_KEY = "Abi";
|
||||
static const char *GDB_BINARY_KEY = "Binary";
|
||||
|
||||
GdbOptionsPage::GdbBinaryToolChainMap GdbOptionsPage::gdbBinaryToolChainMap;
|
||||
bool GdbOptionsPage::gdbBinariesChanged = true;
|
||||
GdbOptionsPage::GdbBinaryToolChainMap GdbOptionsPage::abiToGdbMap;
|
||||
bool GdbOptionsPage::gdbMappingChanged = true;
|
||||
|
||||
void GdbOptionsPage::readGdbBinarySettings() /* static */
|
||||
void GdbOptionsPage::readGdbSettings() /* static */
|
||||
{
|
||||
// FIXME: Convert old settings!
|
||||
using namespace ProjectExplorer;
|
||||
QSettings *settings = Core::ICore::instance()->settings();
|
||||
// Convert gdb binaries from flat settings list (see writeSettings)
|
||||
// into map ("binary1=gdb,1,2", "binary2=symbian_gdb,3,4").
|
||||
gdbBinaryToolChainMap.clear();
|
||||
|
||||
abiToGdbMap.clear();
|
||||
|
||||
int size = settings->beginReadArray(GDB_MAPPING_ARRAY);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
settings->setArrayIndex(i);
|
||||
ProjectExplorer::Abi abi(settings->value(GDB_ABI_KEY).toString());
|
||||
if (!abi.isValid())
|
||||
continue;
|
||||
QString binary = settings->value(GDB_BINARY_KEY).toString();
|
||||
if (binary.isEmpty())
|
||||
continue;
|
||||
abiToGdbMap.insert(abi.toString(), binary);
|
||||
}
|
||||
settings->endArray();
|
||||
|
||||
// Map old settings (pre 2.2):
|
||||
const QChar separator = QLatin1Char(',');
|
||||
const QString keyRoot = QLatin1String(gdbBinariesSettingsGroupC) + QLatin1Char('/') +
|
||||
QLatin1String(debugModeGdbBinaryKeyC);
|
||||
const QString keyRoot = QLatin1String("GdbBinaries/GdbBinaries");
|
||||
for (int i = 1; ; i++) {
|
||||
const QString value = settings->value(keyRoot + QString::number(i)).toString();
|
||||
if (value.isEmpty())
|
||||
@@ -71,81 +86,116 @@ void GdbOptionsPage::readGdbBinarySettings() /* static */
|
||||
QStringList tokens = value.split(separator);
|
||||
if (tokens.size() < 2)
|
||||
break;
|
||||
|
||||
const QString binary = tokens.front();
|
||||
// Skip non-existent absolute binaries allowing for upgrades by the installer.
|
||||
// Force a rewrite of the settings file.
|
||||
const QFileInfo binaryInfo(binary);
|
||||
if (binaryInfo.isAbsolute() && !binaryInfo.isExecutable()) {
|
||||
gdbBinariesChanged = true;
|
||||
const QString msg = QString::fromLatin1("Warning: The gdb binary '%1' does not exist, skipping.\n").arg(binary);
|
||||
qWarning("%s", qPrintable(msg));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create entries for all toolchains.
|
||||
tokens.pop_front();
|
||||
foreach (const QString &t, tokens) {
|
||||
// Paranoia: Check if the there is already a binary configured for the toolchain.
|
||||
const int toolChain = t.toInt();
|
||||
const QString predefinedGdb = gdbBinaryToolChainMap.key(toolChain);
|
||||
if (predefinedGdb.isEmpty()) {
|
||||
gdbBinaryToolChainMap.insert(binary, toolChain);
|
||||
} else {
|
||||
const QString toolChainName =
|
||||
ProjectExplorer::ToolChain::toolChainName(ToolChainType(toolChain));
|
||||
const QString msg =
|
||||
QString::fromLatin1("An inconsistency has been encountered in the Ini-file '%1':\n"
|
||||
"Skipping gdb binary '%2' for toolchain '%3' as '%4' is already configured for it.").
|
||||
arg(settings->fileName(), binary, toolChainName, predefinedGdb);
|
||||
qWarning("%s", qPrintable(msg));
|
||||
QString abi;
|
||||
switch (t.toInt())
|
||||
{
|
||||
case 0: // GCC
|
||||
case 1: // Linux ICC
|
||||
#ifndef Q_OS_WIN
|
||||
abi = ProjectExplorer::Abi::hostAbi().toString();
|
||||
#endif
|
||||
break;
|
||||
case 2: // MinGW
|
||||
case 3: // MSVC
|
||||
case 4: // WINCE
|
||||
#ifdef Q_OS_WIN
|
||||
abi = ProjectExplorer::Abi::hostAbi().toString();
|
||||
#endif
|
||||
break;
|
||||
case 5: // WINSCW
|
||||
abi = ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Symbian,
|
||||
ProjectExplorer::Abi::Symbian_emulator,
|
||||
ProjectExplorer::Abi::Format_ELF,
|
||||
32).toString();
|
||||
break;
|
||||
case 6: // GCCE
|
||||
case 7: // RVCT 2, ARM v5
|
||||
case 8: // RVCT 2, ARM v6
|
||||
case 11: // RVCT GNUPOC
|
||||
case 12: // RVCT 4, ARM v5
|
||||
case 13: // RVCT 4, ARM v6
|
||||
abi = ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Symbian,
|
||||
ProjectExplorer::Abi::Symbian_device,
|
||||
ProjectExplorer::Abi::Format_ELF,
|
||||
32).toString();
|
||||
break;
|
||||
case 9: // GCC Maemo5
|
||||
abi = ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Linux,
|
||||
ProjectExplorer::Abi::Linux_maemo,
|
||||
ProjectExplorer::Abi::Format_ELF,
|
||||
32).toString();
|
||||
|
||||
break;
|
||||
case 14: // GCC Harmattan
|
||||
abi = ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Linux,
|
||||
ProjectExplorer::Abi::Linux_harmattan,
|
||||
ProjectExplorer::Abi::Format_ELF,
|
||||
32).toString();
|
||||
break;
|
||||
case 15: // GCC Meego
|
||||
abi = ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Linux,
|
||||
ProjectExplorer::Abi::Linux_meego,
|
||||
ProjectExplorer::Abi::Format_ELF,
|
||||
32).toString();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (abi.isEmpty() || abiToGdbMap.contains(abi))
|
||||
continue;
|
||||
|
||||
abiToGdbMap.insert(abi, binary);
|
||||
}
|
||||
}
|
||||
// Linux defaults
|
||||
#ifdef Q_OS_UNIX
|
||||
if (gdbBinaryToolChainMap.isEmpty()) {
|
||||
const QString gdb = QLatin1String("gdb");
|
||||
gdbBinaryToolChainMap.insert(gdb, ToolChain_GCC);
|
||||
gdbBinaryToolChainMap.insert(gdb, ToolChain_LINUX_ICC);
|
||||
gdbBinaryToolChainMap.insert(gdb, ToolChain_OTHER);
|
||||
gdbBinaryToolChainMap.insert(gdb, ToolChain_UNKNOWN);
|
||||
}
|
||||
#endif
|
||||
|
||||
gdbMappingChanged = false;
|
||||
}
|
||||
|
||||
void GdbOptionsPage::writeGdbBinarySettings() /* static */
|
||||
void GdbOptionsPage::writeGdbSettings() /* static */
|
||||
{
|
||||
// FIXME: This should actually get called in response to ICore::saveSettingsRequested()
|
||||
if (!gdbMappingChanged)
|
||||
return;
|
||||
|
||||
QSettings *settings = Core::ICore::instance()->settings();
|
||||
// Convert gdb binaries map into a flat settings list of
|
||||
// ("binary1=gdb,1,2", "binary2=symbian_gdb,3,4"). It needs to be ASCII for installers
|
||||
QString lastBinary;
|
||||
QStringList settingsList;
|
||||
const QChar separator = QLatin1Char(',');
|
||||
const GdbBinaryToolChainMap::const_iterator cend = gdbBinaryToolChainMap.constEnd();
|
||||
for (GdbBinaryToolChainMap::const_iterator it = gdbBinaryToolChainMap.constBegin(); it != cend; ++it) {
|
||||
if (it.key() != lastBinary) {
|
||||
lastBinary = it.key(); // Start new entry with first toolchain
|
||||
settingsList.push_back(lastBinary);
|
||||
}
|
||||
settingsList.back().append(separator); // Append toolchain to last binary
|
||||
settingsList.back().append(QString::number(it.value()));
|
||||
|
||||
settings->beginWriteArray(GDB_MAPPING_ARRAY);
|
||||
|
||||
int index = 0;
|
||||
for (QMap<QString, QString>::const_iterator i = abiToGdbMap.constBegin();
|
||||
i != abiToGdbMap.constEnd(); ++i) {
|
||||
if (i.value().isEmpty())
|
||||
continue;
|
||||
|
||||
settings->setArrayIndex(index);
|
||||
++index;
|
||||
|
||||
settings->setValue(GDB_ABI_KEY, i.key());
|
||||
settings->setValue(GDB_BINARY_KEY, i.value());
|
||||
}
|
||||
// Terminate settings list by an empty element such that consecutive keys resulting
|
||||
// from ini-file merging are suppressed while reading.
|
||||
settingsList.push_back(QString());
|
||||
// Write out list
|
||||
settings->beginGroup(QLatin1String(gdbBinariesSettingsGroupC));
|
||||
settings->remove(QString()); // remove all keys in group.
|
||||
const int count = settingsList.size();
|
||||
const QString keyRoot = QLatin1String(debugModeGdbBinaryKeyC);
|
||||
for (int i = 0; i < count; i++)
|
||||
settings->setValue(keyRoot + QString::number(i + 1), settingsList.at(i));
|
||||
settings->endGroup();
|
||||
settings->endArray();
|
||||
|
||||
gdbMappingChanged = false;
|
||||
}
|
||||
|
||||
GdbOptionsPage::GdbOptionsPage()
|
||||
: m_ui(0)
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
QString GdbOptionsPage::settingsId()
|
||||
{
|
||||
@@ -174,10 +224,41 @@ QIcon GdbOptionsPage::categoryIcon() const
|
||||
|
||||
QWidget *GdbOptionsPage::createPage(QWidget *parent)
|
||||
{
|
||||
// Fix up abi mapping now that the ToolChainManager is available:
|
||||
connect(ProjectExplorer::ToolChainManager::instance(), SIGNAL(toolChainAdded(ProjectExplorer::ToolChain*)),
|
||||
this, SLOT(handleToolChainAdditions(ProjectExplorer::ToolChain*)));
|
||||
connect(ProjectExplorer::ToolChainManager::instance(), SIGNAL(toolChainRemoved(ProjectExplorer::ToolChain*)),
|
||||
this, SLOT(handleToolChainRemovals(ProjectExplorer::ToolChain*)));
|
||||
|
||||
// Update mapping now that toolchains are available
|
||||
QList<ProjectExplorer::ToolChain *> tcs =
|
||||
ProjectExplorer::ToolChainManager::instance()->toolChains();
|
||||
|
||||
QStringList abiList;
|
||||
foreach (ProjectExplorer::ToolChain *tc, tcs) {
|
||||
const QString abi = tc->targetAbi().toString();
|
||||
if (!abiList.contains(abi))
|
||||
abiList.append(abi);
|
||||
if (!abiToGdbMap.contains(abi))
|
||||
handleToolChainAdditions(tc);
|
||||
}
|
||||
|
||||
QStringList toRemove;
|
||||
for (QMap<QString, QString>::const_iterator i = abiToGdbMap.constBegin();
|
||||
i != abiToGdbMap.constEnd(); ++i) {
|
||||
if (!abiList.contains(i.key()))
|
||||
toRemove.append(i.key());
|
||||
}
|
||||
|
||||
foreach (const QString &key, toRemove)
|
||||
abiToGdbMap.remove(key);
|
||||
|
||||
// Actual page setup:
|
||||
QWidget *w = new QWidget(parent);
|
||||
m_ui = new Ui::GdbOptionsPage;
|
||||
m_ui->setupUi(w);
|
||||
m_ui->gdbChooserWidget->setGdbBinaries(gdbBinaryToolChainMap);
|
||||
m_ui->gdbChooserWidget->setGdbMapping(abiToGdbMap);
|
||||
|
||||
m_ui->scriptFileChooser->setExpectedKind(Utils::PathChooser::File);
|
||||
m_ui->scriptFileChooser->setPromptDialogTitle(tr("Choose Location of Startup Script File"));
|
||||
|
||||
@@ -201,18 +282,7 @@ QWidget *GdbOptionsPage::createPage(QWidget *parent)
|
||||
m_ui->checkBoxEnableReverseDebugging);
|
||||
m_group.insert(debuggerCore()->action(GdbWatchdogTimeout), 0);
|
||||
|
||||
#if 1
|
||||
m_ui->groupBoxPluginDebugging->hide();
|
||||
#else // The related code (handleAqcuiredInferior()) is disabled as well.
|
||||
m_group.insert(debuggerCore()->action(AllPluginBreakpoints),
|
||||
m_ui->radioButtonAllPluginBreakpoints);
|
||||
m_group.insert(debuggerCore()->action(SelectedPluginBreakpoints),
|
||||
m_ui->radioButtonSelectedPluginBreakpoints);
|
||||
m_group.insert(debuggerCore()->action(NoPluginBreakpoints),
|
||||
m_ui->radioButtonNoPluginBreakpoints);
|
||||
m_group.insert(debuggerCore()->action(SelectedPluginBreakpointsPattern),
|
||||
m_ui->lineEditSelectedPluginBreakpointsPattern);
|
||||
#endif
|
||||
|
||||
m_ui->lineEditSelectedPluginBreakpointsPattern->
|
||||
setEnabled(debuggerCore()->action(SelectedPluginBreakpoints)->value().toBool());
|
||||
@@ -246,11 +316,12 @@ void GdbOptionsPage::apply()
|
||||
{
|
||||
if (!m_ui) // page never shown
|
||||
return;
|
||||
|
||||
m_group.apply(Core::ICore::instance()->settings());
|
||||
if (m_ui->gdbChooserWidget->isDirty()) {
|
||||
gdbBinariesChanged = true;
|
||||
gdbBinaryToolChainMap = m_ui->gdbChooserWidget->gdbBinaries();
|
||||
m_ui->gdbChooserWidget->clearDirty();
|
||||
abiToGdbMap = m_ui->gdbChooserWidget->gdbMapping();
|
||||
m_ui->gdbChooserWidget->setGdbMapping(abiToGdbMap);
|
||||
gdbMappingChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,5 +339,37 @@ bool GdbOptionsPage::matches(const QString &s) const
|
||||
return m_searchKeywords.contains(s, Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
void GdbOptionsPage::handleToolChainAdditions(ProjectExplorer::ToolChain *tc)
|
||||
{
|
||||
ProjectExplorer::Abi tcAbi = tc->targetAbi();
|
||||
|
||||
if (tcAbi.binaryFormat() != ProjectExplorer::Abi::Format_ELF
|
||||
&& tcAbi.binaryFormat() != ProjectExplorer::Abi::Format_Mach_O
|
||||
&& !( tcAbi.os() == ProjectExplorer::Abi::Windows
|
||||
&& tcAbi.osFlavor() == ProjectExplorer::Abi::Windows_msys ))
|
||||
return;
|
||||
if (abiToGdbMap.contains(tcAbi.toString()))
|
||||
return;
|
||||
|
||||
QString binary;
|
||||
#ifdef Q_OS_UNIX
|
||||
ProjectExplorer::Abi hostAbi = ProjectExplorer::Abi::hostAbi();
|
||||
if (hostAbi == tcAbi)
|
||||
binary = QLatin1String("gdb");
|
||||
#endif
|
||||
abiToGdbMap.insert(tc->targetAbi().toString(), binary);
|
||||
}
|
||||
|
||||
void GdbOptionsPage::handleToolChainRemovals(ProjectExplorer::ToolChain *tc)
|
||||
{
|
||||
QList<ProjectExplorer::ToolChain *> tcs = ProjectExplorer::ToolChainManager::instance()->toolChains();
|
||||
foreach (ProjectExplorer::ToolChain *current, tcs) {
|
||||
if (current->targetAbi() == tc->targetAbi())
|
||||
return;
|
||||
}
|
||||
|
||||
abiToGdbMap.remove(tc->targetAbi().toString());
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
@@ -39,6 +39,10 @@
|
||||
#include <coreplugin/dialogs/ioptionspage.h>
|
||||
#include <utils/savedaction.h>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class ToolChain;
|
||||
} // namespace ProjectExplorer
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
@@ -61,11 +65,15 @@ public:
|
||||
|
||||
static QString settingsId();
|
||||
|
||||
typedef QMultiMap<QString, int> GdbBinaryToolChainMap;
|
||||
static GdbBinaryToolChainMap gdbBinaryToolChainMap;
|
||||
static bool gdbBinariesChanged;
|
||||
static void readGdbBinarySettings();
|
||||
static void writeGdbBinarySettings();
|
||||
typedef QMap<QString, QString> GdbBinaryToolChainMap;
|
||||
static GdbBinaryToolChainMap abiToGdbMap;
|
||||
static bool gdbMappingChanged;
|
||||
static void readGdbSettings();
|
||||
static void writeGdbSettings();
|
||||
|
||||
private slots:
|
||||
static void handleToolChainAdditions(ProjectExplorer::ToolChain *);
|
||||
static void handleToolChainRemovals(ProjectExplorer::ToolChain *);
|
||||
|
||||
private:
|
||||
Ui::GdbOptionsPage *m_ui;
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/fancymainwindow.h>
|
||||
#include <projectexplorer/toolchaintype.h>
|
||||
#include <projectexplorer/abi.h>
|
||||
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtGui/QMessageBox>
|
||||
@@ -59,9 +59,11 @@ namespace Internal {
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
RemoteGdbServerAdapter::RemoteGdbServerAdapter(GdbEngine *engine, int toolChainType, QObject *parent) :
|
||||
RemoteGdbServerAdapter::RemoteGdbServerAdapter(GdbEngine *engine,
|
||||
const ProjectExplorer::Abi &abi,
|
||||
QObject *parent) :
|
||||
AbstractGdbAdapter(engine, parent),
|
||||
m_toolChainType(toolChainType)
|
||||
m_abi(abi)
|
||||
{
|
||||
connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)),
|
||||
SLOT(uploadProcError(QProcess::ProcessError)));
|
||||
@@ -75,21 +77,10 @@ RemoteGdbServerAdapter::RemoteGdbServerAdapter(GdbEngine *engine, int toolChainT
|
||||
|
||||
AbstractGdbAdapter::DumperHandling RemoteGdbServerAdapter::dumperHandling() const
|
||||
{
|
||||
switch (m_toolChainType) {
|
||||
case ProjectExplorer::ToolChain_MinGW:
|
||||
case ProjectExplorer::ToolChain_MSVC:
|
||||
case ProjectExplorer::ToolChain_WINCE:
|
||||
case ProjectExplorer::ToolChain_WINSCW:
|
||||
case ProjectExplorer::ToolChain_GCCE:
|
||||
case ProjectExplorer::ToolChain_RVCT2_ARMV5:
|
||||
case ProjectExplorer::ToolChain_RVCT2_ARMV6:
|
||||
case ProjectExplorer::ToolChain_GCC_MAEMO5:
|
||||
case ProjectExplorer::ToolChain_GCC_HARMATTAN:
|
||||
case ProjectExplorer::ToolChain_GCC_MEEGO:
|
||||
if (m_abi.os() == ProjectExplorer::Abi::Symbian
|
||||
|| m_abi.os() == ProjectExplorer::Abi::Windows
|
||||
|| m_abi.binaryFormat() == ProjectExplorer::Abi::Format_ELF)
|
||||
return DumperLoadedByGdb;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return DumperLoadedByGdbPreload;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
#include "abstractgdbadapter.h"
|
||||
#include "localgdbprocess.h"
|
||||
|
||||
#include <projectexplorer/abi.h>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
@@ -51,7 +53,7 @@ class RemoteGdbServerAdapter : public AbstractGdbAdapter
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RemoteGdbServerAdapter(GdbEngine *engine, int toolChainType, QObject *parent = 0);
|
||||
RemoteGdbServerAdapter(GdbEngine *engine, const ProjectExplorer::Abi &abi, QObject *parent = 0);
|
||||
|
||||
private:
|
||||
DumperHandling dumperHandling() const;
|
||||
@@ -93,7 +95,7 @@ private:
|
||||
void handleTargetRemote(const GdbResponse &response);
|
||||
void handleInterruptInferior(const GdbResponse &response);
|
||||
|
||||
const int m_toolChainType;
|
||||
const ProjectExplorer::Abi m_abi;
|
||||
|
||||
QProcess m_uploadProc;
|
||||
LocalGdbProcess m_gdbProc;
|
||||
|
||||
Reference in New Issue
Block a user