ProjectExplorer: Improve the toolchain combo box in the kit options page

- Sort entries by toolchain type and name
- Mark invalid and incomplete toolchains the same way as in the
  toolchains options page

Change-Id: Iaf326b06c6b77c3def076793c2441f290862dae7
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Christian Kandeler
2024-08-28 17:42:09 +02:00
parent 9970ba0a6c
commit e017a10541
3 changed files with 220 additions and 126 deletions

View File

@@ -10,10 +10,12 @@
#include "projectexplorerconstants.h" #include "projectexplorerconstants.h"
#include "projectexplorertr.h" #include "projectexplorertr.h"
#include "toolchainmanager.h" #include "toolchainmanager.h"
#include "toolchainoptionspage.h"
#include <utils/guard.h> #include <utils/guard.h>
#include <utils/layoutbuilder.h> #include <utils/layoutbuilder.h>
#include <utils/macroexpander.h> #include <utils/macroexpander.h>
#include <utils/stringutils.h>
#include <QComboBox> #include <QComboBox>
#include <QGridLayout> #include <QGridLayout>
@@ -21,8 +23,88 @@
using namespace Utils; using namespace Utils;
namespace ProjectExplorer { namespace ProjectExplorer {
namespace Internal { namespace Internal {
class ToolchainListModel : public TreeModel<ToolchainTreeItem>
{
public:
ToolchainListModel(const Kit &kit, const LanguageCategory &category, QObject *parent)
: TreeModel(parent)
, m_kit(kit)
, m_category(category)
{
reset();
}
QModelIndex indexForBundleId(Id bundleId) const
{
if (!bundleId.isValid())
return index(rowCount() - 1, 0); // The "no compiler" item always comes last
const TreeItem *const item = findItemAtLevel<1>(
[bundleId](TreeItem *item) {
const auto tcItem = static_cast<ToolchainTreeItem *>(item);
return tcItem->bundle && tcItem->bundle->bundleId() == bundleId;
});
return item ? indexForItem(item) : QModelIndex();
}
void reset()
{
clear();
const Toolchains ltcList = ToolchainManager::toolchains(
[this](const Toolchain *tc) { return m_category.contains(tc->language()); });
IDeviceConstPtr device = BuildDeviceKitAspect::device(&m_kit);
const QList<Toolchain *> toolchainsForBuildDevice
= Utils::filtered(ltcList, [device](Toolchain *tc) {
return tc->compilerCommand().isSameDevice(device->rootPath());
});
const QList<ToolchainBundle> bundlesForBuildDevice = ToolchainBundle::collectBundles(
toolchainsForBuildDevice, ToolchainBundle::AutoRegister::On);
for (const ToolchainBundle &b : bundlesForBuildDevice)
rootItem()->appendChild(new ToolchainTreeItem(b));
rootItem()->appendChild(new ToolchainTreeItem);
}
private:
const Kit &m_kit;
const LanguageCategory m_category;
};
class ToolchainSortModel : public SortModel
{
public:
ToolchainSortModel(QObject *parent) : SortModel(parent) {}
QModelIndex indexForBundleId(Id bundleId) const
{
return mapFromSource(
static_cast<ToolchainListModel *>(sourceModel())->indexForBundleId(bundleId));
}
void reset() { static_cast<ToolchainListModel *>(sourceModel())->reset(); }
private:
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override
{
const auto source = static_cast<ToolchainListModel *>(sourceModel());
const ToolchainTreeItem *item1 = source->itemForIndex(source_left);
const ToolchainTreeItem *item2 = source->itemForIndex(source_right);
QTC_ASSERT(item1 && item2, return false);
if (!item1->bundle)
return false;
if (!item2->bundle)
return true;
if (item1->bundle->type() != item2->bundle->type()) {
return caseFriendlyCompare(
item1->bundle->typeDisplayName(), item2->bundle->typeDisplayName())
< 0;
}
return SortModel::lessThan(source_left, source_right);
}
};
class ToolchainKitAspectImpl final : public KitAspect class ToolchainKitAspectImpl final : public KitAspect
{ {
public: public:
@@ -51,6 +133,11 @@ public:
cb->setToolTip(factory->description()); cb->setToolTip(factory->description());
setWheelScrollingWithoutFocusBlocked(cb); setWheelScrollingWithoutFocusBlocked(cb);
const auto model = new ToolchainListModel(*kit(), lc, this);
const auto sortModel = new ToolchainSortModel(this);
sortModel->setSourceModel(model);
cb->setModel(sortModel);
m_languageComboboxMap.insert(lc, cb); m_languageComboboxMap.insert(lc, cb);
layout->addWidget(cb, row, 1); layout->addWidget(cb, row, 1);
++row; ++row;
@@ -88,34 +175,18 @@ private:
[lc](const Toolchain *tc) { return lc.contains(tc->language()); }); [lc](const Toolchain *tc) { return lc.contains(tc->language()); });
QComboBox *cb = *it; QComboBox *cb = *it;
cb->clear(); static_cast<ToolchainSortModel *>(cb->model())->reset();
cb->addItem(Tr::tr("<No compiler>"), QByteArray()); cb->model()->sort(0);
const QList<Toolchain *> toolchainsForBuildDevice
= Utils::filtered(ltcList, [device](Toolchain *tc) {
return tc->compilerCommand().isSameDevice(device->rootPath());
});
const QList<ToolchainBundle> bundlesForBuildDevice = ToolchainBundle::collectBundles(
toolchainsForBuildDevice, ToolchainBundle::AutoRegister::On);
for (const ToolchainBundle &b : bundlesForBuildDevice)
cb->addItem(b.displayName(), b.bundleId().toSetting());
cb->setEnabled(cb->count() > 1 && !m_isReadOnly); cb->setEnabled(cb->count() > 1 && !m_isReadOnly);
Id currentBundleId; Id currentBundleId;
for (const Id lang : lc) { for (const Id lang : lc) {
Toolchain * const currentTc = ToolchainKitAspect::toolchain(m_kit, lang); if (Toolchain * const currentTc = ToolchainKitAspect::toolchain(m_kit, lang)) {
if (!currentTc) currentBundleId = currentTc->bundleId();
continue;
for (const ToolchainBundle &b : bundlesForBuildDevice) {
if (b.bundleId() == currentTc->bundleId()) {
currentBundleId = b.bundleId();
break;
}
}
if (currentBundleId.isValid())
break; break;
}
} }
cb->setCurrentIndex(currentBundleId.isValid() ? indexOf(cb, currentBundleId) : -1); cb->setCurrentIndex(indexOf(cb, currentBundleId));
} }
} }
@@ -131,8 +202,11 @@ private:
if (m_ignoreChanges.isLocked() || idx < 0) if (m_ignoreChanges.isLocked() || idx < 0)
return; return;
const QAbstractItemModel *const model
= m_languageComboboxMap.value(languageCategory)->model();
const Id bundleId = Id::fromSetting( const Id bundleId = Id::fromSetting(
m_languageComboboxMap.value(languageCategory)->itemData(idx)); model->data(model->index(idx, 0), ToolchainTreeItem::BundleIdRole));
const Toolchains bundleTcs = ToolchainManager::toolchains( const Toolchains bundleTcs = ToolchainManager::toolchains(
[bundleId](const Toolchain *tc) { return tc->bundleId() == bundleId; }); [bundleId](const Toolchain *tc) { return tc->bundleId() == bundleId; });
for (const Id lang : languageCategory) { for (const Id lang : languageCategory) {
@@ -148,11 +222,7 @@ private:
int indexOf(QComboBox *cb, Id bundleId) int indexOf(QComboBox *cb, Id bundleId)
{ {
for (int i = 0; i < cb->count(); ++i) { return static_cast<ToolchainSortModel *>(cb->model())->indexForBundleId(bundleId).row();
if (bundleId.toSetting() == cb->itemData(i))
return i;
}
return -1;
} }
QWidget *m_mainWidget = nullptr; QWidget *m_mainWidget = nullptr;

View File

@@ -46,63 +46,73 @@ using namespace Utils;
namespace ProjectExplorer { namespace ProjectExplorer {
namespace Internal { namespace Internal {
class ToolChainTreeItem : public TreeItem QVariant ToolchainTreeItem::data(int column, int role) const
{
switch (role) {
case Qt::DisplayRole:
if (column == 0)
return bundle ? bundle->displayName() : Tr::tr("<No toolchain>");
return bundle->typeDisplayName();
case Qt::ToolTipRole: {
if (!bundle)
return {};
QString toolTip;
const ToolchainBundle::Valid validity = bundle->validity();
if (validity != ToolchainBundle::Valid::None) {
toolTip = Tr::tr("<nobr><b>ABI:</b> %1").arg(bundle->targetAbi().toString());
if (validity == ToolchainBundle::Valid::Some)
toolTip.append("<br/>").append(Tr::tr("Not all compilers are set up correctly."));
} else {
toolTip = Tr::tr("This toolchain is invalid.");
}
return QVariant("<div style=\"white-space:pre\">" + toolTip + "</div>");
}
case Qt::DecorationRole:
if (!bundle)
return {};
if (column == 0) {
switch (bundle->validity()) {
case ToolchainBundle::Valid::All:
break;
case ToolchainBundle::Valid::Some:
return Utils::Icons::WARNING.icon();
case ToolchainBundle::Valid::None:
return Utils::Icons::CRITICAL.icon();
}
}
return QVariant();
case BundleIdRole:
return bundle ? bundle->bundleId().toSetting() : QVariant();
}
return {};
}
class ExtendedToolchainTreeItem : public ToolchainTreeItem
{ {
public: public:
ToolChainTreeItem(QStackedWidget *parentWidget, const ToolchainBundle &bundle, bool c) : ExtendedToolchainTreeItem(QStackedWidget *parentWidget, const ToolchainBundle &bundle, bool c) :
bundle(bundle), changed(c), m_parentWidget(parentWidget) ToolchainTreeItem(bundle), changed(c), m_parentWidget(parentWidget)
{} {}
QVariant data(int column, int role) const override QVariant data(int column, int role) const override
{ {
switch (role) { switch (role) {
case Qt::DisplayRole: case Qt::FontRole: {
if (column == 0) QFont font;
return bundle.displayName(); font.setBold(changed);
return bundle.typeDisplayName(); return font;
case Qt::FontRole: {
QFont font;
font.setBold(changed);
return font;
}
case Qt::ToolTipRole: {
QString toolTip;
const ToolchainBundle::Valid validity = bundle.validity();
if (validity != ToolchainBundle::Valid::None) {
toolTip = Tr::tr("<nobr><b>ABI:</b> %1").arg(
changed ? Tr::tr("not up-to-date")
: bundle.targetAbi().toString());
if (validity == ToolchainBundle::Valid::Some)
toolTip.append("<br/>").append(
Tr::tr("Not all compilers are set up correctly."));
} else {
toolTip = Tr::tr("This toolchain is invalid.");
}
return QVariant("<div style=\"white-space:pre\">" + toolTip + "</div>");
}
case Qt::DecorationRole:
if (column == 0) {
switch (bundle.validity()) {
case ToolchainBundle::Valid::All:
break;
case ToolchainBundle::Valid::Some:
return Utils::Icons::WARNING.icon();
case ToolchainBundle::Valid::None:
return Utils::Icons::CRITICAL.icon();
}
}
return QVariant();
} }
return {}; }
return ToolchainTreeItem::data(column, role);
} }
ToolchainConfigWidget *widget() ToolchainConfigWidget *widget()
{ {
if (!m_widget) { if (!m_widget) {
m_widget = bundle.factory()->createConfigurationWidget(bundle).release(); m_widget = bundle->factory()->createConfigurationWidget(*bundle).release();
if (m_widget) { if (m_widget) {
m_parentWidget->addWidget(m_widget); m_parentWidget->addWidget(m_widget);
if (bundle.isAutoDetected()) if (bundle->isAutoDetected())
m_widget->makeReadOnly(); m_widget->makeReadOnly();
QObject::connect(m_widget, &ToolchainConfigWidget::dirty, QObject::connect(m_widget, &ToolchainConfigWidget::dirty,
[this] { [this] {
@@ -114,7 +124,6 @@ public:
return m_widget; return m_widget;
} }
ToolchainBundle bundle;
bool changed; bool changed;
private: private:
@@ -226,15 +235,15 @@ public:
m_removeAllButton = new QPushButton(Tr::tr("Remove All"), this); m_removeAllButton = new QPushButton(Tr::tr("Remove All"), this);
connect(m_removeAllButton, &QAbstractButton::clicked, this, connect(m_removeAllButton, &QAbstractButton::clicked, this,
[this] { [this] {
QList<ToolChainTreeItem *> itemsToRemove; QList<ExtendedToolchainTreeItem *> itemsToRemove;
m_model.forAllItems([&itemsToRemove](TreeItem *item) { m_model.forAllItems([&itemsToRemove](TreeItem *item) {
if (item->level() != 3) if (item->level() != 3)
return; return;
const auto tcItem = static_cast<ToolChainTreeItem *>(item); const auto tcItem = static_cast<ExtendedToolchainTreeItem *>(item);
if (!tcItem->bundle.isSdkProvided()) if (!tcItem->bundle->isSdkProvided())
itemsToRemove << tcItem; itemsToRemove << tcItem;
}); });
for (ToolChainTreeItem * const tcItem : std::as_const(itemsToRemove)) for (ExtendedToolchainTreeItem * const tcItem : std::as_const(itemsToRemove))
markForRemoval(tcItem); markForRemoval(tcItem);
}); });
@@ -292,7 +301,7 @@ public:
this, &ToolChainOptionsWidget::toolChainSelectionChanged); this, &ToolChainOptionsWidget::toolChainSelectionChanged);
connect(m_delButton, &QAbstractButton::clicked, this, [this] { connect(m_delButton, &QAbstractButton::clicked, this, [this] {
if (ToolChainTreeItem *item = currentTreeItem()) if (ExtendedToolchainTreeItem *item = currentTreeItem())
markForRemoval(item); markForRemoval(item);
}); });
@@ -303,10 +312,10 @@ public:
void updateState(); void updateState();
void createToolchains(ToolchainFactory *factory, const QList<Id> &languages); void createToolchains(ToolchainFactory *factory, const QList<Id> &languages);
void cloneToolchains(); void cloneToolchains();
ToolChainTreeItem *currentTreeItem(); ExtendedToolchainTreeItem *currentTreeItem();
void markForRemoval(ToolChainTreeItem *item); void markForRemoval(ExtendedToolchainTreeItem *item);
ToolChainTreeItem *insertBundle(const ToolchainBundle &bundle, bool changed = false); // Insert directly into model ExtendedToolchainTreeItem *insertBundle(const ToolchainBundle &bundle, bool changed = false); // Insert directly into model
void handleToolchainsRegistered(const Toolchains &toolchains); void handleToolchainsRegistered(const Toolchains &toolchains);
void handleToolchainsDeregistered(const Toolchains &toolchains); void handleToolchainsDeregistered(const Toolchains &toolchains);
@@ -326,7 +335,7 @@ public:
void apply() final; void apply() final;
private: private:
TreeModel<TreeItem, ToolChainTreeItem> m_model; TreeModel<TreeItem, ExtendedToolchainTreeItem> m_model;
KitSettingsSortModel m_sortModel; KitSettingsSortModel m_sortModel;
QList<ToolchainFactory *> m_factories; QList<ToolchainFactory *> m_factories;
QTreeView *m_toolChainView; QTreeView *m_toolChainView;
@@ -341,7 +350,7 @@ public:
QHash<LanguageCategory, QPair<StaticTreeItem *, StaticTreeItem *>> m_languageMap; QHash<LanguageCategory, QPair<StaticTreeItem *, StaticTreeItem *>> m_languageMap;
using AddRemoveList = QList<ToolChainTreeItem *>; using AddRemoveList = QList<ExtendedToolchainTreeItem *>;
AddRemoveList m_toAddList; AddRemoveList m_toAddList;
AddRemoveList m_toRemoveList; AddRemoveList m_toRemoveList;
Guard m_registerGuard; Guard m_registerGuard;
@@ -350,12 +359,12 @@ public:
ToolchainDetectionSettings m_detectionSettings; ToolchainDetectionSettings m_detectionSettings;
}; };
void ToolChainOptionsWidget::markForRemoval(ToolChainTreeItem *item) void ToolChainOptionsWidget::markForRemoval(ExtendedToolchainTreeItem *item)
{ {
m_model.takeItem(item); m_model.takeItem(item);
if (const auto it = std::find(m_toAddList.begin(), m_toAddList.end(), item); if (const auto it = std::find(m_toAddList.begin(), m_toAddList.end(), item);
it != m_toAddList.end()) { it != m_toAddList.end()) {
item->bundle.deleteToolchains(); item->bundle->deleteToolchains();
m_toAddList.erase(it); m_toAddList.erase(it);
delete item; delete item;
} else { } else {
@@ -363,11 +372,11 @@ void ToolChainOptionsWidget::markForRemoval(ToolChainTreeItem *item)
} }
} }
ToolChainTreeItem *ToolChainOptionsWidget::insertBundle( ExtendedToolchainTreeItem *ToolChainOptionsWidget::insertBundle(
const ToolchainBundle &bundle, bool changed) const ToolchainBundle &bundle, bool changed)
{ {
StaticTreeItem *parent = parentForBundle(bundle); StaticTreeItem *parent = parentForBundle(bundle);
auto item = new ToolChainTreeItem(m_widgetStack, bundle, changed); auto item = new ExtendedToolchainTreeItem(m_widgetStack, bundle, changed);
parent->appendChild(item); parent->appendChild(item);
return item; return item;
@@ -382,11 +391,11 @@ void ToolChainOptionsWidget::handleToolchainsRegistered(const Toolchains &toolch
if (const auto it = std::find_if( if (const auto it = std::find_if(
m_toAddList.begin(), m_toAddList.begin(),
m_toAddList.end(), m_toAddList.end(),
[&toolchains](ToolChainTreeItem * const item) { [&toolchains](ExtendedToolchainTreeItem * const item) {
return item->bundle.bundleId() == toolchains.first()->bundleId(); return item->bundle->bundleId() == toolchains.first()->bundleId();
}); });
it != m_toAddList.end()) { it != m_toAddList.end()) {
if ((*it)->bundle.toolchains().size() == toolchains.size()) if ((*it)->bundle->toolchains().size() == toolchains.size())
m_toAddList.erase(it); m_toAddList.erase(it);
return; return;
} }
@@ -407,32 +416,32 @@ void ToolChainOptionsWidget::handleToolchainsDeregistered(const Toolchains &tool
if (const auto it = std::find_if( if (const auto it = std::find_if(
m_toRemoveList.begin(), m_toRemoveList.begin(),
m_toRemoveList.end(), m_toRemoveList.end(),
[&toolchains](const ToolChainTreeItem *item) { [&toolchains](const ExtendedToolchainTreeItem *item) {
return item->bundle.toolchains() == toolchains; return item->bundle->toolchains() == toolchains;
}); });
it != m_toRemoveList.end()) { it != m_toRemoveList.end()) {
ToolChainTreeItem * const item = *it; ExtendedToolchainTreeItem * const item = *it;
m_toRemoveList.erase(it); m_toRemoveList.erase(it);
delete item; delete item;
return; return;
} }
QSet<ToolChainTreeItem *> affectedItems; QSet<ExtendedToolchainTreeItem *> affectedItems;
for (Toolchain * const tc : toolchains) { for (Toolchain * const tc : toolchains) {
StaticTreeItem *parent = parentForToolchain(*tc); StaticTreeItem *parent = parentForToolchain(*tc);
auto item = static_cast<ToolChainTreeItem *>( auto item = static_cast<ExtendedToolchainTreeItem *>(
parent->findChildAtLevel(1, [tc](TreeItem *item) { parent->findChildAtLevel(1, [tc](TreeItem *item) {
const auto tcItem = static_cast<ToolChainTreeItem *>(item); const auto tcItem = static_cast<ExtendedToolchainTreeItem *>(item);
return tcItem->bundle.size() > 0 && tcItem->bundle.bundleId() == tc->bundleId(); return tcItem->bundle->size() > 0 && tcItem->bundle->bundleId() == tc->bundleId();
})); }));
const bool removed = item->bundle.removeToolchain(tc); const bool removed = item->bundle->removeToolchain(tc);
QTC_CHECK(removed); QTC_CHECK(removed);
affectedItems << item; affectedItems << item;
} }
for (ToolChainTreeItem *item : std::as_const(affectedItems)) { for (ExtendedToolchainTreeItem *item : std::as_const(affectedItems)) {
ToolchainManager::deregisterToolchains(item->bundle.toolchains()); ToolchainManager::deregisterToolchains(item->bundle->toolchains());
item->bundle.clearToolchains(); item->bundle->clearToolchains();
m_model.destroyItem(item); m_model.destroyItem(item);
} }
@@ -459,7 +468,7 @@ StaticTreeItem *ToolChainOptionsWidget::parentForToolchain(const Toolchain &tc)
void ToolChainOptionsWidget::redetectToolchains() void ToolChainOptionsWidget::redetectToolchains()
{ {
// The second element is the set of toolchains for the respective bundle that were re-discovered. // The second element is the set of toolchains for the respective bundle that were re-discovered.
using ItemToCheck = std::pair<ToolChainTreeItem *, Toolchains>; using ItemToCheck = std::pair<ExtendedToolchainTreeItem *, Toolchains>;
QList<ItemToCheck> itemsToRemove; QList<ItemToCheck> itemsToRemove;
Toolchains knownTcs; Toolchains knownTcs;
@@ -468,11 +477,11 @@ void ToolChainOptionsWidget::redetectToolchains()
m_model.forAllItems([&itemsToRemove, &knownTcs](TreeItem *item) { m_model.forAllItems([&itemsToRemove, &knownTcs](TreeItem *item) {
if (item->level() != 3) if (item->level() != 3)
return; return;
const auto tcItem = static_cast<ToolChainTreeItem *>(item); const auto tcItem = static_cast<ExtendedToolchainTreeItem *>(item);
if (tcItem->bundle.isAutoDetected() && !tcItem->bundle.isSdkProvided()) if (tcItem->bundle->isAutoDetected() && !tcItem->bundle->isSdkProvided())
itemsToRemove << std::make_pair(tcItem, Toolchains()); itemsToRemove << std::make_pair(tcItem, Toolchains());
else else
knownTcs << tcItem->bundle.toolchains(); knownTcs << tcItem->bundle->toolchains();
}); });
Toolchains toAdd; Toolchains toAdd;
@@ -486,7 +495,7 @@ void ToolChainOptionsWidget::redetectToolchains()
continue; continue;
knownTcs << tc; knownTcs << tc;
const auto matchItem = [&](const ItemToCheck &item) { const auto matchItem = [&](const ItemToCheck &item) {
return Utils::contains(item.first->bundle.toolchains(), [&](Toolchain *btc) { return Utils::contains(item.first->bundle->toolchains(), [&](Toolchain *btc) {
return *btc == *tc; return *btc == *tc;
}); });
}; };
@@ -505,7 +514,7 @@ void ToolChainOptionsWidget::redetectToolchains()
// Conversely, if not all toolchains of the bundle were re-discovered, we remove the existing // Conversely, if not all toolchains of the bundle were re-discovered, we remove the existing
// item and the newly discovered toolchains are marked for re-bundling. // item and the newly discovered toolchains are marked for re-bundling.
for (const auto &[item, newToolchains] : itemsToRemove) { for (const auto &[item, newToolchains] : itemsToRemove) {
if (item->bundle.toolchains().size() == newToolchains.size()) { if (item->bundle->toolchains().size() == newToolchains.size()) {
qDeleteAll(newToolchains); qDeleteAll(newToolchains);
} else { } else {
toAdd << newToolchains; toAdd << newToolchains;
@@ -522,7 +531,7 @@ void ToolChainOptionsWidget::redetectToolchains()
void ToolChainOptionsWidget::toolChainSelectionChanged() void ToolChainOptionsWidget::toolChainSelectionChanged()
{ {
ToolChainTreeItem *item = currentTreeItem(); ExtendedToolchainTreeItem *item = currentTreeItem();
QWidget *currentTcWidget = item ? item->widget() : nullptr; QWidget *currentTcWidget = item ? item->widget() : nullptr;
if (currentTcWidget) if (currentTcWidget)
@@ -535,8 +544,8 @@ void ToolChainOptionsWidget::apply()
{ {
// Remove unused tool chains: // Remove unused tool chains:
const AddRemoveList toRemove = m_toRemoveList; const AddRemoveList toRemove = m_toRemoveList;
for (const ToolChainTreeItem * const item : toRemove) for (const ExtendedToolchainTreeItem * const item : toRemove)
ToolchainManager::deregisterToolchains(item->bundle.toolchains()); ToolchainManager::deregisterToolchains(item->bundle->toolchains());
Q_ASSERT(m_toRemoveList.isEmpty()); Q_ASSERT(m_toRemoveList.isEmpty());
@@ -544,8 +553,8 @@ void ToolChainOptionsWidget::apply()
for (const QPair<StaticTreeItem *, StaticTreeItem *> &autoAndManual : m_languageMap) { for (const QPair<StaticTreeItem *, StaticTreeItem *> &autoAndManual : m_languageMap) {
for (StaticTreeItem *parent : {autoAndManual.first, autoAndManual.second}) { for (StaticTreeItem *parent : {autoAndManual.first, autoAndManual.second}) {
for (TreeItem *item : *parent) { for (TreeItem *item : *parent) {
auto tcItem = static_cast<ToolChainTreeItem *>(item); auto tcItem = static_cast<ExtendedToolchainTreeItem *>(item);
if (!tcItem->bundle.isAutoDetected() && tcItem->widget() && tcItem->changed) if (!tcItem->bundle->isAutoDetected() && tcItem->widget() && tcItem->changed)
tcItem->widget()->apply(); tcItem->widget()->apply();
tcItem->changed = false; tcItem->changed = false;
tcItem->update(); tcItem->update();
@@ -556,12 +565,12 @@ void ToolChainOptionsWidget::apply()
// Add new (and already updated) toolchains // Add new (and already updated) toolchains
QStringList removedTcs; QStringList removedTcs;
const AddRemoveList toAdd = m_toAddList; const AddRemoveList toAdd = m_toAddList;
for (ToolChainTreeItem * const item : toAdd) { for (ExtendedToolchainTreeItem * const item : toAdd) {
const Toolchains notRegistered = ToolchainManager::registerToolchains(item->bundle.toolchains()); const Toolchains notRegistered = ToolchainManager::registerToolchains(item->bundle->toolchains());
removedTcs << Utils::transform(notRegistered, &Toolchain::displayName); removedTcs << Utils::transform(notRegistered, &Toolchain::displayName);
} }
for (ToolChainTreeItem * const item : std::as_const(m_toAddList)) { for (ExtendedToolchainTreeItem * const item : std::as_const(m_toAddList)) {
item->bundle.deleteToolchains(); item->bundle->deleteToolchains();
delete item; delete item;
} }
m_toAddList.clear(); m_toAddList.clear();
@@ -603,22 +612,22 @@ void ToolChainOptionsWidget::createToolchains(ToolchainFactory *factory, const Q
} }
const ToolchainBundle bundle(toolchains, ToolchainBundle::AutoRegister::Off); const ToolchainBundle bundle(toolchains, ToolchainBundle::AutoRegister::Off);
ToolChainTreeItem * const item = insertBundle(bundle, true); ExtendedToolchainTreeItem * const item = insertBundle(bundle, true);
m_toAddList << item; m_toAddList << item;
m_toolChainView->setCurrentIndex(m_sortModel.mapFromSource(m_model.indexForItem(item))); m_toolChainView->setCurrentIndex(m_sortModel.mapFromSource(m_model.indexForItem(item)));
} }
void ToolChainOptionsWidget::cloneToolchains() void ToolChainOptionsWidget::cloneToolchains()
{ {
ToolChainTreeItem *current = currentTreeItem(); ExtendedToolchainTreeItem *current = currentTreeItem();
if (!current) if (!current)
return; return;
ToolchainBundle bundle = current->bundle.clone(); ToolchainBundle bundle = current->bundle->clone();
bundle.setDetection(Toolchain::ManualDetection); bundle.setDetection(Toolchain::ManualDetection);
bundle.setDisplayName(Tr::tr("Clone of %1").arg(current->bundle.displayName())); bundle.setDisplayName(Tr::tr("Clone of %1").arg(current->bundle->displayName()));
ToolChainTreeItem * const item = insertBundle(bundle, true); ExtendedToolchainTreeItem * const item = insertBundle(bundle, true);
m_toAddList << item; m_toAddList << item;
m_toolChainView->setCurrentIndex(m_sortModel.mapFromSource(m_model.indexForItem(item))); m_toolChainView->setCurrentIndex(m_sortModel.mapFromSource(m_model.indexForItem(item)));
} }
@@ -627,19 +636,19 @@ void ToolChainOptionsWidget::updateState()
{ {
bool canCopy = false; bool canCopy = false;
bool canDelete = false; bool canDelete = false;
if (ToolChainTreeItem *item = currentTreeItem()) { if (ExtendedToolchainTreeItem *item = currentTreeItem()) {
canCopy = item->bundle.validity() != ToolchainBundle::Valid::None; canCopy = item->bundle->validity() != ToolchainBundle::Valid::None;
canDelete = !item->bundle.isSdkProvided(); canDelete = !item->bundle->isSdkProvided();
} }
m_cloneButton->setEnabled(canCopy); m_cloneButton->setEnabled(canCopy);
m_delButton->setEnabled(canDelete); m_delButton->setEnabled(canDelete);
} }
ToolChainTreeItem *ToolChainOptionsWidget::currentTreeItem() ExtendedToolchainTreeItem *ToolChainOptionsWidget::currentTreeItem()
{ {
TreeItem *item = m_model.itemForIndex(m_sortModel.mapToSource(m_toolChainView->currentIndex())); TreeItem *item = m_model.itemForIndex(m_sortModel.mapToSource(m_toolChainView->currentIndex()));
return (item && item->level() == 3) ? static_cast<ToolChainTreeItem *>(item) : nullptr; return (item && item->level() == 3) ? static_cast<ExtendedToolchainTreeItem *>(item) : nullptr;
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------

View File

@@ -3,7 +3,10 @@
#pragma once #pragma once
#include "toolchain.h"
#include <coreplugin/dialogs/ioptionspage.h> #include <coreplugin/dialogs/ioptionspage.h>
#include <utils/treemodel.h>
#include <QCoreApplication> #include <QCoreApplication>
@@ -16,5 +19,17 @@ public:
ToolChainOptionsPage(); ToolChainOptionsPage();
}; };
class ToolchainTreeItem : public Utils::TreeItem
{
public:
ToolchainTreeItem(const ToolchainBundle &bundle) : bundle(bundle) {}
ToolchainTreeItem() = default;
static const int BundleIdRole = Qt::UserRole;
QVariant data(int column, int role) const override;
std::optional<ToolchainBundle> bundle;
};
} // namespace Internal } // namespace Internal
} // namespace ProjectExplorer } // namespace ProjectExplorer