forked from qt-creator/qt-creator
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:
@@ -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;
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user