Commit 71c6d4d7 authored by hjk's avatar hjk

ProjectExplorer: Using function objects for kit matching

Change-Id: I377298385df345a6d30217bb018964a64897d42e
Reviewed-by: default avatarDaniel Teske <daniel.teske@digia.com>
Reviewed-by: default avatarTobias Hunger <tobias.hunger@digia.com>
parent bf5e43be
......@@ -552,74 +552,31 @@ static QString executableForPid(qint64 pid)
return QString();
}
class AbiKitMatcher : public KitMatcher
static std::function<bool(const Kit *)> cdbMatcher(char wordWidth = 0)
{
public:
explicit AbiKitMatcher(const QList<Abi> &abis) : m_abis(abis) {}
bool matches(const Kit *k) const
{
if (const ToolChain *tc = ToolChainKitInformation::toolChain(k)) {
return m_abis.contains(tc->targetAbi())
&& DebuggerKitInformation::isValidDebugger(k);
}
return false;
}
private:
const QList<Abi> m_abis;
};
class CompatibleAbiKitMatcher : public KitMatcher
{
public:
explicit CompatibleAbiKitMatcher(const QList<Abi> &abis) : m_abis(abis) {}
bool matches(const Kit *k) const
{
if (const ToolChain *tc = ToolChainKitInformation::toolChain(k))
foreach (const Abi &a, m_abis)
if (a.isCompatibleWith(tc->targetAbi()) && DebuggerKitInformation::isValidDebugger(k))
return true;
return false;
}
private:
const QList<Abi> m_abis;
};
class CdbMatcher : KitMatcher
{
public:
CdbMatcher(char wordWidth = 0) : m_wordWidth(wordWidth) {}
bool matches(const Kit *k) const
{
return [wordWidth](const Kit *k) -> bool {
if (DebuggerKitInformation::engineType(k) != CdbEngineType
|| !DebuggerKitInformation::isValidDebugger(k)) {
return false;
}
if (m_wordWidth) {
if (wordWidth) {
const ToolChain *tc = ToolChainKitInformation::toolChain(k);
return tc && m_wordWidth == tc->targetAbi().wordWidth();
return tc && wordWidth == tc->targetAbi().wordWidth();
}
return true;
}
};
}
// Find a CDB kit for debugging unknown processes.
// On a 64bit OS, prefer a 64bit debugger.
static Kit *findUniversalCdbKit()
{
if (Utils::is64BitWindowsSystem()) {
CdbMatcher matcher64(64);
if (Kit *cdb64Kit = KitManager::find(matcher64))
return cdb64Kit;
}
CdbMatcher matcher;
return KitManager::find(matcher);
// Find a CDB kit for debugging unknown processes.
// On a 64bit OS, prefer a 64bit debugger.
static Kit *findUniversalCdbKit()
{
if (Utils::is64BitWindowsSystem()) {
if (Kit *cdb64Kit = KitManager::find(cdbMatcher(64)))
return cdb64Kit;
}
private:
const char m_wordWidth;
};
return KitManager::find(cdbMatcher());
}
bool fillParameters(DebuggerStartParameters *sp, const Kit *kit, QString *errorMessage /* = 0 */)
{
......@@ -640,9 +597,24 @@ bool fillParameters(DebuggerStartParameters *sp, const Kit *kit, QString *errorM
abis = Abi::abisOfBinary(Utils::FileName::fromString(sp->executable));
}
if (!abis.isEmpty()) {
kit = KitManager::find(AbiKitMatcher(abis));
if (!kit)
kit = KitManager::find(CompatibleAbiKitMatcher(abis));
// Try exact abis.
kit = KitManager::find(std::function<bool (const Kit *)>([abis](const Kit *k) -> bool {
if (const ToolChain *tc = ToolChainKitInformation::toolChain(k)) {
return abis.contains(tc->targetAbi())
&& DebuggerKitInformation::isValidDebugger(k);
}
return false;
}));
if (!kit) {
// Or something compatible.
kit = KitManager::find(std::function<bool (const Kit *)>([abis](const Kit *k) -> bool {
if (const ToolChain *tc = ToolChainKitInformation::toolChain(k))
foreach (const Abi &a, abis)
if (a.isCompatibleWith(tc->targetAbi()) && DebuggerKitInformation::isValidDebugger(k))
return true;
return false;
}));
}
}
if (!kit)
kit = KitManager::defaultKit();
......@@ -1464,7 +1436,7 @@ bool DebuggerPluginPrivate::parseArgument(QStringList::const_iterator &it,
return false;
}
DebuggerStartParameters sp;
if (!fillParameters(&sp, CdbMatcher::findUniversalCdbKit(), errorMessage))
if (!fillParameters(&sp, findUniversalCdbKit(), errorMessage))
return false;
sp.startMode = AttachCrashedExternal;
sp.crashParameter = it->section(QLatin1Char(':'), 0, 0);
......@@ -1643,7 +1615,7 @@ void DebuggerPluginPrivate::startRemoteCdbSession()
{
const QByteArray connectionKey = "CdbRemoteConnection";
DebuggerStartParameters sp;
Kit *kit = CdbMatcher::findUniversalCdbKit();
Kit *kit = findUniversalCdbKit();
QTC_ASSERT(kit && fillParameters(&sp, kit), return);
sp.startMode = AttachToRemoteServer;
sp.closeMode = KillAtClose;
......
......@@ -248,7 +248,8 @@ void ToolChainKitInformation::kitsWereLoaded()
void ToolChainKitInformation::toolChainUpdated(ToolChain *tc)
{
foreach (Kit *k, KitManager::matchingKits(ToolChainMatcher(tc)))
auto matcher = KitMatcher([tc](const Kit *k) { return toolChain(k) == tc; });
foreach (Kit *k, KitManager::matchingKits(matcher))
notifyAboutUpdate(k);
}
......@@ -318,6 +319,13 @@ void DeviceTypeKitInformation::setDeviceTypeId(Kit *k, Core::Id type)
k->setValue(DeviceTypeKitInformation::id(), type.toSetting());
}
KitMatcher DeviceTypeKitInformation::deviceTypeMatcher(Core::Id type)
{
return std::function<bool(const Kit *)>([type](const Kit *kit) {
return type.isValid() && deviceTypeId(kit) == type;
});
}
// --------------------------------------------------------------------------
// DeviceInformation:
// --------------------------------------------------------------------------
......
......@@ -67,21 +67,6 @@ public:
static void setSysRoot(Kit *k, const Utils::FileName &v);
};
class PROJECTEXPLORER_EXPORT SysRootMatcher : public KitMatcher
{
public:
SysRootMatcher(const Utils::FileName &fn) : m_sysroot(fn)
{ }
bool matches(const Kit *k) const
{
return SysRootKitInformation::sysRoot(k) == m_sysroot;
}
private:
Utils::FileName m_sysroot;
};
// --------------------------------------------------------------------------
// ToolChainInformation:
// --------------------------------------------------------------------------
......@@ -120,21 +105,6 @@ private slots:
void toolChainRemoved(ProjectExplorer::ToolChain *tc);
};
class PROJECTEXPLORER_EXPORT ToolChainMatcher : public KitMatcher
{
public:
ToolChainMatcher(const ToolChain *tc) : m_tc(tc)
{ }
bool matches(const Kit *k) const
{
return ToolChainKitInformation::toolChain(k) == m_tc;
}
private:
const ToolChain *m_tc;
};
// --------------------------------------------------------------------------
// DeviceTypeInformation:
// --------------------------------------------------------------------------
......@@ -157,24 +127,8 @@ public:
static const Core::Id id();
static const Core::Id deviceTypeId(const Kit *k);
static void setDeviceTypeId(Kit *k, Core::Id type);
};
class PROJECTEXPLORER_EXPORT DeviceTypeMatcher : public KitMatcher
{
public:
DeviceTypeMatcher(Core::Id t) : m_type(t)
{ }
bool matches(const Kit *k) const
{
Core::Id deviceType = DeviceTypeKitInformation::deviceTypeId(k);
if (!deviceType.isValid())
return false;
return deviceType == m_type;
}
private:
const Core::Id m_type;
static KitMatcher deviceTypeMatcher(Core::Id type);
};
// --------------------------------------------------------------------------
......@@ -213,23 +167,6 @@ private slots:
void kitUpdated(ProjectExplorer::Kit *k);
};
class PROJECTEXPLORER_EXPORT DeviceMatcher : public KitMatcher
{
public:
DeviceMatcher(Core::Id id) : m_devId(id)
{ }
DeviceMatcher() { }
bool matches(const Kit *k) const
{
return DeviceKitInformation::deviceId(k) == m_devId;
}
private:
Core::Id m_devId;
};
} // namespace ProjectExplorer
#endif // KITINFORMATION_H
......@@ -37,6 +37,8 @@
#include <QObject>
#include <QPair>
#include <functional>
namespace Utils {
class FileName;
class Environment;
......@@ -103,8 +105,13 @@ private:
class PROJECTEXPLORER_EXPORT KitMatcher
{
public:
virtual ~KitMatcher() { }
virtual bool matches(const Kit *k) const = 0;
typedef std::function<bool(const Kit *)> Matcher;
KitMatcher(const Matcher &m) : m_matcher(m) {}
bool matches(const Kit *kit) const { return m_matcher(kit); }
private:
Matcher m_matcher;
};
class PROJECTEXPLORER_EXPORT KitManager : public QObject
......
......@@ -94,12 +94,17 @@ public:
Core::Context m_projectLanguages;
QVariantMap m_pluginSettings;
Internal::UserFileAccessor *m_accessor;
KitMatcher m_requiredKitMatcher;
KitMatcher m_preferredKitMatcher;
};
ProjectPrivate::ProjectPrivate() :
m_activeTarget(0),
m_editorConfiguration(new EditorConfiguration()),
m_accessor(0)
m_accessor(0),
m_requiredKitMatcher([](const Kit*) { return true; }),
m_preferredKitMatcher([](const Kit*) { return true; })
{ }
ProjectPrivate::~ProjectPrivate()
......@@ -519,6 +524,26 @@ ProjectImporter *Project::createProjectImporter() const
return 0;
}
KitMatcher Project::requiredKitMatcher() const
{
return d->m_requiredKitMatcher;
}
void Project::setRequiredKitMatcher(const KitMatcher &matcher)
{
d->m_preferredKitMatcher = matcher;
}
KitMatcher Project::preferredKitMatcher() const
{
return d->m_preferredKitMatcher;
}
void Project::setPreferredKitMatcher(const KitMatcher &matcher)
{
d->m_requiredKitMatcher = matcher;
}
void Project::onBuildDirectoryChanged()
{
Target *target = qobject_cast<Target *>(sender());
......
......@@ -130,8 +130,12 @@ public:
virtual bool requiresTargetPanel() const;
virtual ProjectImporter *createProjectImporter() const;
virtual KitMatcher *createRequiredKitMatcher() const { return 0; }
virtual KitMatcher *createPreferredKitMatcher() const { return 0; }
KitMatcher requiredKitMatcher() const;
void setRequiredKitMatcher(const KitMatcher &matcher);
KitMatcher preferredKitMatcher() const;
void setPreferredKitMatcher(const KitMatcher &matcher);
virtual bool needsSpecialDeployment() const;
......
......@@ -204,12 +204,8 @@ void TargetSetupPage::initializePage()
selectAtLeastOneKit();
}
void TargetSetupPage::setRequiredKitMatcher(KitMatcher *matcher)
void TargetSetupPage::setRequiredKitMatcher(const KitMatcher &matcher)
{
if (matcher == m_requiredMatcher)
return;
if (m_requiredMatcher)
delete m_requiredMatcher;
m_requiredMatcher = matcher;
}
......@@ -227,12 +223,8 @@ QList<Core::Id> TargetSetupPage::selectedKits() const
return result;
}
void TargetSetupPage::setPreferredKitMatcher(KitMatcher *matcher)
void TargetSetupPage::setPreferredKitMatcher(const KitMatcher &matcher)
{
if (matcher == m_preferredMatcher)
return;
if (m_preferredMatcher)
delete m_preferredMatcher;
m_preferredMatcher = matcher;
}
......@@ -240,8 +232,6 @@ TargetSetupPage::~TargetSetupPage()
{
reset();
delete m_ui;
delete m_preferredMatcher;
delete m_requiredMatcher;
delete m_importer;
}
......@@ -267,14 +257,7 @@ bool TargetSetupPage::isComplete() const
void TargetSetupPage::setupWidgets()
{
QList<Kit *> kitList;
// Known profiles:
if (m_requiredMatcher)
kitList = KitManager::matchingKits(*m_requiredMatcher);
else
kitList = KitManager::kits();
foreach (Kit *k, kitList)
foreach (Kit *k, KitManager::matchingKits(m_requiredMatcher))
addWidget(k);
// Setup import widget:
......@@ -386,9 +369,7 @@ void TargetSetupPage::handleKitUpdate(Kit *k)
TargetSetupWidget *widget = m_widgets.value(k->id());
bool acceptable = true;
if (m_requiredMatcher && !m_requiredMatcher->matches(k))
acceptable = false;
bool acceptable = m_requiredMatcher.matches(k);
if (widget && !acceptable)
removeWidget(k);
......@@ -524,7 +505,7 @@ void TargetSetupPage::removeWidget(Kit *k)
TargetSetupWidget *TargetSetupPage::addWidget(Kit *k)
{
if (!k || (m_requiredMatcher && !m_requiredMatcher->matches(k)))
if (!k || !m_requiredMatcher.matches(k))
return 0;
IBuildConfigurationFactory *factory
......@@ -542,7 +523,7 @@ TargetSetupWidget *TargetSetupPage::addWidget(Kit *k)
m_baseLayout->removeWidget(widget);
m_baseLayout->removeItem(m_spacer);
widget->setKitSelected(m_preferredMatcher && m_preferredMatcher->matches(k));
widget->setKitSelected(m_preferredMatcher.matches(k));
m_widgets.insert(k->id(), widget);
connect(widget, SIGNAL(selectedToggled()),
this, SLOT(kitSelectionChanged()));
......
......@@ -33,6 +33,7 @@
#include "projectexplorer_export.h"
#include "projectimporter.h"
#include "kitinformation.h"
#include <QString>
#include <QWizardPage>
......@@ -68,8 +69,8 @@ public:
void initializePage();
// Call these before initializePage!
void setRequiredKitMatcher(KitMatcher *matcher);
void setPreferredKitMatcher(KitMatcher *matcher);
void setRequiredKitMatcher(const KitMatcher &matcher);
void setPreferredKitMatcher(const KitMatcher &matcher);
/// Sets whether the targetsetupage uses a scrollarea
/// to host the widgets from the factories
......@@ -111,8 +112,8 @@ private:
void setupWidgets();
void reset();
KitMatcher *m_requiredMatcher;
KitMatcher *m_preferredMatcher;
KitMatcher m_requiredMatcher;
KitMatcher m_preferredMatcher;
ProjectImporter *m_importer;
QLayout *m_baseLayout;
QString m_projectPath;
......
......@@ -63,8 +63,8 @@ TargetSetupPageWrapper::TargetSetupPageWrapper(Project *project) :
m_targetSetupPage->setProjectImporter(project->createProjectImporter());
m_targetSetupPage->setUseScrollArea(false);
m_targetSetupPage->setProjectPath(project->projectFilePath().toString());
m_targetSetupPage->setRequiredKitMatcher(project->createRequiredKitMatcher());
m_targetSetupPage->setPreferredKitMatcher(project->createPreferredKitMatcher());
m_targetSetupPage->setRequiredKitMatcher(project->requiredKitMatcher());
m_targetSetupPage->setPreferredKitMatcher(project->preferredKitMatcher());
m_targetSetupPage->initializePage();
m_targetSetupPage->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
updateNoteText();
......
......@@ -344,6 +344,7 @@ QmakeProject::QmakeProject(QmakeManager *manager, const QString &fileName) :
setId(Constants::QMAKEPROJECT_ID);
setProjectContext(Core::Context(QmakeProjectManager::Constants::PROJECT_ID));
setProjectLanguages(Core::Context(ProjectExplorer::Constants::LANG_CXX));
setRequiredKitMatcher(QtSupport::QtKitInformation::qtVersionMatcher());
m_asyncUpdateTimer.setSingleShot(true);
m_asyncUpdateTimer.setInterval(3000);
......@@ -1644,11 +1645,6 @@ ProjectImporter *QmakeProject::createProjectImporter() const
return new QmakeProjectImporter(projectFilePath().toString());
}
KitMatcher *QmakeProject::createRequiredKitMatcher() const
{
return new QtSupport::QtVersionKitMatcher;
}
} // namespace QmakeProjectManager
#include "qmakeproject.moc"
......@@ -140,7 +140,6 @@ public:
ProjectExplorer::ProjectImporter *createProjectImporter() const;
ProjectExplorer::KitMatcher *createRequiredKitMatcher() const;
signals:
void proFileUpdated(QmakeProjectManager::QmakeProFileNode *node, bool, bool);
void buildDirectoryInitialized();
......
......@@ -43,7 +43,9 @@
#include <projectexplorer/session.h>
#include <coreplugin/editormanager/editormanager.h>
using namespace Core;
using namespace ProjectExplorer;
using namespace QtSupport;
namespace QmakeProjectManager {
......@@ -75,14 +77,13 @@ void AbstractMobileAppWizardDialog::updateKitsPage()
QString platform = selectedPlatform();
if (platform.isEmpty()) {
m_kitsPage->setPreferredKitMatcher(
new QtSupport::QtVersionKitMatcher(
Core::FeatureSet( QtSupport::Constants::FEATURE_MOBILE)));
QtKitInformation::qtVersionMatcher(FeatureSet(QtSupport::Constants::FEATURE_MOBILE)));
} else {
m_kitsPage->setPreferredKitMatcher(new QtSupport::QtPlatformKitMatcher(platform));
m_kitsPage->setPreferredKitMatcher(QtKitInformation::platformMatcher(platform));
}
m_kitsPage->setRequiredKitMatcher(new QtSupport::QtVersionKitMatcher(requiredFeatures(),
m_minimumQtVersionNumber,
m_maximumQtVersionNumber));
m_kitsPage->setRequiredKitMatcher(QtKitInformation::qtVersionMatcher(requiredFeatures(),
m_minimumQtVersionNumber,
m_maximumQtVersionNumber));
}
}
......
......@@ -39,6 +39,7 @@
#include <cpptools/cpptoolsconstants.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/targetsetuppage.h>
......@@ -53,6 +54,7 @@
using namespace ProjectExplorer;
using namespace QmakeProjectManager;
using namespace QmakeProjectManager::Internal;
using namespace QtSupport;
// -------------------- QtWizard
QtWizard::QtWizard()
......@@ -209,11 +211,11 @@ int BaseQmakeProjectWizardDialog::addTargetSetupPage(int id)
const QString platform = selectedPlatform();
Core::FeatureSet features = Core::FeatureSet(QtSupport::Constants::FEATURE_DESKTOP);
if (platform.isEmpty())
m_targetSetupPage->setPreferredKitMatcher(new QtSupport::QtVersionKitMatcher(features));
m_targetSetupPage->setPreferredKitMatcher(QtKitInformation::qtVersionMatcher(features));
else
m_targetSetupPage->setPreferredKitMatcher(new QtSupport::QtPlatformKitMatcher(platform));
m_targetSetupPage->setPreferredKitMatcher(QtKitInformation::platformMatcher(platform));
m_targetSetupPage->setRequiredKitMatcher(new QtSupport::QtVersionKitMatcher(requiredFeatures()));
m_targetSetupPage->setRequiredKitMatcher(QtKitInformation::qtVersionMatcher(requiredFeatures()));
resize(900, 450);
if (id >= 0)
......@@ -285,7 +287,7 @@ bool BaseQmakeProjectWizardDialog::isQtPlatformSelected(const QString &platform)
{
QList<Core::Id> selectedKitList = selectedKits();
foreach (Kit *k, KitManager::matchingKits(QtSupport::QtPlatformKitMatcher(platform)))
foreach (Kit *k, KitManager::matchingKits(QtKitInformation::platformMatcher(platform)))
if (selectedKitList.contains(k->id()))
return true;
......
......@@ -55,53 +55,6 @@ using namespace ProjectExplorer;
namespace QmlProjectManager {
namespace Internal {
class QmlProjectKitMatcher : public ProjectExplorer::KitMatcher
{
public:
QmlProjectKitMatcher(const QmlProject::QmlImport &import)
: import(import)
{
}
bool matches(const ProjectExplorer::Kit *k) const
{
if (!k->isValid())
return false;
ProjectExplorer::IDevice::ConstPtr dev = ProjectExplorer::DeviceKitInformation::device(k);
if (dev.isNull() || dev->type() != ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)
return false;
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);
if (!version || version->type() != QLatin1String(QtSupport::Constants::DESKTOPQT))
return false;
bool hasViewer = false; // Initialization needed for dumb compilers.
QtSupport::QtVersionNumber minVersion;
switch (import) {
case QmlProject::UnknownImport:
minVersion = QtSupport::QtVersionNumber(4, 7, 0);
hasViewer = !version->qmlviewerCommand().isEmpty() || !version->qmlsceneCommand().isEmpty();
break;
case QmlProject::QtQuick1Import:
minVersion = QtSupport::QtVersionNumber(4, 7, 1);
hasViewer = !version->qmlviewerCommand().isEmpty();
break;
case QmlProject::QtQuick2Import:
minVersion = QtSupport::QtVersionNumber(5, 0, 0);
hasViewer = !version->qmlsceneCommand().isEmpty();
break;
}
if (version->qtVersion() >= minVersion
&& hasViewer)
return true;
return false;
}
private:
QmlProject::QmlImport import;
};
} // namespace Internal
QmlProject::QmlProject(Internal::Manager *manager, const QString &fileName)
......@@ -394,8 +347,37 @@ bool QmlProject::fromMap(const QVariantMap &map)
if (!activeTarget()) {
// find a kit that matches prerequisites (prefer default one)
Internal::QmlProjectKitMatcher matcher(defaultImport());
QList<Kit*> kits = KitManager::matchingKits(matcher);
QList<Kit*> kits = KitManager::matchingKits(
std::function<bool(const Kit *)>([this](const Kit *k) -> bool {
if (!k->isValid())
return false;