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