forked from qt-creator/qt-creator
ProjectImporter: Generalize handling of temporary data associated with kits
Generalize handling of temporary Qt versions, etc. that is associated with temporary kits while importing projects. Change-Id: I16a0c2e7f32546e131dcbeddc7a1e5048a9ad4c8 Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
|
||||
#include <QLoggingCategory>
|
||||
#include <QMessageBox>
|
||||
#include <QString>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
@@ -48,6 +49,26 @@ static const Core::Id KIT_TEMPORARY_NAME("PE.TempName");
|
||||
static const Core::Id KIT_FINAL_NAME("PE.FinalName");
|
||||
static const Core::Id TEMPORARY_OF_PROJECTS("PE.TempProject");
|
||||
|
||||
static Core::Id fullId(Core::Id id)
|
||||
{
|
||||
const QString prefix = "PE.Temporary.";
|
||||
|
||||
const QString idStr = id.toString();
|
||||
QTC_ASSERT(!idStr.startsWith(prefix), return Core::Id::fromString(idStr));
|
||||
|
||||
return Core::Id::fromString(prefix + idStr);
|
||||
}
|
||||
|
||||
static bool hasOtherUsers(Core::Id id, const QVariant &v, Kit *k)
|
||||
{
|
||||
return Utils::contains(KitManager::kits(), [id, v, k](Kit *in) -> bool {
|
||||
if (in == k)
|
||||
return false;
|
||||
QVariantList tmp = in->value(id).toList();
|
||||
return tmp.contains(v);
|
||||
});
|
||||
}
|
||||
|
||||
ProjectImporter::ProjectImporter(const QString &path) : m_projectPath(path)
|
||||
{ }
|
||||
|
||||
@@ -146,7 +167,7 @@ Target *ProjectImporter::preferredTarget(const QList<Target *> &possibleTargets)
|
||||
return activeTarget;
|
||||
}
|
||||
|
||||
void ProjectImporter::markTemporary(Kit *k) const
|
||||
void ProjectImporter::markKitAsTemporary(Kit *k) const
|
||||
{
|
||||
QTC_ASSERT(!k->hasValue(KIT_IS_TEMPORARY), return);
|
||||
|
||||
@@ -161,13 +182,14 @@ void ProjectImporter::markTemporary(Kit *k) const
|
||||
k->setValue(KIT_IS_TEMPORARY, true);
|
||||
}
|
||||
|
||||
void ProjectImporter::makePermanent(Kit *k) const
|
||||
void ProjectImporter::makePersistent(Kit *k) const
|
||||
{
|
||||
if (!k->hasValue(KIT_IS_TEMPORARY))
|
||||
return;
|
||||
|
||||
UpdateGuard guard(*this);
|
||||
|
||||
KitGuard kitGuard(k);
|
||||
k->removeKey(KIT_IS_TEMPORARY);
|
||||
k->removeKey(TEMPORARY_OF_PROJECTS);
|
||||
const QString tempName = k->value(KIT_TEMPORARY_NAME).toString();
|
||||
@@ -175,11 +197,38 @@ void ProjectImporter::makePermanent(Kit *k) const
|
||||
k->setUnexpandedDisplayName(k->value(KIT_FINAL_NAME).toString());
|
||||
k->removeKey(KIT_TEMPORARY_NAME);
|
||||
k->removeKey(KIT_FINAL_NAME);
|
||||
|
||||
foreach (const TemporaryInformationHandler &tih, m_temporaryHandlers) {
|
||||
const Core::Id fid = fullId(tih.id);
|
||||
const QVariantList temporaryValues = k->value(fid).toList();
|
||||
|
||||
// Mark permanent in all other kits:
|
||||
foreach (Kit *ok, KitManager::kits()) {
|
||||
if (ok == k)
|
||||
continue;
|
||||
|
||||
QVariantList otherTemporaryValues = ok->value(fid).toList();
|
||||
otherTemporaryValues = Utils::filtered(otherTemporaryValues, [&temporaryValues](const QVariant &v) {
|
||||
return temporaryValues.contains(v);
|
||||
});
|
||||
ok->setValueSilently(fid, otherTemporaryValues);
|
||||
}
|
||||
|
||||
// persist:
|
||||
tih.persist(k, temporaryValues);
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectImporter::cleanupKit(Kit *k)
|
||||
{
|
||||
Q_UNUSED(k);
|
||||
foreach (const TemporaryInformationHandler &tih, m_temporaryHandlers) {
|
||||
const Core::Id fid = fullId(tih.id);
|
||||
QVariantList temporaryValues = k->value(fid).toList();
|
||||
temporaryValues = Utils::filtered(temporaryValues, [fid, k](const QVariant &v) {
|
||||
return !hasOtherUsers(fid, v, k);
|
||||
});
|
||||
tih.cleanup(k, temporaryValues);
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectImporter::addProject(Kit *k)
|
||||
@@ -220,7 +269,7 @@ Kit *ProjectImporter::createTemporaryKit(const KitSetupFunction &setup) const
|
||||
{
|
||||
KitGuard kitGuard(k);
|
||||
k->setUnexpandedDisplayName(QCoreApplication::translate("ProjectExplorer::ProjectImporter", "Imported Kit"));;
|
||||
markTemporary(k);
|
||||
markKitAsTemporary(k);
|
||||
|
||||
setup(k);
|
||||
|
||||
@@ -232,4 +281,37 @@ Kit *ProjectImporter::createTemporaryKit(const KitSetupFunction &setup) const
|
||||
return k;
|
||||
}
|
||||
|
||||
bool ProjectImporter::findTemporaryHandler(Core::Id id) const
|
||||
{
|
||||
return Utils::contains(m_temporaryHandlers, [id](const TemporaryInformationHandler &ch) { return ch.id == id; });
|
||||
}
|
||||
|
||||
void ProjectImporter::useTemporaryKitInformation(Core::Id id,
|
||||
ProjectImporter::CleanupFunction cleanup,
|
||||
ProjectImporter::PersistFunction persist)
|
||||
{
|
||||
QTC_ASSERT(!findTemporaryHandler(id), return);
|
||||
m_temporaryHandlers.append({ id, cleanup, persist });
|
||||
}
|
||||
|
||||
void ProjectImporter::addTemporaryData(Core::Id id, const QVariant &cleanupData, Kit *k) const
|
||||
{
|
||||
QTC_ASSERT(findTemporaryHandler(id), return);
|
||||
const Core::Id fid = fullId(id);
|
||||
|
||||
KitGuard guard(k);
|
||||
QVariantList tmp = k->value(fid).toList();
|
||||
QTC_ASSERT(!tmp.contains(cleanupData), return);
|
||||
tmp.append(cleanupData);
|
||||
k->setValue(fid, tmp);
|
||||
}
|
||||
|
||||
bool ProjectImporter::hasKitWithTemporaryData(Core::Id id, const QVariant &data) const
|
||||
{
|
||||
Core::Id fid = fullId(id);
|
||||
return Utils::contains(KitManager::kits(), [data, fid](Kit *k) {
|
||||
return k->value(fid).toList().contains(data);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace ProjectExplorer
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
#include "projectexplorer_export.h"
|
||||
|
||||
#include <coreplugin/id.h>
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
@@ -51,10 +53,8 @@ public:
|
||||
|
||||
bool isUpdating() const { return m_isUpdating; }
|
||||
|
||||
virtual void makePermanent(Kit *k) const;
|
||||
|
||||
// Additional cleanup that has to happen when kits are removed
|
||||
virtual void cleanupKit(Kit *k);
|
||||
void makePersistent(Kit *k) const;
|
||||
void cleanupKit(Kit *k);
|
||||
|
||||
bool isTemporaryKit(Kit *k) const;
|
||||
|
||||
@@ -89,12 +89,30 @@ protected:
|
||||
using KitSetupFunction = std::function<void(Kit *)>;
|
||||
ProjectExplorer::Kit *createTemporaryKit(const KitSetupFunction &setup) const;
|
||||
|
||||
// Handle temporary additions to Kits (Qt Versions, ToolChains, etc.)
|
||||
using CleanupFunction = std::function<void(Kit *, const QVariantList &)>;
|
||||
using PersistFunction = std::function<void(Kit *, const QVariantList &)>;
|
||||
void useTemporaryKitInformation(Core::Id id,
|
||||
CleanupFunction cleanup, PersistFunction persist);
|
||||
void addTemporaryData(Core::Id id, const QVariant &cleanupData, Kit *k) const;
|
||||
// Does *any* kit feature the requested data yet?
|
||||
bool hasKitWithTemporaryData(Core::Id id, const QVariant &data) const;
|
||||
|
||||
private:
|
||||
void markTemporary(Kit *k) const;
|
||||
void markKitAsTemporary(Kit *k) const;
|
||||
bool findTemporaryHandler(Core::Id id) const;
|
||||
|
||||
const QString m_projectPath;
|
||||
mutable bool m_isUpdating = false;
|
||||
|
||||
class TemporaryInformationHandler {
|
||||
public:
|
||||
Core::Id id;
|
||||
CleanupFunction cleanup;
|
||||
PersistFunction persist;
|
||||
};
|
||||
QList<TemporaryInformationHandler> m_temporaryHandlers;
|
||||
|
||||
friend class UpdateGuard;
|
||||
};
|
||||
|
||||
|
||||
@@ -362,7 +362,7 @@ void TargetSetupPage::handleKitUpdate(Kit *k)
|
||||
return;
|
||||
|
||||
if (m_importer)
|
||||
m_importer->makePermanent(k);
|
||||
m_importer->makePersistent(k);
|
||||
|
||||
TargetSetupWidget *widget = m_widgets.value(k->id());
|
||||
|
||||
@@ -543,7 +543,7 @@ bool TargetSetupPage::setupProject(Project *project)
|
||||
|
||||
Kit *k = widget->kit();
|
||||
if (m_importer)
|
||||
m_importer->makePermanent(k);
|
||||
m_importer->makePersistent(k);
|
||||
toSetUp << widget->selectedBuildInfoList();
|
||||
widget->clearKit();
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QList>
|
||||
@@ -43,38 +44,11 @@ using namespace ProjectExplorer;
|
||||
|
||||
namespace QtSupport {
|
||||
|
||||
const Core::Id QT_IS_TEMPORARY("Qt.TempQt");
|
||||
|
||||
static void cleanTemporaryVersion(BaseQtVersion *version) {
|
||||
if (!version)
|
||||
return;
|
||||
|
||||
// count how many kits are using this version
|
||||
const int qtId = version->uniqueId();
|
||||
const int users = Utils::count(KitManager::kits(), [qtId](Kit *k) {
|
||||
return k->value(QT_IS_TEMPORARY, -1).toInt() == qtId;
|
||||
});
|
||||
|
||||
if (users == 0) // Remove if no other kit is using it. (The Kit k is not in KitManager::kits()
|
||||
QtVersionManager::removeVersion(version);
|
||||
}
|
||||
|
||||
void QtProjectImporter::makePermanent(Kit *k) const
|
||||
QtProjectImporter::QtProjectImporter(const QString &path) : ProjectImporter(path)
|
||||
{
|
||||
if (!isTemporaryKit(k))
|
||||
return;
|
||||
|
||||
UpdateGuard guard(*this);
|
||||
const int tempId = k->value(QT_IS_TEMPORARY, -1).toInt();
|
||||
k->removeKeySilently(QT_IS_TEMPORARY);
|
||||
const int qtId = QtKitInformation::qtVersionId(k);
|
||||
if (tempId != qtId)
|
||||
cleanTemporaryVersion(QtVersionManager::version(tempId));
|
||||
|
||||
foreach (Kit *kit, KitManager::kits())
|
||||
if (kit->value(QT_IS_TEMPORARY, -1).toInt() == tempId)
|
||||
kit->removeKeySilently(QT_IS_TEMPORARY);
|
||||
ProjectImporter::makePermanent(k);
|
||||
useTemporaryKitInformation(QtKitInformation::id(),
|
||||
[this](Kit *k, const QVariantList &vl) { cleanupTemporaryQt(k, vl); },
|
||||
[this](Kit *k, const QVariantList &vl) { persistTemporaryQt(k, vl); });
|
||||
}
|
||||
|
||||
QtProjectImporter::QtVersionData
|
||||
@@ -92,9 +66,7 @@ QtProjectImporter::findOrCreateQtVersion(const Utils::FileName &qmakePath) const
|
||||
if (result.qt) {
|
||||
// Check if version is a temporary qt
|
||||
const int qtId = result.qt->uniqueId();
|
||||
result.isTemporary = Utils::anyOf(KitManager::kits(), [&qtId](Kit *k) {
|
||||
return k->value(QT_IS_TEMPORARY, -1).toInt() == qtId;
|
||||
});
|
||||
result.isTemporary = hasKitWithTemporaryData(QtKitInformation::id(), qtId);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -111,17 +83,46 @@ QtProjectImporter::findOrCreateQtVersion(const Utils::FileName &qmakePath) const
|
||||
}
|
||||
|
||||
Kit *QtProjectImporter::createTemporaryKit(const QtVersionData &versionData,
|
||||
const ProjectImporter::KitSetupFunction &setup) const
|
||||
const ProjectImporter::KitSetupFunction &additionalSetup) const
|
||||
{
|
||||
return ProjectImporter::createTemporaryKit([&setup, &versionData](Kit *k) -> void {
|
||||
return ProjectImporter::createTemporaryKit([&additionalSetup, &versionData, this](Kit *k) -> void {
|
||||
QtKitInformation::setQtVersion(k, versionData.qt);
|
||||
if (versionData.isTemporary)
|
||||
k->setValue(QT_IS_TEMPORARY, versionData.qt->uniqueId());
|
||||
addTemporaryData(QtKitInformation::id(), versionData.qt->uniqueId(), k);
|
||||
|
||||
k->setUnexpandedDisplayName(versionData.qt->displayName());;
|
||||
|
||||
setup(k);
|
||||
additionalSetup(k);
|
||||
});
|
||||
}
|
||||
|
||||
static BaseQtVersion *versionFromVariant(const QVariant &v)
|
||||
{
|
||||
bool ok;
|
||||
const int qtId = v.toInt(&ok);
|
||||
QTC_ASSERT(ok, return nullptr);
|
||||
return QtVersionManager::version(qtId);
|
||||
}
|
||||
|
||||
void QtProjectImporter::cleanupTemporaryQt(Kit *k, const QVariantList &vl)
|
||||
{
|
||||
Q_UNUSED(k);
|
||||
|
||||
QTC_ASSERT(vl.count() == 1, return);
|
||||
BaseQtVersion *version = versionFromVariant(vl.at(0));
|
||||
QTC_ASSERT(version, return);
|
||||
QtVersionManager::removeVersion(version);
|
||||
}
|
||||
|
||||
void QtProjectImporter::persistTemporaryQt(Kit *k, const QVariantList &vl)
|
||||
{
|
||||
QTC_ASSERT(vl.count() == 1, return);
|
||||
BaseQtVersion *tmpVersion = versionFromVariant(vl.at(0));
|
||||
BaseQtVersion *actualVersion = QtKitInformation::qtVersion(k);
|
||||
|
||||
// User changed Kit away from temporary Qt that was set up:
|
||||
if (tmpVersion && actualVersion != tmpVersion)
|
||||
QtVersionManager::removeVersion(tmpVersion);
|
||||
}
|
||||
|
||||
} // namespace QtSupport
|
||||
|
||||
@@ -41,9 +41,6 @@ class QTSUPPORT_EXPORT QtProjectImporter : public ProjectExplorer::ProjectImport
|
||||
public:
|
||||
QtProjectImporter(const QString &path);
|
||||
|
||||
void cleanupKit(ProjectExplorer::Kit *k) override;
|
||||
void makePermanent(ProjectExplorer::Kit *k) const override;
|
||||
|
||||
class QtVersionData
|
||||
{
|
||||
public:
|
||||
@@ -55,6 +52,10 @@ protected:
|
||||
QtVersionData findOrCreateQtVersion(const Utils::FileName &qmakePath) const;
|
||||
ProjectExplorer::Kit *createTemporaryKit(const QtVersionData &versionData,
|
||||
const KitSetupFunction &setup) const;
|
||||
|
||||
private:
|
||||
void cleanupTemporaryQt(ProjectExplorer::Kit *k, const QVariantList &vl);
|
||||
void persistTemporaryQt(ProjectExplorer::Kit *k, const QVariantList &vl);
|
||||
};
|
||||
|
||||
} // namespace QmakeProjectManager
|
||||
|
||||
Reference in New Issue
Block a user