ProjectExplorer: Create a thin DeviceRef wrapper class

... around a weak pointer to IDevice to pass around device identity.

The idea is to ramp down the direct use, especially storage, of
IDevice::{Const,}Ptr outside the DeviceManager and use DeviceRef
instead, in order to avoid the problem of device shared pointers
not dying when copies are held in dormant dialogs or similar.

The separate class effectively acts as a weak pointer with somewhat
nicer syntax.

Change-Id: If735ed8af9589137640b73b023d04c063ea876be
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
hjk
2024-12-03 10:10:43 +01:00
parent 5ec07b368b
commit 8fedcb6ba9
7 changed files with 113 additions and 26 deletions

View File

@@ -794,4 +794,57 @@ void DeviceProcessKillerTaskAdapter::start()
task()->start();
}
// DeviceConstRef
DeviceConstRef::DeviceConstRef(const IDevice::ConstPtr &device)
: m_constDevice(device)
{}
DeviceConstRef::DeviceConstRef(const IDevice::Ptr &device)
: m_constDevice(device)
{}
DeviceConstRef::~DeviceConstRef() = default;
Id DeviceConstRef::id() const
{
const IDevice::ConstPtr device = m_constDevice.lock();
QTC_ASSERT(device, return {});
return device->id();
}
QString DeviceConstRef::displayName() const
{
const IDevice::ConstPtr device = m_constDevice.lock();
QTC_ASSERT(device, return {});
return device->displayName();
}
SshParameters DeviceConstRef::sshParameters() const
{
const IDevice::ConstPtr device = m_constDevice.lock();
QTC_ASSERT(device, return {});
return device->sshParameters();
}
// DeviceRef, mutable
DeviceRef::DeviceRef(const IDevice::Ptr &device)
: DeviceConstRef(device), m_mutableDevice(device)
{}
void DeviceRef::setDisplayName(const QString &displayName)
{
const IDevice::Ptr device = m_mutableDevice.lock();
QTC_ASSERT(device, return);
device->setDisplayName(displayName);
}
void DeviceRef::setSshParameters(const SshParameters &params)
{
const IDevice::Ptr device = m_mutableDevice.lock();
QTC_ASSERT(device, return);
device->setSshParameters(params);
}
} // namespace ProjectExplorer

View File

@@ -245,6 +245,33 @@ private:
friend class DeviceManager;
};
class PROJECTEXPLORER_EXPORT DeviceConstRef
{
public:
DeviceConstRef(const IDevice::ConstPtr &device);
DeviceConstRef(const IDevice::Ptr &device);
virtual ~DeviceConstRef();
Utils::Id id() const;
QString displayName() const;
SshParameters sshParameters() const;
private:
std::weak_ptr<const IDevice> m_constDevice;
};
class PROJECTEXPLORER_EXPORT DeviceRef : public DeviceConstRef
{
public:
DeviceRef(const IDevice::Ptr &device);
void setDisplayName(const QString &displayName);
void setSshParameters(const SshParameters &params);
private:
std::weak_ptr<IDevice> m_mutableDevice;
};
class PROJECTEXPLORER_EXPORT DeviceTester : public QObject
{
Q_OBJECT

View File

@@ -7,6 +7,9 @@
namespace ProjectExplorer {
class DeviceRef;
class DeviceConstRef;
class IDevice;
using IDevicePtr = std::shared_ptr<IDevice>;

View File

@@ -28,19 +28,21 @@ public:
};
PublicKeyDeploymentDialog *PublicKeyDeploymentDialog::createDialog(
const IDevice::ConstPtr &deviceConfig, QWidget *parent)
const DeviceConstRef &device, QWidget *parent)
{
const FilePath dir = deviceConfig->sshParameters().privateKeyFile.parentDir();
const FilePath dir = device.sshParameters().privateKeyFile.parentDir();
const FilePath publicKeyFileName = FileUtils::getOpenFilePath(nullptr,
Tr::tr("Choose Public Key File"), dir,
Tr::tr("Public Key Files (*.pub);;All Files (*)"));
if (publicKeyFileName.isEmpty())
return nullptr;
return new PublicKeyDeploymentDialog(deviceConfig, publicKeyFileName, parent);
return new PublicKeyDeploymentDialog(device, publicKeyFileName, parent);
}
PublicKeyDeploymentDialog::PublicKeyDeploymentDialog(const IDevice::ConstPtr &deviceConfig,
const FilePath &publicKeyFileName, QWidget *parent)
PublicKeyDeploymentDialog::PublicKeyDeploymentDialog(
const DeviceConstRef &device,
const FilePath &publicKeyFileName,
QWidget *parent)
: QProgressDialog(parent), d(new PublicKeyDeploymentDialogPrivate)
{
setAutoReset(false);
@@ -76,7 +78,7 @@ PublicKeyDeploymentDialog::PublicKeyDeploymentDialog(const IDevice::ConstPtr &de
+ QString::fromLocal8Bit(reader.data())
+ "' >> .ssh/authorized_keys && chmod 0600 .ssh/authorized_keys";
const SshParameters params = deviceConfig->sshParameters();
const SshParameters params = device.sshParameters();
const QString hostKeyCheckingString = params.hostKeyCheckingMode == SshHostKeyCheckingStrict
? QLatin1String("yes") : QLatin1String("no");
const bool isWindows = HostOsInfo::isWindowsHost()

View File

@@ -18,11 +18,12 @@ class PublicKeyDeploymentDialog : public QProgressDialog
Q_OBJECT
public:
// Asks for public key and returns null if the file dialog is canceled.
static PublicKeyDeploymentDialog *createDialog(
const ProjectExplorer::IDeviceConstPtr &deviceConfig, QWidget *parent = nullptr);
static PublicKeyDeploymentDialog *createDialog(const ProjectExplorer::DeviceConstRef &device,
QWidget *parent = nullptr);
PublicKeyDeploymentDialog(const ProjectExplorer::IDeviceConstPtr &deviceConfig,
const Utils::FilePath &publicKeyFileName, QWidget *parent = nullptr);
PublicKeyDeploymentDialog(const ProjectExplorer::DeviceConstRef &device,
const Utils::FilePath &publicKeyFileName,
QWidget *parent = nullptr);
~PublicKeyDeploymentDialog() override;

View File

@@ -31,7 +31,7 @@ namespace RemoteLinux {
class SetupPage : public QWizardPage
{
public:
explicit SetupPage(const ProjectExplorer::IDevicePtr &device)
explicit SetupPage(const DeviceRef &device)
: m_device(device)
{
setTitle(Tr::tr("Connection"));
@@ -65,11 +65,11 @@ public:
private:
void initializePage() final {
m_nameLineEdit->setText(m_device->displayName());
m_hostNameLineEdit->setText(m_device->sshParameters().host());
m_nameLineEdit->setText(m_device.displayName());
m_hostNameLineEdit->setText(m_device.sshParameters().host());
m_sshPortSpinBox->setValue(22);
m_sshPortSpinBox->setRange(1, 65535);
m_userNameLineEdit->setText(m_device->sshParameters().userName());
m_userNameLineEdit->setText(m_device.sshParameters().userName());
}
bool isComplete() const final {
return !m_nameLineEdit->text().trimmed().isEmpty()
@@ -77,12 +77,12 @@ private:
&& !m_userNameLineEdit->text().trimmed().isEmpty();
}
bool validatePage() final {
m_device->setDisplayName(m_nameLineEdit->text().trimmed());
SshParameters sshParams = m_device->sshParameters();
m_device.setDisplayName(m_nameLineEdit->text().trimmed());
SshParameters sshParams = m_device.sshParameters();
sshParams.setHost(m_hostNameLineEdit->text().trimmed());
sshParams.setUserName(m_userNameLineEdit->text().trimmed());
sshParams.setPort(m_sshPortSpinBox->value());
m_device->setSshParameters(sshParams);
m_device.setSshParameters(sshParams);
return true;
}
@@ -90,13 +90,13 @@ private:
FancyLineEdit *m_hostNameLineEdit;
QSpinBox *m_sshPortSpinBox;
FancyLineEdit *m_userNameLineEdit;
IDevicePtr m_device;
DeviceRef m_device;
};
class KeyDeploymentPage : public QWizardPage
{
public:
explicit KeyDeploymentPage(const ProjectExplorer::IDevicePtr &device)
explicit KeyDeploymentPage(const DeviceRef &device)
: m_device(device)
{
setTitle(Tr::tr("Key Deployment"));
@@ -150,7 +150,7 @@ public:
private:
void initializePage() final {
if (!m_device->sshParameters().privateKeyFile.isEmpty())
if (!m_device.sshParameters().privateKeyFile.isEmpty())
m_keyFileChooser.setFilePath(m_keyFileChooser.filePath());
m_iconLabel.clear();
}
@@ -160,10 +160,10 @@ private:
}
bool validatePage() final {
if (!defaultKeys().contains(m_keyFileChooser.filePath())) {
SshParameters sshParams = m_device->sshParameters();
SshParameters sshParams = m_device.sshParameters();
sshParams.authenticationType = SshParameters::AuthenticationTypeSpecificKey;
sshParams.privateKeyFile = m_keyFileChooser.filePath();
m_device->setSshParameters(sshParams);
m_device.setSshParameters(sshParams);
}
return true;
}
@@ -174,7 +174,7 @@ private:
PathChooser m_keyFileChooser;
QLabel m_iconLabel;
IDevicePtr m_device;
DeviceRef m_device;
};
class FinalPage final : public QWizardPage
@@ -193,7 +193,7 @@ public:
}
};
SshDeviceWizard::SshDeviceWizard(const QString &title, const ProjectExplorer::IDevicePtr &device)
SshDeviceWizard::SshDeviceWizard(const QString &title, const DeviceRef &device)
: Wizard(Core::ICore::dialogParent())
{
setWindowTitle(title);

View File

@@ -5,15 +5,16 @@
#include "remotelinux_export.h"
#include <projectexplorer/devicesupport/idevicefwd.h>
#include <utils/wizard.h>
namespace ProjectExplorer { class DeviceRef; }
namespace RemoteLinux {
class REMOTELINUX_EXPORT SshDeviceWizard : public Utils::Wizard
{
public:
SshDeviceWizard(const QString &title, const ProjectExplorer::IDevicePtr &device);
SshDeviceWizard(const QString &title, const ProjectExplorer::DeviceRef &device);
};
} // namespace RemoteLinux