ProjectExplorer: Allow more runconfigs to be used as clone data source

I believe this can be useful to copy (parts of) run configurations
between related targets, that are not exactly the same, e.g. two
related, but formally independent test binaries.

Change-Id: I5da13098d460671c81acd61a02d18a7b48fdba06
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
hjk
2025-04-23 08:58:14 +02:00
parent b2c98dc218
commit 539b8fe618
4 changed files with 43 additions and 28 deletions

View File

@@ -3,6 +3,7 @@
#include "projectconfiguration.h"
#include "projectexplorerconstants.h"
#include "target.h"
#include <utils/algorithm.h>
@@ -12,9 +13,6 @@
using namespace ProjectExplorer;
using namespace Utils;
const char CONFIGURATION_ID_KEY[] = "ProjectExplorer.ProjectConfiguration.Id";
const char DISPLAY_NAME_KEY[] = "ProjectExplorer.ProjectConfiguration.DisplayName";
// ProjectConfiguration
ProjectConfiguration::ProjectConfiguration(Target *target, Id id)
@@ -71,8 +69,8 @@ QString ProjectConfiguration::toolTip() const
void ProjectConfiguration::toMap(Store &map) const
{
QTC_CHECK(m_id.isValid());
map.insert(CONFIGURATION_ID_KEY, m_id.toSetting());
m_displayName.toMap(map, DISPLAY_NAME_KEY);
map.insert(Constants::CONFIGURATION_ID_KEY, m_id.toSetting());
m_displayName.toMap(map, Constants::DISPLAY_NAME_KEY);
AspectContainer::toMap(map);
}
@@ -83,18 +81,18 @@ Target *ProjectConfiguration::target() const
void ProjectConfiguration::fromMap(const Store &map)
{
Id id = Id::fromSetting(map.value(CONFIGURATION_ID_KEY));
Id id = Id::fromSetting(map.value(Constants::CONFIGURATION_ID_KEY));
// Note: This is only "startsWith", not ==, as RunConfigurations currently still
// mangle in their build keys.
QTC_ASSERT(id.name().startsWith(m_id.name()), reportError(); return);
m_displayName.fromMap(map, DISPLAY_NAME_KEY);
m_displayName.fromMap(map, Constants::DISPLAY_NAME_KEY);
AspectContainer::fromMap(map);
}
Id ProjectExplorer::idFromMap(const Store &map)
{
return Id::fromSetting(map.value(CONFIGURATION_ID_KEY));
return Id::fromSetting(map.value(Constants::CONFIGURATION_ID_KEY));
}
QString ProjectConfiguration::expandedDisplayName() const

View File

@@ -128,6 +128,10 @@ const char COPY_DIRECTORY_STEP[] = "ProjectExplorer.CopyDirectoryStep";
const char DEVICE_CHECK_STEP[] = "ProjectExplorer.DeviceCheckBuildStep";
const char CUSTOM_PROCESS_STEP[] = "ProjectExplorer.ProcessStep";
// Project Configuration
const char CONFIGURATION_ID_KEY[] = "ProjectExplorer.ProjectConfiguration.Id";
const char DISPLAY_NAME_KEY[] = "ProjectExplorer.ProjectConfiguration.DisplayName";
// Language
// Keep these short: These constants are exposed to the MacroExplorer!

View File

@@ -420,19 +420,15 @@ RunConfiguration *RunConfiguration::clone(BuildConfiguration *bc)
void RunConfiguration::cloneFromOther(const RunConfiguration *rc)
{
Store map;
rc->toMap(map);
fromMap(map);
Store ownData;
toMap(ownData);
// Same build config? Then uniquify the name.
if (rc->buildConfiguration() == buildConfiguration()) {
QList<RunConfiguration *> others = buildConfiguration()->runConfigurations();
others.removeOne(this);
const QStringList otherNames = Utils::transform(others, [](const RunConfiguration *rc) {
return rc->displayName();
});
setDisplayName(makeUniquelyNumbered(rc->displayName(), otherNames));
}
Store copyData;
rc->toMap(copyData);
copyData.insert(Constants::CONFIGURATION_ID_KEY, ownData.value(Constants::CONFIGURATION_ID_KEY));
copyData.insert(Constants::DISPLAY_NAME_KEY, ownData.value(Constants::DISPLAY_NAME_KEY));
copyData.insert(BUILD_KEY, ownData.value(BUILD_KEY));
fromMap(copyData);
}
BuildTargetInfo RunConfiguration::buildTargetInfo() const

View File

@@ -24,6 +24,7 @@
#include <QAction>
#include <QComboBox>
#include <QDialogButtonBox>
#include <QFont>
#include <QGridLayout>
#include <QHash>
#include <QInputDialog>
@@ -55,7 +56,7 @@ public:
for (const BuildConfiguration * const bc : t->buildConfigurations()) {
RCList rcsForBuildConfig;
for (const RunConfiguration * const rc : bc->runConfigurations()) {
if (rc != thisRc && rc->buildKey() == thisRc->buildKey())
if (rc != thisRc)
rcsForBuildConfig << rc;
}
if (!rcsForBuildConfig.isEmpty())
@@ -69,27 +70,30 @@ public:
// to removal of any configurations while the dialog is running.
if (eligibleRcs.isEmpty()) {
m_rcModel->rootItem()->appendChild(new StaticTreeItem(
Tr::tr("There are no other run configurations for this application.")));
Tr::tr("There are no other run configurations.")));
m_rcView->setSelectionMode(TreeView::NoSelection);
} else {
for (auto targetIt = eligibleRcs.cbegin(); targetIt != eligibleRcs.cend(); ++targetIt) {
const auto targetItem = new StaticTreeItem(targetIt.key()->displayName());
for (auto bcIt = targetIt.value().cbegin(); bcIt != targetIt.value().cend();
++bcIt) {
const auto bcItem = new StaticTreeItem(bcIt.key()->displayName());
for (const RunConfiguration *const rc : std::as_const(bcIt.value()))
bcItem->appendChild(new RCTreeItem(rc));
for (const RunConfiguration *const rc : std::as_const(bcIt.value())) {
bcItem->appendChild(
new RCTreeItem(rc, rc->buildKey() == thisRc->buildKey()));
}
targetItem->appendChild(bcItem);
}
m_rcModel->rootItem()->appendChild(targetItem);
}
m_rcView->setSelectionMode(TreeView::SingleSelection);
m_rcView->setSelectionBehavior(TreeView::SelectItems);
}
// UI
m_rcView->setModel(m_rcModel);
m_rcView->expandAll();
setWindowTitle(Tr::tr("Clone From Run Configuration"));
m_rcView->setSelectionMode(TreeView::SingleSelection);
m_rcView->setSelectionBehavior(TreeView::SelectItems);
m_rcView->setSortingEnabled(true);
m_rcView->resizeColumnToContents(0);
m_rcView->sortByColumn(0, Qt::AscendingOrder);
@@ -116,10 +120,23 @@ private:
class RCTreeItem : public StaticTreeItem
{
public:
RCTreeItem(const RunConfiguration *rc): StaticTreeItem(rc->displayName()), m_rc(rc) {}
RCTreeItem(const RunConfiguration *rc, bool sameBuildKey)
: StaticTreeItem(rc->displayName()), m_rc(rc), m_sameBuildKey(sameBuildKey) {}
const RunConfiguration *runConfig() const { return m_rc; }
private:
QPointer<const RunConfiguration> m_rc;
QVariant data(int column, int role) const override
{
QTC_ASSERT(column == 0, return {});
if (role == Qt::FontRole && m_sameBuildKey) {
QFont f = StaticTreeItem::data(column, role).value<QFont>();
f.setBold(true);
return f;
}
return StaticTreeItem::data(column, role);
}
const QPointer<const RunConfiguration> m_rc;
const bool m_sameBuildKey;
};
void accept() override