RemoteLinux: Let user override deployment data

That is, instead of what is specified in the project files of the
respective build system, let the user manually set the data in the
deploy configuration.
This is intended as a last resort for use in project managers that are
not able to deduce any deployment information from the project.

Fixes: QTCREATORBUG-21854
Change-Id: I2fefb89a4aa846e52aeca69749ca03534f4f0a67
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Christian Kandeler
2020-01-24 14:38:13 +01:00
parent 6355796f11
commit c4254722df
6 changed files with 142 additions and 22 deletions

View File

@@ -39,6 +39,8 @@ namespace ProjectExplorer {
const char BUILD_STEP_LIST_COUNT[] = "ProjectExplorer.BuildConfiguration.BuildStepListCount";
const char BUILD_STEP_LIST_PREFIX[] = "ProjectExplorer.BuildConfiguration.BuildStepList.";
const char USES_DEPLOYMENT_DATA[] = "ProjectExplorer.DeployConfiguration.CustomDataEnabled";
const char DEPLOYMENT_DATA[] = "ProjectExplorer.DeployConfiguration.CustomData";
DeployConfiguration::DeployConfiguration(Target *target, Core::Id id)
: ProjectConfiguration(target, id),
@@ -67,11 +69,11 @@ const BuildStepList *DeployConfiguration::stepList() const
return &m_stepList;
}
QWidget *DeployConfiguration::createConfigWidget() const
QWidget *DeployConfiguration::createConfigWidget()
{
if (!m_configWidgetCreator)
return nullptr;
return m_configWidgetCreator(target());
return m_configWidgetCreator(this);
}
QVariantMap DeployConfiguration::toMap() const
@@ -79,6 +81,13 @@ QVariantMap DeployConfiguration::toMap() const
QVariantMap map(ProjectConfiguration::toMap());
map.insert(QLatin1String(BUILD_STEP_LIST_COUNT), 1);
map.insert(QLatin1String(BUILD_STEP_LIST_PREFIX) + QLatin1Char('0'), m_stepList.toMap());
map.insert(USES_DEPLOYMENT_DATA, usesCustomDeploymentData());
QVariantMap deployData;
for (int i = 0; i < m_customDeploymentData.fileCount(); ++i) {
const DeployableFile &f = m_customDeploymentData.fileAt(i);
deployData.insert(f.localFilePath().toString(), f.remoteDirectory());
}
map.insert(DEPLOYMENT_DATA, deployData);
return map;
}
@@ -103,6 +112,10 @@ bool DeployConfiguration::fromMap(const QVariantMap &map)
return false;
}
m_usesCustomDeploymentData = map.value(USES_DEPLOYMENT_DATA, false).toBool();
const QVariantMap deployData = map.value(DEPLOYMENT_DATA).toMap();
for (auto it = deployData.begin(); it != deployData.end(); ++it)
m_customDeploymentData.addFile(it.key(), it.value().toString());
return true;
}
@@ -157,14 +170,16 @@ bool DeployConfigurationFactory::canHandle(Target *target) const
return true;
}
void DeployConfigurationFactory::setConfigWidgetCreator(const std::function<QWidget *(Target *)> &configWidgetCreator)
void DeployConfigurationFactory::setConfigWidgetCreator(const DeployConfiguration::WidgetCreator &configWidgetCreator)
{
m_configWidgetCreator = configWidgetCreator;
}
void DeployConfigurationFactory::setUseDeploymentDataView()
{
m_configWidgetCreator = [](Target *target) { return new Internal::DeploymentDataView(target); };
m_configWidgetCreator = [](DeployConfiguration *dc) {
return new Internal::DeploymentDataView(dc);
};
}
void DeployConfigurationFactory::setConfigBaseId(Core::Id deployConfigBaseId)

View File

@@ -28,6 +28,7 @@
#include "projectexplorer_export.h"
#include "buildsteplist.h"
#include "deploymentdata.h"
#include "projectconfiguration.h"
namespace ProjectExplorer {
@@ -50,16 +51,25 @@ public:
BuildStepList *stepList();
const BuildStepList *stepList() const;
QWidget *createConfigWidget() const;
QWidget *createConfigWidget();
bool fromMap(const QVariantMap &map) override;
QVariantMap toMap() const override;
bool isActive() const override;
bool usesCustomDeploymentData() const { return m_usesCustomDeploymentData; }
void setUseCustomDeploymentData(bool enabled) { m_usesCustomDeploymentData = enabled; }
DeploymentData customDeploymentData() const { return m_customDeploymentData; }
void setCustomDeploymentData(const DeploymentData &data) { m_customDeploymentData = data; }
private:
BuildStepList m_stepList;
std::function<QWidget *(Target *)> m_configWidgetCreator;
using WidgetCreator = std::function<QWidget *(DeployConfiguration *)>;
WidgetCreator m_configWidgetCreator;
DeploymentData m_customDeploymentData;
bool m_usesCustomDeploymentData = false;
};
class PROJECTEXPLORER_EXPORT DeployConfigurationFactory
@@ -90,7 +100,7 @@ public:
bool canHandle(ProjectExplorer::Target *target) const;
void setConfigWidgetCreator(const std::function<QWidget *(Target *)> &configWidgetCreator);
void setConfigWidgetCreator(const DeployConfiguration::WidgetCreator &configWidgetCreator);
void setUseDeploymentDataView();
using PostRestore = std::function<void(DeployConfiguration *dc, const QVariantMap &)>;
@@ -108,7 +118,7 @@ private:
QList<Core::Id> m_supportedTargetDeviceTypes;
QList<BuildStepList::StepCreationInfo> m_initialSteps;
QString m_defaultDisplayName;
std::function<QWidget *(Target *)> m_configWidgetCreator;
DeployConfiguration::WidgetCreator m_configWidgetCreator;
PostRestore m_postRestore;
};

View File

@@ -26,6 +26,7 @@
#include "deploymentdataview.h"
#include "buildsystem.h"
#include "deployconfiguration.h"
#include "deploymentdata.h"
#include "target.h"
@@ -33,8 +34,11 @@
#include <utils/treemodel.h>
#include <QAbstractTableModel>
#include <QLabel>
#include <QCheckBox>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QLabel>
#include <QPushButton>
#include <QTreeView>
#include <QVBoxLayout>
@@ -47,19 +51,41 @@ class DeploymentDataItem : public TreeItem
{
public:
DeploymentDataItem() = default;
DeploymentDataItem(const DeployableFile &file) : file(file) {}
DeploymentDataItem(const DeployableFile &file, bool isEditable)
: file(file), isEditable(isEditable) {}
QVariant data(int column, int role) const
Qt::ItemFlags flags(int column) const override
{
if (role == Qt::DisplayRole)
Qt::ItemFlags f = TreeItem::flags(column);
if (isEditable)
f |= Qt::ItemIsEditable;
return f;
}
QVariant data(int column, int role) const override
{
if (role == Qt::DisplayRole || role == Qt::EditRole)
return column == 0 ? file.localFilePath().toUserOutput() : file.remoteDirectory();
return QVariant();
}
bool setData(int column, const QVariant &data, int role) override
{
if (role != Qt::EditRole)
return false;
if (column == 0)
file = DeployableFile(data.toString(), file.remoteDirectory());
else if (column == 1)
file = DeployableFile(file.localFilePath().toString(), data.toString());
return true;
}
DeployableFile file;
bool isEditable = false;
};
DeploymentDataView::DeploymentDataView(Target *target)
DeploymentDataView::DeploymentDataView(DeployConfiguration *dc)
{
auto model = new TreeModel<DeploymentDataItem>(this);
model->setHeader({tr("Local File Path"), tr("Remote Directory")});
@@ -71,18 +97,33 @@ DeploymentDataView::DeploymentDataView(Target *target)
view->setUniformRowHeights(true);
view->setModel(model);
const auto buttonsLayout = new QVBoxLayout;
const auto addButton = new QPushButton(tr("Add"));
const auto removeButton = new QPushButton(tr("Remove"));
buttonsLayout->addWidget(addButton);
buttonsLayout->addWidget(removeButton);
buttonsLayout->addStretch(1);
const auto viewLayout = new QHBoxLayout;
viewLayout->addWidget(view);
viewLayout->addLayout(buttonsLayout);
auto label = new QLabel(tr("Files to deploy:"), this);
const auto sourceCheckBox = new QCheckBox(tr("Override deployment data from build system"));
sourceCheckBox->setChecked(dc->usesCustomDeploymentData());
auto layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(label);
layout->addWidget(view);
layout->addWidget(sourceCheckBox);
layout->addLayout(viewLayout);
auto updatModel = [this, target, model, view] {
const auto updateModel = [dc, model, view] {
model->clear();
QTC_ASSERT(target->buildSystem(), return);
for (const DeployableFile &file : target->buildSystem()->deploymentData().allFiles())
model->rootItem()->appendChild(new DeploymentDataItem(file));
for (const DeployableFile &file : dc->target()->deploymentData().allFiles()) {
model->rootItem()->appendChild(
new DeploymentDataItem(file, dc->usesCustomDeploymentData()));
}
QHeaderView *header = view->header();
header->setSectionResizeMode(0, QHeaderView::Interactive);
@@ -93,8 +134,53 @@ DeploymentDataView::DeploymentDataView(Target *target)
header->setSectionResizeMode(1, QHeaderView::Stretch);
};
connect(target, &Target::deploymentDataChanged, this, updatModel);
updatModel();
const auto deploymentDataFromModel = [model] {
DeploymentData deployData;
for (int i = 0; i < model->rowCount(); ++i) {
const auto item = static_cast<DeploymentDataItem *>(
model->itemForIndex(model->index(i, 0)));
if (!item->file.localFilePath().isEmpty() && !item->file.remoteDirectory().isEmpty())
deployData.addFile(item->file);
}
return deployData;
};
const auto updateButtons = [dc, view, addButton, removeButton] {
addButton->setEnabled(dc->usesCustomDeploymentData());
removeButton->setEnabled(dc->usesCustomDeploymentData()
&& view->selectionModel()->hasSelection());
};
connect(dc->target(), &Target::deploymentDataChanged, this, [dc, updateModel] {
if (!dc->usesCustomDeploymentData())
updateModel();
});
connect(sourceCheckBox, &QCheckBox::toggled, this, [dc, updateModel, updateButtons](bool checked) {
dc->setUseCustomDeploymentData(checked);
updateModel();
updateButtons();
});
connect(addButton, &QPushButton::clicked, this, [model, view] {
const auto newItem = new DeploymentDataItem(DeployableFile(), true);
model->rootItem()->appendChild(newItem);
view->edit(model->indexForItem(newItem));
});
connect(removeButton, &QPushButton::clicked, this, [dc, model, view, deploymentDataFromModel] {
const QModelIndexList selectedIndexes = view->selectionModel()->selectedIndexes();
if (!selectedIndexes.isEmpty()) {
model->destroyItem(model->itemForIndex(selectedIndexes.first()));
dc->setCustomDeploymentData(deploymentDataFromModel());
}
});
connect(model, &QAbstractItemModel::dataChanged, this, [dc, deploymentDataFromModel] {
if (dc->usesCustomDeploymentData())
dc->setCustomDeploymentData(deploymentDataFromModel());
});
connect(view->selectionModel(), &QItemSelectionModel::selectionChanged, this, [updateButtons] {
updateButtons();
});
updateModel();
updateButtons();
}
} // Internal

View File

@@ -29,7 +29,7 @@
namespace ProjectExplorer {
class Target;
class DeployConfiguration;
namespace Internal {
@@ -38,7 +38,7 @@ class DeploymentDataView : public QWidget
Q_OBJECT
public:
explicit DeploymentDataView(Target *target);
explicit DeploymentDataView(DeployConfiguration *dc);
};
} // Internal

View File

@@ -221,6 +221,14 @@ BuildSystem *Target::fallbackBuildSystem() const
}
DeploymentData Target::deploymentData() const
{
const DeployConfiguration * const dc = activeDeployConfiguration();
if (dc && dc->usesCustomDeploymentData())
return dc->customDeploymentData();
return buildSystemDeploymentData();
}
DeploymentData Target::buildSystemDeploymentData() const
{
QTC_ASSERT(buildSystem(), return {});
return buildSystem()->deploymentData();

View File

@@ -115,6 +115,7 @@ public:
BuildSystem *fallbackBuildSystem() const;
DeploymentData deploymentData() const;
DeploymentData buildSystemDeploymentData() const;
const QList<BuildTargetInfo> applicationTargets() const;
BuildTargetInfo buildTarget(const QString &buildKey) const;