Merge remote-tracking branch 'origin/4.0'

Change-Id: I80bc3371c6d7cf9f2d46cbcf8e79e4761213d8aa
This commit is contained in:
Eike Ziller
2016-05-27 12:01:36 +02:00
70 changed files with 1243 additions and 339 deletions

View File

@@ -30,6 +30,7 @@
#include "cmakeprojectmanager.h"
#include "cmaketool.h"
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <projectexplorer/kit.h>
@@ -49,6 +50,7 @@
#include <QFile>
#include <QFileInfo>
#include <QFileSystemWatcher>
#include <QMessageBox>
#include <QRegularExpression>
#include <QSet>
#include <QTemporaryDir>
@@ -61,20 +63,37 @@ namespace CMakeProjectManager {
namespace Internal {
static QStringList toArguments(const CMakeConfig &config, const ProjectExplorer::Kit *k) {
const QStringList argList
= Utils::transform(config, [k](const CMakeConfigItem &i) -> QString {
const QString tmp = i.toString();
return tmp.isEmpty() ? QString()
: QString::fromLatin1("-D") + k->macroExpander()->expand(tmp);
});
return Utils::filtered(argList, [](const QString &s) { return !s.isEmpty(); });
return Utils::transform(config, [k](const CMakeConfigItem &i) -> QString {
QString a = QString::fromLatin1("-D");
a.append(QString::fromUtf8(i.key));
switch (i.type) {
case CMakeConfigItem::FILEPATH:
a.append(QLatin1String(":FILEPATH="));
break;
case CMakeConfigItem::PATH:
a.append(QLatin1String(":PATH="));
break;
case CMakeConfigItem::BOOL:
a.append(QLatin1String(":BOOL="));
break;
case CMakeConfigItem::STRING:
a.append(QLatin1String(":STRING="));
break;
case CMakeConfigItem::INTERNAL:
a.append(QLatin1String(":INTERNAL="));
break;
}
a.append(i.expandedValue(k));
return a;
});
}
// --------------------------------------------------------------------
// BuildDirManager:
// --------------------------------------------------------------------
BuildDirManager::BuildDirManager(const CMakeBuildConfiguration *bc) :
BuildDirManager::BuildDirManager(CMakeBuildConfiguration *bc) :
m_buildConfiguration(bc),
m_watcher(new QFileSystemWatcher(this))
{
@@ -82,7 +101,7 @@ BuildDirManager::BuildDirManager(const CMakeBuildConfiguration *bc) :
m_projectName = sourceDirectory().fileName();
m_reparseTimer.setSingleShot(true);
m_reparseTimer.setInterval(500);
m_reparseTimer.setInterval(5000);
connect(&m_reparseTimer, &QTimer::timeout, this, &BuildDirManager::parse);
connect(m_watcher, &QFileSystemWatcher::fileChanged, this, [this]() {
@@ -155,6 +174,7 @@ void BuildDirManager::resetData()
{
m_hasData = false;
m_cmakeCache.clear();
m_projectName.clear();
m_buildTargets.clear();
m_watchedFiles.clear();
@@ -177,22 +197,23 @@ bool BuildDirManager::persistCMakeState()
delete m_tempDir;
m_tempDir = nullptr;
parse();
resetData();
QTimer::singleShot(0, this, &BuildDirManager::parse); // make sure signals only happen afterwards!
return true;
}
void BuildDirManager::parse()
{
checkConfiguration();
CMakeTool *tool = CMakeKitInformation::cmakeTool(kit());
const QString generator = CMakeGeneratorKitInformation::generator(kit());
QTC_ASSERT(tool, return);
QTC_ASSERT(!generator.isEmpty(), return);
// Pop up a dialog asking the user to rerun cmake
QString cbpFile = CMakeManager::findCbpFile(QDir(workDirectory().toString()));
QFileInfo cbpFileFi(cbpFile);
const QString cbpFile = CMakeManager::findCbpFile(QDir(workDirectory().toString()));
const QFileInfo cbpFileFi = cbpFile.isEmpty() ? QFileInfo() : QFileInfo(cbpFile);
if (!cbpFileFi.exists()) {
// Initial create:
startCMake(tool, generator, intendedConfiguration());
@@ -201,8 +222,8 @@ void BuildDirManager::parse()
const bool mustUpdate = m_watchedFiles.isEmpty()
|| Utils::anyOf(m_watchedFiles, [&cbpFileFi](const Utils::FileName &f) {
return f.toFileInfo().lastModified() > cbpFileFi.lastModified();
});
return f.toFileInfo().lastModified() > cbpFileFi.lastModified();
});
if (mustUpdate) {
startCMake(tool, generator, CMakeConfig());
} else {
@@ -254,21 +275,21 @@ void BuildDirManager::clearFiles()
CMakeConfig BuildDirManager::parsedConfiguration() const
{
if (!m_hasData)
return CMakeConfig();
Utils::FileName cacheFile = workDirectory();
cacheFile.appendPath(QLatin1String("CMakeCache.txt"));
QString errorMessage;
CMakeConfig result = parseConfiguration(cacheFile, &errorMessage);
if (!errorMessage.isEmpty())
emit errorOccured(errorMessage);
const Utils::FileName sourceOfBuildDir
= Utils::FileName::fromUtf8(CMakeConfigItem::valueOf("CMAKE_HOME_DIRECTORY", result));
if (sourceOfBuildDir != sourceDirectory()) // Use case-insensitive compare where appropriate
emit errorOccured(tr("The build directory is not for %1").arg(sourceDirectory().toUserOutput()));
return result;
if (m_cmakeCache.isEmpty()) {
Utils::FileName cacheFile = workDirectory();
cacheFile.appendPath(QLatin1String("CMakeCache.txt"));
if (!cacheFile.exists())
return m_cmakeCache;
QString errorMessage;
m_cmakeCache = parseConfiguration(cacheFile, &errorMessage);
if (!errorMessage.isEmpty())
emit errorOccured(errorMessage);
const Utils::FileName sourceOfBuildDir
= Utils::FileName::fromUtf8(CMakeConfigItem::valueOf("CMAKE_HOME_DIRECTORY", m_cmakeCache));
if (sourceOfBuildDir != sourceDirectory()) // Use case-insensitive compare where appropriate
emit errorOccured(tr("The build directory is not for %1").arg(sourceDirectory().toUserOutput()));
}
return m_cmakeCache;
}
void BuildDirManager::stopProcess()
@@ -335,6 +356,7 @@ void BuildDirManager::extractData()
return;
m_watcher->addPath(cbpFile);
m_watcher->addPath(workDirectory().toString() + QLatin1String("/CMakeCache.txt"));
// setFolderName
CMakeCbpParser cbpparser;
@@ -497,6 +519,61 @@ void BuildDirManager::processCMakeError()
});
}
void BuildDirManager::checkConfiguration()
{
if (m_tempDir) // always throw away changes in the tmpdir!
return;
ProjectExplorer::Kit *k = m_buildConfiguration->target()->kit();
const CMakeConfig cache = parsedConfiguration();
if (cache.isEmpty())
return; // No cache file yet.
CMakeConfig newConfig;
QSet<QString> changedKeys;
QSet<QString> removedKeys;
foreach (const CMakeConfigItem &iBc, intendedConfiguration()) {
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(k)) {
changedKeys << QString::fromUtf8(iBc.key);
newConfig.append(iCache);
} else {
newConfig.append(iBc);
}
}
if (!changedKeys.isEmpty() || !removedKeys.isEmpty()) {
QSet<QString> total = removedKeys + changedKeys;
QStringList keyList = total.toList();
Utils::sort(keyList);
QString table = QLatin1String("<table>");
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());
}
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->setStandardButtons(QMessageBox::Discard | QMessageBox::Apply);
box->setDefaultButton(QMessageBox::Discard);
int ret = box->exec();
if (ret == QMessageBox::Apply)
m_buildConfiguration->setCMakeConfiguration(newConfig);
}
}
static QByteArray trimCMakeCacheLine(const QByteArray &in) {
int start = 0;
while (start < in.count() && (in.at(start) == ' ' || in.at(start) == '\t'))
@@ -587,6 +664,8 @@ CMakeConfig BuildDirManager::parseConfiguration(const Utils::FileName &cacheFile
void BuildDirManager::maybeForceReparse()
{
checkConfiguration();
const QByteArray GENERATOR_KEY = "CMAKE_GENERATOR";
const QByteArray EXTRA_GENERATOR_KEY = "CMAKE_EXTRA_GENERATOR";
const QByteArray CMAKE_COMMAND_KEY = "CMAKE_COMMAND";

View File

@@ -63,7 +63,7 @@ class BuildDirManager : public QObject
Q_OBJECT
public:
BuildDirManager(const CMakeBuildConfiguration *bc);
BuildDirManager(CMakeBuildConfiguration *bc);
~BuildDirManager() override;
const ProjectExplorer::Kit *kit() const;
@@ -87,6 +87,8 @@ public:
void clearFiles();
CMakeConfig parsedConfiguration() const;
void checkConfiguration();
static CMakeConfig parseConfiguration(const Utils::FileName &cacheFile,
QString *errorMessage);
@@ -106,12 +108,12 @@ private:
void processCMakeOutput();
void processCMakeError();
bool m_hasData = false;
const CMakeBuildConfiguration *m_buildConfiguration = nullptr;
CMakeBuildConfiguration *m_buildConfiguration = nullptr;
Utils::QtcProcess *m_cmakeProcess = nullptr;
QTemporaryDir *m_tempDir = nullptr;
mutable CMakeConfig m_cmakeCache;
QSet<Utils::FileName> m_watchedFiles;
QString m_projectName;

View File

@@ -156,10 +156,6 @@ void CMakeBuildConfiguration::ctor()
void CMakeBuildConfiguration::maybeForceReparse()
{
ProjectExplorer::Kit *k = target()->kit();
CMakeConfig config = cmakeConfiguration();
config.append(CMakeConfigurationKitInformation::configuration(k)); // last value wins...
setCMakeConfiguration(config);
m_buildDirManager->maybeForceReparse();
}
@@ -206,18 +202,14 @@ QList<ConfigModel::DataItem> CMakeBuildConfiguration::completeCMakeConfiguration
if (m_completeConfigurationCache.isEmpty())
m_completeConfigurationCache = m_buildDirManager->parsedConfiguration();
CMakeConfig cache = Utils::filtered(m_completeConfigurationCache,
[](const CMakeConfigItem &i) {
return i.type != CMakeConfigItem::INTERNAL
&& i.type != CMakeConfigItem::STATIC;
});
return Utils::transform(cache, [](const CMakeConfigItem &i) {
return Utils::transform(m_completeConfigurationCache,
[this](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.isAdvanced = i.isAdvanced;
j.isAdvanced = i.isAdvanced || i.type == CMakeConfigItem::INTERNAL;
switch (i.type) {
case CMakeConfigItem::FILEPATH:
j.type = ConfigModel::DataItem::FILE;
@@ -272,7 +264,6 @@ void CMakeBuildConfiguration::setCurrentCMakeConfiguration(const QList<ConfigMod
return ni;
});
// There is a buildDirManager, so there must also be an active BC:
const CMakeConfig config = cmakeConfiguration() + newConfig;
setCMakeConfiguration(config);
@@ -303,11 +294,28 @@ static CMakeConfig removeDuplicates(const CMakeConfig &config)
void CMakeBuildConfiguration::setCMakeConfiguration(const CMakeConfig &config)
{
m_configuration = removeDuplicates(config);
const Kit *k = target()->kit();
CMakeConfig kitConfig = CMakeConfigurationKitInformation::configuration(k);
bool hasKitOverride = false;
foreach (const CMakeConfigItem &i, m_configuration) {
const QString b = CMakeConfigItem::expandedValueOf(k, i.key, kitConfig);
if (!b.isNull() && i.expandedValue(k) != b) {
hasKitOverride = true;
break;
}
}
if (hasKitOverride)
setWarning(tr("CMake Configuration set by the Kit was overridden in the project."));
else
setWarning(QString());
}
CMakeConfig CMakeBuildConfiguration::cmakeConfiguration() const
{
return m_configuration;
return removeDuplicates(CMakeConfigurationKitInformation::configuration(target()->kit())
+ m_configuration);
}
void CMakeBuildConfiguration::setError(const QString &message)
@@ -319,11 +327,24 @@ void CMakeBuildConfiguration::setError(const QString &message)
emit errorOccured(m_error);
}
void CMakeBuildConfiguration::setWarning(const QString &message)
{
if (m_warning == message)
return;
m_warning = message;
emit warningOccured(m_warning);
}
QString CMakeBuildConfiguration::error() const
{
return m_error;
}
QString CMakeBuildConfiguration::warning() const
{
return m_warning;
}
ProjectExplorer::NamedWidget *CMakeBuildConfiguration::createConfigWidget()
{
return new CMakeBuildSettingsWidget(this);
@@ -475,7 +496,6 @@ CMakeBuildInfo *CMakeBuildConfigurationFactory::createBuildInfo(const ProjectExp
auto info = new CMakeBuildInfo(this);
info->kitId = k->id();
info->sourceDirectory = sourceDir;
info->configuration = CMakeConfigurationKitInformation::configuration(k);
CMakeConfigItem buildTypeItem;
switch (buildType) {

View File

@@ -68,6 +68,7 @@ public:
CMakeConfig cmakeConfiguration() const;
QString error() const;
QString warning() const;
BuildDirManager *buildDirManager() const;
@@ -83,6 +84,7 @@ public:
signals:
void errorOccured(const QString &message);
void warningOccured(const QString &message);
void parsingStarted();
void dataAvailable();
@@ -97,9 +99,11 @@ private:
void setCurrentCMakeConfiguration(const QList<ConfigModel::DataItem> &items);
void setError(const QString &message);
void setWarning(const QString &message);
CMakeConfig m_configuration;
QString m_error;
QString m_warning;
mutable QList<CMakeConfigItem> m_completeConfigurationCache;

View File

@@ -48,6 +48,7 @@
#include <QPushButton>
#include <QSortFilterProxyModel>
#include <QSpacerItem>
#include <QMenu>
namespace CMakeProjectManager {
namespace Internal {
@@ -108,6 +109,17 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
boxLayout->addWidget(m_errorMessageLabel);
mainLayout->addLayout(boxLayout, row, 0, 1, 3, Qt::AlignHCenter);
++row;
m_warningLabel = new QLabel;
m_warningLabel->setPixmap(Core::Icons::WARNING.pixmap());
m_warningLabel->setVisible(false);
m_warningMessageLabel = new QLabel;
m_warningMessageLabel->setVisible(false);
auto boxLayout2 = new QHBoxLayout;
boxLayout2->addWidget(m_warningLabel);
boxLayout2->addWidget(m_warningMessageLabel);
mainLayout->addLayout(boxLayout2, row, 0, 1, 3, Qt::AlignHCenter);
++row;
mainLayout->addItem(new QSpacerItem(20, 10), row, 0);
@@ -142,6 +154,20 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
mainLayout->addWidget(findWrapper, row, 0, 1, 2);
auto buttonLayout = new QVBoxLayout;
m_addButton = new QPushButton(tr("&Add"));
buttonLayout->addWidget(m_addButton);
{
m_addButtonMenu = new QMenu;
m_addButtonMenu->addAction(tr("&Boolean"))->setData(
QVariant::fromValue(static_cast<int>(ConfigModel::DataItem::BOOLEAN)));
m_addButtonMenu->addAction(tr("&String"))->setData(
QVariant::fromValue(static_cast<int>(ConfigModel::DataItem::STRING)));
m_addButtonMenu->addAction(tr("&Directory"))->setData(
QVariant::fromValue(static_cast<int>(ConfigModel::DataItem::DIRECTORY)));
m_addButtonMenu->addAction(tr("&File"))->setData(
QVariant::fromValue(static_cast<int>(ConfigModel::DataItem::FILE)));
m_addButton->setMenu(m_addButtonMenu);
}
m_editButton = new QPushButton(tr("&Edit"));
buttonLayout->addWidget(m_editButton);
m_resetButton = new QPushButton(tr("&Reset"));
@@ -161,6 +187,7 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
updateAdvancedCheckBox();
setError(bc->error());
setWarning(bc->warning());
connect(project, &CMakeProject::parsingStarted, this, [this]() {
updateButtonState();
@@ -201,24 +228,49 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
m_configView->setCurrentIndex(idx);
m_configView->edit(idx);
});
connect(m_addButtonMenu, &QMenu::triggered, this, [this](QAction *action) {
ConfigModel::DataItem::Type type =
static_cast<ConfigModel::DataItem::Type>(action->data().value<int>());
QString value = tr("<UNSET>");
if (type == ConfigModel::DataItem::BOOLEAN)
value = QString::fromLatin1("OFF");
m_configModel->appendConfiguration(tr("<UNSET>"), value, type);
QModelIndex idx;
idx = m_configView->model()->index(
m_configView->model()->rowCount(idx) - 1, 0);
m_configView->setCurrentIndex(idx);
m_configView->edit(idx);
});
connect(bc, &CMakeBuildConfiguration::errorOccured, this, &CMakeBuildSettingsWidget::setError);
connect(bc, &CMakeBuildConfiguration::warningOccured, this, &CMakeBuildSettingsWidget::setWarning);
}
void CMakeBuildSettingsWidget::setError(const QString &message)
{
bool showWarning = !message.isEmpty();
m_errorLabel->setVisible(showWarning);
bool showError = !message.isEmpty();
m_errorLabel->setVisible(showError);
m_errorLabel->setToolTip(message);
m_errorMessageLabel->setVisible(showWarning);
m_errorMessageLabel->setVisible(showError);
m_errorMessageLabel->setText(message);
m_errorMessageLabel->setToolTip(message);
m_configView->setVisible(!showWarning);
m_editButton->setVisible(!showWarning);
m_resetButton->setVisible(!showWarning);
m_showAdvancedCheckBox->setVisible(!showWarning);
m_reconfigureButton->setVisible(!showWarning);
m_configView->setVisible(!showError);
m_editButton->setVisible(!showError);
m_resetButton->setVisible(!showError);
m_showAdvancedCheckBox->setVisible(!showError);
m_reconfigureButton->setVisible(!showError);
}
void CMakeBuildSettingsWidget::setWarning(const QString &message)
{
bool showWarning = !message.isEmpty();
m_warningLabel->setVisible(showWarning);
m_warningLabel->setToolTip(message);
m_warningMessageLabel->setVisible(showWarning);
m_warningMessageLabel->setText(message);
m_warningMessageLabel->setToolTip(message);
}
void CMakeBuildSettingsWidget::updateButtonState()

View File

@@ -37,6 +37,7 @@ class QLabel;
class QPushButton;
class QTreeView;
class QSortFilterProxyModel;
class QMenu;
QT_END_NAMESPACE
namespace CMakeProjectManager {
@@ -54,6 +55,7 @@ public:
CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc);
void setError(const QString &message);
void setWarning(const QString &message);
private:
void updateButtonState();
@@ -64,13 +66,17 @@ private:
ConfigModel *m_configModel;
QSortFilterProxyModel *m_configFilterModel;
Utils::ProgressIndicator *m_progressIndicator;
QPushButton *m_addButton;
QMenu *m_addButtonMenu;
QPushButton *m_editButton;
QPushButton *m_resetButton;
QCheckBox *m_showAdvancedCheckBox;
QPushButton *m_reconfigureButton;
QTimer m_showProgressTimer;
QLabel *m_errorLabel;
QLabel *m_warningLabel;
QLabel *m_errorMessageLabel;
QLabel *m_warningMessageLabel;
};
} // namespace Internal

View File

@@ -25,6 +25,9 @@
#include "cmakeconfigitem.h"
#include <projectexplorer/kit.h>
#include <utils/macroexpander.h>
#include <utils/qtcassert.h>
#include <QString>
@@ -60,6 +63,21 @@ QByteArray CMakeConfigItem::valueOf(const QByteArray &key, const QList<CMakeConf
return QByteArray();
}
QString CMakeConfigItem::expandedValueOf(const ProjectExplorer::Kit *k, const QByteArray &key,
const QList<CMakeConfigItem> &input)
{
for (auto it = input.constBegin(); it != input.constEnd(); ++it) {
if (it->key == key)
return it->expandedValue(k);
}
return QString();
}
QString CMakeConfigItem::expandedValue(const ProjectExplorer::Kit *k) const
{
return k->macroExpander()->expand(QString::fromUtf8(value));
}
std::function<bool (const CMakeConfigItem &a, const CMakeConfigItem &b)> CMakeConfigItem::sortOperator()
{
return [](const CMakeConfigItem &a, const CMakeConfigItem &b) { return a.key < b.key; };

View File

@@ -30,6 +30,8 @@
#include <functional>
namespace ProjectExplorer { class Kit; }
namespace CMakeProjectManager {
class CMakeConfigItem {
@@ -41,9 +43,12 @@ public:
CMakeConfigItem(const QByteArray &k, const QByteArray &v);
static QByteArray valueOf(const QByteArray &key, const QList<CMakeConfigItem> &input);
static QString expandedValueOf(const ProjectExplorer::Kit *k, const QByteArray &key,
const QList<CMakeConfigItem> &input);
bool isNull() const { return key.isEmpty(); }
QString expandedValue(const ProjectExplorer::Kit *k) const;
static std::function<bool(const CMakeConfigItem &a, const CMakeConfigItem &b)> sortOperator();
static CMakeConfigItem fromString(const QString &s);
QString toString() const;

View File

@@ -341,8 +341,10 @@ void CMakeProject::runCMake()
return;
BuildDirManager *bdm = bc->buildDirManager();
if (bdm && !bdm->isParsing())
if (bdm && !bdm->isParsing()) {
bdm->checkConfiguration();
bdm->forceReparse();
}
}
QList<CMakeBuildTarget> CMakeProject::buildTargets() const

View File

@@ -35,7 +35,8 @@ namespace CMakeProjectManager {
static bool isTrue(const QString &value)
{
const QString lower = value.toLower();
return lower == QStringLiteral("true") || lower == QStringLiteral("on") || lower == QStringLiteral("1");
return lower == QStringLiteral("true") || lower == QStringLiteral("on")
|| lower == QStringLiteral("1") || lower == QStringLiteral("yes");
}
ConfigModel::ConfigModel(QObject *parent) : QAbstractTableModel(parent)
@@ -71,7 +72,10 @@ Qt::ItemFlags ConfigModel::flags(const QModelIndex &index) const
else
return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
} else {
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
if (item.isUserNew)
return flags |= Qt::ItemIsEditable;
return flags;
}
}
@@ -163,7 +167,7 @@ bool ConfigModel::setData(const QModelIndex &index, const QVariant &value, int r
InternalDataItem &item = itemAtRow(index.row());
switch (index.column()) {
case 0:
if (!item.key.isEmpty())
if (!item.key.isEmpty() && !item.isUserNew)
return false;
item.key = newValue;
item.isUserNew = true;
@@ -202,6 +206,25 @@ QVariant ConfigModel::headerData(int section, Qt::Orientation orientation, int r
}
}
void ConfigModel::appendConfiguration(const QString &key,
const QString &value,
const ConfigModel::DataItem::Type type,
const QString &description)
{
DataItem item;
item.key = key;
item.type = type;
item.value = value;
item.description = description;
InternalDataItem internalItem(item);
internalItem.isUserNew = true;
beginResetModel();
m_configuration.append(internalItem);
endResetModel();
}
void ConfigModel::setConfiguration(const QList<ConfigModel::DataItem> &config)
{
QList<DataItem> tmp = config;

View File

@@ -55,6 +55,10 @@ public:
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
void appendConfiguration(const QString &key,
const QString &value = QString(),
const DataItem::Type type = DataItem::UNKNOWN,
const QString &description = QString());
void setConfiguration(const QList<DataItem> &config);
void flush();
void resetAllChanges();