diff --git a/src/plugins/debugger/debuggerkitaspect.cpp b/src/plugins/debugger/debuggerkitaspect.cpp index 285c8ee7cd9..215806a8b53 100644 --- a/src/plugins/debugger/debuggerkitaspect.cpp +++ b/src/plugins/debugger/debuggerkitaspect.cpp @@ -8,6 +8,7 @@ #include "debuggertr.h" #include +#include #include #include #include diff --git a/src/plugins/projectexplorer/CMakeLists.txt b/src/plugins/projectexplorer/CMakeLists.txt index e41e22d6747..04473e85890 100644 --- a/src/plugins/projectexplorer/CMakeLists.txt +++ b/src/plugins/projectexplorer/CMakeLists.txt @@ -52,6 +52,7 @@ add_qtc_plugin(ProjectExplorer devicesupport/desktopprocesssignaloperation.cpp devicesupport/desktopprocesssignaloperation.h devicesupport/devicecheckbuildstep.cpp devicesupport/devicecheckbuildstep.h devicesupport/devicefactoryselectiondialog.cpp devicesupport/devicefactoryselectiondialog.h + devicesupport/devicekitaspects.cpp devicesupport/devicekitaspects.h devicesupport/devicemanager.cpp devicesupport/devicemanager.h devicesupport/devicemanagermodel.cpp devicesupport/devicemanagermodel.h devicesupport/deviceprocessesdialog.cpp devicesupport/deviceprocessesdialog.h diff --git a/src/plugins/projectexplorer/devicesupport/devicekitaspects.cpp b/src/plugins/projectexplorer/devicesupport/devicekitaspects.cpp new file mode 100644 index 00000000000..6a673fdc8b5 --- /dev/null +++ b/src/plugins/projectexplorer/devicesupport/devicekitaspects.cpp @@ -0,0 +1,697 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "devicekitaspects.h" + +#include "devicemanager.h" +#include "devicemanagermodel.h" +#include "idevicefactory.h" +#include "sshparameters.h" +#include "../kit.h" +#include "../kitaspect.h" +#include "../kitmanager.h" +#include "../projectexplorerconstants.h" +#include "../projectexplorertr.h" + +#include +#include +#include +#include + +#include + +#include + +using namespace Utils; + +namespace ProjectExplorer { + +// -------------------------------------------------------------------------- +// DeviceTypeKitAspect: +// -------------------------------------------------------------------------- +namespace Internal { +class DeviceTypeKitAspectImpl final : public KitAspect +{ +public: + DeviceTypeKitAspectImpl(Kit *workingCopy, const KitAspectFactory *factory) + : KitAspect(workingCopy, factory) + { + using ItemData = std::tuple; + const auto model = new ListModel(this); + model->setDataAccessor([](const ItemData &d, int column, int role) -> QVariant { + if (column != 0) + return {}; + if (role == Qt::DisplayRole) + return std::get<0>(d); + if (role == KitAspect::IdRole) + return std::get<1>(d).toSetting(); + if (role == Qt::DecorationRole) + return std::get<2>(d); + return {}; + }); + auto getter = [](const Kit &k) { return DeviceTypeKitAspect::deviceTypeId(&k).toSetting(); }; + auto setter = [](Kit &k, const QVariant &type) { + DeviceTypeKitAspect::setDeviceTypeId(&k, Id::fromSetting(type)); + }; + auto resetModel = [model] { + model->clear(); + for (IDeviceFactory *factory : IDeviceFactory::allDeviceFactories()) { + model->appendItem( + std::make_tuple(factory->displayName(), factory->deviceType(), factory->icon())); + } + }; + setListAspectSpec( + {model, std::move(getter), std::move(setter), std::move(resetModel)}); + } +}; + +class DeviceTypeKitAspectFactory : public KitAspectFactory +{ +public: + DeviceTypeKitAspectFactory(); + + void setup(Kit *k) override; + Tasks validate(const Kit *k) const override; + KitAspect *createKitAspect(Kit *k) const override; + ItemList toUserOutput(const Kit *k) const override; + + QSet supportedPlatforms(const Kit *k) const override; + QSet availableFeatures(const Kit *k) const override; +}; + +DeviceTypeKitAspectFactory::DeviceTypeKitAspectFactory() +{ + setId(DeviceTypeKitAspect::id()); + setDisplayName(Tr::tr("Run device type")); + setDescription(Tr::tr("The type of device to run applications on.")); + setPriority(33000); + makeEssential(); +} + +void DeviceTypeKitAspectFactory::setup(Kit *k) +{ + if (k && !k->hasValue(id())) + k->setValue(id(), QByteArray(Constants::DESKTOP_DEVICE_TYPE)); +} + +Tasks DeviceTypeKitAspectFactory::validate(const Kit *k) const +{ + Q_UNUSED(k) + return {}; +} + +KitAspect *DeviceTypeKitAspectFactory::createKitAspect(Kit *k) const +{ + QTC_ASSERT(k, return nullptr); + return new Internal::DeviceTypeKitAspectImpl(k, this); +} + +KitAspectFactory::ItemList DeviceTypeKitAspectFactory::toUserOutput(const Kit *k) const +{ + QTC_ASSERT(k, return {}); + Id type = DeviceTypeKitAspect::deviceTypeId(k); + QString typeDisplayName = Tr::tr("Unknown device type"); + if (type.isValid()) { + if (IDeviceFactory *factory = IDeviceFactory::find(type)) + typeDisplayName = factory->displayName(); + } + return {{Tr::tr("Device type"), typeDisplayName}}; +} + +QSet DeviceTypeKitAspectFactory::supportedPlatforms(const Kit *k) const +{ + return {DeviceTypeKitAspect::deviceTypeId(k)}; +} + +QSet DeviceTypeKitAspectFactory::availableFeatures(const Kit *k) const +{ + Id id = DeviceTypeKitAspect::deviceTypeId(k); + if (id.isValid()) + return {id.withPrefix("DeviceType.")}; + return {}; +} + +const DeviceTypeKitAspectFactory theDeviceTypeKitAspectFactory; +} // namespace Internal + +const Id DeviceTypeKitAspect::id() +{ + return "PE.Profile.DeviceType"; +} + +const Id DeviceTypeKitAspect::deviceTypeId(const Kit *k) +{ + return k ? Id::fromSetting(k->value(DeviceTypeKitAspect::id())) : Id(); +} + +void DeviceTypeKitAspect::setDeviceTypeId(Kit *k, Id type) +{ + QTC_ASSERT(k, return); + k->setValue(DeviceTypeKitAspect::id(), type.toSetting()); +} + +// -------------------------------------------------------------------------- +// DeviceKitAspect: +// -------------------------------------------------------------------------- +namespace Internal { +class DeviceKitAspectImpl final : public KitAspect +{ +public: + DeviceKitAspectImpl(Kit *workingCopy, const KitAspectFactory *factory) + : KitAspect(workingCopy, factory), + m_comboBox(createSubWidget()), + m_model(new DeviceManagerModel(DeviceManager::instance())) + { + setManagingPage(Constants::DEVICE_SETTINGS_PAGE_ID); + m_comboBox->setSizePolicy(QSizePolicy::Preferred, + m_comboBox->sizePolicy().verticalPolicy()); + m_comboBox->setModel(m_model); + m_comboBox->setMinimumContentsLength(16); // Don't stretch too much for Kit Page + refresh(); + m_comboBox->setToolTip(factory->description()); + + connect(m_model, &QAbstractItemModel::modelAboutToBeReset, + this, &DeviceKitAspectImpl::modelAboutToReset); + connect(m_model, &QAbstractItemModel::modelReset, + this, &DeviceKitAspectImpl::modelReset); + connect(m_comboBox, &QComboBox::currentIndexChanged, + this, &DeviceKitAspectImpl::currentDeviceChanged); + } + + ~DeviceKitAspectImpl() override + { + delete m_comboBox; + delete m_model; + } + +private: + void addToInnerLayout(Layouting::Layout &builder) override + { + addMutableAction(m_comboBox); + builder.addItem(m_comboBox); + } + + void makeReadOnly() override { m_comboBox->setEnabled(false); } + + Id settingsPageItemToPreselect() const override { return DeviceKitAspect::deviceId(kit()); } + + void refresh() override + { + m_model->setTypeFilter(DeviceTypeKitAspect::deviceTypeId(kit())); + m_comboBox->setCurrentIndex(m_model->indexOf(DeviceKitAspect::device(kit()))); + } + + void modelAboutToReset() + { + m_selectedId = m_model->deviceId(m_comboBox->currentIndex()); + m_ignoreChanges.lock(); + } + + void modelReset() + { + m_comboBox->setCurrentIndex(m_model->indexForId(m_selectedId)); + m_ignoreChanges.unlock(); + } + + void currentDeviceChanged() + { + if (m_ignoreChanges.isLocked()) + return; + DeviceKitAspect::setDeviceId(kit(), m_model->deviceId(m_comboBox->currentIndex())); + } + + Guard m_ignoreChanges; + QComboBox *m_comboBox; + DeviceManagerModel *m_model; + Id m_selectedId; +}; + +class DeviceKitAspectFactory : public KitAspectFactory +{ +public: + DeviceKitAspectFactory(); + +private: + Tasks validate(const Kit *k) const override; + void fix(Kit *k) override; + void setup(Kit *k) override; + + KitAspect *createKitAspect(Kit *k) const override; + + QString displayNamePostfix(const Kit *k) const override; + + ItemList toUserOutput(const Kit *k) const override; + + void addToMacroExpander(Kit *kit, MacroExpander *expander) const override; + + QVariant defaultValue(const Kit *k) const; + + void onKitsLoaded() override; + void deviceUpdated(Id dataId); + void devicesChanged(); + void kitUpdated(Kit *k); +}; + +DeviceKitAspectFactory::DeviceKitAspectFactory() +{ + setId(DeviceKitAspect::id()); + setDisplayName(Tr::tr("Run device")); + setDescription(Tr::tr("The device to run the applications on.")); + setPriority(32000); +} + +QVariant DeviceKitAspectFactory::defaultValue(const Kit *k) const +{ + Id type = DeviceTypeKitAspect::deviceTypeId(k); + // Use default device if that is compatible: + IDevice::ConstPtr dev = DeviceManager::instance()->defaultDevice(type); + if (dev && dev->isCompatibleWith(k)) + return dev->id().toString(); + // Use any other device that is compatible: + for (int i = 0; i < DeviceManager::instance()->deviceCount(); ++i) { + dev = DeviceManager::instance()->deviceAt(i); + if (dev && dev->isCompatibleWith(k)) + return dev->id().toString(); + } + // Fail: No device set up. + return {}; +} + +Tasks DeviceKitAspectFactory::validate(const Kit *k) const +{ + IDevice::ConstPtr dev = DeviceKitAspect::device(k); + Tasks result; + if (!dev) + result.append(BuildSystemTask(Task::Warning, Tr::tr("No device set."))); + else if (!dev->isCompatibleWith(k)) + result.append(BuildSystemTask(Task::Error, Tr::tr("Device is incompatible with this kit."))); + + if (dev) + result.append(dev->validate()); + + return result; +} + +void DeviceKitAspectFactory::fix(Kit *k) +{ + IDevice::ConstPtr dev = DeviceKitAspect::device(k); + if (dev && !dev->isCompatibleWith(k)) { + qWarning("Device is no longer compatible with kit \"%s\", removing it.", + qPrintable(k->displayName())); + DeviceKitAspect::setDeviceId(k, Id()); + } +} + +void DeviceKitAspectFactory::setup(Kit *k) +{ + QTC_ASSERT(DeviceManager::instance()->isLoaded(), return); + IDevice::ConstPtr dev = DeviceKitAspect::device(k); + if (dev && dev->isCompatibleWith(k)) + return; + + DeviceKitAspect::setDeviceId(k, Id::fromSetting(defaultValue(k))); +} + +KitAspect *DeviceKitAspectFactory::createKitAspect(Kit *k) const +{ + QTC_ASSERT(k, return nullptr); + return new Internal::DeviceKitAspectImpl(k, this); +} + +QString DeviceKitAspectFactory::displayNamePostfix(const Kit *k) const +{ + IDevice::ConstPtr dev = DeviceKitAspect::device(k); + return dev ? dev->displayName() : QString(); +} + +KitAspectFactory::ItemList DeviceKitAspectFactory::toUserOutput(const Kit *k) const +{ + IDevice::ConstPtr dev = DeviceKitAspect::device(k); + return {{Tr::tr("Device"), dev ? dev->displayName() : Tr::tr("Unconfigured") }}; +} + +void DeviceKitAspectFactory::addToMacroExpander(Kit *kit, MacroExpander *expander) const +{ + QTC_ASSERT(kit, return); + expander->registerVariable("Device:HostAddress", Tr::tr("Host address"), [kit] { + const IDevice::ConstPtr device = DeviceKitAspect::device(kit); + return device ? device->sshParameters().host() : QString(); + }); + expander->registerVariable("Device:SshPort", Tr::tr("SSH port"), [kit] { + const IDevice::ConstPtr device = DeviceKitAspect::device(kit); + return device ? QString::number(device->sshParameters().port()) : QString(); + }); + expander->registerVariable("Device:UserName", Tr::tr("User name"), [kit] { + const IDevice::ConstPtr device = DeviceKitAspect::device(kit); + return device ? device->sshParameters().userName() : QString(); + }); + expander->registerVariable("Device:KeyFile", Tr::tr("Private key file"), [kit] { + const IDevice::ConstPtr device = DeviceKitAspect::device(kit); + return device ? device->sshParameters().privateKeyFile.toString() : QString(); + }); + expander->registerVariable("Device:Name", Tr::tr("Device name"), [kit] { + const IDevice::ConstPtr device = DeviceKitAspect::device(kit); + return device ? device->displayName() : QString(); + }); + expander->registerFileVariables("Device::Root", Tr::tr("Device root directory"), [kit] { + const IDevice::ConstPtr device = DeviceKitAspect::device(kit); + return device ? device->rootPath() : FilePath{}; + }); +} + +void DeviceKitAspectFactory::onKitsLoaded() +{ + for (Kit *k : KitManager::kits()) + fix(k); + + DeviceManager *dm = DeviceManager::instance(); + connect(dm, &DeviceManager::deviceListReplaced, this, &DeviceKitAspectFactory::devicesChanged); + connect(dm, &DeviceManager::deviceAdded, this, &DeviceKitAspectFactory::devicesChanged); + connect(dm, &DeviceManager::deviceRemoved, this, &DeviceKitAspectFactory::devicesChanged); + connect(dm, &DeviceManager::deviceUpdated, this, &DeviceKitAspectFactory::deviceUpdated); + + connect(KitManager::instance(), &KitManager::kitUpdated, + this, &DeviceKitAspectFactory::kitUpdated); + connect(KitManager::instance(), &KitManager::unmanagedKitUpdated, + this, &DeviceKitAspectFactory::kitUpdated); +} + +void DeviceKitAspectFactory::deviceUpdated(Id id) +{ + for (Kit *k : KitManager::kits()) { + if (DeviceKitAspect::deviceId(k) == id) + notifyAboutUpdate(k); + } +} + +void DeviceKitAspectFactory::kitUpdated(Kit *k) +{ + setup(k); // Set default device if necessary +} + +void DeviceKitAspectFactory::devicesChanged() +{ + for (Kit *k : KitManager::kits()) + setup(k); // Set default device if necessary +} + +const DeviceKitAspectFactory theDeviceKitAspectFactory; + +} // namespace Internal + + +Id DeviceKitAspect::id() +{ + return "PE.Profile.Device"; +} + +IDevice::ConstPtr DeviceKitAspect::device(const Kit *k) +{ + QTC_ASSERT(DeviceManager::instance()->isLoaded(), return IDevice::ConstPtr()); + return DeviceManager::instance()->find(deviceId(k)); +} + +Id DeviceKitAspect::deviceId(const Kit *k) +{ + return k ? Id::fromSetting(k->value(DeviceKitAspect::id())) : Id(); +} + +void DeviceKitAspect::setDevice(Kit *k, IDevice::ConstPtr dev) +{ + setDeviceId(k, dev ? dev->id() : Id()); +} + +void DeviceKitAspect::setDeviceId(Kit *k, Id id) +{ + QTC_ASSERT(k, return); + k->setValue(DeviceKitAspect::id(), id.toSetting()); +} + +FilePath DeviceKitAspect::deviceFilePath(const Kit *k, const QString &pathOnDevice) +{ + if (IDevice::ConstPtr dev = device(k)) + return dev->filePath(pathOnDevice); + return FilePath::fromString(pathOnDevice); +} + +// -------------------------------------------------------------------------- +// BuildDeviceKitAspect: +// -------------------------------------------------------------------------- +namespace Internal { +class BuildDeviceKitAspectImpl final : public KitAspect +{ +public: + BuildDeviceKitAspectImpl(Kit *workingCopy, const KitAspectFactory *factory) + : KitAspect(workingCopy, factory), + m_comboBox(createSubWidget()), + m_model(new DeviceManagerModel(DeviceManager::instance())) + { + setManagingPage(Constants::DEVICE_SETTINGS_PAGE_ID); + m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy()); + m_comboBox->setModel(m_model); + refresh(); + m_comboBox->setToolTip(factory->description()); + + connect(m_model, &QAbstractItemModel::modelAboutToBeReset, + this, &BuildDeviceKitAspectImpl::modelAboutToReset); + connect(m_model, &QAbstractItemModel::modelReset, + this, &BuildDeviceKitAspectImpl::modelReset); + connect(m_comboBox, &QComboBox::currentIndexChanged, + this, &BuildDeviceKitAspectImpl::currentDeviceChanged); + } + + ~BuildDeviceKitAspectImpl() override + { + delete m_comboBox; + delete m_model; + } + +private: + void addToInnerLayout(Layouting::Layout &builder) override + { + addMutableAction(m_comboBox); + builder.addItem(m_comboBox); + } + + void makeReadOnly() override { m_comboBox->setEnabled(false); } + + void refresh() override + { + QList blackList; + const DeviceManager *dm = DeviceManager::instance(); + for (int i = 0; i < dm->deviceCount(); ++i) { + IDevice::ConstPtr device = dm->deviceAt(i); + if (!device->usableAsBuildDevice()) + blackList.append(device->id()); + } + + m_model->setFilter(blackList); + m_comboBox->setCurrentIndex(m_model->indexOf(BuildDeviceKitAspect::device(kit()))); + } + + void modelAboutToReset() + { + m_selectedId = m_model->deviceId(m_comboBox->currentIndex()); + m_ignoreChanges.lock(); + } + + void modelReset() + { + m_comboBox->setCurrentIndex(m_model->indexForId(m_selectedId)); + m_ignoreChanges.unlock(); + } + + void currentDeviceChanged() + { + if (m_ignoreChanges.isLocked()) + return; + BuildDeviceKitAspect::setDeviceId(kit(), m_model->deviceId(m_comboBox->currentIndex())); + } + + Guard m_ignoreChanges; + QComboBox *m_comboBox; + DeviceManagerModel *m_model; + Id m_selectedId; +}; + +class BuildDeviceKitAspectFactory : public KitAspectFactory +{ +public: + BuildDeviceKitAspectFactory(); + +private: + void setup(Kit *k) override; + Tasks validate(const Kit *k) const override; + + KitAspect *createKitAspect(Kit *k) const override; + + QString displayNamePostfix(const Kit *k) const override; + + ItemList toUserOutput(const Kit *k) const override; + + void addToMacroExpander(Kit *kit, MacroExpander *expander) const override; + + void onKitsLoaded() override; + void deviceUpdated(Id dataId); + void devicesChanged(); + void kitUpdated(Kit *k); +}; + +BuildDeviceKitAspectFactory::BuildDeviceKitAspectFactory() +{ + setId(BuildDeviceKitAspect::id()); + setDisplayName(Tr::tr("Build device")); + setDescription(Tr::tr("The device used to build applications on.")); + setPriority(31900); +} + +static IDeviceConstPtr defaultDevice() +{ + return DeviceManager::defaultDesktopDevice(); +} + +void BuildDeviceKitAspectFactory::setup(Kit *k) +{ + QTC_ASSERT(DeviceManager::instance()->isLoaded(), return ); + IDevice::ConstPtr dev = BuildDeviceKitAspect::device(k); + if (dev) + return; + + dev = defaultDevice(); + BuildDeviceKitAspect::setDeviceId(k, dev ? dev->id() : Id()); +} + +Tasks BuildDeviceKitAspectFactory::validate(const Kit *k) const +{ + IDevice::ConstPtr dev = BuildDeviceKitAspect::device(k); + Tasks result; + if (!dev) + result.append(BuildSystemTask(Task::Warning, Tr::tr("No build device set."))); + + return result; +} + +KitAspect *BuildDeviceKitAspectFactory::createKitAspect(Kit *k) const +{ + QTC_ASSERT(k, return nullptr); + return new Internal::BuildDeviceKitAspectImpl(k, this); +} + +QString BuildDeviceKitAspectFactory::displayNamePostfix(const Kit *k) const +{ + IDevice::ConstPtr dev = BuildDeviceKitAspect::device(k); + return dev ? dev->displayName() : QString(); +} + +KitAspectFactory::ItemList BuildDeviceKitAspectFactory::toUserOutput(const Kit *k) const +{ + IDevice::ConstPtr dev = BuildDeviceKitAspect::device(k); + return {{Tr::tr("Build device"), dev ? dev->displayName() : Tr::tr("Unconfigured")}}; +} + +void BuildDeviceKitAspectFactory::addToMacroExpander(Kit *kit, MacroExpander *expander) const +{ + QTC_ASSERT(kit, return); + expander->registerVariable("BuildDevice:HostAddress", Tr::tr("Build host address"), [kit] { + const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit); + return device ? device->sshParameters().host() : QString(); + }); + expander->registerVariable("BuildDevice:SshPort", Tr::tr("Build SSH port"), [kit] { + const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit); + return device ? QString::number(device->sshParameters().port()) : QString(); + }); + expander->registerVariable("BuildDevice:UserName", Tr::tr("Build user name"), [kit] { + const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit); + return device ? device->sshParameters().userName() : QString(); + }); + expander->registerVariable("BuildDevice:KeyFile", Tr::tr("Build private key file"), [kit] { + const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit); + return device ? device->sshParameters().privateKeyFile.toString() : QString(); + }); + expander->registerVariable("BuildDevice:Name", Tr::tr("Build device name"), [kit] { + const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit); + return device ? device->displayName() : QString(); + }); + expander + ->registerFileVariables("BuildDevice::Root", Tr::tr("Build device root directory"), [kit] { + const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit); + return device ? device->rootPath() : FilePath{}; + }); +} + +void BuildDeviceKitAspectFactory::onKitsLoaded() +{ + for (Kit *k : KitManager::kits()) + fix(k); + + DeviceManager *dm = DeviceManager::instance(); + connect(dm, &DeviceManager::deviceListReplaced, + this, &BuildDeviceKitAspectFactory::devicesChanged); + connect(dm, &DeviceManager::deviceAdded, + this, &BuildDeviceKitAspectFactory::devicesChanged); + connect(dm, &DeviceManager::deviceRemoved, + this, &BuildDeviceKitAspectFactory::devicesChanged); + connect(dm, &DeviceManager::deviceUpdated, + this, &BuildDeviceKitAspectFactory::deviceUpdated); + connect(KitManager::instance(), &KitManager::kitUpdated, + this, &BuildDeviceKitAspectFactory::kitUpdated); + connect(KitManager::instance(), &KitManager::unmanagedKitUpdated, + this, &BuildDeviceKitAspectFactory::kitUpdated); +} + +void BuildDeviceKitAspectFactory::deviceUpdated(Id id) +{ + const QList kits = KitManager::kits(); + for (Kit *k : kits) { + if (BuildDeviceKitAspect::deviceId(k) == id) + notifyAboutUpdate(k); + } +} + +void BuildDeviceKitAspectFactory::kitUpdated(Kit *k) +{ + setup(k); // Set default device if necessary +} + +void BuildDeviceKitAspectFactory::devicesChanged() +{ + const QList kits = KitManager::kits(); + for (Kit *k : kits) + setup(k); // Set default device if necessary +} + +const BuildDeviceKitAspectFactory theBuildDeviceKitAspectFactory; + +} // namespace Internal + +Id BuildDeviceKitAspect::id() +{ + return "PE.Profile.BuildDevice"; +} + +IDevice::ConstPtr BuildDeviceKitAspect::device(const Kit *k) +{ + QTC_ASSERT(DeviceManager::instance()->isLoaded(), return IDevice::ConstPtr()); + IDevice::ConstPtr dev = DeviceManager::instance()->find(deviceId(k)); + if (!dev) + dev = Internal::defaultDevice(); + return dev; +} + +Id BuildDeviceKitAspect::deviceId(const Kit *k) +{ + return k ? Id::fromSetting(k->value(BuildDeviceKitAspect::id())) : Id(); +} + +void BuildDeviceKitAspect::setDevice(Kit *k, IDevice::ConstPtr dev) +{ + setDeviceId(k, dev ? dev->id() : Id()); +} + +void BuildDeviceKitAspect::setDeviceId(Kit *k, Id id) +{ + QTC_ASSERT(k, return); + k->setValue(BuildDeviceKitAspect::id(), id.toSetting()); +} + +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/devicesupport/devicekitaspects.h b/src/plugins/projectexplorer/devicesupport/devicekitaspects.h new file mode 100644 index 00000000000..1c3907d38a5 --- /dev/null +++ b/src/plugins/projectexplorer/devicesupport/devicekitaspects.h @@ -0,0 +1,45 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include "idevicefwd.h" +#include "../projectexplorer_export.h" + +#include + +namespace Utils { class FilePath; } + +namespace ProjectExplorer { +class Kit; + +class PROJECTEXPLORER_EXPORT DeviceTypeKitAspect +{ +public: + static const Utils::Id id(); + static const Utils::Id deviceTypeId(const Kit *k); + static void setDeviceTypeId(Kit *k, Utils::Id type); +}; + +class PROJECTEXPLORER_EXPORT DeviceKitAspect +{ +public: + static Utils::Id id(); + static IDeviceConstPtr device(const Kit *k); + static Utils::Id deviceId(const Kit *k); + static void setDevice(Kit *k, IDeviceConstPtr dev); + static void setDeviceId(Kit *k, Utils::Id dataId); + static Utils::FilePath deviceFilePath(const Kit *k, const QString &pathOnDevice); +}; + +class PROJECTEXPLORER_EXPORT BuildDeviceKitAspect +{ +public: + static Utils::Id id(); + static IDeviceConstPtr device(const Kit *k); + static Utils::Id deviceId(const Kit *k); + static void setDevice(Kit *k, IDeviceConstPtr dev); + static void setDeviceId(Kit *k, Utils::Id dataId); +}; + +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/kitaspects.cpp b/src/plugins/projectexplorer/kitaspects.cpp index 7f9c5e16ef5..89505f6c48a 100644 --- a/src/plugins/projectexplorer/kitaspects.cpp +++ b/src/plugins/projectexplorer/kitaspects.cpp @@ -3,18 +3,11 @@ #include "kitaspects.h" -#include "abi.h" -#include "devicesupport/devicemanager.h" -#include "devicesupport/devicemanagermodel.h" -#include "devicesupport/idevicefactory.h" -#include "devicesupport/sshparameters.h" -#include "projectexplorerconstants.h" #include "projectexplorertr.h" #include "kit.h" #include "kitaspect.h" #include "kitmanager.h" #include "toolchain.h" -#include "toolchainmanager.h" #include #include @@ -30,16 +23,9 @@ #include #include -#include -#include -#include -#include -#include #include #include -#include - using namespace Utils; namespace ProjectExplorer { @@ -88,7 +74,6 @@ private: PathChooser *m_chooser; Guard m_ignoreChanges; }; -} // namespace Internal class SysRootKitAspectFactory : public KitAspectFactory { @@ -106,7 +91,7 @@ SysRootKitAspectFactory::SysRootKitAspectFactory() setId(SysRootKitAspect::id()); setDisplayName(Tr::tr("Sysroot")); setDescription(Tr::tr("The root directory of the system image to use.
" - "Leave empty when building for the desktop.")); + "Leave empty when building for the desktop.")); setPriority(27000); } @@ -122,13 +107,13 @@ Tasks SysRootKitAspectFactory::validate(const Kit *k) const if (!dir.exists()) { result << BuildSystemTask(Task::Warning, - Tr::tr("Sys Root \"%1\" does not exist in the file system.").arg(dir.toUserOutput())); + Tr::tr("Sys Root \"%1\" does not exist in the file system.").arg(dir.toUserOutput())); } else if (!dir.isDir()) { result << BuildSystemTask(Task::Warning, - Tr::tr("Sys Root \"%1\" is not a directory.").arg(dir.toUserOutput())); + Tr::tr("Sys Root \"%1\" is not a directory.").arg(dir.toUserOutput())); } else if (dir.dirEntries(QDir::AllEntries | QDir::NoDotAndDotDot).isEmpty()) { result << BuildSystemTask(Task::Warning, - Tr::tr("Sys Root \"%1\" is empty.").arg(dir.toUserOutput())); + Tr::tr("Sys Root \"%1\" is empty.").arg(dir.toUserOutput())); } return result; } @@ -154,6 +139,10 @@ void SysRootKitAspectFactory::addToMacroExpander(Kit *kit, MacroExpander *expand }); } +const SysRootKitAspectFactory theSyRootKitAspectFactory; + +} // namespace Internal + Id SysRootKitAspect::id() { return "PE.Profile.SysRoot"; @@ -192,674 +181,6 @@ void SysRootKitAspect::setSysRoot(Kit *k, const FilePath &v) k->setValue(SysRootKitAspect::id(), v.toString()); } -const SysRootKitAspectFactory theSyRootKitAspectFactory; - -// -------------------------------------------------------------------------- -// DeviceTypeKitAspect: -// -------------------------------------------------------------------------- -namespace Internal { -class DeviceTypeKitAspectImpl final : public KitAspect -{ -public: - DeviceTypeKitAspectImpl(Kit *workingCopy, const KitAspectFactory *factory) - : KitAspect(workingCopy, factory) - { - using ItemData = std::tuple; - const auto model = new ListModel(this); - model->setDataAccessor([](const ItemData &d, int column, int role) -> QVariant { - if (column != 0) - return {}; - if (role == Qt::DisplayRole) - return std::get<0>(d); - if (role == KitAspect::IdRole) - return std::get<1>(d).toSetting(); - if (role == Qt::DecorationRole) - return std::get<2>(d); - return {}; - }); - auto getter = [](const Kit &k) { return DeviceTypeKitAspect::deviceTypeId(&k).toSetting(); }; - auto setter = [](Kit &k, const QVariant &type) { - DeviceTypeKitAspect::setDeviceTypeId(&k, Id::fromSetting(type)); - }; - auto resetModel = [model] { - model->clear(); - for (IDeviceFactory *factory : IDeviceFactory::allDeviceFactories()) { - model->appendItem( - std::make_tuple(factory->displayName(), factory->deviceType(), factory->icon())); - } - }; - setListAspectSpec( - {model, std::move(getter), std::move(setter), std::move(resetModel)}); - } -}; -} // namespace Internal - -class DeviceTypeKitAspectFactory : public KitAspectFactory -{ -public: - DeviceTypeKitAspectFactory(); - - void setup(Kit *k) override; - Tasks validate(const Kit *k) const override; - KitAspect *createKitAspect(Kit *k) const override; - ItemList toUserOutput(const Kit *k) const override; - - QSet supportedPlatforms(const Kit *k) const override; - QSet availableFeatures(const Kit *k) const override; -}; - -DeviceTypeKitAspectFactory::DeviceTypeKitAspectFactory() -{ - setId(DeviceTypeKitAspect::id()); - setDisplayName(Tr::tr("Run device type")); - setDescription(Tr::tr("The type of device to run applications on.")); - setPriority(33000); - makeEssential(); -} - -void DeviceTypeKitAspectFactory::setup(Kit *k) -{ - if (k && !k->hasValue(id())) - k->setValue(id(), QByteArray(Constants::DESKTOP_DEVICE_TYPE)); -} - -Tasks DeviceTypeKitAspectFactory::validate(const Kit *k) const -{ - Q_UNUSED(k) - return {}; -} - -KitAspect *DeviceTypeKitAspectFactory::createKitAspect(Kit *k) const -{ - QTC_ASSERT(k, return nullptr); - return new Internal::DeviceTypeKitAspectImpl(k, this); -} - -KitAspectFactory::ItemList DeviceTypeKitAspectFactory::toUserOutput(const Kit *k) const -{ - QTC_ASSERT(k, return {}); - Id type = DeviceTypeKitAspect::deviceTypeId(k); - QString typeDisplayName = Tr::tr("Unknown device type"); - if (type.isValid()) { - if (IDeviceFactory *factory = IDeviceFactory::find(type)) - typeDisplayName = factory->displayName(); - } - return {{Tr::tr("Device type"), typeDisplayName}}; -} - -const Id DeviceTypeKitAspect::id() -{ - return "PE.Profile.DeviceType"; -} - -const Id DeviceTypeKitAspect::deviceTypeId(const Kit *k) -{ - return k ? Id::fromSetting(k->value(DeviceTypeKitAspect::id())) : Id(); -} - -void DeviceTypeKitAspect::setDeviceTypeId(Kit *k, Id type) -{ - QTC_ASSERT(k, return); - k->setValue(DeviceTypeKitAspect::id(), type.toSetting()); -} - -QSet DeviceTypeKitAspectFactory::supportedPlatforms(const Kit *k) const -{ - return {DeviceTypeKitAspect::deviceTypeId(k)}; -} - -QSet DeviceTypeKitAspectFactory::availableFeatures(const Kit *k) const -{ - Id id = DeviceTypeKitAspect::deviceTypeId(k); - if (id.isValid()) - return {id.withPrefix("DeviceType.")}; - return {}; -} - -const DeviceTypeKitAspectFactory theDeviceTypeKitAspectFactory; - -// -------------------------------------------------------------------------- -// DeviceKitAspect: -// -------------------------------------------------------------------------- -namespace Internal { -class DeviceKitAspectImpl final : public KitAspect -{ -public: - DeviceKitAspectImpl(Kit *workingCopy, const KitAspectFactory *factory) - : KitAspect(workingCopy, factory), - m_comboBox(createSubWidget()), - m_model(new DeviceManagerModel(DeviceManager::instance())) - { - setManagingPage(Constants::DEVICE_SETTINGS_PAGE_ID); - m_comboBox->setSizePolicy(QSizePolicy::Preferred, - m_comboBox->sizePolicy().verticalPolicy()); - m_comboBox->setModel(m_model); - m_comboBox->setMinimumContentsLength(16); // Don't stretch too much for Kit Page - refresh(); - m_comboBox->setToolTip(factory->description()); - - connect(m_model, &QAbstractItemModel::modelAboutToBeReset, - this, &DeviceKitAspectImpl::modelAboutToReset); - connect(m_model, &QAbstractItemModel::modelReset, - this, &DeviceKitAspectImpl::modelReset); - connect(m_comboBox, &QComboBox::currentIndexChanged, - this, &DeviceKitAspectImpl::currentDeviceChanged); - } - - ~DeviceKitAspectImpl() override - { - delete m_comboBox; - delete m_model; - } - -private: - void addToInnerLayout(Layouting::Layout &builder) override - { - addMutableAction(m_comboBox); - builder.addItem(m_comboBox); - } - - void makeReadOnly() override { m_comboBox->setEnabled(false); } - - Id settingsPageItemToPreselect() const override { return DeviceKitAspect::deviceId(kit()); } - - void refresh() override - { - m_model->setTypeFilter(DeviceTypeKitAspect::deviceTypeId(kit())); - m_comboBox->setCurrentIndex(m_model->indexOf(DeviceKitAspect::device(kit()))); - } - - void modelAboutToReset() - { - m_selectedId = m_model->deviceId(m_comboBox->currentIndex()); - m_ignoreChanges.lock(); - } - - void modelReset() - { - m_comboBox->setCurrentIndex(m_model->indexForId(m_selectedId)); - m_ignoreChanges.unlock(); - } - - void currentDeviceChanged() - { - if (m_ignoreChanges.isLocked()) - return; - DeviceKitAspect::setDeviceId(kit(), m_model->deviceId(m_comboBox->currentIndex())); - } - - Guard m_ignoreChanges; - QComboBox *m_comboBox; - DeviceManagerModel *m_model; - Id m_selectedId; -}; -} // namespace Internal - -class DeviceKitAspectFactory : public KitAspectFactory -{ -public: - DeviceKitAspectFactory(); - -private: - Tasks validate(const Kit *k) const override; - void fix(Kit *k) override; - void setup(Kit *k) override; - - KitAspect *createKitAspect(Kit *k) const override; - - QString displayNamePostfix(const Kit *k) const override; - - ItemList toUserOutput(const Kit *k) const override; - - void addToMacroExpander(Kit *kit, MacroExpander *expander) const override; - - QVariant defaultValue(const Kit *k) const; - - void onKitsLoaded() override; - void deviceUpdated(Id dataId); - void devicesChanged(); - void kitUpdated(Kit *k); -}; - -DeviceKitAspectFactory::DeviceKitAspectFactory() -{ - setId(DeviceKitAspect::id()); - setDisplayName(Tr::tr("Run device")); - setDescription(Tr::tr("The device to run the applications on.")); - setPriority(32000); -} - -QVariant DeviceKitAspectFactory::defaultValue(const Kit *k) const -{ - Id type = DeviceTypeKitAspect::deviceTypeId(k); - // Use default device if that is compatible: - IDevice::ConstPtr dev = DeviceManager::instance()->defaultDevice(type); - if (dev && dev->isCompatibleWith(k)) - return dev->id().toString(); - // Use any other device that is compatible: - for (int i = 0; i < DeviceManager::instance()->deviceCount(); ++i) { - dev = DeviceManager::instance()->deviceAt(i); - if (dev && dev->isCompatibleWith(k)) - return dev->id().toString(); - } - // Fail: No device set up. - return {}; -} - -Tasks DeviceKitAspectFactory::validate(const Kit *k) const -{ - IDevice::ConstPtr dev = DeviceKitAspect::device(k); - Tasks result; - if (!dev) - result.append(BuildSystemTask(Task::Warning, Tr::tr("No device set."))); - else if (!dev->isCompatibleWith(k)) - result.append(BuildSystemTask(Task::Error, Tr::tr("Device is incompatible with this kit."))); - - if (dev) - result.append(dev->validate()); - - return result; -} - -void DeviceKitAspectFactory::fix(Kit *k) -{ - IDevice::ConstPtr dev = DeviceKitAspect::device(k); - if (dev && !dev->isCompatibleWith(k)) { - qWarning("Device is no longer compatible with kit \"%s\", removing it.", - qPrintable(k->displayName())); - DeviceKitAspect::setDeviceId(k, Id()); - } -} - -void DeviceKitAspectFactory::setup(Kit *k) -{ - QTC_ASSERT(DeviceManager::instance()->isLoaded(), return); - IDevice::ConstPtr dev = DeviceKitAspect::device(k); - if (dev && dev->isCompatibleWith(k)) - return; - - DeviceKitAspect::setDeviceId(k, Id::fromSetting(defaultValue(k))); -} - -KitAspect *DeviceKitAspectFactory::createKitAspect(Kit *k) const -{ - QTC_ASSERT(k, return nullptr); - return new Internal::DeviceKitAspectImpl(k, this); -} - -QString DeviceKitAspectFactory::displayNamePostfix(const Kit *k) const -{ - IDevice::ConstPtr dev = DeviceKitAspect::device(k); - return dev ? dev->displayName() : QString(); -} - -KitAspectFactory::ItemList DeviceKitAspectFactory::toUserOutput(const Kit *k) const -{ - IDevice::ConstPtr dev = DeviceKitAspect::device(k); - return {{Tr::tr("Device"), dev ? dev->displayName() : Tr::tr("Unconfigured") }}; -} - -void DeviceKitAspectFactory::addToMacroExpander(Kit *kit, MacroExpander *expander) const -{ - QTC_ASSERT(kit, return); - expander->registerVariable("Device:HostAddress", Tr::tr("Host address"), [kit] { - const IDevice::ConstPtr device = DeviceKitAspect::device(kit); - return device ? device->sshParameters().host() : QString(); - }); - expander->registerVariable("Device:SshPort", Tr::tr("SSH port"), [kit] { - const IDevice::ConstPtr device = DeviceKitAspect::device(kit); - return device ? QString::number(device->sshParameters().port()) : QString(); - }); - expander->registerVariable("Device:UserName", Tr::tr("User name"), [kit] { - const IDevice::ConstPtr device = DeviceKitAspect::device(kit); - return device ? device->sshParameters().userName() : QString(); - }); - expander->registerVariable("Device:KeyFile", Tr::tr("Private key file"), [kit] { - const IDevice::ConstPtr device = DeviceKitAspect::device(kit); - return device ? device->sshParameters().privateKeyFile.toString() : QString(); - }); - expander->registerVariable("Device:Name", Tr::tr("Device name"), [kit] { - const IDevice::ConstPtr device = DeviceKitAspect::device(kit); - return device ? device->displayName() : QString(); - }); - expander->registerFileVariables("Device::Root", Tr::tr("Device root directory"), [kit] { - const IDevice::ConstPtr device = DeviceKitAspect::device(kit); - return device ? device->rootPath() : FilePath{}; - }); -} - -Id DeviceKitAspect::id() -{ - return "PE.Profile.Device"; -} - -IDevice::ConstPtr DeviceKitAspect::device(const Kit *k) -{ - QTC_ASSERT(DeviceManager::instance()->isLoaded(), return IDevice::ConstPtr()); - return DeviceManager::instance()->find(deviceId(k)); -} - -Id DeviceKitAspect::deviceId(const Kit *k) -{ - return k ? Id::fromSetting(k->value(DeviceKitAspect::id())) : Id(); -} - -void DeviceKitAspect::setDevice(Kit *k, IDevice::ConstPtr dev) -{ - setDeviceId(k, dev ? dev->id() : Id()); -} - -void DeviceKitAspect::setDeviceId(Kit *k, Id id) -{ - QTC_ASSERT(k, return); - k->setValue(DeviceKitAspect::id(), id.toSetting()); -} - -FilePath DeviceKitAspect::deviceFilePath(const Kit *k, const QString &pathOnDevice) -{ - if (IDevice::ConstPtr dev = device(k)) - return dev->filePath(pathOnDevice); - return FilePath::fromString(pathOnDevice); -} - -void DeviceKitAspectFactory::onKitsLoaded() -{ - for (Kit *k : KitManager::kits()) - fix(k); - - DeviceManager *dm = DeviceManager::instance(); - connect(dm, &DeviceManager::deviceListReplaced, this, &DeviceKitAspectFactory::devicesChanged); - connect(dm, &DeviceManager::deviceAdded, this, &DeviceKitAspectFactory::devicesChanged); - connect(dm, &DeviceManager::deviceRemoved, this, &DeviceKitAspectFactory::devicesChanged); - connect(dm, &DeviceManager::deviceUpdated, this, &DeviceKitAspectFactory::deviceUpdated); - - connect(KitManager::instance(), &KitManager::kitUpdated, - this, &DeviceKitAspectFactory::kitUpdated); - connect(KitManager::instance(), &KitManager::unmanagedKitUpdated, - this, &DeviceKitAspectFactory::kitUpdated); -} - -void DeviceKitAspectFactory::deviceUpdated(Id id) -{ - for (Kit *k : KitManager::kits()) { - if (DeviceKitAspect::deviceId(k) == id) - notifyAboutUpdate(k); - } -} - -void DeviceKitAspectFactory::kitUpdated(Kit *k) -{ - setup(k); // Set default device if necessary -} - -void DeviceKitAspectFactory::devicesChanged() -{ - for (Kit *k : KitManager::kits()) - setup(k); // Set default device if necessary -} - -const DeviceKitAspectFactory theDeviceKitAspectFactory; - - -// -------------------------------------------------------------------------- -// BuildDeviceKitAspect: -// -------------------------------------------------------------------------- -namespace Internal { -class BuildDeviceKitAspectImpl final : public KitAspect -{ -public: - BuildDeviceKitAspectImpl(Kit *workingCopy, const KitAspectFactory *factory) - : KitAspect(workingCopy, factory), - m_comboBox(createSubWidget()), - m_model(new DeviceManagerModel(DeviceManager::instance())) - { - setManagingPage(Constants::DEVICE_SETTINGS_PAGE_ID); - m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy()); - m_comboBox->setModel(m_model); - refresh(); - m_comboBox->setToolTip(factory->description()); - - connect(m_model, &QAbstractItemModel::modelAboutToBeReset, - this, &BuildDeviceKitAspectImpl::modelAboutToReset); - connect(m_model, &QAbstractItemModel::modelReset, - this, &BuildDeviceKitAspectImpl::modelReset); - connect(m_comboBox, &QComboBox::currentIndexChanged, - this, &BuildDeviceKitAspectImpl::currentDeviceChanged); - } - - ~BuildDeviceKitAspectImpl() override - { - delete m_comboBox; - delete m_model; - } - -private: - void addToInnerLayout(Layouting::Layout &builder) override - { - addMutableAction(m_comboBox); - builder.addItem(m_comboBox); - } - - void makeReadOnly() override { m_comboBox->setEnabled(false); } - - void refresh() override - { - QList blackList; - const DeviceManager *dm = DeviceManager::instance(); - for (int i = 0; i < dm->deviceCount(); ++i) { - IDevice::ConstPtr device = dm->deviceAt(i); - if (!device->usableAsBuildDevice()) - blackList.append(device->id()); - } - - m_model->setFilter(blackList); - m_comboBox->setCurrentIndex(m_model->indexOf(BuildDeviceKitAspect::device(kit()))); - } - - void modelAboutToReset() - { - m_selectedId = m_model->deviceId(m_comboBox->currentIndex()); - m_ignoreChanges.lock(); - } - - void modelReset() - { - m_comboBox->setCurrentIndex(m_model->indexForId(m_selectedId)); - m_ignoreChanges.unlock(); - } - - void currentDeviceChanged() - { - if (m_ignoreChanges.isLocked()) - return; - BuildDeviceKitAspect::setDeviceId(kit(), m_model->deviceId(m_comboBox->currentIndex())); - } - - Guard m_ignoreChanges; - QComboBox *m_comboBox; - DeviceManagerModel *m_model; - Id m_selectedId; -}; -} // namespace Internal - -class BuildDeviceKitAspectFactory : public KitAspectFactory -{ -public: - BuildDeviceKitAspectFactory(); - -private: - void setup(Kit *k) override; - Tasks validate(const Kit *k) const override; - - KitAspect *createKitAspect(Kit *k) const override; - - QString displayNamePostfix(const Kit *k) const override; - - ItemList toUserOutput(const Kit *k) const override; - - void addToMacroExpander(Kit *kit, MacroExpander *expander) const override; - - void onKitsLoaded() override; - void deviceUpdated(Id dataId); - void devicesChanged(); - void kitUpdated(Kit *k); -}; - -BuildDeviceKitAspectFactory::BuildDeviceKitAspectFactory() -{ - setId(BuildDeviceKitAspect::id()); - setDisplayName(Tr::tr("Build device")); - setDescription(Tr::tr("The device used to build applications on.")); - setPriority(31900); -} - -static IDeviceConstPtr defaultDevice() -{ - return DeviceManager::defaultDesktopDevice(); -} - -void BuildDeviceKitAspectFactory::setup(Kit *k) -{ - QTC_ASSERT(DeviceManager::instance()->isLoaded(), return ); - IDevice::ConstPtr dev = BuildDeviceKitAspect::device(k); - if (dev) - return; - - dev = defaultDevice(); - BuildDeviceKitAspect::setDeviceId(k, dev ? dev->id() : Id()); -} - -Tasks BuildDeviceKitAspectFactory::validate(const Kit *k) const -{ - IDevice::ConstPtr dev = BuildDeviceKitAspect::device(k); - Tasks result; - if (!dev) - result.append(BuildSystemTask(Task::Warning, Tr::tr("No build device set."))); - - return result; -} - -KitAspect *BuildDeviceKitAspectFactory::createKitAspect(Kit *k) const -{ - QTC_ASSERT(k, return nullptr); - return new Internal::BuildDeviceKitAspectImpl(k, this); -} - -QString BuildDeviceKitAspectFactory::displayNamePostfix(const Kit *k) const -{ - IDevice::ConstPtr dev = BuildDeviceKitAspect::device(k); - return dev ? dev->displayName() : QString(); -} - -KitAspectFactory::ItemList BuildDeviceKitAspectFactory::toUserOutput(const Kit *k) const -{ - IDevice::ConstPtr dev = BuildDeviceKitAspect::device(k); - return {{Tr::tr("Build device"), dev ? dev->displayName() : Tr::tr("Unconfigured")}}; -} - -void BuildDeviceKitAspectFactory::addToMacroExpander(Kit *kit, MacroExpander *expander) const -{ - QTC_ASSERT(kit, return); - expander->registerVariable("BuildDevice:HostAddress", Tr::tr("Build host address"), [kit] { - const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit); - return device ? device->sshParameters().host() : QString(); - }); - expander->registerVariable("BuildDevice:SshPort", Tr::tr("Build SSH port"), [kit] { - const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit); - return device ? QString::number(device->sshParameters().port()) : QString(); - }); - expander->registerVariable("BuildDevice:UserName", Tr::tr("Build user name"), [kit] { - const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit); - return device ? device->sshParameters().userName() : QString(); - }); - expander->registerVariable("BuildDevice:KeyFile", Tr::tr("Build private key file"), [kit] { - const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit); - return device ? device->sshParameters().privateKeyFile.toString() : QString(); - }); - expander->registerVariable("BuildDevice:Name", Tr::tr("Build device name"), [kit] { - const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit); - return device ? device->displayName() : QString(); - }); - expander - ->registerFileVariables("BuildDevice::Root", Tr::tr("Build device root directory"), [kit] { - const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit); - return device ? device->rootPath() : FilePath{}; - }); -} - -Id BuildDeviceKitAspect::id() -{ - return "PE.Profile.BuildDevice"; -} - -IDevice::ConstPtr BuildDeviceKitAspect::device(const Kit *k) -{ - QTC_ASSERT(DeviceManager::instance()->isLoaded(), return IDevice::ConstPtr()); - IDevice::ConstPtr dev = DeviceManager::instance()->find(deviceId(k)); - if (!dev) - dev = defaultDevice(); - return dev; -} - -Id BuildDeviceKitAspect::deviceId(const Kit *k) -{ - return k ? Id::fromSetting(k->value(BuildDeviceKitAspect::id())) : Id(); -} - -void BuildDeviceKitAspect::setDevice(Kit *k, IDevice::ConstPtr dev) -{ - setDeviceId(k, dev ? dev->id() : Id()); -} - -void BuildDeviceKitAspect::setDeviceId(Kit *k, Id id) -{ - QTC_ASSERT(k, return); - k->setValue(BuildDeviceKitAspect::id(), id.toSetting()); -} - -void BuildDeviceKitAspectFactory::onKitsLoaded() -{ - for (Kit *k : KitManager::kits()) - fix(k); - - DeviceManager *dm = DeviceManager::instance(); - connect(dm, &DeviceManager::deviceListReplaced, - this, &BuildDeviceKitAspectFactory::devicesChanged); - connect(dm, &DeviceManager::deviceAdded, - this, &BuildDeviceKitAspectFactory::devicesChanged); - connect(dm, &DeviceManager::deviceRemoved, - this, &BuildDeviceKitAspectFactory::devicesChanged); - connect(dm, &DeviceManager::deviceUpdated, - this, &BuildDeviceKitAspectFactory::deviceUpdated); - connect(KitManager::instance(), &KitManager::kitUpdated, - this, &BuildDeviceKitAspectFactory::kitUpdated); - connect(KitManager::instance(), &KitManager::unmanagedKitUpdated, - this, &BuildDeviceKitAspectFactory::kitUpdated); -} - -void BuildDeviceKitAspectFactory::deviceUpdated(Id id) -{ - const QList kits = KitManager::kits(); - for (Kit *k : kits) { - if (BuildDeviceKitAspect::deviceId(k) == id) - notifyAboutUpdate(k); - } -} - -void BuildDeviceKitAspectFactory::kitUpdated(Kit *k) -{ - setup(k); // Set default device if necessary -} - -void BuildDeviceKitAspectFactory::devicesChanged() -{ - const QList kits = KitManager::kits(); - for (Kit *k : kits) - setup(k); // Set default device if necessary -} - -const BuildDeviceKitAspectFactory theBuildDeviceKitAspectFactory; - // -------------------------------------------------------------------------- // EnvironmentKitAspect: // -------------------------------------------------------------------------- diff --git a/src/plugins/projectexplorer/kitaspects.h b/src/plugins/projectexplorer/kitaspects.h index ba81caf1d0e..1c9b785a744 100644 --- a/src/plugins/projectexplorer/kitaspects.h +++ b/src/plugins/projectexplorer/kitaspects.h @@ -4,18 +4,16 @@ #pragma once #include "abi.h" -#include "devicesupport/idevicefwd.h" -#include "kit.h" +#include "devicesupport/devicekitaspects.h" #include "toolchainkitaspect.h" #include namespace ProjectExplorer { +class Kit; class Toolchain; class ToolchainBundle; -// SysRootKitAspect - class PROJECTEXPLORER_EXPORT SysRootKitAspect { public: @@ -24,44 +22,6 @@ public: static void setSysRoot(Kit *k, const Utils::FilePath &v); }; -// DeviceTypeKitAspect - -class PROJECTEXPLORER_EXPORT DeviceTypeKitAspect -{ -public: - static const Utils::Id id(); - static const Utils::Id deviceTypeId(const Kit *k); - static void setDeviceTypeId(Kit *k, Utils::Id type); -}; - -// DeviceKitAspect - -class PROJECTEXPLORER_EXPORT DeviceKitAspect -{ -public: - static Utils::Id id(); - static IDeviceConstPtr device(const Kit *k); - static Utils::Id deviceId(const Kit *k); - static void setDevice(Kit *k, IDeviceConstPtr dev); - static void setDeviceId(Kit *k, Utils::Id dataId); - static Utils::FilePath deviceFilePath(const Kit *k, const QString &pathOnDevice); -}; - - -// BuildDeviceKitAspect - -class PROJECTEXPLORER_EXPORT BuildDeviceKitAspect -{ -public: - static Utils::Id id(); - static IDeviceConstPtr device(const Kit *k); - static Utils::Id deviceId(const Kit *k); - static void setDevice(Kit *k, IDeviceConstPtr dev); - static void setDeviceId(Kit *k, Utils::Id dataId); -}; - -// EnvironmentKitAspect - class PROJECTEXPLORER_EXPORT EnvironmentKitAspect { public: diff --git a/src/plugins/projectexplorer/makestep.cpp b/src/plugins/projectexplorer/makestep.cpp index 2a985057754..36051201008 100644 --- a/src/plugins/projectexplorer/makestep.cpp +++ b/src/plugins/projectexplorer/makestep.cpp @@ -6,6 +6,7 @@ #include "buildconfiguration.h" #include "devicesupport/idevice.h" #include "gnumakeparser.h" +#include "kit.h" #include "kitaspects.h" #include "processparameters.h" #include "projectexplorer.h" diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs index c961be266ae..8281cd8ce3f 100644 --- a/src/plugins/projectexplorer/projectexplorer.qbs +++ b/src/plugins/projectexplorer/projectexplorer.qbs @@ -208,6 +208,7 @@ QtcPlugin { "desktopdevicefactory.cpp", "desktopdevicefactory.h", "devicecheckbuildstep.cpp", "devicecheckbuildstep.h", "devicefactoryselectiondialog.cpp", "devicefactoryselectiondialog.h", + "devicekitaspects.cpp", "devicekitaspects.h", "devicemanager.cpp", "devicemanager.h", "devicemanagermodel.cpp", "devicemanagermodel.h", "deviceprocessesdialog.cpp", "deviceprocessesdialog.h",