From 145be455eedf8d61cef7cfbe8b495834fd7ebfc0 Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Wed, 24 Feb 2021 14:33:38 +0100 Subject: [PATCH] CMakeProjectManager: Add Batch Edit support for CMake configuration For the initial CMake parameters one can have an edit dialog. Now it's possible to batch edit variables also after the project has been configured. Change-Id: I406b8e7db16147032a75c82fddf9b7acec85c4bf Reviewed-by: Eike Ziller --- .../cmakebuildconfiguration.cpp | 54 +++++++++++++++++++ .../cmakeprojectmanager/configmodel.cpp | 53 +++++++++--------- src/plugins/cmakeprojectmanager/configmodel.h | 42 ++++++++++++++- 3 files changed, 118 insertions(+), 31 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index c6e9dd0a759..e29d54dba97 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -66,14 +66,18 @@ #include #include #include +#include #include #include +#include +#include #include #include #include #include #include +#include #include #include @@ -112,6 +116,8 @@ private: bool eventFilter(QObject *target, QEvent *event) override; + void batchEditConfiguration(); + CMakeBuildConfiguration *m_buildConfiguration; QTreeView *m_configView; ConfigModel *m_configModel; @@ -130,6 +136,8 @@ private: QTimer m_showProgressTimer; FancyLineEdit *m_filterEdit; InfoLabel *m_warningMessageLabel; + + QPushButton *m_batchEditButton = nullptr; }; static QModelIndex mapToSource(const QAbstractItemView *view, const QModelIndex &idx) @@ -288,6 +296,9 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc) m_clearSelectionButton->setEnabled(false); buttonLayout->addWidget(m_clearSelectionButton); buttonLayout->addWidget(m_resetButton); + m_batchEditButton = new QPushButton(tr("Batch Edit...")); + m_batchEditButton->setToolTip(tr("Set or reset multiple values in the CMake Configuration.")); + buttonLayout->addWidget(m_batchEditButton); buttonLayout->addItem(new QSpacerItem(10, 10, QSizePolicy::Fixed, QSizePolicy::Fixed)); m_showAdvancedCheckBox = new QCheckBox(tr("Advanced")); buttonLayout->addWidget(m_showAdvancedCheckBox); @@ -403,6 +414,8 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc) m_configView->setCurrentIndex(idx); m_configView->edit(idx); }); + connect(m_batchEditButton, &QAbstractButton::clicked, + this, &CMakeBuildSettingsWidget::batchEditConfiguration); connect(bc, &CMakeBuildConfiguration::errorOccurred, this, &CMakeBuildSettingsWidget::setError); connect(bc, &CMakeBuildConfiguration::warningOccurred, this, &CMakeBuildSettingsWidget::setWarning); @@ -418,6 +431,47 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc) updateSelection(); } + +void CMakeBuildSettingsWidget::batchEditConfiguration() +{ + auto dialog = new QDialog(this); + dialog->setWindowTitle(tr("Edit CMake Configuration")); + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->setModal(true); + auto layout = new QVBoxLayout(dialog); + auto editor = new QPlainTextEdit(dialog); + + auto label = new QLabel(dialog); + label->setText(tr("Enter one CMake variable per line.\n" + "To set or change a variable, use -D:=.\n" + " can have one of the following values: FILEPATH, PATH, BOOL, INTERNAL, or STRING.\n" + "To unset a variable, use -U.\n")); + editor->setMinimumSize(800, 200); + + auto chooser = new Utils::VariableChooser(dialog); + chooser->addSupportedWidget(editor); + chooser->addMacroExpanderProvider([this]() { return m_buildConfiguration->macroExpander(); }); + + auto buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); + + layout->addWidget(editor); + layout->addWidget(label); + layout->addWidget(buttons); + + connect(buttons, &QDialogButtonBox::accepted, dialog, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, dialog, &QDialog::reject); + connect(dialog, &QDialog::accepted, this, [=]{ + const CMakeConfig config = CMakeConfigItem::itemsFromArguments( + editor->toPlainText().split('\n', Qt::SkipEmptyParts)); + + m_configModel->setBatchEditConfiguration(config); + }); + + editor->setPlainText(m_buildConfiguration->configurationChangesArguments().join('\n')); + + dialog->show(); +} + void CMakeBuildSettingsWidget::setError(const QString &message) { m_buildConfiguration->buildDirectoryAspect()->setProblem(message); diff --git a/src/plugins/cmakeprojectmanager/configmodel.cpp b/src/plugins/cmakeprojectmanager/configmodel.cpp index 8dea7e57efc..f30adb22394 100644 --- a/src/plugins/cmakeprojectmanager/configmodel.cpp +++ b/src/plugins/cmakeprojectmanager/configmodel.cpp @@ -209,38 +209,33 @@ QList ConfigModel::configurationForCMake() const void ConfigModel::setConfiguration(const CMakeConfig &config) { setConfiguration(Utils::transform(config, [](const CMakeConfigItem &i) { - ConfigModel::DataItem j; - j.key = QString::fromUtf8(i.key); - j.value = QString::fromUtf8(i.value); - j.description = QString::fromUtf8(i.documentation); - j.values = i.values; - j.inCMakeCache = i.inCMakeCache; - - j.isAdvanced = i.isAdvanced; - j.isHidden = i.type == CMakeConfigItem::INTERNAL || i.type == CMakeConfigItem::STATIC; - - switch (i.type) { - case CMakeConfigItem::FILEPATH: - j.type = ConfigModel::DataItem::FILE; - break; - case CMakeConfigItem::PATH: - j.type = ConfigModel::DataItem::DIRECTORY; - break; - case CMakeConfigItem::BOOL: - j.type = ConfigModel::DataItem::BOOLEAN; - break; - case CMakeConfigItem::STRING: - j.type = ConfigModel::DataItem::STRING; - break; - default: - j.type = ConfigModel::DataItem::UNKNOWN; - break; - } - - return j; + return DataItem(i); })); } +void ConfigModel::setBatchEditConfiguration(const CMakeConfig &config) +{ + for (const auto &c: config) { + DataItem di(c); + auto existing = std::find(m_configuration.begin(), m_configuration.end(), di); + if (existing != m_configuration.end()) { + existing->isUnset = c.isUnset; + if (!c.isUnset) { + existing->isUserChanged = true; + existing->setType(c.type); + existing->value = QString::fromUtf8(c.value); + existing->newValue = existing->value; + } + } else if (!c.isUnset) { + InternalDataItem i(di); + i.isUserNew = true; + i.newValue = di.value; + m_configuration.append(i); + } + } + + generateTree(); +} void ConfigModel::setConfiguration(const QList &config) { diff --git a/src/plugins/cmakeprojectmanager/configmodel.h b/src/plugins/cmakeprojectmanager/configmodel.h index 7c5cfa205b1..74b12c7d742 100644 --- a/src/plugins/cmakeprojectmanager/configmodel.h +++ b/src/plugins/cmakeprojectmanager/configmodel.h @@ -44,8 +44,45 @@ public: ItemIsAdvancedRole = Qt::UserRole, }; - class DataItem { - public: + struct DataItem { + bool operator == (const DataItem& other) const { + return key == other.key; + } + + DataItem() {} + DataItem(const CMakeConfigItem &cmi) { + key = QString::fromUtf8(cmi.key); + value = QString::fromUtf8(cmi.value); + description = QString::fromUtf8(cmi.documentation); + values = cmi.values; + inCMakeCache = cmi.inCMakeCache; + + isAdvanced = cmi.isAdvanced; + isHidden = cmi.type == CMakeConfigItem::INTERNAL || cmi.type == CMakeConfigItem::STATIC; + + setType(cmi.type); + } + + void setType(CMakeConfigItem::Type cmt) { + switch (cmt) { + case CMakeConfigItem::FILEPATH: + type = FILE; + break; + case CMakeConfigItem::PATH: + type = DIRECTORY; + break; + case CMakeConfigItem::BOOL: + type = BOOLEAN; + break; + case CMakeConfigItem::STRING: + type = STRING; + break; + default: + type = UNKNOWN; + break; + } + } + enum Type { BOOLEAN, FILE, DIRECTORY, STRING, UNKNOWN}; QString key; @@ -70,6 +107,7 @@ public: const QString &description = QString(), const QStringList &values = QStringList()); void setConfiguration(const CMakeConfig &config); + void setBatchEditConfiguration(const CMakeConfig &config); void setConfiguration(const QList &config); void setConfigurationFromKit(const QHash &kitConfig);