diff --git a/src/plugins/projectexplorer/deployconfiguration.cpp b/src/plugins/projectexplorer/deployconfiguration.cpp index 29c80cb175a..f4100036468 100644 --- a/src/plugins/projectexplorer/deployconfiguration.cpp +++ b/src/plugins/projectexplorer/deployconfiguration.cpp @@ -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 &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) diff --git a/src/plugins/projectexplorer/deployconfiguration.h b/src/plugins/projectexplorer/deployconfiguration.h index 9c82d93466f..156fb526749 100644 --- a/src/plugins/projectexplorer/deployconfiguration.h +++ b/src/plugins/projectexplorer/deployconfiguration.h @@ -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 m_configWidgetCreator; + using WidgetCreator = std::function; + 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 &configWidgetCreator); + void setConfigWidgetCreator(const DeployConfiguration::WidgetCreator &configWidgetCreator); void setUseDeploymentDataView(); using PostRestore = std::function; @@ -108,7 +118,7 @@ private: QList m_supportedTargetDeviceTypes; QList m_initialSteps; QString m_defaultDisplayName; - std::function m_configWidgetCreator; + DeployConfiguration::WidgetCreator m_configWidgetCreator; PostRestore m_postRestore; }; diff --git a/src/plugins/projectexplorer/deploymentdataview.cpp b/src/plugins/projectexplorer/deploymentdataview.cpp index 8796c897db1..f3fcc072b4f 100644 --- a/src/plugins/projectexplorer/deploymentdataview.cpp +++ b/src/plugins/projectexplorer/deploymentdataview.cpp @@ -26,6 +26,7 @@ #include "deploymentdataview.h" #include "buildsystem.h" +#include "deployconfiguration.h" #include "deploymentdata.h" #include "target.h" @@ -33,8 +34,11 @@ #include #include -#include +#include +#include #include +#include +#include #include #include @@ -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(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( + 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 diff --git a/src/plugins/projectexplorer/deploymentdataview.h b/src/plugins/projectexplorer/deploymentdataview.h index 178a96e3bb9..105e9086203 100644 --- a/src/plugins/projectexplorer/deploymentdataview.h +++ b/src/plugins/projectexplorer/deploymentdataview.h @@ -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 diff --git a/src/plugins/projectexplorer/target.cpp b/src/plugins/projectexplorer/target.cpp index 91a9b600ac2..aa20d94aa82 100644 --- a/src/plugins/projectexplorer/target.cpp +++ b/src/plugins/projectexplorer/target.cpp @@ -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(); diff --git a/src/plugins/projectexplorer/target.h b/src/plugins/projectexplorer/target.h index 6a9d7aa5120..2e452fac22c 100644 --- a/src/plugins/projectexplorer/target.h +++ b/src/plugins/projectexplorer/target.h @@ -115,6 +115,7 @@ public: BuildSystem *fallbackBuildSystem() const; DeploymentData deploymentData() const; + DeploymentData buildSystemDeploymentData() const; const QList applicationTargets() const; BuildTargetInfo buildTarget(const QString &buildKey) const;