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 <tim.jenssen@qt.io>
This commit is contained in:
Tobias Hunger
2017-09-29 23:34:52 +02:00
parent f4cd9cdb6a
commit 3f73f3a4f4
5 changed files with 67 additions and 32 deletions

View File

@@ -375,41 +375,40 @@ bool BuildDirManager::checkConfiguration()
return false; // No cache file yet. return false; // No cache file yet.
CMakeConfig newConfig; CMakeConfig newConfig;
QSet<QString> changedKeys; QHash<QString, QPair<QString, QString>> changedKeys;
QSet<QString> removedKeys; foreach (const CMakeConfigItem &projectItem, m_parameters.configuration) {
foreach (const CMakeConfigItem &iBc, m_parameters.configuration) { const QString projectKey = QString::fromUtf8(projectItem.key);
const CMakeConfigItem &iCache const QString projectValue = projectItem.expandedValue(m_parameters.expander);
= Utils::findOrDefault(cache, [&iBc](const CMakeConfigItem &i) { return i.key == iBc.key; }); const CMakeConfigItem &cmakeItem
if (iCache.isNull()) { = Utils::findOrDefault(cache, [&projectItem](const CMakeConfigItem &i) { return i.key == projectItem.key; });
removedKeys << QString::fromUtf8(iBc.key); const QString iCacheValue = QString::fromUtf8(cmakeItem.value);
} else if (QString::fromUtf8(iCache.value) != iBc.expandedValue(m_parameters.expander)) { if (cmakeItem.isNull()) {
changedKeys << QString::fromUtf8(iBc.key); changedKeys.insert(projectKey, qMakePair(tr("<removed>"), projectValue));
newConfig.append(iCache); } else if (iCacheValue != projectValue) {
changedKeys.insert(projectKey, qMakePair(iCacheValue, projectValue));
newConfig.append(cmakeItem);
} else { } else {
newConfig.append(iBc); newConfig.append(projectItem);
} }
} }
if (!changedKeys.isEmpty() || !removedKeys.isEmpty()) { if (!changedKeys.isEmpty()) {
QSet<QString> total = removedKeys + changedKeys; QStringList keyList = changedKeys.keys();
QStringList keyList = total.toList();
Utils::sort(keyList); 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) { foreach (const QString &k, keyList) {
QString change; const QPair<QString, QString> data = changedKeys.value(k);
if (removedKeys.contains(k)) table += QString::fromLatin1("\n<tr><td>%1</td><td>%2</td><td>%3</td></tr>")
change = tr("<removed>"); .arg(k)
else .arg(data.first.toHtmlEscaped())
change = QString::fromUtf8(CMakeConfigItem::valueOf(k.toUtf8(), cache)).trimmed(); .arg(data.second.toHtmlEscaped());
if (change.isEmpty())
change = tr("<empty>");
table += QString::fromLatin1("\n<tr><td>%1</td><td>%2</td></tr>").arg(k).arg(change.toHtmlEscaped());
} }
table += QLatin1String("\n</table>"); table += QLatin1String("\n</table>");
QPointer<QMessageBox> box = new QMessageBox(Core::ICore::mainWindow()); QPointer<QMessageBox> box = new QMessageBox(Core::ICore::mainWindow());
box->setText(tr("CMake configuration has changed on disk.")); 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 *defaultButton = box->addButton(tr("Overwrite Changes in CMake"), QMessageBox::RejectRole);
auto *applyButton = box->addButton(tr("Apply Changes to Project"), QMessageBox::ApplyRole); auto *applyButton = box->addButton(tr("Apply Changes to Project"), QMessageBox::ApplyRole);
box->setDefaultButton(defaultButton); box->setDefaultButton(defaultButton);

View File

@@ -286,7 +286,7 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
connect(m_resetButton, &QPushButton::clicked, m_configModel, &ConfigModel::resetAllChanges); connect(m_resetButton, &QPushButton::clicked, m_configModel, &ConfigModel::resetAllChanges);
connect(m_reconfigureButton, &QPushButton::clicked, this, [this]() { 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]() { connect(m_unsetButton, &QPushButton::clicked, this, [this]() {
m_configModel->toggleUnsetFlag(mapToSource(m_configView, m_configView->currentIndex())); m_configModel->toggleUnsetFlag(mapToSource(m_configView, m_configView->currentIndex()));
@@ -320,7 +320,12 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
connect(m_buildConfiguration->target(), &ProjectExplorer::Target::kitChanged, connect(m_buildConfiguration->target(), &ProjectExplorer::Target::kitChanged,
this, &CMakeBuildSettingsWidget::updateFromKit); this, &CMakeBuildSettingsWidget::updateFromKit);
connect(m_buildConfiguration, &CMakeBuildConfiguration::enabledChanged, 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()); updateSelection(QModelIndex(), QModelIndex());
} }
@@ -381,7 +386,19 @@ void CMakeBuildSettingsWidget::updateFromKit()
for (const CMakeConfigItem &i : config) for (const CMakeConfigItem &i : config)
configHash.insert(QString::fromUtf8(i.key), i.expandedValue(k)); 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) void CMakeBuildSettingsWidget::updateSelection(const QModelIndex &current, const QModelIndex &previous)

View File

@@ -65,6 +65,7 @@ private:
void updateAdvancedCheckBox(); void updateAdvancedCheckBox();
void updateFromKit(); void updateFromKit();
void setConfigurationForCMake();
void updateSelection(const QModelIndex &current, const QModelIndex &previous); void updateSelection(const QModelIndex &current, const QModelIndex &previous);
QAction *createForceAction(int type, const QModelIndex &idx); QAction *createForceAction(int type, const QModelIndex &idx);

View File

@@ -94,14 +94,31 @@ void ConfigModel::setConfiguration(const QList<DataItem> &config)
setConfiguration(Utils::transform(config, [](const DataItem &di) { return InternalDataItem(di); })); 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; m_kitConfiguration = kitConfig;
for (InternalDataItem &i : m_configuration) { for (InternalDataItem &i : m_configuration) {
if (m_kitConfiguration.contains(i.key)) { if (m_kitConfiguration.contains(i.key))
i.kitValue = m_kitConfiguration.value(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); setConfiguration(m_configuration);
} }
@@ -202,7 +219,7 @@ ConfigModel::DataItem ConfigModel::dataItemFromIndex(const QModelIndex &idx)
return DataItem(); return DataItem();
} }
QList<ConfigModel::DataItem> ConfigModel::configurationChanges() const QList<ConfigModel::DataItem> ConfigModel::configurationForCMake() const
{ {
const QList<InternalDataItem> tmp const QList<InternalDataItem> tmp
= Utils::filtered(m_configuration, [](const InternalDataItem &i) { = Utils::filtered(m_configuration, [](const InternalDataItem &i) {

View File

@@ -70,7 +70,8 @@ public:
const QStringList &values = QStringList()); const QStringList &values = QStringList());
void setConfiguration(const CMakeConfig &config); void setConfiguration(const CMakeConfig &config);
void setConfiguration(const QList<DataItem> &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 flush();
void resetAllChanges(); void resetAllChanges();
@@ -84,7 +85,7 @@ public:
static DataItem dataItemFromIndex(const QModelIndex &idx); static DataItem dataItemFromIndex(const QModelIndex &idx);
QList<DataItem> configurationChanges() const; QList<DataItem> configurationForCMake() const;
private: private: