From 2a7bf0fdaf2abf92936bc6e9a472dfc67395ec9a Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 1 Aug 2024 12:30:23 +0200 Subject: [PATCH] Project: Base IDevice on AspectContainer This is effectively the same approach as taken with ProjectConfiguration. Having the settings separate leads to quite some boilerplate and in the end to parallel IDevice and DeviceSettings hierarchies. The unusual registration of the docker aspects are due to the multiple inheritance, we need to "dynamic" downcast. Change-Id: I50864e2009f4e525d635decf1c9beaad5e6a5f1f Reviewed-by: Christian Kandeler --- src/plugins/android/androiddevice.cpp | 8 +- .../baremetaldeviceconfigurationwizard.cpp | 2 +- .../device-detection/devicedetector.cpp | 2 +- src/plugins/boot2qt/qdbdevice.cpp | 2 +- src/plugins/docker/dockerdevice.cpp | 323 ++++++++---------- src/plugins/docker/dockerdevice.h | 48 +-- src/plugins/docker/dockerdevicewidget.cpp | 36 +- src/plugins/ios/iosdevice.cpp | 6 +- src/plugins/ios/iossimulator.cpp | 2 +- src/plugins/mcusupport/mcusupportdevice.cpp | 2 +- .../devicesupport/desktopdevice.cpp | 2 +- .../devicesupport/devicemanager.cpp | 7 +- .../devicesupport/devicesettingspage.cpp | 4 +- .../projectexplorer/devicesupport/idevice.cpp | 42 +-- .../projectexplorer/devicesupport/idevice.h | 19 +- .../devicesupport/idevicefactory.cpp | 2 +- src/plugins/projectexplorer/kitaspects.cpp | 2 +- src/plugins/qnx/qnxdevice.cpp | 2 +- src/plugins/remotelinux/linuxdevice.cpp | 10 +- src/plugins/remotelinux/sshdevicewizard.cpp | 2 +- src/plugins/webassembly/webassemblydevice.cpp | 2 +- 21 files changed, 229 insertions(+), 296 deletions(-) diff --git a/src/plugins/android/androiddevice.cpp b/src/plugins/android/androiddevice.cpp index ddcb5a09e6d..23acd90bc84 100644 --- a/src/plugins/android/androiddevice.cpp +++ b/src/plugins/android/androiddevice.cpp @@ -177,7 +177,7 @@ static IDevice::Ptr createDeviceFromInfo(const CreateAvdInfo &info) const Id deviceId = AndroidDevice::idFromAvdInfo(info); dev->setupId(IDevice::AutoDetected, deviceId); dev->setMachineType(IDevice::Emulator); - dev->settings()->displayName.setValue(info.name); + dev->displayName.setValue(info.name); dev->setDeviceState(IDevice::DeviceConnected); dev->setAvdPath(avdFilePath() / (info.name + ".avd")); dev->setExtraData(Constants::AndroidAvdName, info.name); @@ -349,7 +349,7 @@ AndroidDevice::AndroidDevice() { setupId(IDevice::AutoDetected, Constants::ANDROID_DEVICE_ID); setType(Constants::ANDROID_DEVICE_TYPE); - settings()->displayName.setDefaultValue(Tr::tr("Run on Android")); + displayName.setDefaultValue(Tr::tr("Run on Android")); setDisplayType(Tr::tr("Android")); setMachineType(IDevice::Hardware); setOsType(OsType::OsTypeOtherUnix); @@ -672,7 +672,7 @@ static void handleDevicesListChange(const QString &serialNumber) } else { AndroidDevice *newDev = new AndroidDevice(); newDev->setupId(IDevice::AutoDetected, id); - newDev->settings()->displayName.setValue(displayName); + newDev->displayName.setValue(displayName); newDev->setMachineType(IDevice::Hardware); newDev->setDeviceState(state); @@ -758,7 +758,7 @@ static void handleAvdListChange(const AndroidDeviceInfoList &avdList) AndroidDevice *newDev = new AndroidDevice; newDev->setupId(IDevice::AutoDetected, deviceId); - newDev->settings()->displayName.setValue(displayName); + newDev->displayName.setValue(displayName); newDev->setMachineType(item.type); newDev->setDeviceState(item.state); diff --git a/src/plugins/baremetal/baremetaldeviceconfigurationwizard.cpp b/src/plugins/baremetal/baremetaldeviceconfigurationwizard.cpp index 20b27d77e60..b716bb37de4 100644 --- a/src/plugins/baremetal/baremetaldeviceconfigurationwizard.cpp +++ b/src/plugins/baremetal/baremetaldeviceconfigurationwizard.cpp @@ -26,7 +26,7 @@ ProjectExplorer::IDevice::Ptr BareMetalDeviceConfigurationWizard::device() const { const auto dev = BareMetalDevice::create(); dev->setupId(ProjectExplorer::IDevice::ManuallyAdded, Utils::Id()); - dev->settings()->displayName.setDefaultValue(m_setupPage->configurationName()); + dev->displayName.setDefaultValue(m_setupPage->configurationName()); dev->setType(Constants::BareMetalOsType); dev->setMachineType(ProjectExplorer::IDevice::Hardware); dev->setDebugServerProviderId(m_setupPage->debugServerProviderId()); diff --git a/src/plugins/boot2qt/device-detection/devicedetector.cpp b/src/plugins/boot2qt/device-detection/devicedetector.cpp index 60e71def4ad..03402904bd8 100644 --- a/src/plugins/boot2qt/device-detection/devicedetector.cpp +++ b/src/plugins/boot2qt/device-detection/devicedetector.cpp @@ -84,7 +84,7 @@ void DeviceDetector::handleDeviceEvent(QdbDeviceTracker::DeviceEventType eventTy const QString name = Tr::tr("Boot to Qt device %1").arg(serial); QdbDevice::Ptr device = QdbDevice::create(); device->setupId(IDevice::AutoDetected, deviceId); - device->settings()->displayName.setValue(name); + device->displayName.setValue(name); device->setType(Qdb::Constants::QdbLinuxOsType); device->setMachineType(IDevice::Hardware); device->setExtraData(ProjectExplorer::Constants::SUPPORTS_RSYNC, true); diff --git a/src/plugins/boot2qt/qdbdevice.cpp b/src/plugins/boot2qt/qdbdevice.cpp index cdae7227f78..b40b7ca98f1 100644 --- a/src/plugins/boot2qt/qdbdevice.cpp +++ b/src/plugins/boot2qt/qdbdevice.cpp @@ -207,7 +207,7 @@ public: { QdbDevice::Ptr device = QdbDevice::create(); - device->settings()->displayName.setValue(settingsPage.deviceName()); + device->displayName.setValue(settingsPage.deviceName()); device->setupId(ProjectExplorer::IDevice::ManuallyAdded, Utils::Id()); device->setType(Constants::QdbLinuxOsType); device->setMachineType(ProjectExplorer::IDevice::Hardware); diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index 8f873b8a5c9..f3039170f42 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -142,128 +142,8 @@ public: } }; -void DockerDeviceSettings::fromMap(const Store &map) -{ - DeviceSettings::fromMap(map); - - // This is the only place where we can correctly set the default name. - // Only here do we know the image id and the repo reliably, no matter - // where or how we were created. - if (displayName.value() == displayName.defaultValue()) { - displayName.setDefaultValue( - Tr::tr("Docker Image \"%1\" (%2)").arg(repoAndTag()).arg(imageId.value())); - } -} - -DockerDeviceSettings::DockerDeviceSettings() -{ - imageId.setSettingsKey(DockerDeviceDataImageIdKey); - imageId.setLabelText(Tr::tr("Image ID:")); - imageId.setReadOnly(true); - - repo.setSettingsKey(DockerDeviceDataRepoKey); - repo.setLabelText(Tr::tr("Repository:")); - repo.setReadOnly(true); - - tag.setSettingsKey(DockerDeviceDataTagKey); - tag.setLabelText(Tr::tr("Tag:")); - tag.setReadOnly(true); - - useLocalUidGid.setSettingsKey(DockerDeviceUseOutsideUser); - useLocalUidGid.setLabelText(Tr::tr("Run as outside user:")); - useLocalUidGid.setDefaultValue(true); - useLocalUidGid.setLabelPlacement(BoolAspect::LabelPlacement::InExtraLabel); - - keepEntryPoint.setSettingsKey(DockerDeviceKeepEntryPoint); - keepEntryPoint.setLabelText(Tr::tr("Do not modify entry point:")); - keepEntryPoint.setDefaultValue(false); - keepEntryPoint.setLabelPlacement(BoolAspect::LabelPlacement::InExtraLabel); - - enableLldbFlags.setSettingsKey(DockerDeviceEnableLldbFlags); - enableLldbFlags.setLabelText(Tr::tr("Enable flags needed for LLDB:")); - enableLldbFlags.setDefaultValue(false); - enableLldbFlags.setLabelPlacement(BoolAspect::LabelPlacement::InExtraLabel); - - mounts.setSettingsKey(DockerDeviceMappedPaths); - mounts.setLabelText(Tr::tr("Paths to mount:")); - mounts.setDefaultValue({Core::DocumentManager::projectsDirectory().toString()}); - mounts.setToolTip(Tr::tr("Maps paths in this list one-to-one to the docker container.")); - mounts.setPlaceHolderText(Tr::tr("Host directories to mount into the container.")); - - extraArgs.setSettingsKey(DockerDeviceExtraArgs); - extraArgs.setLabelText(Tr::tr("Extra arguments:")); - extraArgs.setToolTip(Tr::tr("Extra arguments to pass to docker create.")); - extraArgs.setDisplayStyle(StringAspect::LineEditDisplay); - - clangdExecutable.setSettingsKey(DockerDeviceClangDExecutable); - clangdExecutable.setLabelText(Tr::tr("Clangd Executable:")); - clangdExecutable.setAllowPathFromDevice(true); - - network.setSettingsKey("Network"); - network.setLabelText(Tr::tr("Network:")); - network.setDefaultValue("bridge"); - network.setFillCallback([this](const StringSelectionAspect::ResultCallback &cb) { - auto future = DockerApi::instance()->networks(); - - auto watcher = new QFutureWatcher>>(this); - watcher->setFuture(future); - QObject::connect(watcher, - &QFutureWatcher>>::finished, - this, - [watcher, cb]() { - expected_str> result = watcher->result(); - if (result) { - auto items = transform(*result, [](const Network &network) { - QStandardItem *item = new QStandardItem(network.name); - item->setData(network.name); - item->setToolTip(network.toString()); - return item; - }); - cb(items); - } else { - QStandardItem *errorItem = new QStandardItem(Tr::tr("Error")); - errorItem->setToolTip(result.error()); - cb({errorItem}); - } - }); - }); - - connect(DockerApi::instance(), - &DockerApi::dockerDaemonAvailableChanged, - &network, - &StringSelectionAspect::refill); - - clangdExecutable.setValidationFunction( - [this](const QString &newValue) -> FancyLineEdit::AsyncValidationFuture { - const FilePath rootPath = FilePath::fromParts(Constants::DOCKER_DEVICE_SCHEME, - repoAndTagEncoded(), - u"/"); - return asyncRun([rootPath, newValue]() -> expected_str { - QString changedValue = newValue; - FilePath path = FilePath::fromUserInput(newValue); - if (!path.needsDevice()) { - const FilePath onDevicePath = rootPath.withNewMappedPath(path); - if (onDevicePath.exists()) { - changedValue = onDevicePath.toUserOutput(); - path = onDevicePath; - } else { - return make_unexpected( - Tr::tr("The path \"%1\" does not exist.").arg(onDevicePath.toUserOutput())); - } - } - QString error; - bool result = checkClangdVersion(path, &error); - if (!result) - return make_unexpected(error); - return changedValue; - }); - }); - - containerStatus.setText(Tr::tr("stopped")); -} - // Used for "docker run" -QString DockerDeviceSettings::repoAndTag() const +QString DockerDevice::repoAndTag() const { if (repo() == "") return imageId(); @@ -274,12 +154,12 @@ QString DockerDeviceSettings::repoAndTag() const return repo() + ':' + tag(); } -QString DockerDeviceSettings::repoAndTagEncoded() const +QString DockerDevice::repoAndTagEncoded() const { return repoAndTag().replace(':', '.'); } -FilePath DockerDeviceSettings::rootPath() const +FilePath DockerDevice::rootPath() const { return FilePath::fromParts(Constants::DOCKER_DEVICE_SCHEME, repoAndTagEncoded(), u"/"); } @@ -289,9 +169,8 @@ class DockerDevicePrivate : public QObject public: DockerDevicePrivate(DockerDevice *parent) : q(parent) - , deviceSettings(static_cast(q->settings())) { - QObject::connect(deviceSettings, &DockerDeviceSettings::applied, this, [this] { + QObject::connect(q, &DockerDevice::applied, this, [this] { if (!m_container.isEmpty()) { stopCurrentContainer(); } @@ -310,10 +189,6 @@ public: QString containerId() { return m_container; } - QString repoAndTag() const { return deviceSettings->repoAndTag(); } - QString repoAndTagEncoded() const { return deviceSettings->repoAndTagEncoded(); } - QString dockerImageId() const { return deviceSettings->imageId(); } - expected_str> osTypeAndArch() const; expected_str environment(); @@ -337,11 +212,11 @@ public: std::optional clangdExecutable() const { - if (deviceSettings->clangdExecutable().isEmpty()) + if (q->clangdExecutableAspect().isEmpty()) return std::nullopt; - if (!deviceSettings->clangdExecutable().needsDevice()) - return deviceSettings->rootPath().withNewMappedPath(deviceSettings->clangdExecutable()); - return deviceSettings->clangdExecutable(); + if (!q->clangdExecutableAspect().needsDevice()) + return q->rootPath().withNewMappedPath(q->clangdExecutableAspect()); + return q->clangdExecutableAspect(); } QStringList createMountArgs() const; @@ -349,7 +224,6 @@ public: bool isImageAvailable() const; DockerDevice *const q; - DockerDeviceSettings *deviceSettings; struct MountPair { @@ -569,7 +443,7 @@ Tasks DockerDevicePrivate::validateMounts() const { Tasks result; - for (const FilePath &mount : deviceSettings->mounts()) { + for (const FilePath &mount : q->mounts()) { if (!mount.isDir()) { const QString message = Tr::tr("Path \"%1\" is not a directory or does not exist.") .arg(mount.toUserOutput()); @@ -593,10 +467,114 @@ QString DockerDeviceFileAccess::mapToDevicePath(const QString &hostPath) const return newPath; } -DockerDevice::DockerDevice(std::unique_ptr deviceSettings) - : ProjectExplorer::IDevice(std::move(deviceSettings)) - , d(new DockerDevicePrivate(this)) +DockerDevice::DockerDevice() + : d(new DockerDevicePrivate(this)) { + imageId.setSettingsKey(DockerDeviceDataImageIdKey); + imageId.setLabelText(Tr::tr("Image ID:")); + imageId.setReadOnly(true); + + repo.setSettingsKey(DockerDeviceDataRepoKey); + repo.setLabelText(Tr::tr("Repository:")); + repo.setReadOnly(true); + + tag.setSettingsKey(DockerDeviceDataTagKey); + tag.setLabelText(Tr::tr("Tag:")); + tag.setReadOnly(true); + + useLocalUidGid.setSettingsKey(DockerDeviceUseOutsideUser); + useLocalUidGid.setLabelText(Tr::tr("Run as outside user:")); + useLocalUidGid.setDefaultValue(true); + useLocalUidGid.setLabelPlacement(BoolAspect::LabelPlacement::InExtraLabel); + + keepEntryPoint.setSettingsKey(DockerDeviceKeepEntryPoint); + keepEntryPoint.setLabelText(Tr::tr("Do not modify entry point:")); + keepEntryPoint.setDefaultValue(false); + keepEntryPoint.setLabelPlacement(BoolAspect::LabelPlacement::InExtraLabel); + + enableLldbFlags.setSettingsKey(DockerDeviceEnableLldbFlags); + enableLldbFlags.setLabelText(Tr::tr("Enable flags needed for LLDB:")); + enableLldbFlags.setDefaultValue(false); + enableLldbFlags.setLabelPlacement(BoolAspect::LabelPlacement::InExtraLabel); + + mounts.setSettingsKey(DockerDeviceMappedPaths); + mounts.setLabelText(Tr::tr("Paths to mount:")); + mounts.setDefaultValue({Core::DocumentManager::projectsDirectory().toString()}); + mounts.setToolTip(Tr::tr("Maps paths in this list one-to-one to the docker container.")); + mounts.setPlaceHolderText(Tr::tr("Host directories to mount into the container.")); + + extraArgs.setSettingsKey(DockerDeviceExtraArgs); + extraArgs.setLabelText(Tr::tr("Extra arguments:")); + extraArgs.setToolTip(Tr::tr("Extra arguments to pass to docker create.")); + extraArgs.setDisplayStyle(StringAspect::LineEditDisplay); + + clangdExecutableAspect.setSettingsKey(DockerDeviceClangDExecutable); + clangdExecutableAspect.setLabelText(Tr::tr("Clangd Executable:")); + clangdExecutableAspect.setAllowPathFromDevice(true); + + network.setSettingsKey("Network"); + network.setLabelText(Tr::tr("Network:")); + network.setDefaultValue("bridge"); + network.setFillCallback([this](const StringSelectionAspect::ResultCallback &cb) { + auto future = DockerApi::instance()->networks(); + + auto watcher = new QFutureWatcher>>(this); + watcher->setFuture(future); + QObject::connect(watcher, + &QFutureWatcher>>::finished, + this, + [watcher, cb]() { + expected_str> result = watcher->result(); + if (result) { + auto items = transform(*result, [](const Network &network) { + QStandardItem *item = new QStandardItem(network.name); + item->setData(network.name); + item->setToolTip(network.toString()); + return item; + }); + cb(items); + } else { + QStandardItem *errorItem = new QStandardItem(Tr::tr("Error")); + errorItem->setToolTip(result.error()); + cb({errorItem}); + } + }); + }); + + connect(DockerApi::instance(), + &DockerApi::dockerDaemonAvailableChanged, + &network, + &StringSelectionAspect::refill); + + clangdExecutableAspect.setValidationFunction( + [this](const QString &newValue) -> FancyLineEdit::AsyncValidationFuture { + const FilePath rootPath = FilePath::fromParts(Constants::DOCKER_DEVICE_SCHEME, + repoAndTagEncoded(), + u"/"); + return asyncRun([rootPath, newValue]() -> expected_str { + QString changedValue = newValue; + FilePath path = FilePath::fromUserInput(newValue); + if (!path.needsDevice()) { + const FilePath onDevicePath = rootPath.withNewMappedPath(path); + if (onDevicePath.exists()) { + changedValue = onDevicePath.toUserOutput(); + path = onDevicePath; + } else { + return make_unexpected( + Tr::tr("The path \"%1\" does not exist.").arg(onDevicePath.toUserOutput())); + } + } + QString error; + bool result = checkClangdVersion(path, &error); + if (!result) + return make_unexpected(error); + return changedValue; + }); + }); + + containerStatus.setText(Tr::tr("stopped")); + + auto createBridgeFileAccess = [this]() -> expected_str> { expected_str cmdBridgePath = d->getCmdBridgePath(); @@ -874,7 +852,7 @@ QStringList DockerDevicePrivate::createMountArgs() const QStringList cmds; QList mounts; - for (const FilePath &m : deviceSettings->mounts()) + for (const FilePath &m : q->mounts()) mounts.append({m, m}); if (cmdBridgePath && cmdBridgePath->isSameDevice(settings().dockerBinaryPath())) @@ -893,12 +871,12 @@ bool DockerDevicePrivate::isImageAvailable() const Process proc; proc.setCommand( {settings().dockerBinaryPath(), - {"image", "list", deviceSettings->repoAndTag(), "--format", "{{.Repository}}:{{.Tag}}"}}); + {"image", "list", q->repoAndTag(), "--format", "{{.Repository}}:{{.Tag}}"}}); proc.runBlocking(); if (proc.result() != ProcessResult::FinishedWithSuccess) return false; - if (proc.stdOut().trimmed() == deviceSettings->repoAndTag()) + if (proc.stdOut().trimmed() == q->repoAndTag()) return true; return false; @@ -919,26 +897,26 @@ CommandLine DockerDevicePrivate::createCommandLine() #ifdef Q_OS_UNIX // no getuid() and getgid() on Windows. - if (deviceSettings->useLocalUidGid()) + if (q->useLocalUidGid()) dockerCreate.addArgs({"-u", QString("%1:%2").arg(getuid()).arg(getgid())}); #endif - if (!deviceSettings->network().isEmpty()) { + if (!q->network().isEmpty()) { dockerCreate.addArg("--network"); - dockerCreate.addArg(deviceSettings->network()); + dockerCreate.addArg(q->network()); } dockerCreate.addArgs(createMountArgs()); - if (!deviceSettings->keepEntryPoint()) + if (!q->keepEntryPoint()) dockerCreate.addArgs({"--entrypoint", "/bin/sh"}); - if (deviceSettings->enableLldbFlags()) + if (q->enableLldbFlags()) dockerCreate.addArgs({"--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"}); - dockerCreate.addArgs(deviceSettings->extraArgs(), CommandLine::Raw); + dockerCreate.addArgs(q->extraArgs(), CommandLine::Raw); - dockerCreate.addArg(deviceSettings->repoAndTag()); + dockerCreate.addArg(q->repoAndTag()); return dockerCreate; } @@ -946,7 +924,7 @@ CommandLine DockerDevicePrivate::createCommandLine() expected_str DockerDevicePrivate::createContainer() { if (!isImageAvailable()) - return make_unexpected(Tr::tr("Image \"%1\" is not available.").arg(repoAndTag())); + return make_unexpected(Tr::tr("Image \"%1\" is not available.").arg(q->repoAndTag())); const CommandLine cmdLine = createCommandLine(); @@ -1005,7 +983,7 @@ expected_str DockerDevicePrivate::updateContainerAccess() result = make_unexpected(QString("Failed to start container: %1").arg(result.error())); QTimer::singleShot(0, this, [this, containerStatus] { - deviceSettings->containerStatus.setText(containerStatus); + q->containerStatus.setText(containerStatus); }); return result; @@ -1019,13 +997,19 @@ void DockerDevice::setMounts(const QStringList &mounts) const void DockerDevice::fromMap(const Store &map) { ProjectExplorer::IDevice::fromMap(map); - d->deviceSettings->fromMap(map); + + // This is the only place where we can correctly set the default name. + // Only here do we know the image id and the repo reliably, no matter + // where or how we were created. + if (displayName.value() == displayName.defaultValue()) { + displayName.setDefaultValue( + Tr::tr("Docker Image \"%1\" (%2)").arg(repoAndTag()).arg(imageId.value())); + } } void DockerDevice::toMap(Store &map) const { IDevice::toMap(map); - d->deviceSettings->toMap(map); } ProcessInterface *DockerDevice::createProcessInterface() const @@ -1046,15 +1030,10 @@ bool DockerDevice::usableAsBuildDevice() const FilePath DockerDevice::filePath(const QString &pathOnDevice) const { return FilePath::fromParts(Constants::DOCKER_DEVICE_SCHEME, - d->repoAndTagEncoded(), + repoAndTagEncoded(), pathOnDevice); } -FilePath DockerDevice::rootPath() const -{ - return d->deviceSettings->rootPath(); -} - bool DockerDevice::handlesFile(const FilePath &filePath) const { if (filePath.scheme() == u"device" && filePath.host() == id().toString()) @@ -1062,13 +1041,13 @@ bool DockerDevice::handlesFile(const FilePath &filePath) const const bool isDockerScheme = filePath.scheme() == Constants::DOCKER_DEVICE_SCHEME; - if (isDockerScheme && filePath.host() == d->dockerImageId()) + if (isDockerScheme && filePath.host() == imageId()) return true; - if (isDockerScheme && filePath.host() == d->repoAndTagEncoded()) + if (isDockerScheme && filePath.host() == repoAndTagEncoded()) return true; - if (isDockerScheme && filePath.host() == d->repoAndTag()) + if (isDockerScheme && filePath.host() == repoAndTag()) return true; return false; @@ -1301,12 +1280,10 @@ public: m_proxyModel->mapToSource(selectedRows.front())); QTC_ASSERT(item, return {}); - auto deviceSettings = std::make_unique(); - deviceSettings->repo.setValue(item->repo); - deviceSettings->tag.setValue(item->tag); - deviceSettings->imageId.setValue(item->imageId); - - auto device = DockerDevice::create(std::move(deviceSettings)); + auto device = DockerDevice::create(); + device->repo.setValue(item->repo); + device->tag.setValue(item->tag); + device->imageId.setValue(item->imageId); return device; } @@ -1336,7 +1313,7 @@ DockerDeviceFactory::DockerDeviceFactory() return wizard.device(); }); setConstructionFunction([this] { - auto device = DockerDevice::create(std::make_unique()); + auto device = DockerDevice::create(); QMutexLocker lk(&m_deviceListMutex); m_existingDevices.push_back(device); return device; @@ -1357,7 +1334,7 @@ expected_str> DockerDevicePrivate::osTypeAnd Process proc; proc.setCommand( {settings().dockerBinaryPath(), - {"image", "inspect", repoAndTag(), "--format", "{{.Os}}\t{{.Architecture}}"}}); + {"image", "inspect", q->repoAndTag(), "--format", "{{.Os}}\t{{.Architecture}}"}}); proc.runBlocking(); if (proc.result() != ProcessResult::FinishedWithSuccess) return make_unexpected(Tr::tr("Failed to inspect image: %1").arg(proc.allOutput())); @@ -1398,8 +1375,8 @@ void DockerDevicePrivate::shutdown() void DockerDevicePrivate::changeMounts(QStringList newMounts) { newMounts.removeDuplicates(); - if (deviceSettings->mounts.value() != newMounts) { - deviceSettings->mounts.value() = newMounts; + if (q->mounts.value() != newMounts) { + q->mounts.value() = newMounts; stopCurrentContainer(); // Force re-start with new mounts. } } @@ -1407,7 +1384,7 @@ void DockerDevicePrivate::changeMounts(QStringList newMounts) expected_str DockerDevicePrivate::localSource(const FilePath &other) const { const auto devicePath = FilePath::fromString(other.path()); - for (const FilePath &mount : deviceSettings->mounts()) { + for (const FilePath &mount : q->mounts()) { const FilePath mountPoint = mount; if (devicePath.isChildOf(mountPoint)) { const FilePath relativePath = devicePath.relativeChildPath(mountPoint); @@ -1423,7 +1400,7 @@ bool DockerDevicePrivate::ensureReachable(const FilePath &other) if (other.isSameDevice(q->rootPath())) return true; - for (const FilePath &mount : deviceSettings->mounts()) { + for (const FilePath &mount : q->mounts()) { if (other.isChildOf(mount)) return true; diff --git a/src/plugins/docker/dockerdevice.h b/src/plugins/docker/dockerdevice.h index 709ae09e0f0..bf2bc16e73a 100644 --- a/src/plugins/docker/dockerdevice.h +++ b/src/plugins/docker/dockerdevice.h @@ -12,46 +12,18 @@ namespace Docker::Internal { -class DockerDeviceSettings : public ProjectExplorer::DeviceSettings -{ -public: - DockerDeviceSettings(); - - void fromMap(const Utils::Store &map) override; - - QString repoAndTag() const; - QString repoAndTagEncoded() const; - Utils::FilePath rootPath() const; - - Utils::StringAspect imageId{this}; - Utils::StringAspect repo{this}; - Utils::StringAspect tag{this}; - Utils::BoolAspect useLocalUidGid{this}; - Utils::FilePathListAspect mounts{this}; - Utils::BoolAspect keepEntryPoint{this}; - Utils::BoolAspect enableLldbFlags{this}; - Utils::FilePathAspect clangdExecutable{this}; - Utils::StringSelectionAspect network{this}; - Utils::StringAspect extraArgs{this}; - - Utils::TextDisplay containerStatus{this}; -}; - class DockerDevice : public ProjectExplorer::IDevice { public: using Ptr = std::shared_ptr; using ConstPtr = std::shared_ptr; - explicit DockerDevice(std::unique_ptr settings); + DockerDevice(); ~DockerDevice(); void shutdown(); - static Ptr create(std::unique_ptr settings) - { - return Ptr(new DockerDevice(std::move(settings))); - } + static Ptr create() { return Ptr(new DockerDevice); } Utils::CommandLine createCommandLine() const; @@ -85,6 +57,22 @@ public: bool prepareForBuild(const ProjectExplorer::Target *target) override; std::optional clangdExecutable() const override; + QString repoAndTag() const; + QString repoAndTagEncoded() const; + + Utils::StringAspect imageId{this}; + Utils::StringAspect repo{this}; + Utils::StringAspect tag{this}; + Utils::BoolAspect useLocalUidGid{this}; + Utils::FilePathListAspect mounts{this}; + Utils::BoolAspect keepEntryPoint{this}; + Utils::BoolAspect enableLldbFlags{this}; + Utils::FilePathAspect clangdExecutableAspect{this}; + Utils::StringSelectionAspect network{this}; + Utils::StringAspect extraArgs{this}; + + Utils::TextDisplay containerStatus{this}; + protected: void fromMap(const Utils::Store &map) final; void toMap(Utils::Store &map) const final; diff --git a/src/plugins/docker/dockerdevicewidget.cpp b/src/plugins/docker/dockerdevicewidget.cpp index 9721fb1f333..3ab529d243c 100644 --- a/src/plugins/docker/dockerdevicewidget.cpp +++ b/src/plugins/docker/dockerdevicewidget.cpp @@ -34,8 +34,6 @@ DockerDeviceWidget::DockerDeviceWidget(const IDevice::Ptr &device) auto dockerDevice = std::dynamic_pointer_cast(device); QTC_ASSERT(dockerDevice, return); - DockerDeviceSettings *deviceSettings = static_cast(device->settings()); - using namespace Layouting; auto daemonStateLabel = new QLabel(Tr::tr("Daemon state:")); @@ -58,13 +56,13 @@ DockerDeviceWidget::DockerDeviceWidget(const IDevice::Ptr &device) auto pathListLabel = new InfoLabel(Tr::tr("Paths to mount:")); pathListLabel->setAdditionalToolTip(Tr::tr("Source directory list should not be empty.")); - auto markupMounts = [deviceSettings, pathListLabel] { - const bool isEmpty = deviceSettings->mounts.volatileValue().isEmpty(); + auto markupMounts = [dockerDevice, pathListLabel] { + const bool isEmpty = dockerDevice->mounts.volatileValue().isEmpty(); pathListLabel->setType(isEmpty ? InfoLabel::Warning : InfoLabel::None); }; markupMounts(); - connect(&deviceSettings->mounts, &FilePathListAspect::volatileValueChanged, this, markupMounts); + connect(&dockerDevice->mounts, &FilePathListAspect::volatileValueChanged, this, markupMounts); auto logView = new QTextBrowser; connect(&m_kitItemDetector, &KitDetector::logOutput, @@ -104,7 +102,7 @@ DockerDeviceWidget::DockerDeviceWidget(const IDevice::Ptr &device) connect(autoDetectButton, &QPushButton::clicked, this, - [this, logView, dockerDevice, searchPaths, deviceSettings] { + [this, logView, dockerDevice, searchPaths] { logView->clear(); expected_str startResult = dockerDevice->updateContainerAccess(); @@ -121,7 +119,7 @@ DockerDeviceWidget::DockerDeviceWidget(const IDevice::Ptr &device) }); if (!clangdPath.isEmpty()) - deviceSettings->clangdExecutable.setValue(clangdPath); + dockerDevice->clangdExecutableAspect.setValue(clangdPath); m_kitItemDetector.autoDetect(dockerDevice->id().toString(), searchPaths()); @@ -169,20 +167,20 @@ DockerDeviceWidget::DockerDeviceWidget(const IDevice::Ptr &device) Column { noMargin, Form { - deviceSettings->repo, br, - deviceSettings->tag, br, - deviceSettings->imageId, br, + dockerDevice->repo, br, + dockerDevice->tag, br, + dockerDevice->imageId, br, daemonStateLabel, m_daemonReset, m_daemonState, br, - Tr::tr("Container state:"), deviceSettings->containerStatus, br, - deviceSettings->useLocalUidGid, br, - deviceSettings->keepEntryPoint, br, - deviceSettings->enableLldbFlags, br, - deviceSettings->clangdExecutable, br, - deviceSettings->network, br, - deviceSettings->extraArgs, br, + Tr::tr("Container state:"), dockerDevice->containerStatus, br, + dockerDevice->useLocalUidGid, br, + dockerDevice->keepEntryPoint, br, + dockerDevice->enableLldbFlags, br, + dockerDevice->clangdExecutableAspect, br, + dockerDevice->network, br, + dockerDevice->extraArgs, br, Column { pathListLabel, - deviceSettings->mounts, + dockerDevice->mounts, }, br, If { dockerDevice->isAutoDetected(), {}, {detectionControls} }, noMargin, @@ -199,7 +197,7 @@ DockerDeviceWidget::DockerDeviceWidget(const IDevice::Ptr &device) }; QObject::connect(searchDirsComboBox, &QComboBox::activated, this, updateDirectoriesLineEdit); - connect(deviceSettings, &AspectContainer::applied, this, [createLineLabel, dockerDevice] { + connect(&*dockerDevice, &AspectContainer::applied, this, [createLineLabel, dockerDevice] { createLineLabel->setText(dockerDevice->createCommandLine().toUserOutput()); }); } diff --git a/src/plugins/ios/iosdevice.cpp b/src/plugins/ios/iosdevice.cpp index c749209e1d1..14ffa9c26bf 100644 --- a/src/plugins/ios/iosdevice.cpp +++ b/src/plugins/ios/iosdevice.cpp @@ -107,7 +107,7 @@ IosDevice::IosDevice(CtorHelper) : m_lastPort(Constants::IOS_DEVICE_PORT_START) { setType(Constants::IOS_DEVICE_TYPE); - settings()->displayName.setDefaultValue(IosDevice::name()); + displayName.setDefaultValue(IosDevice::name()); setDisplayType(Tr::tr("iOS")); setMachineType(IDevice::Hardware); setOsType(Utils::OsTypeMac); @@ -248,7 +248,7 @@ void IosDeviceManager::deviceConnected(const QString &uid, const QString &name) if (!dev) { auto newDev = new IosDevice(uid); if (!name.isNull()) - newDev->settings()->displayName.setValue(name); + newDev->displayName.setValue(name); qCDebug(detectLog) << "adding ios device " << uid; devManager->addDevice(IDevice::ConstPtr(newDev)); } else if (dev->deviceState() != IDevice::DeviceConnected && @@ -364,7 +364,7 @@ void IosDeviceManager::deviceInfo(const QString &uid, } if (!skipUpdate) { if (info.contains(kDeviceName)) - newDev->settings()->displayName.setValue(info.value(kDeviceName)); + newDev->displayName.setValue(info.value(kDeviceName)); newDev->m_extraInfo = info; newDev->m_handler = handler; qCDebug(detectLog) << "updated info of ios device " << uid; diff --git a/src/plugins/ios/iossimulator.cpp b/src/plugins/ios/iossimulator.cpp index ed9a5abf66a..67a51788f6d 100644 --- a/src/plugins/ios/iossimulator.cpp +++ b/src/plugins/ios/iossimulator.cpp @@ -28,7 +28,7 @@ IosSimulator::IosSimulator(Id id) setType(Constants::IOS_SIMULATOR_TYPE); setMachineType(IDevice::Emulator); setOsType(Utils::OsTypeMac); - settings()->displayName.setDefaultValue(Tr::tr("iOS Simulator")); + displayName.setDefaultValue(Tr::tr("iOS Simulator")); setDisplayType(Tr::tr("iOS Simulator")); setDeviceState(DeviceStateUnknown); } diff --git a/src/plugins/mcusupport/mcusupportdevice.cpp b/src/plugins/mcusupport/mcusupportdevice.cpp index ad611f265fe..cae42c5529e 100644 --- a/src/plugins/mcusupport/mcusupportdevice.cpp +++ b/src/plugins/mcusupport/mcusupportdevice.cpp @@ -16,7 +16,7 @@ McuSupportDevice::McuSupportDevice() setupId(IDevice::AutoDetected, Constants::DEVICE_ID); setType(Constants::DEVICE_TYPE); const QString displayNameAndType = Tr::tr("MCU Device"); - settings()->displayName.setDefaultValue(displayNameAndType); + displayName.setDefaultValue(displayNameAndType); setDisplayType(displayNameAndType); setDeviceState(IDevice::DeviceStateUnknown); setMachineType(IDevice::Hardware); diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp index b9558f17f1b..74f5b87173f 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp @@ -42,7 +42,7 @@ DesktopDevice::DesktopDevice() setupId(IDevice::AutoDetected, DESKTOP_DEVICE_ID); setType(DESKTOP_DEVICE_TYPE); - settings()->displayName.setDefaultValue(Tr::tr("Local PC")); + displayName.setDefaultValue(Tr::tr("Local PC")); setDisplayType(Tr::tr("Desktop")); setDeviceState(IDevice::DeviceStateUnknown); diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp index 50944ae3335..adce395456c 100644 --- a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp @@ -261,8 +261,7 @@ void DeviceManager::addDevice(const IDevice::ConstPtr &_device) } // TODO: make it thread safe? - device->settings()->displayName.setValue( - Utils::makeUniquelyNumbered(device->displayName(), names)); + device->displayName.setValue(Utils::makeUniquelyNumbered(device->displayName(), names)); const int pos = d->indexForId(device->id()); @@ -568,7 +567,7 @@ void ProjectExplorerTest::testDeviceManager() TestDeviceFactory factory; TestDevice::Ptr dev = IDevice::Ptr(new TestDevice); - dev->settings()->displayName.setValue(QLatin1String("blubbdiblubbfurz!")); + dev->displayName.setValue(QLatin1String("blubbdiblubbfurz!")); QVERIFY(dev->isAutoDetected()); QCOMPARE(dev->deviceState(), IDevice::DeviceStateUnknown); QCOMPARE(dev->type(), TestDevice::testTypeId()); @@ -629,7 +628,7 @@ void ProjectExplorerTest::testDeviceManager() TestDevice::Ptr dev3 = IDevice::Ptr(new TestDevice); QVERIFY(dev->id() != dev3->id()); - dev3->settings()->displayName.setValue(dev->displayName()); + dev3->displayName.setValue(dev->displayName()); mgr->addDevice(dev3); QCOMPARE(mgr->deviceAt(mgr->deviceCount() - 1)->displayName(), QString(dev3->displayName() + QLatin1Char('2'))); diff --git a/src/plugins/projectexplorer/devicesupport/devicesettingspage.cpp b/src/plugins/projectexplorer/devicesupport/devicesettingspage.cpp index 59ead38b9f3..9695af16563 100644 --- a/src/plugins/projectexplorer/devicesupport/devicesettingspage.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicesettingspage.cpp @@ -274,7 +274,7 @@ void DeviceSettingsWidget::setDeviceInfoWidgetsEnabled(bool enable) void DeviceSettingsWidget::updateDeviceFromUi() { - currentDevice()->settings()->apply(); + currentDevice()->doApply(); if (m_configWidget) m_configWidget->updateDeviceFromUi(); } @@ -340,7 +340,7 @@ void DeviceSettingsWidget::currentDeviceChanged(int index) } Layouting::Column item{Layouting::noMargin}; - device->settings()->displayName.addToLayout(item); + device->displayName.addToLayout(item); QWidget *newEdit = item.emerge(); QLayoutItem *oldItem = m_generalFormLayout->replaceWidget(m_deviceNameEditWidget, newEdit); QTC_CHECK(oldItem); diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp index afbd3d54f75..fcc0b7af0f3 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp @@ -120,16 +120,10 @@ const IDevice::MachineType DefaultMachineType = IDevice::Hardware; const int DefaultTimeout = 10; namespace Internal { + class IDevicePrivate { public: - IDevicePrivate(std::unique_ptr s) - : settings(std::move(s)) - { - if (!settings) - settings = std::make_unique(); - } - QString displayType; Id type; IDevice::Origin origin = IDevice::AutoDetected; @@ -153,12 +147,14 @@ public: QList deviceActions; Store extraData; IDevice::OpenTerminal openTerminal; - - std::unique_ptr settings; }; + } // namespace Internal -DeviceSettings::DeviceSettings() +DeviceTester::DeviceTester(QObject *parent) : QObject(parent) { } + +IDevice::IDevice() + : d(new Internal::IDevicePrivate) { setAutoApply(false); @@ -201,13 +197,6 @@ DeviceSettings::DeviceSettings() }); } -DeviceTester::DeviceTester(QObject *parent) : QObject(parent) { } - -IDevice::IDevice(std::unique_ptr settings) - : d(new Internal::IDevicePrivate(std::move(settings))) -{ -} - IDevice::~IDevice() = default; void IDevice::setOpenTerminal(const IDevice::OpenTerminal &openTerminal) @@ -319,11 +308,6 @@ expected_str IDevice::systemEnvironmentWithError() const return access->deviceEnvironment(); } -QString IDevice::displayName() const -{ - return d->settings->displayName(); -} - QString IDevice::displayType() const { return d->displayType; @@ -495,8 +479,8 @@ Id IDevice::idFromMap(const Store &map) void IDevice::fromMap(const Store &map) { + AspectContainer::fromMap(map); d->type = typeFromMap(map); - settings()->fromMap(map); d->id = Id::fromSetting(map.value(IdKey)); d->osType = osTypeFromString(map.value(ClientOsTypeKey).toString()).value_or(OsTypeLinux); @@ -543,7 +527,7 @@ void IDevice::fromMap(const Store &map) void IDevice::toMap(Store &map) const { - d->settings->toMap(map); + AspectContainer::toMap(map); map.insert(TypeKey, d->type.toString()); map.insert(ClientOsTypeKey, osTypeToString(d->osType)); @@ -587,11 +571,6 @@ IDevice::Ptr IDevice::clone() const return device; } -DeviceSettings *IDevice::settings() const -{ - return d->settings.get(); -} - QString IDevice::deviceStateToString() const { switch (d->deviceState) { @@ -725,6 +704,11 @@ std::optional IDevice::clangdExecutable() const return std::nullopt; } +void IDevice::doApply() const +{ + const_cast(this)->apply(); +} + void DeviceProcessSignalOperation::setDebuggerCommand(const FilePath &cmd) { m_debuggerCommand = cmd; diff --git a/src/plugins/projectexplorer/devicesupport/idevice.h b/src/plugins/projectexplorer/devicesupport/idevice.h index 77d4b01f01c..7bdb347a89e 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.h +++ b/src/plugins/projectexplorer/devicesupport/idevice.h @@ -83,16 +83,9 @@ public: std::function(const QByteArray &commandOutput)> parsePorts; }; -class PROJECTEXPLORER_EXPORT DeviceSettings : public Utils::AspectContainer -{ -public: - DeviceSettings(); - - Utils::StringAspect displayName{this}; -}; - // See cpp file for documentation. -class PROJECTEXPLORER_EXPORT IDevice : public std::enable_shared_from_this +class PROJECTEXPLORER_EXPORT IDevice + : public Utils::AspectContainer, public std::enable_shared_from_this { friend class Internal::IDevicePrivate; public: @@ -107,9 +100,7 @@ public: virtual Ptr clone() const; - DeviceSettings *settings() const; - - QString displayName() const; + Utils::StringAspect displayName{this}; // Provide some information on the device suitable for formated // output, e.g. in tool tips. Get a list of name value pairs. @@ -229,8 +220,10 @@ public: virtual void checkOsType() {} + void doApply() const; + protected: - IDevice(std::unique_ptr settings = nullptr); + IDevice(); virtual void fromMap(const Utils::Store &map); virtual void toMap(Utils::Store &map) const; diff --git a/src/plugins/projectexplorer/devicesupport/idevicefactory.cpp b/src/plugins/projectexplorer/devicesupport/idevicefactory.cpp index 9d229924749..ac80ccbb883 100644 --- a/src/plugins/projectexplorer/devicesupport/idevicefactory.cpp +++ b/src/plugins/projectexplorer/devicesupport/idevicefactory.cpp @@ -79,7 +79,7 @@ IDevice::Ptr IDeviceFactory::construct() const IDevice::Ptr device = m_constructor(); QTC_ASSERT(device, return {}); - device->settings()->displayName.setDefaultValue(displayName()); + device->displayName.setDefaultValue(displayName()); return device; } diff --git a/src/plugins/projectexplorer/kitaspects.cpp b/src/plugins/projectexplorer/kitaspects.cpp index 3bc4d8332b8..450edb5084d 100644 --- a/src/plugins/projectexplorer/kitaspects.cpp +++ b/src/plugins/projectexplorer/kitaspects.cpp @@ -1313,7 +1313,7 @@ void BuildDeviceKitAspectFactory::addToMacroExpander(Kit *kit, MacroExpander *ex }); expander->registerVariable("BuildDevice:Name", Tr::tr("Build device name"), [kit] { const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit); - return device ? device->settings()->displayName() : QString(); + return device ? device->displayName() : QString(); }); expander ->registerFileVariables("BuildDevice::Root", Tr::tr("Build device root directory"), [kit] { diff --git a/src/plugins/qnx/qnxdevice.cpp b/src/plugins/qnx/qnxdevice.cpp index 4d04d69b42c..3b253245924 100644 --- a/src/plugins/qnx/qnxdevice.cpp +++ b/src/plugins/qnx/qnxdevice.cpp @@ -64,7 +64,7 @@ public: QnxDevice() { setDisplayType(Tr::tr("QNX")); - settings()->displayName.setDefaultValue(Tr::tr("QNX Device")); + displayName.setDefaultValue(Tr::tr("QNX Device")); setOsType(OsTypeOtherUnix); setupId(IDevice::ManuallyAdded); setType(Constants::QNX_QNX_OS_TYPE); diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index 9edab31f5af..eb7cb59147d 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -307,12 +307,6 @@ public: LinuxDevicePrivate *m_dev; }; -class LinuxDeviceSettings : public DeviceSettings -{ -public: - LinuxDeviceSettings() { displayName.setDefaultValue(Tr::tr("Remote Linux Device")); } -}; - class LinuxDevicePrivate { public: @@ -1019,12 +1013,12 @@ private: // LinuxDevice LinuxDevice::LinuxDevice() - : IDevice(std::make_unique()) - , d(new LinuxDevicePrivate(this)) + : d(new LinuxDevicePrivate(this)) { setFileAccess(&d->m_fileAccess); setDisplayType(Tr::tr("Remote Linux")); setOsType(OsTypeLinux); + displayName.setDefaultValue(Tr::tr("Remote Linux Device")); setupId(IDevice::ManuallyAdded, Utils::Id()); setType(Constants::GenericLinuxOsType); diff --git a/src/plugins/remotelinux/sshdevicewizard.cpp b/src/plugins/remotelinux/sshdevicewizard.cpp index 2cf001cd175..b24de479533 100644 --- a/src/plugins/remotelinux/sshdevicewizard.cpp +++ b/src/plugins/remotelinux/sshdevicewizard.cpp @@ -77,7 +77,7 @@ private: && !m_userNameLineEdit->text().trimmed().isEmpty(); } bool validatePage() final { - m_device->settings()->displayName.setValue(m_nameLineEdit->text().trimmed()); + m_device->displayName.setValue(m_nameLineEdit->text().trimmed()); SshParameters sshParams = m_device->sshParameters(); sshParams.setHost(m_hostNameLineEdit->text().trimmed()); sshParams.setUserName(m_userNameLineEdit->text().trimmed()); diff --git a/src/plugins/webassembly/webassemblydevice.cpp b/src/plugins/webassembly/webassemblydevice.cpp index e3f798b207d..90c789d2f42 100644 --- a/src/plugins/webassembly/webassemblydevice.cpp +++ b/src/plugins/webassembly/webassemblydevice.cpp @@ -35,7 +35,7 @@ public: setupId(IDevice::AutoDetected, Constants::WEBASSEMBLY_DEVICE_DEVICE_ID); setType(Constants::WEBASSEMBLY_DEVICE_TYPE); const QString displayNameAndType = Tr::tr("Web Browser"); - settings()->displayName.setDefaultValue(displayNameAndType); + displayName.setDefaultValue(displayNameAndType); setDisplayType(displayNameAndType); setDeviceState(IDevice::DeviceStateUnknown); setMachineType(IDevice::Hardware);