ProjectExplorer: Let toolchains be (de)registered in bulk

When some code adds or removes a bunch of toolchains at once, that
should be made explicit and also be reflected by the respective signal
emissions.
Fix some leaks and typos along the way.

Change-Id: I4a1f12a2378316c5faf70e85a88adc467f076caf
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Christian Kandeler
2024-07-18 11:10:24 +02:00
parent eb6c95b50d
commit 9d0c144892
13 changed files with 198 additions and 169 deletions

View File

@@ -1248,23 +1248,17 @@ void AndroidConfigurations::registerNewToolchains()
{ {
const Toolchains existingAndroidToolchains const Toolchains existingAndroidToolchains
= ToolchainManager::toolchains(Utils::equal(&Toolchain::typeId, Id(Constants::ANDROID_TOOLCHAIN_TYPEID))); = ToolchainManager::toolchains(Utils::equal(&Toolchain::typeId, Id(Constants::ANDROID_TOOLCHAIN_TYPEID)));
ToolchainManager::registerToolchains(autodetectToolchains(existingAndroidToolchains));
const Toolchains newToolchains = autodetectToolchains(existingAndroidToolchains);
for (Toolchain *tc : newToolchains)
ToolchainManager::registerToolchain(tc);
registerCustomToolchainsAndDebuggers(); registerCustomToolchainsAndDebuggers();
} }
void AndroidConfigurations::removeOldToolchains() void AndroidConfigurations::removeOldToolchains()
{ {
const auto tcs = ToolchainManager::toolchains(Utils::equal(&Toolchain::typeId, const auto tcs = Utils::filtered(
Id(Constants::ANDROID_TOOLCHAIN_TYPEID))); ToolchainManager::toolchains(
for (Toolchain *tc : tcs) { Utils::equal(&Toolchain::typeId, Id(Constants::ANDROID_TOOLCHAIN_TYPEID))),
if (!tc->isValid()) &Toolchain::isValid);
ToolchainManager::deregisterToolchain(tc); ToolchainManager::deregisterToolchains(tcs);
}
} }
void AndroidConfigurations::removeUnusedDebuggers() void AndroidConfigurations::removeUnusedDebuggers()
@@ -1411,8 +1405,8 @@ void AndroidConfigurations::registerCustomToolchainsAndDebuggers()
const Toolchains customToolchains const Toolchains customToolchains
= autodetectToolchainsFromNdks(existingAndroidToolchains, customNdks, true); = autodetectToolchainsFromNdks(existingAndroidToolchains, customNdks, true);
ToolchainManager::registerToolchains(customToolchains);
for (Toolchain *tc : customToolchains) { for (Toolchain *tc : customToolchains) {
ToolchainManager::registerToolchain(tc);
const auto androidToolchain = static_cast<AndroidToolchain *>(tc); const auto androidToolchain = static_cast<AndroidToolchain *>(tc);
QString abiStr; QString abiStr;
if (androidToolchain) if (androidToolchain)

View File

@@ -106,13 +106,11 @@ void KitDetectorPrivate::undoAutoDetect() const
}; };
emit q->logOutput('\n' + ProjectExplorer::Tr::tr("Removing toolchain entries...")); emit q->logOutput('\n' + ProjectExplorer::Tr::tr("Removing toolchain entries..."));
const Toolchains toolchains = ToolchainManager::toolchains(); const Toolchains toDeregister = Utils::filtered(
for (Toolchain *toolchain : toolchains) { ToolchainManager::toolchains(), Utils::equal(&Toolchain::detectionSource, m_sharedId));
if (toolchain && toolchain->detectionSource() == m_sharedId) { for (Toolchain * toolchain : toDeregister)
emit q->logOutput(ProjectExplorer::Tr::tr("Removed \"%1\"").arg(toolchain->displayName())); emit q->logOutput(ProjectExplorer::Tr::tr("Removed \"%1\"").arg(toolchain->displayName()));
ToolchainManager::deregisterToolchain(toolchain); ToolchainManager::deregisterToolchains(toDeregister);
}
};
if (auto cmakeManager = ExtensionSystem::PluginManager::getObjectByName("CMakeToolManager")) { if (auto cmakeManager = ExtensionSystem::PluginManager::getObjectByName("CMakeToolManager")) {
QString logMessage; QString logMessage;
@@ -260,11 +258,12 @@ Toolchains KitDetectorPrivate::autoDetectToolchains()
const ToolchainDetector detector(alreadyKnown, m_device, m_searchPaths); const ToolchainDetector detector(alreadyKnown, m_device, m_searchPaths);
const Toolchains newToolchains = factory->autoDetect(detector); const Toolchains newToolchains = factory->autoDetect(detector);
for (Toolchain *toolchain : newToolchains) { for (Toolchain *toolchain : newToolchains) {
emit q->logOutput(ProjectExplorer::Tr::tr("Found \"%1\"").arg(toolchain->compilerCommand().toUserOutput())); emit q->logOutput(ProjectExplorer::Tr::tr("Found \"%1\"")
.arg(toolchain->compilerCommand().toUserOutput()));
toolchain->setDetectionSource(m_sharedId); toolchain->setDetectionSource(m_sharedId);
ToolchainManager::registerToolchain(toolchain);
alreadyKnown.append(toolchain);
} }
ToolchainManager::registerToolchains(newToolchains);
alreadyKnown.append(newToolchains);
allNewToolchains.append(newToolchains); allNewToolchains.append(newToolchains);
} }
emit q->logOutput(ProjectExplorer::Tr::tr("%1 new toolchains found.").arg(allNewToolchains.size())); emit q->logOutput(ProjectExplorer::Tr::tr("%1 new toolchains found.").arg(allNewToolchains.size()));

View File

@@ -441,52 +441,56 @@ static Toolchain *mingwToolchain(const FilePath &path, Id language)
return toolChain; return toolChain;
} }
// FIXME: Do not register languages separately.
static Toolchain *armGccToolchain(const FilePath &path, Id language) static Toolchain *armGccToolchain(const FilePath &path, Id language)
{ {
Toolchain *toolChain = ToolchainManager::toolchain([&path, language](const Toolchain *t) { Toolchain *toolchain = ToolchainManager::toolchain([&path, language](const Toolchain *t) {
return t->compilerCommand() == path && t->language() == language; return t->compilerCommand() == path && t->language() == language;
}); });
if (!toolChain) { if (!toolchain) {
if (ToolchainFactory * const gccFactory = ToolchainFactory::factoryForType( if (ToolchainFactory * const gccFactory = ToolchainFactory::factoryForType(
ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID)) { ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID)) {
const QList<Toolchain *> detected = gccFactory->detectForImport({path, language}); QList<Toolchain *> detected = gccFactory->detectForImport({path, language});
if (!detected.isEmpty()) { if (!detected.isEmpty()) {
toolChain = detected.first(); toolchain = detected.takeFirst();
toolChain->setDetection(Toolchain::ManualDetection); ToolchainManager::registerToolchains({toolchain});
toolChain->setDisplayName("Arm GCC"); toolchain->setDetection(Toolchain::ManualDetection);
ToolchainManager::registerToolchain(toolChain); toolchain->setDisplayName("Arm GCC");
qDeleteAll(detected);
} }
} }
} }
return toolChain; return toolchain;
} }
static Toolchain *iarToolchain(const FilePath &path, Id language) static Toolchain *iarToolchain(const FilePath &path, Id language)
{ {
Toolchain *toolChain = ToolchainManager::toolchain([language](const Toolchain *t) { Toolchain *toolchain = ToolchainManager::toolchain([language](const Toolchain *t) {
return t->typeId() == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID return t->typeId() == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID
&& t->language() == language; && t->language() == language;
}); });
if (!toolChain) { if (!toolchain) {
if (ToolchainFactory * const iarFactory = ToolchainFactory::factoryForType( if (ToolchainFactory * const iarFactory = ToolchainFactory::factoryForType(
BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID)) { BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID)) {
Toolchains detected = iarFactory->autoDetect( Toolchains detected = iarFactory->autoDetect(
{{}, DeviceManager::defaultDesktopDevice(), {}}); {{}, DeviceManager::defaultDesktopDevice(), {}});
if (detected.isEmpty()) if (detected.isEmpty())
detected = iarFactory->detectForImport({path, language}); detected = iarFactory->detectForImport({path, language});
for (auto tc : detected) { Toolchains toRegister;
if (tc->language() == language) { Toolchains toDelete;
toolChain = tc; std::tie(toRegister, toDelete)
toolChain->setDetection(Toolchain::ManualDetection); = Utils::partition(detected, Utils::equal(&Toolchain::language, language));
toolChain->setDisplayName("IAREW"); for (Toolchain * const tc : toRegister) {
ToolchainManager::registerToolchain(toolChain); tc->setDetection(Toolchain::ManualDetection);
} tc->setDisplayName("IAREW");
} }
ToolchainManager::registerToolchains(toRegister);
qDeleteAll(toDelete);
} }
} }
return toolChain; return toolchain;
} }
Toolchain *McuToolchainPackage::toolChain(Id language) const Toolchain *McuToolchainPackage::toolChain(Id language) const

View File

@@ -217,7 +217,7 @@ void verifyIarToolchain(const McuToolchainPackagePtr &iarToolchainPackage)
Id iarId{BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID}; Id iarId{BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID};
Toolchain *iarToolchain{ProjectExplorer::ToolchainFactory::createToolchain(iarId)}; Toolchain *iarToolchain{ProjectExplorer::ToolchainFactory::createToolchain(iarId)};
iarToolchain->setLanguage(cxxLanguageId); iarToolchain->setLanguage(cxxLanguageId);
ToolchainManager::registerToolchain(iarToolchain); ToolchainManager::registerToolchains({iarToolchain});
QVERIFY(iarToolchainPackage != nullptr); QVERIFY(iarToolchainPackage != nullptr);
QCOMPARE(iarToolchainPackage->cmakeVariableName(), TOOLCHAIN_DIR_CMAKE_VARIABLE); QCOMPARE(iarToolchainPackage->cmakeVariableName(), TOOLCHAIN_DIR_CMAKE_VARIABLE);
@@ -241,7 +241,7 @@ void verifyArmGccToolchain(const McuToolchainPackagePtr &armGccPackage, const QS
Toolchain *armToolchain{ProjectExplorer::ToolchainFactory::createToolchain(armGccId)}; Toolchain *armToolchain{ProjectExplorer::ToolchainFactory::createToolchain(armGccId)};
armToolchain->setLanguage(cxxLanguageId); armToolchain->setLanguage(cxxLanguageId);
ToolchainManager::registerToolchain(armToolchain); ToolchainManager::registerToolchains({armToolchain});
QVERIFY(armGccPackage != nullptr); QVERIFY(armGccPackage != nullptr);
QCOMPARE(armGccPackage->cmakeVariableName(), TOOLCHAIN_DIR_CMAKE_VARIABLE); QCOMPARE(armGccPackage->cmakeVariableName(), TOOLCHAIN_DIR_CMAKE_VARIABLE);

View File

@@ -1769,18 +1769,28 @@ GccToolchainConfigWidget::GccToolchainConfigWidget(GccToolchain *tc) :
updateParentToolchainComboBox(); updateParentToolchainComboBox();
})); }));
m_parentToolchainConnections.append( m_parentToolchainConnections.append(
connect(tcManager, &ToolchainManager::toolhainAdded, this, [this](Toolchain *tc) { connect(tcManager, &ToolchainManager::toolchainsRegistered,
if (tc->typeId() == Constants::MINGW_TOOLCHAIN_TYPEID) this, [this](const Toolchains &toolchains) {
if (Utils::contains(
toolchains,
Utils::equal(&Toolchain::typeId, Id(Constants::MINGW_TOOLCHAIN_TYPEID)))) {
updateParentToolchainComboBox(); updateParentToolchainComboBox();
}
})); }));
m_parentToolchainConnections.append( m_parentToolchainConnections.append(
connect(tcManager, &ToolchainManager::toolchainRemoved, this, [this](Toolchain *tc) { connect(tcManager, &ToolchainManager::toolchainsDeregistered, this,
if (tc->id() == toolchain()->id()) { [this](const Toolchains &toolchains) {
for (QMetaObject::Connection &connection : m_parentToolchainConnections) bool updateParentComboBox = false;
QObject::disconnect(connection); for (Toolchain * const tc : toolchains) {
return; if (tc->id() == toolchain()->id()) {
for (QMetaObject::Connection &connection : m_parentToolchainConnections)
QObject::disconnect(connection);
return;
if (tc->typeId() == Constants::MINGW_TOOLCHAIN_TYPEID)
updateParentComboBox = true;
}
} }
if (tc->typeId() == Constants::MINGW_TOOLCHAIN_TYPEID) if (updateParentComboBox)
updateParentToolchainComboBox(); updateParentToolchainComboBox();
})); }));
@@ -1980,20 +1990,33 @@ void GccToolchain::syncAutodetectedWithParentToolchains()
// Subscribe only autodetected toolchains. // Subscribe only autodetected toolchains.
ToolchainManager *tcManager = ToolchainManager::instance(); ToolchainManager *tcManager = ToolchainManager::instance();
m_mingwToolchainAddedConnection m_mingwToolchainAddedConnection
= connect(tcManager, &ToolchainManager::toolhainAdded, this, [this](Toolchain *tc) { = connect(tcManager, &ToolchainManager::toolchainsRegistered, this,
if (tc->typeId() == Constants::MINGW_TOOLCHAIN_TYPEID [this](const Toolchains &toolchains) {
&& !mingwToolchainFromId(m_parentToolchainId)) { if (mingwToolchainFromId(m_parentToolchainId))
m_parentToolchainId = tc->id(); return;
for (Toolchain * const tc : toolchains) {
if (tc->typeId() == Constants::MINGW_TOOLCHAIN_TYPEID) {
m_parentToolchainId = tc->id();
break;
}
} }
}); });
m_thisToolchainRemovedConnection m_thisToolchainRemovedConnection
= connect(tcManager, &ToolchainManager::toolchainRemoved, this, [this](Toolchain *tc) { = connect(tcManager, &ToolchainManager::toolchainsDeregistered, this,
if (tc == this) { [this](const Toolchains &toolchains) {
QObject::disconnect(m_thisToolchainRemovedConnection); bool updateParentId = false;
QObject::disconnect(m_mingwToolchainAddedConnection); for (Toolchain * const tc : toolchains) {
} else if (m_parentToolchainId == tc->id()) { if (tc == this) {
QObject::disconnect(m_thisToolchainRemovedConnection);
QObject::disconnect(m_mingwToolchainAddedConnection);
} else if (m_parentToolchainId == tc->id()) {
updateParentId = true;
}
}
if (updateParentId) {
const Toolchains mingwTCs = mingwToolchains(); const Toolchains mingwTCs = mingwToolchains();
m_parentToolchainId = mingwTCs.isEmpty() ? QByteArray() : mingwTCs.front()->id(); m_parentToolchainId = mingwTCs.isEmpty() ? QByteArray()
: mingwTCs.front()->id();
} }
}); });
} }

View File

@@ -343,7 +343,7 @@ private:
void onKitsLoaded() override; void onKitsLoaded() override;
void toolChainUpdated(Toolchain *tc); void toolChainUpdated(Toolchain *tc);
void toolChainRemoved(Toolchain *tc); void toolChainsDeregistered();
}; };
ToolchainKitAspectFactory::ToolchainKitAspectFactory() ToolchainKitAspectFactory::ToolchainKitAspectFactory()
@@ -695,8 +695,8 @@ void ToolchainKitAspectFactory::onKitsLoaded()
for (Kit *k : KitManager::kits()) for (Kit *k : KitManager::kits())
fix(k); fix(k);
connect(ToolchainManager::instance(), &ToolchainManager::toolchainRemoved, connect(ToolchainManager::instance(), &ToolchainManager::toolchainsDeregistered,
this, &ToolchainKitAspectFactory::toolChainRemoved); this, &ToolchainKitAspectFactory::toolChainsDeregistered);
connect(ToolchainManager::instance(), &ToolchainManager::toolchainUpdated, connect(ToolchainManager::instance(), &ToolchainManager::toolchainUpdated,
this, &ToolchainKitAspectFactory::toolChainUpdated); this, &ToolchainKitAspectFactory::toolChainUpdated);
} }
@@ -709,9 +709,8 @@ void ToolchainKitAspectFactory::toolChainUpdated(Toolchain *tc)
} }
} }
void ToolchainKitAspectFactory::toolChainRemoved(Toolchain *tc) void ToolchainKitAspectFactory::toolChainsDeregistered()
{ {
Q_UNUSED(tc)
for (Kit *k : KitManager::kits()) for (Kit *k : KitManager::kits())
fix(k); fix(k);
} }

View File

@@ -318,23 +318,21 @@ static Toolchain *toolChainFromVariant(const QVariant &v)
void ProjectImporter::cleanupTemporaryToolchains(Kit *k, const QVariantList &vl) void ProjectImporter::cleanupTemporaryToolchains(Kit *k, const QVariantList &vl)
{ {
for (const QVariant &v : vl) { ToolchainManager::deregisterToolchains(Utils::transform(vl, toolChainFromVariant));
Toolchain *tc = toolChainFromVariant(v); ToolchainKitAspect::setToolchain(k, nullptr);
QTC_ASSERT(tc, continue);
ToolchainManager::deregisterToolchain(tc);
ToolchainKitAspect::setToolchain(k, nullptr);
}
} }
void ProjectImporter::persistTemporaryToolchains(Kit *k, const QVariantList &vl) void ProjectImporter::persistTemporaryToolchains(Kit *k, const QVariantList &vl)
{ {
Toolchains toDeregister;
for (const QVariant &v : vl) { for (const QVariant &v : vl) {
Toolchain *tmpTc = toolChainFromVariant(v); Toolchain *tmpTc = toolChainFromVariant(v);
QTC_ASSERT(tmpTc, continue); QTC_ASSERT(tmpTc, continue);
Toolchain *actualTc = ToolchainKitAspect::toolchain(k, tmpTc->language()); Toolchain *actualTc = ToolchainKitAspect::toolchain(k, tmpTc->language());
if (tmpTc && actualTc != tmpTc) if (tmpTc && actualTc != tmpTc)
ToolchainManager::deregisterToolchain(tmpTc); toDeregister << tmpTc;
} }
ToolchainManager::deregisterToolchains(toDeregister);
} }
void ProjectImporter::useTemporaryKitAspect(Utils::Id id, void ProjectImporter::useTemporaryKitAspect(Utils::Id id,
@@ -374,10 +372,7 @@ static ProjectImporter::ToolchainData createToolChains(const ToolchainDescriptio
data.tcs = factory->detectForImport(tcd); data.tcs = factory->detectForImport(tcd);
if (data.tcs.isEmpty()) if (data.tcs.isEmpty())
continue; continue;
ToolchainManager::registerToolchains(data.tcs);
for (Toolchain *tc : std::as_const(data.tcs))
ToolchainManager::registerToolchain(tc);
data.areTemporary = true; data.areTemporary = true;
break; break;
} }

View File

@@ -787,14 +787,16 @@ void AsyncToolchainDetector::run()
[watcher, [watcher,
alreadyRegistered = m_alreadyRegistered]() { alreadyRegistered = m_alreadyRegistered]() {
Toolchains existingTcs = ToolchainManager::toolchains(); Toolchains existingTcs = ToolchainManager::toolchains();
Toolchains toRegister;
for (Toolchain *tc : watcher->result()) { for (Toolchain *tc : watcher->result()) {
if (tc->isValid() && !alreadyRegistered(tc, existingTcs)) { if (tc->isValid() && !alreadyRegistered(tc, existingTcs)) {
ToolchainManager::registerToolchain(tc); toRegister << tc;
existingTcs << tc; existingTcs << tc;
} else { } else {
delete tc; delete tc;
} }
} }
ToolchainManager::registerToolchains(toRegister);
watcher->deleteLater(); watcher->deleteLater();
}); });
watcher->setFuture(Utils::asyncRun(m_func, m_detector)); watcher->setFuture(Utils::asyncRun(m_func, m_detector));

View File

@@ -78,8 +78,9 @@ ToolchainManager::ToolchainManager(QObject *parent) :
connect(Core::ICore::instance(), &Core::ICore::saveSettingsRequested, connect(Core::ICore::instance(), &Core::ICore::saveSettingsRequested,
this, &ToolchainManager::saveToolchains); this, &ToolchainManager::saveToolchains);
connect(this, &ToolchainManager::toolhainAdded, this, &ToolchainManager::toolchainsChanged); connect(this, &ToolchainManager::toolchainsRegistered,
connect(this, &ToolchainManager::toolchainRemoved, this, &ToolchainManager::toolchainsChanged); this, &ToolchainManager::toolchainsChanged);
connect(this, &ToolchainManager::toolchainsDeregistered, this, &ToolchainManager::toolchainsChanged);
connect(this, &ToolchainManager::toolchainUpdated, this, &ToolchainManager::toolchainsChanged); connect(this, &ToolchainManager::toolchainUpdated, this, &ToolchainManager::toolchainsChanged);
QtcSettings * const s = Core::ICore::settings(); QtcSettings * const s = Core::ICore::settings();
@@ -106,8 +107,7 @@ void ToolchainManager::restoreToolchains()
QTC_ASSERT(!d->m_accessor, return); QTC_ASSERT(!d->m_accessor, return);
d->m_accessor = std::make_unique<Internal::ToolchainSettingsAccessor>(); d->m_accessor = std::make_unique<Internal::ToolchainSettingsAccessor>();
for (Toolchain *tc : d->m_accessor->restoreToolchains(Core::ICore::dialogParent())) registerToolchains(d->m_accessor->restoreToolchains(Core::ICore::dialogParent()));
registerToolchain(tc);
d->m_loaded = true; d->m_loaded = true;
emit m_instance->toolchainsLoaded(); emit m_instance->toolchainsLoaded();
@@ -191,37 +191,54 @@ void ToolchainManager::notifyAboutUpdate(Toolchain *tc)
emit m_instance->toolchainUpdated(tc); emit m_instance->toolchainUpdated(tc);
} }
bool ToolchainManager::registerToolchain(Toolchain *tc) Toolchains ToolchainManager::registerToolchains(const Toolchains &toolchains)
{ {
QTC_ASSERT(tc, return false); Toolchains registered;
QTC_ASSERT(isLanguageSupported(tc->language()), Toolchains notRegistered;
qDebug() << qPrintable("language \"" + tc->language().toString()
+ "\" unknown while registering \""
+ tc->compilerCommand().toString() + "\"");
return false);
QTC_ASSERT(d->m_accessor, return false);
if (d->m_toolChains.contains(tc)) for (Toolchain * const tc : toolchains) {
return true; QTC_ASSERT(tc, notRegistered << tc; continue);
for (const Toolchain *current : std::as_const(d->m_toolChains)) { QTC_ASSERT(isLanguageSupported(tc->language()),
if (*tc == *current && !tc->isAutoDetected()) qDebug() << qPrintable("language \"" + tc->language().toString()
return false; + "\" unknown while registering \""
QTC_ASSERT(current->id() != tc->id(), return false); + tc->compilerCommand().toString() + "\"");
notRegistered << tc;
continue);
QTC_ASSERT(d->m_accessor, notRegistered << tc; continue);
QTC_ASSERT(!d->m_toolChains.contains(tc), continue);
QTC_ASSERT(!Utils::contains(d->m_toolChains, Utils::equal(&Toolchain::id, tc->id())),
notRegistered << tc;
continue);
if (!tc->isAutoDetected()
&& Utils::contains(d->m_toolChains, [tc](const Toolchain *existing) {
return *tc == *existing;
})) {
notRegistered << tc;
continue;
}
d->m_toolChains << tc;
registered << tc;
} }
d->m_toolChains.append(tc); if (!registered.isEmpty())
emit m_instance->toolhainAdded(tc); emit m_instance->toolchainsRegistered(registered);
return true; return notRegistered;
} }
void ToolchainManager::deregisterToolchain(Toolchain *tc) void ToolchainManager::deregisterToolchains(const Toolchains &toolchains)
{ {
QTC_CHECK(d->m_loaded); QTC_CHECK(d->m_loaded);
if (!tc || !d->m_toolChains.contains(tc)) Toolchains deregistered;
return; for (Toolchain * const tc : toolchains) {
d->m_toolChains.removeOne(tc); QTC_ASSERT(tc, continue);
emit m_instance->toolchainRemoved(tc); const bool removed = d->m_toolChains.removeOne(tc);
delete tc; QTC_ASSERT(removed, continue);
deregistered << tc;
}
if (!deregistered.isEmpty())
emit m_instance->toolchainsDeregistered(deregistered);
qDeleteAll(toolchains);
} }
QList<Id> ToolchainManager::allLanguages() QList<Id> ToolchainManager::allLanguages()

View File

@@ -48,8 +48,8 @@ public:
static bool isLoaded(); static bool isLoaded();
static bool registerToolchain(Toolchain *tc); static Toolchains registerToolchains(const Toolchains &toolchains);
static void deregisterToolchain(Toolchain *tc); static void deregisterToolchains(const Toolchains &toolchains);
static QList<Utils::Id> allLanguages(); static QList<Utils::Id> allLanguages();
static bool registerLanguage(const Utils::Id &language, const QString &displayName); static bool registerLanguage(const Utils::Id &language, const QString &displayName);
@@ -68,9 +68,9 @@ public:
void saveToolchains(); void saveToolchains();
signals: signals:
void toolhainAdded(ProjectExplorer::Toolchain *); void toolchainsRegistered(const Toolchains &registered);
// Toolchain is still valid when this call happens! // Toolchains are still valid when this call happens!
void toolchainRemoved(ProjectExplorer::Toolchain *); void toolchainsDeregistered(const Toolchains &deregistered);
// Toolchain was updated. // Toolchain was updated.
void toolchainUpdated(ProjectExplorer::Toolchain *); void toolchainUpdated(ProjectExplorer::Toolchain *);
// Something changed. // Something changed.

View File

@@ -275,10 +275,10 @@ public:
horizontalLayout->addLayout(verticalLayout); horizontalLayout->addLayout(verticalLayout);
horizontalLayout->addLayout(buttonLayout); horizontalLayout->addLayout(buttonLayout);
connect(ToolchainManager::instance(), &ToolchainManager::toolhainAdded, connect(ToolchainManager::instance(), &ToolchainManager::toolchainsRegistered,
this, &ToolChainOptionsWidget::addToolChain); this, &ToolChainOptionsWidget::handleToolchainsRegistered);
connect(ToolchainManager::instance(), &ToolchainManager::toolchainRemoved, connect(ToolchainManager::instance(), &ToolchainManager::toolchainsDeregistered,
this, &ToolChainOptionsWidget::removeToolChain); this, &ToolChainOptionsWidget::handleToolchainsDeregistered);
connect(m_toolChainView->selectionModel(), &QItemSelectionModel::currentChanged, connect(m_toolChainView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &ToolChainOptionsWidget::toolChainSelectionChanged); this, &ToolChainOptionsWidget::toolChainSelectionChanged);
@@ -301,8 +301,8 @@ public:
void markForRemoval(ToolChainTreeItem *item); void markForRemoval(ToolChainTreeItem *item);
ToolChainTreeItem *insertToolChain(ProjectExplorer::Toolchain *tc, bool changed = false); // Insert directly into model ToolChainTreeItem *insertToolChain(ProjectExplorer::Toolchain *tc, bool changed = false); // Insert directly into model
void addToolChain(ProjectExplorer::Toolchain *); void handleToolchainsRegistered(const Toolchains &toolchains);
void removeToolChain(ProjectExplorer::Toolchain *); void handleToolchainsDeregistered(const Toolchains &toolchains);
StaticTreeItem *parentForToolChain(Toolchain *tc); StaticTreeItem *parentForToolChain(Toolchain *tc);
QAction *createAction(const QString &name, ToolchainFactory *factory, Utils::Id language) QAction *createAction(const QString &name, ToolchainFactory *factory, Utils::Id language)
@@ -361,33 +361,39 @@ ToolChainTreeItem *ToolChainOptionsWidget::insertToolChain(Toolchain *tc, bool c
return item; return item;
} }
void ToolChainOptionsWidget::addToolChain(Toolchain *tc) void ToolChainOptionsWidget::handleToolchainsRegistered(const Toolchains &toolchains)
{ {
if (Utils::eraseOne(m_toAddList, [tc](const ToolChainTreeItem *item) { for (Toolchain * const tc : toolchains) {
return item->toolChain == tc; })) { if (Utils::eraseOne(m_toAddList, [tc](const ToolChainTreeItem *item) {
// do not delete here! return item->toolChain == tc; })) {
return; // do not delete here!
} continue;
}
insertToolChain(tc); insertToolChain(tc);
}
updateState(); updateState();
} }
void ToolChainOptionsWidget::removeToolChain(Toolchain *tc) void ToolChainOptionsWidget::handleToolchainsDeregistered(const Toolchains &toolchains)
{ {
if (auto it = std::find_if(m_toRemoveList.begin(), m_toRemoveList.end(), for (Toolchain * const tc : toolchains) {
[tc](const ToolChainTreeItem *item) { return item->toolChain == tc; }); if (auto it = std::find_if(
m_toRemoveList.begin(),
m_toRemoveList.end(),
[tc](const ToolChainTreeItem *item) { return item->toolChain == tc; });
it != m_toRemoveList.end()) { it != m_toRemoveList.end()) {
m_toRemoveList.erase(it); m_toRemoveList.erase(it);
delete *it; delete *it;
return; continue;
} }
StaticTreeItem *parent = parentForToolChain(tc); StaticTreeItem *parent = parentForToolChain(tc);
auto item = parent->findChildAtLevel(1, [tc](TreeItem *item) { auto item = parent->findChildAtLevel(1, [tc](TreeItem *item) {
return static_cast<ToolChainTreeItem *>(item)->toolChain == tc; return static_cast<ToolChainTreeItem *>(item)->toolChain == tc;
}); });
m_model.destroyItem(item); m_model.destroyItem(item);
}
updateState(); updateState();
} }
@@ -453,9 +459,8 @@ void ToolChainOptionsWidget::toolChainSelectionChanged()
void ToolChainOptionsWidget::apply() void ToolChainOptionsWidget::apply()
{ {
// Remove unused tool chains: // Remove unused tool chains:
QList<ToolChainTreeItem *> nodes = m_toRemoveList; ToolchainManager::deregisterToolchains(
for (const ToolChainTreeItem *n : std::as_const(nodes)) Utils::transform(m_toRemoveList, &ToolChainTreeItem::toolChain));
ToolchainManager::deregisterToolchain(n->toolChain);
Q_ASSERT(m_toRemoveList.isEmpty()); Q_ASSERT(m_toRemoveList.isEmpty());
@@ -474,13 +479,10 @@ void ToolChainOptionsWidget::apply()
} }
// Add new (and already updated) tool chains // Add new (and already updated) tool chains
QStringList removedTcs; const Toolchains notRegistered = ToolchainManager::registerToolchains(
nodes = m_toAddList; Utils::transform(m_toAddList, &ToolChainTreeItem::toolChain));
for (const ToolChainTreeItem *n : std::as_const(nodes)) { const QStringList removedTcs = Utils::transform(notRegistered, &Toolchain::displayName);
if (!ToolchainManager::registerToolchain(n->toolChain))
removedTcs << n->toolChain->displayName();
}
//
const QList<ToolChainTreeItem *> toAddList = m_toAddList; const QList<ToolChainTreeItem *> toAddList = m_toAddList;
for (ToolChainTreeItem *n : toAddList) for (ToolChainTreeItem *n : toAddList)
markForRemoval(n); markForRemoval(n);

View File

@@ -187,8 +187,7 @@ void QnxConfiguration::deactivate()
} }
} }
for (Toolchain *tc : toolChainsToRemove) ToolchainManager::deregisterToolchains(toolChainsToRemove);
ToolchainManager::deregisterToolchain(tc);
for (const DebuggerItem &debuggerItem : std::as_const(debuggersToRemove)) for (const DebuggerItem &debuggerItem : std::as_const(debuggersToRemove))
DebuggerItemManager::deregisterDebugger(debuggerItem.id()); DebuggerItemManager::deregisterDebugger(debuggerItem.id());
@@ -227,26 +226,25 @@ QVariant QnxConfiguration::createDebugger(const QnxTarget &target)
Toolchains QnxConfiguration::createToolChains(const QnxTarget &target) Toolchains QnxConfiguration::createToolChains(const QnxTarget &target)
{ {
Toolchains toolChains; Toolchains toolchains;
for (const Id language : {ProjectExplorer::Constants::C_LANGUAGE_ID, for (const Id language : {ProjectExplorer::Constants::C_LANGUAGE_ID,
ProjectExplorer::Constants::CXX_LANGUAGE_ID}) { ProjectExplorer::Constants::CXX_LANGUAGE_ID}) {
auto toolChain = new QnxToolchain; auto toolchain = new QnxToolchain;
toolChain->setDetection(Toolchain::ManualDetection); toolchain->setDetection(Toolchain::ManualDetection);
toolChain->setLanguage(language); toolchain->setLanguage(language);
toolChain->setTargetAbi(target.m_abi); toolchain->setTargetAbi(target.m_abi);
toolChain->setDisplayName(Tr::tr("QCC for %1 (%2)") toolchain->setDisplayName(Tr::tr("QCC for %1 (%2)")
.arg(m_configName) .arg(m_configName)
.arg(target.shortDescription())); .arg(target.shortDescription()));
toolChain->sdpPath.setValue(m_envFile.parentDir()); toolchain->sdpPath.setValue(m_envFile.parentDir());
toolChain->cpuDir.setValue(target.cpuDir()); toolchain->cpuDir.setValue(target.cpuDir());
toolChain->resetToolchain(m_qccCompiler); toolchain->resetToolchain(m_qccCompiler);
ToolchainManager::registerToolchain(toolChain); toolchains.append(toolchain);
toolChains.append(toolChain);
} }
return toolChains; ToolchainManager::registerToolchains(toolchains);
return toolchains;
} }
void QnxConfiguration::createKit(const QnxTarget &target) void QnxConfiguration::createKit(const QnxTarget &target)

View File

@@ -146,17 +146,13 @@ static Toolchains doAutoDetect(const ToolchainDetector &detector)
void registerToolChains() void registerToolChains()
{ {
// Remove old toolchains // Remove old toolchains
for (Toolchain *tc : ToolchainManager::findToolchains(toolChainAbi())) { const Toolchains oldToolchains = Utils::filtered(
if (tc->detection() != Toolchain::AutoDetection) ToolchainManager::findToolchains(toolChainAbi()),
continue; Utils::equal(&Toolchain::detection, Toolchain::AutoDetection));
ToolchainManager::deregisterToolchain(tc); ToolchainManager::deregisterToolchains(oldToolchains);
};
// Create new toolchains and register them // Create new toolchains and register them
ToolchainDetector detector({}, {}, {}); ToolchainManager::registerToolchains(doAutoDetect(ToolchainDetector({}, {}, {})));
const Toolchains toolchains = doAutoDetect(detector);
for (auto toolChain : toolchains)
ToolchainManager::registerToolchain(toolChain);
// Let kits pick up the new toolchains // Let kits pick up the new toolchains
for (Kit *kit : KitManager::kits()) { for (Kit *kit : KitManager::kits()) {