diff --git a/src/plugins/projectexplorer/abi.cpp b/src/plugins/projectexplorer/abi.cpp index f0a4bf64cb0..0697ce28c57 100644 --- a/src/plugins/projectexplorer/abi.cpp +++ b/src/plugins/projectexplorer/abi.cpp @@ -532,6 +532,30 @@ QString Abi::toString(int w) return QString::fromLatin1("%1bit").arg(w); } +QList Abi::flavorsForOs(const Abi::OS &o) +{ + QList result; + switch (o) { + case BsdOS: + return result << FreeBsdFlavor << OpenBsdFlavor << NetBsdFlavor; + case LinuxOS: + return result << GenericLinuxFlavor << HarmattanLinuxFlavor << MaemoLinuxFlavor << MeegoLinuxFlavor; + case MacOS: + return result << GenericMacFlavor; + case SymbianOS: + return result << SymbianDeviceFlavor << SymbianEmulatorFlavor; + case UnixOS: + return result << GenericUnixFlavor << SolarisUnixFlavor; + case WindowsOS: + return result << WindowsMsvc2005Flavor << WindowsMsvc2008Flavor << WindowsMsvc2010Flavor + << WindowsMSysFlavor << WindowsCEFlavor; + case UnknownOS: + return result << UnknownFlavor; + default: + break; + } + return result; +} Abi Abi::hostAbi() { @@ -742,4 +766,23 @@ void ProjectExplorer::ProjectExplorerPlugin::testAbiOfBinary() QCOMPARE(result.at(i).toString(), abis.at(i)); } +void ProjectExplorer::ProjectExplorerPlugin::testFlavorForOs() +{ + QList > flavorLists; + for (int i = 0; i != static_cast(Abi::UnknownOS); ++i) + flavorLists.append(Abi::flavorsForOs(static_cast(i))); + + int foundCounter = 0; + for (int i = 0; i != Abi::UnknownFlavor; ++i) { + foundCounter = 0; + // make sure i is in exactly on of the flavor lists! + foreach (const QList &l, flavorLists) { + QVERIFY(!l.contains(Abi::UnknownFlavor)); + if (l.contains(static_cast(i))) + ++foundCounter; + } + QCOMPARE(foundCounter, 1); + } +} + #endif diff --git a/src/plugins/projectexplorer/abi.h b/src/plugins/projectexplorer/abi.h index 44630c4eeaf..2e03138b15a 100644 --- a/src/plugins/projectexplorer/abi.h +++ b/src/plugins/projectexplorer/abi.h @@ -47,28 +47,26 @@ class PROJECTEXPLORER_EXPORT Abi { public: enum Architecture { - UnknownArchitecture, ArmArchitecture, X86Architecture, ItaniumArchitecture, MipsArcitecture, - PowerPCArchitecture + PowerPCArchitecture, + UnknownArchitecture }; enum OS { - UnknownOS, BsdOS, LinuxOS, MacOS, SymbianOS, UnixOS, - WindowsOS + WindowsOS, + UnknownOS }; enum OSFlavor { - UnknownFlavor, - - // FreeBSD + // BSDs FreeBsdFlavor, NetBsdFlavor, OpenBsdFlavor, @@ -95,15 +93,17 @@ public: WindowsMsvc2008Flavor, WindowsMsvc2010Flavor, WindowsMSysFlavor, - WindowsCEFlavor + WindowsCEFlavor, + + UnknownFlavor }; enum BinaryFormat { - UnknownFormat, ElfFormat, MachOFormat, PEFormat, - RuntimeQmlFormat + RuntimeQmlFormat, + UnknownFormat }; Abi() : @@ -135,6 +135,8 @@ public: static QString toString(const BinaryFormat &bf); static QString toString(int w); + static QList flavorsForOs(const OS &o); + static Abi hostAbi(); static QList abisOfBinary(const QString &path); diff --git a/src/plugins/projectexplorer/abiwidget.cpp b/src/plugins/projectexplorer/abiwidget.cpp new file mode 100644 index 00000000000..edd17f90ea1 --- /dev/null +++ b/src/plugins/projectexplorer/abiwidget.cpp @@ -0,0 +1,220 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ + +#include "abiwidget.h" + +#include +#include +#include + +/*! + \class ProjectExplorer::AbiWidget + + \brief A widget to set an ABI. + + \sa ProjectExplorer::Abi +*/ + +namespace ProjectExplorer { +namespace Internal { + +// -------------------------------------------------------------------------- +// AbiWidgetPrivate: +// -------------------------------------------------------------------------- + +class AbiWidgetPrivate +{ +public: + QComboBox *m_abi; + + QComboBox *m_architectureComboBox; + QComboBox *m_osComboBox; + QComboBox *m_osFlavorComboBox; + QComboBox *m_binaryFormatComboBox; + QComboBox *m_wordWidthComboBox; +}; + +} // namespace Internal + +// -------------------------------------------------------------------------- +// AbiWidget +// -------------------------------------------------------------------------- + +AbiWidget::AbiWidget(QWidget *parent) : + QWidget(parent), + d(new Internal::AbiWidgetPrivate) +{ + QHBoxLayout *layout = new QHBoxLayout(this); + layout->setMargin(0); + layout->setSpacing(2); + + d->m_abi = new QComboBox(this); + layout->addWidget(d->m_abi); + connect(d->m_abi, SIGNAL(currentIndexChanged(int)), this, SLOT(modeChanged())); + + layout->addSpacing(10); + + d->m_architectureComboBox = new QComboBox(this); + layout->addWidget(d->m_architectureComboBox); + for (int i = 0; i <= static_cast(Abi::UnknownArchitecture); ++i) + d->m_architectureComboBox->addItem(Abi::toString(static_cast(i)), i); + d->m_architectureComboBox->setCurrentIndex(static_cast(Abi::UnknownArchitecture)); + connect(d->m_architectureComboBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(abiChanged())); + + QLabel *separator1 = new QLabel(this); + separator1->setText(QLatin1String("-")); + layout->addWidget(separator1); + + d->m_osComboBox = new QComboBox(this); + layout->addWidget(d->m_osComboBox); + for (int i = 0; i <= static_cast(Abi::UnknownOS); ++i) + d->m_osComboBox->addItem(Abi::toString(static_cast(i)), i); + d->m_osComboBox->setCurrentIndex(static_cast(Abi::UnknownOS)); + connect(d->m_osComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(osChanged())); + + QLabel *separator2 = new QLabel(this); + separator2->setText(QLatin1String("-")); + layout->addWidget(separator2); + + d->m_osFlavorComboBox = new QComboBox(this); + layout->addWidget(d->m_osFlavorComboBox); + osChanged(); + connect(d->m_osFlavorComboBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(abiChanged())); + + QLabel *separator3 = new QLabel(this); + separator3->setText(QLatin1String("-")); + layout->addWidget(separator3); + + d->m_binaryFormatComboBox = new QComboBox(this); + layout->addWidget(d->m_binaryFormatComboBox); + for (int i = 0; i <= static_cast(Abi::UnknownFormat); ++i) + d->m_binaryFormatComboBox->addItem(Abi::toString(static_cast(i)), i); + d->m_binaryFormatComboBox->setCurrentIndex(static_cast(Abi::UnknownFormat)); + connect(d->m_binaryFormatComboBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(abiChanged())); + + QLabel *separator4 = new QLabel(this); + separator4->setText(QLatin1String("-")); + layout->addWidget(separator4); + + d->m_wordWidthComboBox = new QComboBox(this); + layout->addWidget(d->m_wordWidthComboBox); + + d->m_wordWidthComboBox->addItem(Abi::toString(32), 32); + d->m_wordWidthComboBox->addItem(Abi::toString(64), 64); + d->m_wordWidthComboBox->addItem(Abi::toString(0), 0); + d->m_wordWidthComboBox->setCurrentIndex(2); + connect(d->m_wordWidthComboBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(abiChanged())); + + layout->setStretchFactor(d->m_abi, 1); + + setAbis(QList(), Abi::hostAbi()); +} + +AbiWidget::~AbiWidget() +{ + delete d; +} + +void AbiWidget::setAbis(const QList &abiList, const Abi ¤t) +{ + blockSignals(true); + d->m_abi->clear(); + + d->m_abi->addItem(tr(""), QLatin1String("custom")); + d->m_abi->setCurrentIndex(0); + for (int i = 0; i < abiList.count(); ++i) { + const QString abiString = abiList.at(i).toString(); + d->m_abi->addItem(abiString, abiString); + if (abiList.at(i) == current) + d->m_abi->setCurrentIndex(i + 1); + } + + if (d->m_abi->currentIndex() == 0) { + d->m_abi->setCurrentIndex(0); + d->m_architectureComboBox->setCurrentIndex(static_cast(current.architecture())); + d->m_osComboBox->setCurrentIndex(static_cast(current.os())); + osChanged(); + for (int i = 0; i < d->m_osFlavorComboBox->count(); ++i) { + if (d->m_osFlavorComboBox->itemData(i).toInt() == current.osFlavor()) { + d->m_osFlavorComboBox->setCurrentIndex(i); + break; + } + } + d->m_binaryFormatComboBox->setCurrentIndex(static_cast(current.binaryFormat())); + for (int i = 0; i < d->m_wordWidthComboBox->count(); ++i) { + if (d->m_wordWidthComboBox->itemData(i).toInt() == current.wordWidth()) { + d->m_wordWidthComboBox->setCurrentIndex(i); + break; + } + } + } + + blockSignals(false); +} + +Abi AbiWidget::currentAbi() const +{ + if (d->m_abi->currentIndex() > 0) + return Abi(d->m_abi->itemData(d->m_abi->currentIndex()).toString()); + + return Abi(static_cast(d->m_architectureComboBox->currentIndex()), + static_cast(d->m_osComboBox->currentIndex()), + static_cast(d->m_osFlavorComboBox->itemData(d->m_osFlavorComboBox->currentIndex()).toInt()), + static_cast(d->m_binaryFormatComboBox->currentIndex()), + d->m_wordWidthComboBox->itemData(d->m_wordWidthComboBox->currentIndex()).toInt()); +} + +void AbiWidget::osChanged() +{ + d->m_osFlavorComboBox->blockSignals(true); + d->m_osFlavorComboBox->clear(); + Abi::OS os = static_cast(d->m_osComboBox->itemData(d->m_osComboBox->currentIndex()).toInt()); + QList flavors = Abi::flavorsForOs(os); + foreach (Abi::OSFlavor f, flavors) + d->m_osFlavorComboBox->addItem(Abi::toString(f), static_cast(f)); + d->m_osFlavorComboBox->setCurrentIndex(0); // default to generic flavor + d->m_osFlavorComboBox->blockSignals(false); + + emit abiChanged(); +} + +void AbiWidget::modeChanged() +{ + const bool customMode = (d->m_abi->currentIndex() == 0); + d->m_architectureComboBox->setEnabled(customMode); + d->m_osComboBox->setEnabled(customMode); + d->m_osFlavorComboBox->setEnabled(customMode); + d->m_binaryFormatComboBox->setEnabled(customMode); + d->m_wordWidthComboBox->setEnabled(customMode); +} + +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/abiwidget.h b/src/plugins/projectexplorer/abiwidget.h new file mode 100644 index 00000000000..1b8a9350f01 --- /dev/null +++ b/src/plugins/projectexplorer/abiwidget.h @@ -0,0 +1,76 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ + +#ifndef PROJECTEXPLORER_ABIWIDGET_H +#define PROJECTEXPLORER_ABIWIDGET_H + +#include "projectexplorer_export.h" + +#include "abi.h" + +#include + +namespace ProjectExplorer { + +namespace Internal { +class AbiWidgetPrivate; +} // namespace + +// -------------------------------------------------------------------------- +// AbiWidget: +// -------------------------------------------------------------------------- + +class PROJECTEXPLORER_EXPORT AbiWidget : public QWidget +{ + Q_OBJECT + +public: + AbiWidget(QWidget *parent = 0); + ~AbiWidget(); + + void setAbis(const QList &, const Abi ¤t); + Abi currentAbi() const; + +signals: + void abiChanged(); + +private slots: + void osChanged(); + void modeChanged(); + +private: + Internal::AbiWidgetPrivate *const d; +}; + +} // namespace ProjectExplorer + +#endif // PROJECTEXPLORER_ABIWIDGET_H diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index 0eb81abb8af..7241f30b3c3 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -322,10 +322,8 @@ void GccToolChain::setTargetAbi(const Abi &abi) return; updateSupportedAbis(); - if (m_supportedAbis.contains(abi)) { - m_targetAbi = abi; - toolChainUpdated(); - } + m_targetAbi = abi; + toolChainUpdated(); } QList GccToolChain::supportedAbis() const @@ -596,7 +594,7 @@ QList Internal::GccToolChainFactory::autoDetectToolchains(const QSt Internal::GccToolChainConfigWidget::GccToolChainConfigWidget(GccToolChain *tc) : ToolChainConfigWidget(tc), m_compilerPath(new Utils::PathChooser), - m_abiComboBox(new QComboBox) + m_abiWidget(new AbiWidget) { Q_ASSERT(tc); @@ -607,14 +605,14 @@ Internal::GccToolChainConfigWidget::GccToolChainConfigWidget(GccToolChain *tc) : m_compilerPath->setCommandVersionArguments(gnuVersionArgs); connect(m_compilerPath, SIGNAL(changed(QString)), this, SLOT(handlePathChange())); layout->addRow(tr("&Compiler path:"), m_compilerPath); - layout->addRow(tr("&ABI:"), m_abiComboBox); + layout->addRow(tr("&ABI:"), m_abiWidget); addDebuggerCommandControls(layout, gnuVersionArgs); addErrorLabel(layout); - populateAbiList(tc->supportedAbis()); + populateAbiList(tc->supportedAbis(), tc->targetAbi()); - connect(m_abiComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(handleAbiChange())); + connect(m_abiWidget, SIGNAL(abiChanged()), this, SLOT(handleAbiChange())); setFromToolchain(); } @@ -631,28 +629,15 @@ void Internal::GccToolChainConfigWidget::apply() if (path.isEmpty()) path = m_compilerPath->rawPath(); tc->setCompilerPath(path); - tc->setTargetAbi(m_abiList.at(m_abiComboBox->currentIndex())); + tc->setTargetAbi(m_abiWidget->currentAbi()); tc->setDisplayName(displayName); // reset display name tc->setDebuggerCommand(debuggerCommand()); m_autoDebuggerCommand = QLatin1String(""); } -void Internal::GccToolChainConfigWidget::populateAbiList(const QList &list) +void Internal::GccToolChainConfigWidget::populateAbiList(const QList &list, const Abi ¤t) { - GccToolChain *tc = static_cast(toolChain()); - Abi currentAbi = tc->targetAbi(); - - m_abiComboBox->clear(); - m_abiList = list; - - if (m_abiList.isEmpty()) - m_abiList.append(Abi()); - - for (int i = 0; i < m_abiList.count(); ++i) { - m_abiComboBox->addItem(m_abiList.at(i).toString()); - if (m_abiList.at(i) == currentAbi) - m_abiComboBox->setCurrentIndex(i); - } + m_abiWidget->setAbis(list, current); handleAbiChange(); } @@ -662,7 +647,7 @@ void Internal::GccToolChainConfigWidget::setFromToolchain() Q_ASSERT(tc); m_compilerPath->setPath(tc->compilerPath()); setDebuggerCommand(tc->debuggerCommand()); - populateAbiList(tc->supportedAbis()); + populateAbiList(tc->supportedAbis(), tc->targetAbi()); } bool Internal::GccToolChainConfigWidget::isDirty() const @@ -670,13 +655,13 @@ bool Internal::GccToolChainConfigWidget::isDirty() const GccToolChain *tc = static_cast(toolChain()); Q_ASSERT(tc); return m_compilerPath->path() != tc->compilerPath() - || m_abiList.at(m_abiComboBox->currentIndex()) != tc->targetAbi(); + || m_abiWidget->currentAbi() != tc->targetAbi(); } void Internal::GccToolChainConfigWidget::makeReadOnly() { m_compilerPath->setEnabled(false); - m_abiComboBox->setEnabled(false); + m_abiWidget->setEnabled(false); ToolChainConfigWidget::makeReadOnly(); } @@ -686,14 +671,14 @@ void Internal::GccToolChainConfigWidget::handlePathChange() QList abiList; if (QFileInfo(path).isExecutable()) abiList = guessGccAbi(path, Utils::Environment::systemEnvironment().toStringList()); - populateAbiList(abiList); + populateAbiList(abiList, m_abiWidget->currentAbi()); emit dirty(toolChain()); } void Internal::GccToolChainConfigWidget::handleAbiChange() { - if (m_autoDebuggerCommand == debuggerCommand() && m_abiComboBox->currentIndex() >= 0) { - ProjectExplorer::Abi abi = m_abiList.at(m_abiComboBox->currentIndex()); + if (m_autoDebuggerCommand == debuggerCommand()) { + ProjectExplorer::Abi abi = m_abiWidget->currentAbi(); m_autoDebuggerCommand = ToolChainManager::instance()->defaultDebugger(abi); setDebuggerCommand(m_autoDebuggerCommand); } diff --git a/src/plugins/projectexplorer/gcctoolchainfactories.h b/src/plugins/projectexplorer/gcctoolchainfactories.h index 14cdea6b94f..6bef83d6bef 100644 --- a/src/plugins/projectexplorer/gcctoolchainfactories.h +++ b/src/plugins/projectexplorer/gcctoolchainfactories.h @@ -36,6 +36,7 @@ #include "toolchain.h" #include "toolchainconfigwidget.h" #include "abi.h" +#include "abiwidget.h" #include @@ -97,11 +98,11 @@ private slots: void handleAbiChange(); private: - void populateAbiList(const QList &); + void populateAbiList(const QList &supported, const Abi ¤t); void setFromToolchain(); Utils::PathChooser *m_compilerPath; - QComboBox *m_abiComboBox; + AbiWidget *m_abiWidget; QString m_autoDebuggerCommand; QList m_abiList; diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h index cae6c504a99..554280edde4 100644 --- a/src/plugins/projectexplorer/projectexplorer.h +++ b/src/plugins/projectexplorer/projectexplorer.h @@ -247,6 +247,7 @@ private slots: void testAbiOfBinary_data(); void testAbiOfBinary(); + void testFlavorForOs(); #endif private: diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro index 60466c6b45f..08f372ce152 100644 --- a/src/plugins/projectexplorer/projectexplorer.pro +++ b/src/plugins/projectexplorer/projectexplorer.pro @@ -8,6 +8,7 @@ include(customwizard/customwizard.pri) INCLUDEPATH += $$PWD/../../libs/utils HEADERS += projectexplorer.h \ abi.h \ + abiwidget.h \ clangparser.h \ gcctoolchain.h \ projectexplorer_export.h \ @@ -104,6 +105,7 @@ HEADERS += projectexplorer.h \ SOURCES += projectexplorer.cpp \ abi.cpp \ + abiwidget.cpp \ clangparser.cpp \ gcctoolchain.cpp \ projectwindow.cpp \