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);