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 <eike.ziller@qt.io>
This commit is contained in:
Cristian Adam
2021-02-24 14:33:38 +01:00
parent 52e0cb6623
commit 145be455ee
3 changed files with 118 additions and 31 deletions

View File

@@ -66,14 +66,18 @@
#include <utils/progressindicator.h>
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
#include <utils/variablechooser.h>
#include <QBoxLayout>
#include <QCheckBox>
#include <QDialog>
#include <QDialogButtonBox>
#include <QDir>
#include <QGridLayout>
#include <QLoggingCategory>
#include <QMenu>
#include <QMessageBox>
#include <QPlainTextEdit>
#include <QPushButton>
#include <QTimer>
@@ -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<variable>:<type>=<value>.\n"
"<type> can have one of the following values: FILEPATH, PATH, BOOL, INTERNAL, or STRING.\n"
"To unset a variable, use -U<variable>.\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);

View File

@@ -209,38 +209,33 @@ QList<ConfigModel::DataItem> 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<ConfigModel::InternalDataItem> &config)
{

View File

@@ -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<DataItem> &config);
void setConfigurationFromKit(const QHash<QString, QString> &kitConfig);