diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp index 0338d282e51..d3ec14e8a70 100644 --- a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp @@ -52,6 +52,18 @@ namespace ProjectExplorer { namespace Internal { +static IDevice::Ptr findAutoDetectedDevice(const QList &deviceList, + const QString &type, const QString &fingerprint) +{ + foreach (const IDevice::Ptr &device, deviceList) { + if (device->isAutoDetected() && device->type() == type + && device->fingerprint() == fingerprint) { + return device; + } + } + return IDevice::Ptr(); +} + const char DeviceManagerKey[] = "DeviceManager"; const char DeviceListKey[] = "DeviceList"; const char DefaultDevicesKey[] = "DefaultDevices"; @@ -62,6 +74,7 @@ public: static DeviceManager *instance; static DeviceManager *clonedInstance; QList devices; + QList inactiveAutoDetectedDevices; QHash defaultDevices; }; DeviceManager *DeviceManagerPrivate::instance = 0; @@ -192,7 +205,10 @@ void DeviceManager::fromMap(const QVariantMap &map) QTC_ASSERT(device, continue); if (device->internalId() == IDevice::invalidId()) device->setInternalId(unusedId()); - d->devices << device; + if (device->isAutoDetected()) + d->inactiveAutoDetectedDevices << device; + else + d->devices << device; } } @@ -207,10 +223,10 @@ QVariantMap DeviceManager::toMap() const } map.insert(QLatin1String(DefaultDevicesKey), defaultDeviceMap); QVariantList deviceList; - foreach (const IDevice::ConstPtr &device, d->devices) { - if (!device->isAutoDetected()) - deviceList << device->toMap(); - } + foreach (const IDevice::ConstPtr &device, d->devices) + deviceList << device->toMap(); + foreach (const IDevice::ConstPtr &device, d->inactiveAutoDetectedDevices) + deviceList << device->toMap(); map.insert(QLatin1String(DeviceListKey), deviceList); return map; } @@ -224,6 +240,8 @@ QString DeviceManager::settingsFilePath() void DeviceManager::addDevice(const IDevice::Ptr &device) { QTC_ASSERT(this != DeviceManagerPrivate::instance || (device->isAutoDetected()), return); + QTC_ASSERT(!device->isAutoDetected() || !findAutoDetectedDevice(d->devices, device->type(), + device->fingerprint()), return); // Ensure uniqueness of name. QString name = device->displayName(); @@ -241,13 +259,25 @@ void DeviceManager::addDevice(const IDevice::Ptr &device) d->devices << device; if (this == d->instance && d->clonedInstance) d->clonedInstance->addDevice(device->clone()); + if (this == d->instance) { + QList::Iterator it = d->inactiveAutoDetectedDevices.begin(); + while (it != d->inactiveAutoDetectedDevices.end()) { + if (it->data()->type() == device->type() + && it->data()->fingerprint() == device->fingerprint()) { + d->inactiveAutoDetectedDevices.erase(it); + break; + } + ++it; + } + } + emit deviceAdded(device); emit updated(); } void DeviceManager::removeDevice(int idx) { - const IDevice::ConstPtr device = deviceAt(idx); + const IDevice::Ptr device = mutableDeviceAt(idx); QTC_ASSERT(device, return); QTC_ASSERT(this != DeviceManagerPrivate::instance || device->isAutoDetected(), return); @@ -269,6 +299,8 @@ void DeviceManager::removeDevice(int idx) d->clonedInstance->removeDevice(d->clonedInstance-> indexForInternalId(device->internalId())); } + if (this == d->instance && device->isAutoDetected()) + d->inactiveAutoDetectedDevices << device; emit updated(); } @@ -357,6 +389,12 @@ IDevice::ConstPtr DeviceManager::find(IDevice::Id id) const return index == -1 ? IDevice::ConstPtr() : deviceAt(index); } +IDevice::ConstPtr DeviceManager::findInactiveAutoDetectedDevice(const QString &type, + const QString &fingerprint) +{ + return findAutoDetectedDevice(d->inactiveAutoDetectedDevices, type, fingerprint); +} + IDevice::ConstPtr DeviceManager::defaultDevice(const QString &deviceType) const { const IDevice::Id id = d->defaultDevices.value(deviceType, IDevice::invalidId()); diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.h b/src/plugins/projectexplorer/devicesupport/devicemanager.h index 81a4b2e723a..cdb4a567f04 100644 --- a/src/plugins/projectexplorer/devicesupport/devicemanager.h +++ b/src/plugins/projectexplorer/devicesupport/devicemanager.h @@ -40,6 +40,7 @@ namespace ProjectExplorer { class IDeviceFactory; + namespace Internal { class DeviceManagerPrivate; class DeviceSettingsWidget; @@ -58,6 +59,8 @@ public: int deviceCount() const; IDevice::ConstPtr deviceAt(int index) const; IDevice::ConstPtr find(IDevice::Id id) const; + IDevice::ConstPtr findInactiveAutoDetectedDevice(const QString &type, + const QString &fingerprint); IDevice::ConstPtr defaultDevice(const QString &deviceType) const; bool hasDevice(const QString &name) const; IDevice::Id internalId(const IDevice::ConstPtr &device) const; diff --git a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp index 37d709ebe1c..161ab40b235 100644 --- a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp @@ -183,8 +183,8 @@ void DeviceSettingsWidget::displayCurrent() m_ui->defaultDeviceButton->setEnabled( m_deviceManager->defaultDevice(current->type()) != current); m_ui->osTypeValueLabel->setText(DeviceManager::displayNameForDeviceType(current->type())); - m_ui->autoDetectionValueLabel->setText(current->isAutoDetected() ? tr("Yes") : tr("No")); - + m_ui->autoDetectionValueLabel->setText(current->isAutoDetected() + ? tr("Yes (fingerprint is '%1')").arg(current->fingerprint()) : tr("No")); m_nameValidator->setDisplayName(current->displayName()); m_ui->removeConfigButton->setEnabled(!current->isAutoDetected()); fillInValues(); diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp index 516e9182d88..14c2c0e2e11 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp @@ -31,6 +31,8 @@ **************************************************************************/ #include "idevice.h" +#include + #include /*! @@ -74,6 +76,15 @@ * \brief Identify the device internally. */ +/*! + * \fn QString ProjectExplorer::IDevice::fingerprint() const + * \brief Uniquely identifies an auto-detected device. + * The fingerprint can later be used to retrieve changes the user has done to the settings + * of an auto-detected device so they are not lost when the device goes away, e.g. because + * it has been disconnected. + * \sa ProjectExplorer::DeviceManager::findInactiveAutoDetectedDevice() + */ + /*! * \fn ProjectExplorer::IDevice::Id ProjectExplorer::IDevice::invalidId() * \brief A value that no device can ever have as its internal id. @@ -103,6 +114,8 @@ namespace ProjectExplorer { const char DisplayNameKey[] = "Name"; const char TypeKey[] = "OsType"; const char InternalIdKey[] = "InternalId"; +const char OriginKey[] = "Origin"; +const char FingerprintKey[] = "FingerPrint"; namespace Internal { class IDevicePrivate @@ -112,6 +125,7 @@ public: QString type; IDevice::Origin origin; IDevice::Id internalId; + QString fingerprint; }; } // namespace Internal @@ -119,10 +133,13 @@ IDevice::IDevice() : d(new Internal::IDevicePrivate) { } -IDevice::IDevice(const QString &type, Origin origin) : d(new Internal::IDevicePrivate) +IDevice::IDevice(const QString &type, Origin origin, const QString fingerprint) + : d(new Internal::IDevicePrivate) { d->type = type; d->origin = origin; + d->fingerprint = fingerprint; + QTC_CHECK(d->origin == ManuallyAdded || !d->fingerprint.isEmpty()); } IDevice::IDevice(const IDevice &other) : d(new Internal::IDevicePrivate) @@ -155,6 +172,11 @@ bool IDevice::isAutoDetected() const return d->origin == AutoDetected; } +QString IDevice::fingerprint() const +{ + return d->fingerprint; +} + IDevice::Id IDevice::internalId() const { return d->internalId; @@ -178,9 +200,11 @@ QString IDevice::typeFromMap(const QVariantMap &map) void IDevice::fromMap(const QVariantMap &map) { d->type = typeFromMap(map); - d->origin = ManuallyAdded; d->displayName = map.value(QLatin1String(DisplayNameKey)).toString(); d->internalId = map.value(QLatin1String(InternalIdKey), invalidId()).toULongLong(); + d->origin = static_cast(map.value(QLatin1String(OriginKey), ManuallyAdded).toInt()); + d->fingerprint = map.value(QLatin1String(FingerprintKey)).toString(); + QTC_CHECK(d->origin == ManuallyAdded || !d->fingerprint.isEmpty()); } QVariantMap IDevice::toMap() const @@ -189,6 +213,8 @@ QVariantMap IDevice::toMap() const map.insert(QLatin1String(DisplayNameKey), d->displayName); map.insert(QLatin1String(TypeKey), d->type); map.insert(QLatin1String(InternalIdKey), d->internalId); + map.insert(QLatin1String(OriginKey), d->origin); + map.insert(QLatin1String(FingerprintKey), d->fingerprint); return map; } diff --git a/src/plugins/projectexplorer/devicesupport/idevice.h b/src/plugins/projectexplorer/devicesupport/idevice.h index 1d917c0bcaa..047d7698d6a 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.h +++ b/src/plugins/projectexplorer/devicesupport/idevice.h @@ -59,6 +59,7 @@ public: QString type() const; bool isAutoDetected() const; + QString fingerprint() const; Id internalId() const; virtual void fromMap(const QVariantMap &map); @@ -70,7 +71,7 @@ public: protected: IDevice(); - IDevice(const QString &type, Origin origin); + IDevice(const QString &type, Origin origin, const QString fingerprint = QString()); IDevice(const IDevice &other); virtual QVariantMap toMap() const; diff --git a/src/plugins/remotelinux/linuxdeviceconfiguration.cpp b/src/plugins/remotelinux/linuxdeviceconfiguration.cpp index ad5f95fb99f..7ffc5e492f6 100644 --- a/src/plugins/remotelinux/linuxdeviceconfiguration.cpp +++ b/src/plugins/remotelinux/linuxdeviceconfiguration.cpp @@ -79,9 +79,9 @@ LinuxDeviceConfiguration::~LinuxDeviceConfiguration() } LinuxDeviceConfiguration::Ptr LinuxDeviceConfiguration::create(const QString &name, - const QString &type, MachineType machineType, Origin origin) + const QString &type, MachineType machineType, Origin origin, const QString &fingerprint) { - return Ptr(new LinuxDeviceConfiguration(name, type, machineType, origin)); + return Ptr(new LinuxDeviceConfiguration(name, type, machineType, origin, fingerprint)); } LinuxDeviceConfiguration::LinuxDeviceConfiguration() : d(new LinuxDeviceConfigurationPrivate) @@ -89,8 +89,8 @@ LinuxDeviceConfiguration::LinuxDeviceConfiguration() : d(new LinuxDeviceConfigur } LinuxDeviceConfiguration::LinuxDeviceConfiguration(const QString &name, const QString &type, - MachineType machineType, Origin origin) - : IDevice(type, origin), d(new LinuxDeviceConfigurationPrivate) + MachineType machineType, Origin origin, const QString &fingerprint) + : IDevice(type, origin, fingerprint), d(new LinuxDeviceConfigurationPrivate) { setDisplayName(name); d->machineType = machineType; diff --git a/src/plugins/remotelinux/linuxdeviceconfiguration.h b/src/plugins/remotelinux/linuxdeviceconfiguration.h index c5385a168c9..58c9d11e8d2 100644 --- a/src/plugins/remotelinux/linuxdeviceconfiguration.h +++ b/src/plugins/remotelinux/linuxdeviceconfiguration.h @@ -68,14 +68,14 @@ public: static Ptr create(); static Ptr create(const QString &name, const QString &type, MachineType machineType, - Origin origin = ManuallyAdded); + Origin origin = ManuallyAdded, const QString &fingerprint = QString()); void fromMap(const QVariantMap &map); ProjectExplorer::IDevice::Ptr clone() const; private: LinuxDeviceConfiguration(); LinuxDeviceConfiguration(const QString &name, const QString &type, MachineType machineType, - Origin origin); + Origin origin, const QString &fingerprint); LinuxDeviceConfiguration(const LinuxDeviceConfiguration &other); LinuxDeviceConfiguration &operator=(const LinuxDeviceConfiguration &);