~ci-train-bot/unity-scopes-shell/unity-scopes-shell-ubuntu-xenial-landing-047

« back to all changes in this revision

Viewing changes to src/Unity/settingsmodel.cpp

  • Committer: CI Train Bot
  • Author(s): Marcus Tomlinson
  • Date: 2016-04-05 06:03:53 UTC
  • mfrom: (295.2.9 lp-1552082)
  • Revision ID: ci-train-bot@canonical.com-20160405060353-p34z0d694i11bsfx
Replace QSettings with unity::util::IniParser Fixes: #1552082
Approved by: Pawel Stolowski

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
#include "localization.h"
22
22
#include "utils.h"
23
23
 
 
24
#include <unity/util/ResourcePtr.h>
 
25
#include <unity/UnityExceptions.h>
 
26
 
24
27
#include <QDebug>
25
28
#include <QDir>
26
29
#include <QTextCodec>
27
30
#include <QTimer>
28
31
 
 
32
#include <fcntl.h>
 
33
#include <unistd.h>
 
34
 
29
35
using namespace scopes_ng;
30
36
namespace sc = unity::scopes;
31
37
 
 
38
namespace
 
39
{
 
40
 
 
41
typedef unity::util::ResourcePtr<int, std::function<void(int)>> FileLock;
 
42
 
 
43
static FileLock unixLock(const QString& path, bool writeLock)
 
44
{
 
45
    FileLock fileLock(::open(path.toUtf8(), writeLock ? O_WRONLY : O_RDONLY), [](int fd)
 
46
    {
 
47
        if (fd != -1)
 
48
        {
 
49
            close(fd);
 
50
        }
 
51
    });
 
52
 
 
53
    if (fileLock.get() == -1)
 
54
    {
 
55
        throw unity::FileException("Couldn't open file " + path.toStdString(), errno);
 
56
    }
 
57
 
 
58
    struct flock fl;
 
59
    fl.l_whence = SEEK_SET;
 
60
    fl.l_start = 0;
 
61
    fl.l_len = 0;
 
62
    fl.l_type = writeLock ? F_WRLCK : F_RDLCK;
 
63
 
 
64
    if (::fcntl(fileLock.get(), F_SETLKW, &fl) != 0)
 
65
    {
 
66
        throw unity::FileException("Couldn't get file lock for " + path.toStdString(), errno);
 
67
    }
 
68
 
 
69
    return fileLock;
 
70
}
 
71
 
 
72
static const char* GROUP_NAME = "General";
 
73
 
 
74
}  // namespace
 
75
 
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);
40
84
 
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"));
 
86
 
 
87
    try
 
88
    {
 
89
        tryLoadSettings();
 
90
    }
 
91
    catch(const unity::FileException& e)
 
92
    {
 
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();
 
95
    }
43
96
 
44
97
    for (const auto &it : settingsDefinitions.toList())
45
98
    {
122
175
                break;
123
176
            case Roles::RoleValue:
124
177
            {
125
 
                result = m_settings->value(data->id, data->defaultValue);
 
178
                try
 
179
                {
 
180
                    tryLoadSettings();
 
181
                    switch (data->variantType)
 
182
                    {
 
183
                        case QVariant::Bool:
 
184
                            result = m_settings->get_boolean(GROUP_NAME, data->id.toStdString());
 
185
                            break;
 
186
                        case QVariant::UInt:
 
187
                            result = m_settings->get_int(GROUP_NAME, data->id.toStdString());
 
188
                            break;
 
189
                        case QVariant::Double:
 
190
                            result = m_settings->get_double(GROUP_NAME, data->id.toStdString());
 
191
                            break;
 
192
                        case QVariant::String:
 
193
                            result = m_settings->get_string(GROUP_NAME, data->id.toStdString()).c_str();
 
194
                            break;
 
195
                        default:
 
196
                            result = data->defaultValue;
 
197
                    }
 
198
                }
 
199
                catch(const unity::FileException& e)
 
200
                {
 
201
                    qWarning() << "SettingsModel::data: Failed to read settings file:" << e.what();
 
202
                    result = data->defaultValue;
 
203
                }
 
204
                catch(const unity::LogicException&)
 
205
                {
 
206
                    qWarning() << "SettingsModel::data: Failed to get a value for setting:" << data->id;
 
207
                    result = data->defaultValue;
 
208
                }
126
209
                result.convert(data->variantType);
127
210
                break;
128
211
            }
164
247
 
165
248
QVariant SettingsModel::value(const QString& id) const
166
249
{
167
 
    m_settings->sync();
168
 
 
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))
182
263
    {
183
264
        QSharedPointer<Data> data = m_data_by_id[id];
184
 
        auto result = m_settings->value(data->id, data->defaultValue);
 
265
        QVariant result;
 
266
        try
 
267
        {
 
268
            tryLoadSettings();
 
269
            switch (data->variantType)
 
270
            {
 
271
                case QVariant::Bool:
 
272
                    result = m_settings->get_boolean(GROUP_NAME, data->id.toStdString());
 
273
                    break;
 
274
                case QVariant::UInt:
 
275
                    result = m_settings->get_int(GROUP_NAME, data->id.toStdString());
 
276
                    break;
 
277
                case QVariant::Double:
 
278
                    result = m_settings->get_double(GROUP_NAME, data->id.toStdString());
 
279
                    break;
 
280
                case QVariant::String:
 
281
                    result = m_settings->get_string(GROUP_NAME, data->id.toStdString()).c_str();
 
282
                    break;
 
283
                default:
 
284
                    result = data->defaultValue;
 
285
            }
 
286
        }
 
287
        catch(const unity::FileException& e)
 
288
        {
 
289
            qWarning() << "SettingsModel::value: Failed to read settings file:" << e.what();
 
290
            result = data->defaultValue;
 
291
        }
 
292
        catch(const unity::LogicException&)
 
293
        {
 
294
            qWarning() << "SettingsModel::value: Failed to get a value for setting:" << data->id;
 
295
            result = data->defaultValue;
 
296
        }
185
297
        result.convert(data->variantType);
186
298
        return result;
187
299
    }
352
464
    }
353
465
    else if (m_data_by_id.contains(setting_id))
354
466
    {
355
 
        m_settings->setValue(setting_id, value);
356
 
        m_settings->sync(); // make sure the change to setting value is synced to fs
 
467
        try
 
468
        {
 
469
            tryLoadSettings();
 
470
            switch (value.type())
 
471
            {
 
472
                case QVariant::Bool:
 
473
                    m_settings->set_boolean(GROUP_NAME, setting_id.toStdString(), value.toBool());
 
474
                    break;
 
475
                case QVariant::Int:
 
476
                case QVariant::UInt:
 
477
                    m_settings->set_int(GROUP_NAME, setting_id.toStdString(), value.toUInt());
 
478
                    break;
 
479
                case QVariant::Double:
 
480
                    m_settings->set_double(GROUP_NAME, setting_id.toStdString(), value.toDouble());
 
481
                    break;
 
482
                case QVariant::String:
 
483
                    m_settings->set_string(GROUP_NAME, setting_id.toStdString(), value.toString().toStdString());
 
484
                    break;
 
485
                default:
 
486
                    qWarning() << "SettingsModel::settings_timeout: Invalid value type for setting:" << setting_id;
 
487
            }
 
488
            FileLock lock = unixLock(m_settings_path, true);
 
489
            m_settings->sync(); // make sure the change to setting value is synced to fs
 
490
 
 
491
            Q_EMIT settingsChanged();
 
492
        }
 
493
        catch(const unity::FileException& e)
 
494
        {
 
495
            qWarning() << "SettingsModel::settings_timeout: Failed to write settings file:" << e.what();
 
496
        }
 
497
        catch(const unity::LogicException&)
 
498
        {
 
499
            qWarning() << "SettingsModel::settings_timeout: Failed to set a value for setting:" << setting_id;
 
500
        }
357
501
    }
358
502
    else
359
503
    {
360
504
        qWarning() << "No such setting:" << setting_id;
361
505
    }
362
 
 
363
 
    Q_EMIT settingsChanged();
 
506
}
 
507
 
 
508
void SettingsModel::tryLoadSettings() const
 
509
{
 
510
    if (!m_settings)
 
511
    {
 
512
        QFileInfo checkFile(m_settings_path);
 
513
        if (!checkFile.exists() || !checkFile.isFile())
 
514
        {
 
515
            // Config file does not exist, so we create an empty one.
 
516
            if (!QFile(m_settings_path).open(QFile::WriteOnly))
 
517
            {
 
518
                throw unity::FileException("Could not create an empty settings file at: " + m_settings_path.toStdString(), -1);
 
519
            }
 
520
        }
 
521
 
 
522
        FileLock lock = unixLock(m_settings_path, false);
 
523
        m_settings.reset(new unity::util::IniParser(m_settings_path.toUtf8()));
 
524
    }
364
525
}