21
21
#include "localization.h"
24
#include <unity/util/ResourcePtr.h>
25
#include <unity/UnityExceptions.h>
26
29
#include <QTextCodec>
29
35
using namespace scopes_ng;
30
36
namespace sc = unity::scopes;
41
typedef unity::util::ResourcePtr<int, std::function<void(int)>> FileLock;
43
static FileLock unixLock(const QString& path, bool writeLock)
45
FileLock fileLock(::open(path.toUtf8(), writeLock ? O_WRONLY : O_RDONLY), [](int fd)
53
if (fileLock.get() == -1)
55
throw unity::FileException("Couldn't open file " + path.toStdString(), errno);
59
fl.l_whence = SEEK_SET;
62
fl.l_type = writeLock ? F_WRLCK : F_RDLCK;
64
if (::fcntl(fileLock.get(), F_SETLKW, &fl) != 0)
66
throw unity::FileException("Couldn't get file lock for " + path.toStdString(), errno);
72
static const char* GROUP_NAME = "General";
32
76
SettingsModel::SettingsModel(const QDir& configDir, const QString& scopeId,
33
77
const QVariant& settingsDefinitions, QObject* parent,
34
78
int settingsTimeout)
38
82
configDir.mkpath(scopeId);
39
83
QDir databaseDir = configDir.filePath(scopeId);
41
m_settings.reset(new QSettings(databaseDir.filePath(QStringLiteral("settings.ini")), QSettings::IniFormat));
42
m_settings->setIniCodec("UTF-8");
85
m_settings_path = databaseDir.filePath(QStringLiteral("settings.ini"));
91
catch(const unity::FileException& e)
93
// Something has gone wrong, at this point we'll just have to continue with a null m_settings.
94
qWarning() << "SettingsModel::SettingsModel: Failed to read settings file:" << e.what();
44
97
for (const auto &it : settingsDefinitions.toList())
123
176
case Roles::RoleValue:
125
result = m_settings->value(data->id, data->defaultValue);
181
switch (data->variantType)
184
result = m_settings->get_boolean(GROUP_NAME, data->id.toStdString());
187
result = m_settings->get_int(GROUP_NAME, data->id.toStdString());
189
case QVariant::Double:
190
result = m_settings->get_double(GROUP_NAME, data->id.toStdString());
192
case QVariant::String:
193
result = m_settings->get_string(GROUP_NAME, data->id.toStdString()).c_str();
196
result = data->defaultValue;
199
catch(const unity::FileException& e)
201
qWarning() << "SettingsModel::data: Failed to read settings file:" << e.what();
202
result = data->defaultValue;
204
catch(const unity::LogicException&)
206
qWarning() << "SettingsModel::data: Failed to get a value for setting:" << data->id;
207
result = data->defaultValue;
126
209
result.convert(data->variantType);
165
248
QVariant SettingsModel::value(const QString& id) const
169
250
// Check for the setting id in the child scopes list first, in case the
170
251
// aggregator is incorrectly using a scope id as a settings as well.
171
252
if (m_child_scopes_data_by_id.contains(id))
181
262
else if (m_data_by_id.contains(id))
183
264
QSharedPointer<Data> data = m_data_by_id[id];
184
auto result = m_settings->value(data->id, data->defaultValue);
269
switch (data->variantType)
272
result = m_settings->get_boolean(GROUP_NAME, data->id.toStdString());
275
result = m_settings->get_int(GROUP_NAME, data->id.toStdString());
277
case QVariant::Double:
278
result = m_settings->get_double(GROUP_NAME, data->id.toStdString());
280
case QVariant::String:
281
result = m_settings->get_string(GROUP_NAME, data->id.toStdString()).c_str();
284
result = data->defaultValue;
287
catch(const unity::FileException& e)
289
qWarning() << "SettingsModel::value: Failed to read settings file:" << e.what();
290
result = data->defaultValue;
292
catch(const unity::LogicException&)
294
qWarning() << "SettingsModel::value: Failed to get a value for setting:" << data->id;
295
result = data->defaultValue;
185
297
result.convert(data->variantType);
353
465
else if (m_data_by_id.contains(setting_id))
355
m_settings->setValue(setting_id, value);
356
m_settings->sync(); // make sure the change to setting value is synced to fs
470
switch (value.type())
473
m_settings->set_boolean(GROUP_NAME, setting_id.toStdString(), value.toBool());
477
m_settings->set_int(GROUP_NAME, setting_id.toStdString(), value.toUInt());
479
case QVariant::Double:
480
m_settings->set_double(GROUP_NAME, setting_id.toStdString(), value.toDouble());
482
case QVariant::String:
483
m_settings->set_string(GROUP_NAME, setting_id.toStdString(), value.toString().toStdString());
486
qWarning() << "SettingsModel::settings_timeout: Invalid value type for setting:" << setting_id;
488
FileLock lock = unixLock(m_settings_path, true);
489
m_settings->sync(); // make sure the change to setting value is synced to fs
491
Q_EMIT settingsChanged();
493
catch(const unity::FileException& e)
495
qWarning() << "SettingsModel::settings_timeout: Failed to write settings file:" << e.what();
497
catch(const unity::LogicException&)
499
qWarning() << "SettingsModel::settings_timeout: Failed to set a value for setting:" << setting_id;
360
504
qWarning() << "No such setting:" << setting_id;
363
Q_EMIT settingsChanged();
508
void SettingsModel::tryLoadSettings() const
512
QFileInfo checkFile(m_settings_path);
513
if (!checkFile.exists() || !checkFile.isFile())
515
// Config file does not exist, so we create an empty one.
516
if (!QFile(m_settings_path).open(QFile::WriteOnly))
518
throw unity::FileException("Could not create an empty settings file at: " + m_settings_path.toStdString(), -1);
522
FileLock lock = unixLock(m_settings_path, false);
523
m_settings.reset(new unity::util::IniParser(m_settings_path.toUtf8()));