/
ssusettings.cpp
194 lines (157 loc) · 6.09 KB
/
ssusettings.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/**
* @file ssusettings.cpp
* @copyright 2013 Jolla Ltd.
* @author Bernd Wachter <bwachter@lart.info>
* @date 2013
*/
#include <QStringList>
#include <QDirIterator>
#include <QFileInfo>
#include <QDateTime>
#include "sandbox_p.h"
#include "ssusettings.h"
#include "ssulog.h"
SsuSettings::SsuSettings(): QSettings(){
}
SsuSettings::SsuSettings(const QString &fileName, Format format, QObject *parent):
QSettings(Sandbox::map(fileName), format, parent){
}
SsuSettings::SsuSettings(const QString &fileName, Format format, const QString &defaultFileName, QObject *parent):
QSettings(Sandbox::map(fileName), format, parent){
defaultSettingsFile = Sandbox::map(defaultFileName);
upgrade();
}
SsuSettings::SsuSettings(const QString &fileName, const QString &settingsDirectory, QObject *parent):
QSettings(Sandbox::map(fileName), QSettings::IniFormat, parent){
settingsd = Sandbox::map(settingsDirectory);
merge();
}
void SsuSettings::merge(bool keepOld){
if (settingsd == "")
return;
bool skipMerge = true;
SsuLog *ssuLog = SsuLog::instance();
QDirIterator it(settingsd, QDir::AllEntries|QDir::NoDot|QDir::NoDotDot, QDirIterator::FollowSymlinks);
QStringList settingsFiles;
QFileInfo oldSettingsInfo(fileName());
while (it.hasNext()){
QString f = it.next();
settingsFiles.append(it.filePath());
QFileInfo info(it.filePath());
if (info.lastModified() >= oldSettingsInfo.lastModified())
skipMerge = false;
}
if (skipMerge){
ssuLog->print(LOG_DEBUG, QString("Configuration file is newer than all config.d files, skipping merge"));
return;
}
settingsFiles.sort();
// delete all keys in the cached settings
if (settingsFiles.count() > 0 && !keepOld)
clear();
merge(this, settingsFiles);
sync();
}
void SsuSettings::merge(QSettings *masterSettings, const QStringList &settingsFiles){
SsuLog *ssuLog = SsuLog::instance();
foreach (const QString &settingsFile, settingsFiles){
QSettings settings(settingsFile, QSettings::IniFormat);
QStringList groups = settings.childGroups();
ssuLog->print(LOG_DEBUG, QString("Merging %1 into %2")
.arg(settingsFile)
.arg(masterSettings->fileName()));
foreach (const QString &group, groups){
masterSettings->beginGroup(group);
settings.beginGroup(group);
QStringList keys = settings.allKeys();
foreach (const QString &key, keys){
masterSettings->setValue(key, settings.value(key));
}
settings.endGroup();
masterSettings->endGroup();
}
}
}
/*
* If you change anything here, run `make update-upgrade-test-recipe` inside
* tests/ut_settings/ and check the impact of your changes with
* `git diff testdata/upgrade/recipe`. See ut_settings/upgradetesthelper.cpp for
* more details.
*/
void SsuSettings::upgrade(){
int configVersion=0;
int defaultConfigVersion=0;
SsuLog *ssuLog = SsuLog::instance();
if (defaultSettingsFile == "")
return;
QSettings defaultSettings(defaultSettingsFile, QSettings::IniFormat);
if (contains("configVersion"))
configVersion = value("configVersion").toInt();
if (defaultSettings.contains("configVersion"))
defaultConfigVersion = defaultSettings.value("configVersion").toInt();
if (configVersion < defaultConfigVersion){
ssuLog->print(LOG_DEBUG, QString("Configuration is outdated, updating from %1 to %2")
.arg(configVersion)
.arg(defaultConfigVersion));
for (int i=configVersion+1;i<=defaultConfigVersion;i++){
QStringList defaultKeys;
QString currentSection = QString("%1/").arg(i);
ssuLog->print(LOG_DEBUG, QString("Processing configuration version %1").arg(i));
defaultSettings.beginGroup(currentSection);
defaultKeys = defaultSettings.allKeys();
defaultSettings.endGroup();
foreach (const QString &key, defaultKeys){
// Default keys support both commands and new keys
if (key.compare("cmd-remove", Qt::CaseSensitive) == 0){
// Remove keys listed in value as string list
QStringList oldKeys = defaultSettings.value(currentSection + key).toStringList();
foreach (const QString &oldKey, oldKeys){
if (contains(oldKey)){
remove(oldKey);
ssuLog->print(LOG_DEBUG, QString("Removing old key: %1").arg(oldKey));
}
}
} else if (!contains(key)){
// Add new keys..
setValue(key, defaultSettings.value(currentSection + key));
ssuLog->print(LOG_DEBUG, QString("Adding key: %1").arg(key));
} else {
// ... or update the ones where default values has changed.
QVariant oldValue;
// check if an old value exists in an older configuration version
for (int j=i-1;j>0;j--){
if (defaultSettings.contains(QString("%1/").arg(j)+key)){
oldValue = defaultSettings.value(QString("%1/").arg(j)+key);
break;
}
}
// skip updating if there is no old value, since we can't check if the
// default value has changed
if (oldValue.isNull())
continue;
QVariant newValue = defaultSettings.value(currentSection + key);
if (oldValue == newValue){
// old and new value match, no need to do anything, apart from beating the
// person who added a useless key
continue;
} else {
// default value has changed, so check if the configuration is still
// using the old default value...
QVariant currentValue = value(key);
// testcase: handles properly default update of thing with changed value in ssu.ini?
if (currentValue == oldValue){
// ...and update the key if it does
setValue(key, newValue);
ssuLog->print(LOG_DEBUG, QString("Updating %1 from %2 to %3")
.arg(key)
.arg(currentValue.toString())
.arg(newValue.toString()));
}
}
}
}
setValue("configVersion", i);
}
sync();
}
}