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 <QLoggingCategory>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
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 KIT_FINAL_NAME("PE.FinalName");
|
||||||
static const Core::Id TEMPORARY_OF_PROJECTS("PE.TempProject");
|
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)
|
ProjectImporter::ProjectImporter(const QString &path) : m_projectPath(path)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@@ -146,7 +167,7 @@ Target *ProjectImporter::preferredTarget(const QList<Target *> &possibleTargets)
|
|||||||
return activeTarget;
|
return activeTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectImporter::markTemporary(Kit *k) const
|
void ProjectImporter::markKitAsTemporary(Kit *k) const
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!k->hasValue(KIT_IS_TEMPORARY), return);
|
QTC_ASSERT(!k->hasValue(KIT_IS_TEMPORARY), return);
|
||||||
|
|
||||||
@@ -161,13 +182,14 @@ void ProjectImporter::markTemporary(Kit *k) const
|
|||||||
k->setValue(KIT_IS_TEMPORARY, true);
|
k->setValue(KIT_IS_TEMPORARY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectImporter::makePermanent(Kit *k) const
|
void ProjectImporter::makePersistent(Kit *k) const
|
||||||
{
|
{
|
||||||
if (!k->hasValue(KIT_IS_TEMPORARY))
|
if (!k->hasValue(KIT_IS_TEMPORARY))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UpdateGuard guard(*this);
|
UpdateGuard guard(*this);
|
||||||
|
|
||||||
|
KitGuard kitGuard(k);
|
||||||
k->removeKey(KIT_IS_TEMPORARY);
|
k->removeKey(KIT_IS_TEMPORARY);
|
||||||
k->removeKey(TEMPORARY_OF_PROJECTS);
|
k->removeKey(TEMPORARY_OF_PROJECTS);
|
||||||
const QString tempName = k->value(KIT_TEMPORARY_NAME).toString();
|
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->setUnexpandedDisplayName(k->value(KIT_FINAL_NAME).toString());
|
||||||
k->removeKey(KIT_TEMPORARY_NAME);
|
k->removeKey(KIT_TEMPORARY_NAME);
|
||||||
k->removeKey(KIT_FINAL_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)
|
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)
|
void ProjectImporter::addProject(Kit *k)
|
||||||
@@ -220,7 +269,7 @@ Kit *ProjectImporter::createTemporaryKit(const KitSetupFunction &setup) const
|
|||||||
{
|
{
|
||||||
KitGuard kitGuard(k);
|
KitGuard kitGuard(k);
|
||||||
k->setUnexpandedDisplayName(QCoreApplication::translate("ProjectExplorer::ProjectImporter", "Imported Kit"));;
|
k->setUnexpandedDisplayName(QCoreApplication::translate("ProjectExplorer::ProjectImporter", "Imported Kit"));;
|
||||||
markTemporary(k);
|
markKitAsTemporary(k);
|
||||||
|
|
||||||
setup(k);
|
setup(k);
|
||||||
|
|
||||||
@@ -232,4 +281,37 @@ Kit *ProjectImporter::createTemporaryKit(const KitSetupFunction &setup) const
|
|||||||
return k;
|
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
|
} // namespace ProjectExplorer
|
||||||
|
|||||||
@@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
#include "projectexplorer_export.h"
|
#include "projectexplorer_export.h"
|
||||||
|
|
||||||
|
#include <coreplugin/id.h>
|
||||||
|
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
@@ -51,10 +53,8 @@ public:
|
|||||||
|
|
||||||
bool isUpdating() const { return m_isUpdating; }
|
bool isUpdating() const { return m_isUpdating; }
|
||||||
|
|
||||||
virtual void makePermanent(Kit *k) const;
|
void makePersistent(Kit *k) const;
|
||||||
|
void cleanupKit(Kit *k);
|
||||||
// Additional cleanup that has to happen when kits are removed
|
|
||||||
virtual void cleanupKit(Kit *k);
|
|
||||||
|
|
||||||
bool isTemporaryKit(Kit *k) const;
|
bool isTemporaryKit(Kit *k) const;
|
||||||
|
|
||||||
@@ -89,12 +89,30 @@ protected:
|
|||||||
using KitSetupFunction = std::function<void(Kit *)>;
|
using KitSetupFunction = std::function<void(Kit *)>;
|
||||||
ProjectExplorer::Kit *createTemporaryKit(const KitSetupFunction &setup) const;
|
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:
|
private:
|
||||||
void markTemporary(Kit *k) const;
|
void markKitAsTemporary(Kit *k) const;
|
||||||
|
bool findTemporaryHandler(Core::Id id) const;
|
||||||
|
|
||||||
const QString m_projectPath;
|
const QString m_projectPath;
|
||||||
mutable bool m_isUpdating = false;
|
mutable bool m_isUpdating = false;
|
||||||
|
|
||||||
|
class TemporaryInformationHandler {
|
||||||
|
public:
|
||||||
|
Core::Id id;
|
||||||
|
CleanupFunction cleanup;
|
||||||
|
PersistFunction persist;
|
||||||
|
};
|
||||||
|
QList<TemporaryInformationHandler> m_temporaryHandlers;
|
||||||
|
|
||||||
friend class UpdateGuard;
|
friend class UpdateGuard;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -362,7 +362,7 @@ void TargetSetupPage::handleKitUpdate(Kit *k)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_importer)
|
if (m_importer)
|
||||||
m_importer->makePermanent(k);
|
m_importer->makePersistent(k);
|
||||||
|
|
||||||
TargetSetupWidget *widget = m_widgets.value(k->id());
|
TargetSetupWidget *widget = m_widgets.value(k->id());
|
||||||
|
|
||||||
@@ -543,7 +543,7 @@ bool TargetSetupPage::setupProject(Project *project)
|
|||||||
|
|
||||||
Kit *k = widget->kit();
|
Kit *k = widget->kit();
|
||||||
if (m_importer)
|
if (m_importer)
|
||||||
m_importer->makePermanent(k);
|
m_importer->makePersistent(k);
|
||||||
toSetUp << widget->selectedBuildInfoList();
|
toSetUp << widget->selectedBuildInfoList();
|
||||||
widget->clearKit();
|
widget->clearKit();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
@@ -43,38 +44,11 @@ using namespace ProjectExplorer;
|
|||||||
|
|
||||||
namespace QtSupport {
|
namespace QtSupport {
|
||||||
|
|
||||||
const Core::Id QT_IS_TEMPORARY("Qt.TempQt");
|
QtProjectImporter::QtProjectImporter(const QString &path) : ProjectImporter(path)
|
||||||
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
if (!isTemporaryKit(k))
|
useTemporaryKitInformation(QtKitInformation::id(),
|
||||||
return;
|
[this](Kit *k, const QVariantList &vl) { cleanupTemporaryQt(k, vl); },
|
||||||
|
[this](Kit *k, const QVariantList &vl) { persistTemporaryQt(k, vl); });
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QtProjectImporter::QtVersionData
|
QtProjectImporter::QtVersionData
|
||||||
@@ -92,9 +66,7 @@ QtProjectImporter::findOrCreateQtVersion(const Utils::FileName &qmakePath) const
|
|||||||
if (result.qt) {
|
if (result.qt) {
|
||||||
// Check if version is a temporary qt
|
// Check if version is a temporary qt
|
||||||
const int qtId = result.qt->uniqueId();
|
const int qtId = result.qt->uniqueId();
|
||||||
result.isTemporary = Utils::anyOf(KitManager::kits(), [&qtId](Kit *k) {
|
result.isTemporary = hasKitWithTemporaryData(QtKitInformation::id(), qtId);
|
||||||
return k->value(QT_IS_TEMPORARY, -1).toInt() == qtId;
|
|
||||||
});
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,17 +83,46 @@ QtProjectImporter::findOrCreateQtVersion(const Utils::FileName &qmakePath) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
Kit *QtProjectImporter::createTemporaryKit(const QtVersionData &versionData,
|
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);
|
QtKitInformation::setQtVersion(k, versionData.qt);
|
||||||
if (versionData.isTemporary)
|
if (versionData.isTemporary)
|
||||||
k->setValue(QT_IS_TEMPORARY, versionData.qt->uniqueId());
|
addTemporaryData(QtKitInformation::id(), versionData.qt->uniqueId(), k);
|
||||||
|
|
||||||
k->setUnexpandedDisplayName(versionData.qt->displayName());;
|
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
|
} // namespace QtSupport
|
||||||
|
|||||||
@@ -41,9 +41,6 @@ class QTSUPPORT_EXPORT QtProjectImporter : public ProjectExplorer::ProjectImport
|
|||||||
public:
|
public:
|
||||||
QtProjectImporter(const QString &path);
|
QtProjectImporter(const QString &path);
|
||||||
|
|
||||||
void cleanupKit(ProjectExplorer::Kit *k) override;
|
|
||||||
void makePermanent(ProjectExplorer::Kit *k) const override;
|
|
||||||
|
|
||||||
class QtVersionData
|
class QtVersionData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -55,6 +52,10 @@ protected:
|
|||||||
QtVersionData findOrCreateQtVersion(const Utils::FileName &qmakePath) const;
|
QtVersionData findOrCreateQtVersion(const Utils::FileName &qmakePath) const;
|
||||||
ProjectExplorer::Kit *createTemporaryKit(const QtVersionData &versionData,
|
ProjectExplorer::Kit *createTemporaryKit(const QtVersionData &versionData,
|
||||||
const KitSetupFunction &setup) const;
|
const KitSetupFunction &setup) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void cleanupTemporaryQt(ProjectExplorer::Kit *k, const QVariantList &vl);
|
||||||
|
void persistTemporaryQt(ProjectExplorer::Kit *k, const QVariantList &vl);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmakeProjectManager
|
} // namespace QmakeProjectManager
|
||||||
|
|||||||
Reference in New Issue
Block a user