Commit 3f73f3a4 authored by Tobias Hunger's avatar Tobias Hunger

CMake: Fix "CMake settings have changed on disk"

* Improve the UI by showing settings in CMake and the project
* Fix setting CMake configuration to project

Change-Id: I6e127344551fa00f3f7e6170465cb3dda2e4a634
Task-number: QTCREATORBUG-17555
Reviewed-by: Tim Jenssen's avatarTim Jenssen <tim.jenssen@qt.io>
parent f4cd9cdb
......@@ -375,41 +375,40 @@ bool BuildDirManager::checkConfiguration()
return false; // No cache file yet.
CMakeConfig newConfig;
QSet<QString> changedKeys;
QSet<QString> removedKeys;
foreach (const CMakeConfigItem &iBc, m_parameters.configuration) {
const CMakeConfigItem &iCache
= Utils::findOrDefault(cache, [&iBc](const CMakeConfigItem &i) { return i.key == iBc.key; });
if (iCache.isNull()) {
removedKeys << QString::fromUtf8(iBc.key);
} else if (QString::fromUtf8(iCache.value) != iBc.expandedValue(m_parameters.expander)) {
changedKeys << QString::fromUtf8(iBc.key);
newConfig.append(iCache);
QHash<QString, QPair<QString, QString>> changedKeys;
foreach (const CMakeConfigItem &projectItem, m_parameters.configuration) {
const QString projectKey = QString::fromUtf8(projectItem.key);
const QString projectValue = projectItem.expandedValue(m_parameters.expander);
const CMakeConfigItem &cmakeItem
= Utils::findOrDefault(cache, [&projectItem](const CMakeConfigItem &i) { return i.key == projectItem.key; });
const QString iCacheValue = QString::fromUtf8(cmakeItem.value);
if (cmakeItem.isNull()) {
changedKeys.insert(projectKey, qMakePair(tr("<removed>"), projectValue));
} else if (iCacheValue != projectValue) {
changedKeys.insert(projectKey, qMakePair(iCacheValue, projectValue));
newConfig.append(cmakeItem);
} else {
newConfig.append(iBc);
newConfig.append(projectItem);
}
}
if (!changedKeys.isEmpty() || !removedKeys.isEmpty()) {
QSet<QString> total = removedKeys + changedKeys;
QStringList keyList = total.toList();
if (!changedKeys.isEmpty()) {
QStringList keyList = changedKeys.keys();
Utils::sort(keyList);
QString table = QLatin1String("<table>");
QString table = QString::fromLatin1("<table><tr><th>%1</th><th>%2</th><th>%3</th></tr>")
.arg(tr("Key")).arg(tr("CMake")).arg(tr("Project"));
foreach (const QString &k, keyList) {
QString change;
if (removedKeys.contains(k))
change = tr("<removed>");
else
change = QString::fromUtf8(CMakeConfigItem::valueOf(k.toUtf8(), cache)).trimmed();
if (change.isEmpty())
change = tr("<empty>");
table += QString::fromLatin1("\n<tr><td>%1</td><td>%2</td></tr>").arg(k).arg(change.toHtmlEscaped());
const QPair<QString, QString> data = changedKeys.value(k);
table += QString::fromLatin1("\n<tr><td>%1</td><td>%2</td><td>%3</td></tr>")
.arg(k)
.arg(data.first.toHtmlEscaped())
.arg(data.second.toHtmlEscaped());
}
table += QLatin1String("\n</table>");
QPointer<QMessageBox> box = new QMessageBox(Core::ICore::mainWindow());
box->setText(tr("CMake configuration has changed on disk."));
box->setInformativeText(tr("The CMakeCache.txt file has changed: %1").arg(table));
box->setInformativeText(table);
auto *defaultButton = box->addButton(tr("Overwrite Changes in CMake"), QMessageBox::RejectRole);
auto *applyButton = box->addButton(tr("Apply Changes to Project"), QMessageBox::ApplyRole);
box->setDefaultButton(defaultButton);
......
......@@ -286,7 +286,7 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
connect(m_resetButton, &QPushButton::clicked, m_configModel, &ConfigModel::resetAllChanges);
connect(m_reconfigureButton, &QPushButton::clicked, this, [this]() {
m_buildConfiguration->setConfigurationForCMake(m_configModel->configurationChanges());
m_buildConfiguration->setConfigurationForCMake(m_configModel->configurationForCMake());
});
connect(m_unsetButton, &QPushButton::clicked, this, [this]() {
m_configModel->toggleUnsetFlag(mapToSource(m_configView, m_configView->currentIndex()));
......@@ -320,7 +320,12 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
connect(m_buildConfiguration->target(), &ProjectExplorer::Target::kitChanged,
this, &CMakeBuildSettingsWidget::updateFromKit);
connect(m_buildConfiguration, &CMakeBuildConfiguration::enabledChanged,
this, [this]() { setError(m_buildConfiguration->disabledReason()); });
this, [this]() {
setError(m_buildConfiguration->disabledReason());
setConfigurationForCMake();
});
connect(m_buildConfiguration, &CMakeBuildConfiguration::configurationForCMakeChanged,
this, [this]() { setConfigurationForCMake(); });
updateSelection(QModelIndex(), QModelIndex());
}
......@@ -381,7 +386,19 @@ void CMakeBuildSettingsWidget::updateFromKit()
for (const CMakeConfigItem &i : config)
configHash.insert(QString::fromUtf8(i.key), i.expandedValue(k));
m_configModel->setKitConfiguration(configHash);
m_configModel->setConfigurationFromKit(configHash);
}
void CMakeBuildSettingsWidget::setConfigurationForCMake()
{
QHash<QString, QString> config;
const CMakeConfig configList = m_buildConfiguration->configurationForCMake();
for (const CMakeConfigItem &i : configList) {
config.insert(QString::fromUtf8(i.key),
CMakeConfigItem::expandedValueOf(m_buildConfiguration->target()->kit(),
i.key, configList));
}
m_configModel->setConfigurationForCMake(config);
}
void CMakeBuildSettingsWidget::updateSelection(const QModelIndex &current, const QModelIndex &previous)
......
......@@ -65,6 +65,7 @@ private:
void updateAdvancedCheckBox();
void updateFromKit();
void setConfigurationForCMake();
void updateSelection(const QModelIndex &current, const QModelIndex &previous);
QAction *createForceAction(int type, const QModelIndex &idx);
......
......@@ -94,13 +94,30 @@ void ConfigModel::setConfiguration(const QList<DataItem> &config)
setConfiguration(Utils::transform(config, [](const DataItem &di) { return InternalDataItem(di); }));
}
void ConfigModel::setKitConfiguration(const QHash<QString, QString> &kitConfig)
void ConfigModel::setConfigurationFromKit(const QHash<QString, QString> &kitConfig)
{
m_kitConfiguration = kitConfig;
for (InternalDataItem &i : m_configuration) {
if (m_kitConfiguration.contains(i.key)) {
if (m_kitConfiguration.contains(i.key))
i.kitValue = m_kitConfiguration.value(i.key);
}
setConfiguration(m_configuration);
}
void ConfigModel::setConfigurationForCMake(const QHash<QString, QString> &config)
{
for (InternalDataItem &i : m_configuration) {
if (!config.contains(i.key))
continue;
const QString v = config.value(i.key);
if (i.value == v) {
i.newValue.clear();
i.isUserChanged = false;
} else {
i.newValue = v;
i.isUserChanged = true;
}
}
setConfiguration(m_configuration);
......@@ -202,7 +219,7 @@ ConfigModel::DataItem ConfigModel::dataItemFromIndex(const QModelIndex &idx)
return DataItem();
}
QList<ConfigModel::DataItem> ConfigModel::configurationChanges() const
QList<ConfigModel::DataItem> ConfigModel::configurationForCMake() const
{
const QList<InternalDataItem> tmp
= Utils::filtered(m_configuration, [](const InternalDataItem &i) {
......
......@@ -70,7 +70,8 @@ public:
const QStringList &values = QStringList());
void setConfiguration(const CMakeConfig &config);
void setConfiguration(const QList<DataItem> &config);
void setKitConfiguration(const QHash<QString, QString> &kitConfig);
void setConfigurationFromKit(const QHash<QString, QString> &kitConfig);
void setConfigurationForCMake(const QHash<QString, QString> &config);
void flush();
void resetAllChanges();
......@@ -84,7 +85,7 @@ public:
static DataItem dataItemFromIndex(const QModelIndex &idx);
QList<DataItem> configurationChanges() const;
QList<DataItem> configurationForCMake() const;
private:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment