Commit c0e50601 authored by Christian Kandeler's avatar Christian Kandeler

DeviceManager: Remember auto-detected devices.

The current implementation "forgets" auto-detected devices when
they've been disconnected or Creator has been closed.
This has the drawback that potential changes by users to the connection
parameters cannot become persistent. This is overcome by introducing a
device fingerprint and keeping removed auto-connected devices in a
special list from which they can later be retrieved, typically when the
device gets connected again.

Change-Id: I98cfd25c677e6a2a46891a0facf3a28f0a0c3465
Reviewed-by: default avatarNikolai Kosjar <nikolai.kosjar@nokia.com>
parent 7049c72f
......@@ -52,6 +52,18 @@
namespace ProjectExplorer {
namespace Internal {
static IDevice::Ptr findAutoDetectedDevice(const QList<IDevice::Ptr> &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<IDevice::Ptr> devices;
QList<IDevice::Ptr> inactiveAutoDetectedDevices;
QHash<QString, IDevice::Id> 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<IDevice::Ptr>::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());
......
......@@ -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;
......
......@@ -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();
......
......@@ -31,6 +31,8 @@
**************************************************************************/
#include "idevice.h"
#include <utils/qtcassert.h>
#include <QString>
/*!
......@@ -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<Origin>(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;
}
......
......@@ -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;
......
......@@ -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;
......
......@@ -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 &);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment