1 /* GCompris - ApplicationSettings.cpp
2  *
3  * SPDX-FileCopyrightText: 2014-2016 Johnny Jazeix <jazeix@gmail.com>
4  *
5  * Authors:
6  *   Johnny Jazeix <jazeix@gmail.com>
7  *
8  *   SPDX-License-Identifier: GPL-3.0-or-later
9  */
10 
11 #include "ApplicationSettings.h"
12 #include "ApplicationInfo.h"
13 
14 #include "DownloadManager.h"
15 
16 #include <qmath.h>
17 #include <QUrl>
18 #include <QUrlQuery>
19 #include <QGuiApplication>
20 #include <QScreen>
21 #include <QLocale>
22 #include <QRect>
23 
24 #include <QtQml>
25 
26 #define GC_DEFAULT_FONT QLatin1String("Andika-R.otf")
27 #define GC_DEFAULT_FONT_CAPITALIZATION 0 // Font.MixedCase
28 #define GC_DEFAULT_FONT_LETTER_SPACING 0
29 
30 static const char *GENERAL_GROUP_KEY = "General";
31 static const char *ADMIN_GROUP_KEY = "Admin";
32 static const char *INTERNAL_GROUP_KEY = "Internal";
33 static const char *FAVORITE_GROUP_KEY = "Favorite";
34 static const char *LEVELS_GROUP_KEY = "Levels";
35 
36 static const char *FULLSCREEN_KEY = "fullscreen";
37 static const char *PREVIOUS_HEIGHT_KEY = "previousHeight";
38 static const char *PREVIOUS_WIDTH_KEY = "previousWidth";
39 static const char *ENABLE_AUDIO_VOICES_KEY = "enableAudioVoices";
40 static const char *ENABLE_AUDIO_EFFECTS_KEY = "enableAudioEffects";
41 static const char *ENABLE_BACKGROUND_MUSIC_KEY = "enableBackgroundMusic";
42 static const char *VIRTUALKEYBOARD_KEY = "virtualKeyboard";
43 static const char *LOCALE_KEY = "locale";
44 static const char *FONT_KEY = "font";
45 static const char *IS_CURRENT_FONT_EMBEDDED = "isCurrentFontEmbedded";
46 static const char *ENABLE_AUTOMATIC_DOWNLOADS = "enableAutomaticDownloads";
47 static const char *FILTERED_BACKGROUND_MUSIC_KEY = "filteredBackgroundMusic";
48 static const char *BACKGROUND_MUSIC_VOLUME_KEY = "backgroundMusicVolume";
49 static const char *AUDIO_EFFECTS_VOLUME_KEY = "audioEffectsVolume";
50 
51 static const char *DOWNLOAD_SERVER_URL_KEY = "downloadServerUrl";
52 static const char *CACHE_PATH_KEY = "cachePath";
53 static const char *USERDATA_PATH_KEY = "userDataPath";
54 static const char *RENDERER_KEY = "renderer";
55 
56 static const char *EXE_COUNT_KEY = "exeCount";
57 static const char *LAST_GC_VERSION_RAN = "lastGCVersionRan";
58 
59 static const char *FILTER_LEVEL_MIN = "filterLevelMin";
60 static const char *FILTER_LEVEL_MAX = "filterLevelMax";
61 
62 static const char *BASE_FONT_SIZE_KEY = "baseFontSize";
63 static const char *FONT_CAPITALIZATION = "fontCapitalization";
64 static const char *FONT_LETTER_SPACING = "fontLetterSpacing";
65 
66 static const char *DEFAULT_CURSOR = "defaultCursor";
67 static const char *NO_CURSOR = "noCursor";
68 static const char *KIOSK_KEY = "kiosk";
69 static const char *SECTION_VISIBLE = "sectionVisible";
70 static const char *WORDSET = "wordset";
71 static const char *USE_WORDSET = "useWordset";
72 
73 static const char *PROGRESS_KEY = "progress";
74 
75 static const char *DEFAULT_DOWNLOAD_SERVER = "https://cdn.kde.org/gcompris";
76 
77 ApplicationSettings *ApplicationSettings::m_instance = nullptr;
78 
ApplicationSettings(const QString & configPath,QObject * parent)79 ApplicationSettings::ApplicationSettings(const QString &configPath, QObject *parent) :
80     QObject(parent),
81     m_baseFontSizeMin(-7), m_baseFontSizeMax(7),
82     m_fontLetterSpacingMin(0.0), m_fontLetterSpacingMax(8.0),
83     m_config(configPath, QSettings::IniFormat)
84 {
85     const QRect &screenSize = QGuiApplication::screens().at(0)->availableGeometry();
86     // initialize from settings file or default
87 
88     // general group
89     m_config.beginGroup(GENERAL_GROUP_KEY);
90     m_isAudioEffectsEnabled = m_config.value(ENABLE_AUDIO_EFFECTS_KEY, true).toBool();
91     m_isBackgroundMusicEnabled = m_config.value(ENABLE_BACKGROUND_MUSIC_KEY, true).toBool();
92     m_isFullscreen = m_config.value(FULLSCREEN_KEY, true).toBool();
93     m_previousHeight = m_config.value(PREVIOUS_HEIGHT_KEY, screenSize.height()).toUInt();
94     m_previousWidth = m_config.value(PREVIOUS_WIDTH_KEY, screenSize.width()).toUInt();
95     m_isAudioVoicesEnabled = m_config.value(ENABLE_AUDIO_VOICES_KEY, true).toBool();
96     m_isVirtualKeyboard = m_config.value(VIRTUALKEYBOARD_KEY,
97                                          ApplicationInfo::getInstance()->isMobile())
98                               .toBool();
99     m_locale = m_config.value(LOCALE_KEY, GC_DEFAULT_LOCALE).toString();
100     m_font = m_config.value(FONT_KEY, GC_DEFAULT_FONT).toString();
101     if (m_font == QLatin1String("Andika-R.ttf"))
102         m_font = "Andika-R.otf";
103     m_fontCapitalization = m_config.value(FONT_CAPITALIZATION, GC_DEFAULT_FONT_CAPITALIZATION).toUInt();
104     m_fontLetterSpacing = m_config.value(FONT_LETTER_SPACING, GC_DEFAULT_FONT_LETTER_SPACING).toReal();
105     m_isEmbeddedFont = m_config.value(IS_CURRENT_FONT_EMBEDDED, true).toBool();
106     m_filteredBackgroundMusic = m_config.value(FILTERED_BACKGROUND_MUSIC_KEY, ApplicationInfo::getInstance()->getBackgroundMusicFromRcc()).toStringList();
107     m_backgroundMusicVolume = m_config.value(BACKGROUND_MUSIC_VOLUME_KEY, 0.2).toReal();
108     m_audioEffectsVolume = m_config.value(AUDIO_EFFECTS_VOLUME_KEY, 0.7).toReal();
109 
110 #if defined(WITH_KIOSK_MODE)
111     m_isKioskMode = m_config.value(KIOSK_KEY, true).toBool();
112 #else
113     m_isKioskMode = m_config.value(KIOSK_KEY, false).toBool();
114 #endif
115 
116     m_sectionVisible = m_config.value(SECTION_VISIBLE, true).toBool();
117     m_wordset = m_config.value(WORDSET, "").toString();
118     m_useWordset = m_config.value(USE_WORDSET, true).toBool();
119     m_isAutomaticDownloadsEnabled = m_config.value(ENABLE_AUTOMATIC_DOWNLOADS,
120                                                    !ApplicationInfo::getInstance()->isMobile() && ApplicationInfo::isDownloadAllowed())
121                                         .toBool();
122     m_filterLevelMin = m_config.value(FILTER_LEVEL_MIN, 1).toUInt();
123     m_filterLevelMax = m_config.value(FILTER_LEVEL_MAX, 6).toUInt();
124     m_defaultCursor = m_config.value(DEFAULT_CURSOR, false).toBool();
125     m_noCursor = m_config.value(NO_CURSOR, false).toBool();
126     m_baseFontSize = m_config.value(BASE_FONT_SIZE_KEY, 0).toInt();
127 
128     m_config.sync(); // make sure all defaults are written back
129     m_config.endGroup();
130 
131     // admin group
132     m_config.beginGroup(ADMIN_GROUP_KEY);
133     m_downloadServerUrl = m_config.value(DOWNLOAD_SERVER_URL_KEY, QLatin1String(DEFAULT_DOWNLOAD_SERVER)).toString();
134     if (m_downloadServerUrl == "http://gcompris.net") {
135         setDownloadServerUrl(DEFAULT_DOWNLOAD_SERVER);
136     }
137     m_cachePath = m_config.value(CACHE_PATH_KEY, QStandardPaths::writableLocation(QStandardPaths::CacheLocation)).toString();
138 #if defined(UBUNTUTOUCH)
139     m_userDataPath = m_config.value(USERDATA_PATH_KEY, QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).toString();
140 #else
141     m_userDataPath = m_config.value(USERDATA_PATH_KEY, QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/GCompris")).toString();
142 #endif
143     m_renderer = m_config.value(RENDERER_KEY, GRAPHICAL_RENDERER).toString();
144     m_config.endGroup();
145 
146     // internal group
147     m_config.beginGroup(INTERNAL_GROUP_KEY);
148     m_exeCount = m_config.value(EXE_COUNT_KEY, 0).toUInt();
149     m_lastGCVersionRan = m_config.value(LAST_GC_VERSION_RAN, 0).toUInt();
150     m_config.endGroup();
151 
152     // no group
153     m_isBarHidden = false;
154 
155     connect(this, &ApplicationSettings::audioVoicesEnabledChanged, this, &ApplicationSettings::notifyAudioVoicesEnabledChanged);
156     connect(this, &ApplicationSettings::audioEffectsEnabledChanged, this, &ApplicationSettings::notifyAudioEffectsEnabledChanged);
157     connect(this, &ApplicationSettings::backgroundMusicEnabledChanged, this, &ApplicationSettings::notifyBackgroundMusicEnabledChanged);
158     connect(this, &ApplicationSettings::filteredBackgroundMusicChanged, this, &ApplicationSettings::notifyFilteredBackgroundMusicChanged);
159     connect(this, &ApplicationSettings::fullscreenChanged, this, &ApplicationSettings::notifyFullscreenChanged);
160     connect(this, &ApplicationSettings::previousHeightChanged, this, &ApplicationSettings::notifyPreviousHeightChanged);
161     connect(this, &ApplicationSettings::previousWidthChanged, this, &ApplicationSettings::notifyPreviousWidthChanged);
162     connect(this, &ApplicationSettings::localeChanged, this, &ApplicationSettings::notifyLocaleChanged);
163     connect(this, &ApplicationSettings::fontChanged, this, &ApplicationSettings::notifyFontChanged);
164     connect(this, &ApplicationSettings::virtualKeyboardChanged, this, &ApplicationSettings::notifyVirtualKeyboardChanged);
165     connect(this, &ApplicationSettings::automaticDownloadsEnabledChanged, this, &ApplicationSettings::notifyAutomaticDownloadsEnabledChanged);
166     connect(this, &ApplicationSettings::filterLevelMinChanged, this, &ApplicationSettings::notifyFilterLevelMinChanged);
167     connect(this, &ApplicationSettings::filterLevelMaxChanged, this, &ApplicationSettings::notifyFilterLevelMaxChanged);
168     connect(this, &ApplicationSettings::sectionVisibleChanged, this, &ApplicationSettings::notifySectionVisibleChanged);
169     connect(this, &ApplicationSettings::wordsetChanged, this, &ApplicationSettings::notifyWordsetChanged);
170     connect(this, &ApplicationSettings::useWordsetChanged, this, &ApplicationSettings::notifyUseWordsetChanged);
171     connect(this, &ApplicationSettings::kioskModeChanged, this, &ApplicationSettings::notifyKioskModeChanged);
172     connect(this, &ApplicationSettings::downloadServerUrlChanged, this, &ApplicationSettings::notifyDownloadServerUrlChanged);
173     connect(this, &ApplicationSettings::cachePathChanged, this, &ApplicationSettings::notifyCachePathChanged);
174     connect(this, &ApplicationSettings::userDataPathChanged, this, &ApplicationSettings::notifyUserDataPathChanged);
175     connect(this, &ApplicationSettings::rendererChanged, this, &ApplicationSettings::notifyRendererChanged);
176     connect(this, &ApplicationSettings::exeCountChanged, this, &ApplicationSettings::notifyExeCountChanged);
177     connect(this, &ApplicationSettings::barHiddenChanged, this, &ApplicationSettings::notifyBarHiddenChanged);
178     connect(this, &ApplicationSettings::lastGCVersionRanChanged, this, &ApplicationSettings::notifyLastGCVersionRanChanged);
179     connect(this, &ApplicationSettings::backgroundMusicVolumeChanged, this, &ApplicationSettings::notifyBackgroundMusicVolumeChanged);
180     connect(this, &ApplicationSettings::audioEffectsVolumeChanged, this, &ApplicationSettings::notifyAudioEffectsVolumeChanged);
181 }
182 
~ApplicationSettings()183 ApplicationSettings::~ApplicationSettings()
184 {
185     // make sure settings file is up2date:
186     // general group
187     m_config.beginGroup(GENERAL_GROUP_KEY);
188     m_config.setValue(ENABLE_AUDIO_VOICES_KEY, m_isAudioVoicesEnabled);
189     m_config.setValue(ENABLE_BACKGROUND_MUSIC_KEY, m_isBackgroundMusicEnabled);
190     m_config.setValue(FILTERED_BACKGROUND_MUSIC_KEY, m_filteredBackgroundMusic);
191     m_config.setValue(BACKGROUND_MUSIC_VOLUME_KEY, m_backgroundMusicVolume);
192     m_config.setValue(AUDIO_EFFECTS_VOLUME_KEY, m_audioEffectsVolume);
193     m_config.setValue(LOCALE_KEY, m_locale);
194     m_config.setValue(FONT_KEY, m_font);
195     m_config.setValue(IS_CURRENT_FONT_EMBEDDED, m_isEmbeddedFont);
196     m_config.setValue(FULLSCREEN_KEY, m_isFullscreen);
197     m_config.setValue(PREVIOUS_HEIGHT_KEY, m_previousHeight);
198     m_config.setValue(PREVIOUS_WIDTH_KEY, m_previousWidth);
199     m_config.setValue(VIRTUALKEYBOARD_KEY, m_isVirtualKeyboard);
200     m_config.setValue(ENABLE_AUTOMATIC_DOWNLOADS, m_isAutomaticDownloadsEnabled);
201     m_config.setValue(FILTER_LEVEL_MIN, m_filterLevelMin);
202     m_config.setValue(FILTER_LEVEL_MAX, m_filterLevelMax);
203     m_config.setValue(KIOSK_KEY, m_isKioskMode);
204     m_config.setValue(SECTION_VISIBLE, m_sectionVisible);
205     m_config.setValue(WORDSET, m_wordset);
206     m_config.setValue(USE_WORDSET, m_useWordset);
207     m_config.setValue(DEFAULT_CURSOR, m_defaultCursor);
208     m_config.setValue(NO_CURSOR, m_noCursor);
209     m_config.setValue(BASE_FONT_SIZE_KEY, m_baseFontSize);
210     m_config.setValue(FONT_CAPITALIZATION, m_fontCapitalization);
211     m_config.setValue(FONT_LETTER_SPACING, m_fontLetterSpacing);
212     m_config.endGroup();
213 
214     // admin group
215     m_config.beginGroup(ADMIN_GROUP_KEY);
216     m_config.setValue(DOWNLOAD_SERVER_URL_KEY, m_downloadServerUrl);
217     m_config.setValue(CACHE_PATH_KEY, m_cachePath);
218     m_config.setValue(USERDATA_PATH_KEY, m_userDataPath);
219     m_config.setValue(RENDERER_KEY, m_renderer);
220     m_config.endGroup();
221 
222     // internal group
223     m_config.beginGroup(INTERNAL_GROUP_KEY);
224     m_config.setValue(EXE_COUNT_KEY, m_exeCount);
225     m_config.setValue(LAST_GC_VERSION_RAN, m_lastGCVersionRan);
226     m_config.endGroup();
227 
228     m_config.sync();
229 
230     m_instance = nullptr;
231 }
232 
notifyAudioVoicesEnabledChanged()233 void ApplicationSettings::notifyAudioVoicesEnabledChanged()
234 {
235     updateValueInConfig(GENERAL_GROUP_KEY, ENABLE_AUDIO_VOICES_KEY, m_isAudioVoicesEnabled);
236     qDebug() << "notifyAudioVoices: " << m_isAudioVoicesEnabled;
237 }
238 
notifyAudioEffectsEnabledChanged()239 void ApplicationSettings::notifyAudioEffectsEnabledChanged()
240 {
241     updateValueInConfig(GENERAL_GROUP_KEY, ENABLE_AUDIO_EFFECTS_KEY, m_isAudioEffectsEnabled);
242     qDebug() << "notifyAudioEffects: " << m_isAudioEffectsEnabled;
243 }
244 
notifyBackgroundMusicEnabledChanged()245 void ApplicationSettings::notifyBackgroundMusicEnabledChanged()
246 {
247     updateValueInConfig(GENERAL_GROUP_KEY, ENABLE_BACKGROUND_MUSIC_KEY, m_isBackgroundMusicEnabled);
248     qDebug() << "notifyBackgroundMusic: " << m_isBackgroundMusicEnabled;
249 }
250 
notifyFilteredBackgroundMusicChanged()251 void ApplicationSettings::notifyFilteredBackgroundMusicChanged()
252 {
253     updateValueInConfig(GENERAL_GROUP_KEY, FILTERED_BACKGROUND_MUSIC_KEY, m_filteredBackgroundMusic);
254     qDebug() << "filteredBackgroundMusic: " << m_filteredBackgroundMusic;
255 }
256 
notifyBackgroundMusicVolumeChanged()257 void ApplicationSettings::notifyBackgroundMusicVolumeChanged()
258 {
259     updateValueInConfig(GENERAL_GROUP_KEY, BACKGROUND_MUSIC_VOLUME_KEY, m_backgroundMusicVolume);
260     qDebug() << "backgroundMusicVolume: " << m_backgroundMusicVolume;
261 }
262 
notifyAudioEffectsVolumeChanged()263 void ApplicationSettings::notifyAudioEffectsVolumeChanged()
264 {
265     updateValueInConfig(GENERAL_GROUP_KEY, AUDIO_EFFECTS_VOLUME_KEY, m_audioEffectsVolume);
266     qDebug() << "audioEffectsVolume: " << m_audioEffectsVolume;
267 }
268 
notifyLocaleChanged()269 void ApplicationSettings::notifyLocaleChanged()
270 {
271     updateValueInConfig(GENERAL_GROUP_KEY, LOCALE_KEY, m_locale);
272     qDebug() << "new locale: " << m_locale;
273 }
274 
notifyFontChanged()275 void ApplicationSettings::notifyFontChanged()
276 {
277     updateValueInConfig(GENERAL_GROUP_KEY, FONT_KEY, m_font);
278     qDebug() << "new font: " << m_font;
279 }
280 
notifyEmbeddedFontChanged()281 void ApplicationSettings::notifyEmbeddedFontChanged()
282 {
283     updateValueInConfig(GENERAL_GROUP_KEY, IS_CURRENT_FONT_EMBEDDED, m_isEmbeddedFont);
284     qDebug() << "new font is embedded: " << m_isEmbeddedFont;
285 }
286 
notifyFontCapitalizationChanged()287 void ApplicationSettings::notifyFontCapitalizationChanged()
288 {
289     updateValueInConfig(GENERAL_GROUP_KEY, FONT_CAPITALIZATION, m_fontCapitalization);
290     qDebug() << "new fontCapitalization: " << m_fontCapitalization;
291 }
292 
notifyFontLetterSpacingChanged()293 void ApplicationSettings::notifyFontLetterSpacingChanged()
294 {
295     updateValueInConfig(GENERAL_GROUP_KEY, FONT_LETTER_SPACING, m_fontLetterSpacing);
296     qDebug() << "new fontLetterSpacing: " << m_fontLetterSpacing;
297 }
298 
notifyFullscreenChanged()299 void ApplicationSettings::notifyFullscreenChanged()
300 {
301     updateValueInConfig(GENERAL_GROUP_KEY, FULLSCREEN_KEY, m_isFullscreen);
302     qDebug() << "fullscreen set to: " << m_isFullscreen;
303 }
304 
notifyPreviousHeightChanged()305 void ApplicationSettings::notifyPreviousHeightChanged()
306 {
307     updateValueInConfig(GENERAL_GROUP_KEY, PREVIOUS_HEIGHT_KEY, m_previousHeight);
308     qDebug() << "previous height set to: " << m_previousHeight;
309 }
310 
notifyPreviousWidthChanged()311 void ApplicationSettings::notifyPreviousWidthChanged()
312 {
313     updateValueInConfig(GENERAL_GROUP_KEY, PREVIOUS_WIDTH_KEY, m_previousWidth);
314     qDebug() << "previous width set to: " << m_previousWidth;
315 }
316 
notifyVirtualKeyboardChanged()317 void ApplicationSettings::notifyVirtualKeyboardChanged()
318 {
319     updateValueInConfig(GENERAL_GROUP_KEY, VIRTUALKEYBOARD_KEY, m_isVirtualKeyboard);
320     qDebug() << "virtualkeyboard set to: " << m_isVirtualKeyboard;
321 }
322 
isAutomaticDownloadsEnabled() const323 bool ApplicationSettings::isAutomaticDownloadsEnabled() const
324 {
325     return m_isAutomaticDownloadsEnabled && ApplicationInfo::isDownloadAllowed();
326 }
setIsAutomaticDownloadsEnabled(const bool newIsAutomaticDownloadsEnabled)327 void ApplicationSettings::setIsAutomaticDownloadsEnabled(const bool newIsAutomaticDownloadsEnabled)
328 {
329     if (ApplicationInfo::isDownloadAllowed()) {
330         m_isAutomaticDownloadsEnabled = newIsAutomaticDownloadsEnabled;
331         emit automaticDownloadsEnabledChanged();
332     }
333 }
notifyAutomaticDownloadsEnabledChanged()334 void ApplicationSettings::notifyAutomaticDownloadsEnabledChanged()
335 {
336     updateValueInConfig(GENERAL_GROUP_KEY, ENABLE_AUTOMATIC_DOWNLOADS, m_isAutomaticDownloadsEnabled);
337     qDebug() << "enableAutomaticDownloads set to: " << m_isAutomaticDownloadsEnabled;
338 }
339 
notifyFilterLevelMinChanged()340 void ApplicationSettings::notifyFilterLevelMinChanged()
341 {
342     updateValueInConfig(GENERAL_GROUP_KEY, FILTER_LEVEL_MIN, m_filterLevelMin);
343     qDebug() << "filterLevelMin set to: " << m_filterLevelMin;
344 }
345 
notifyFilterLevelMaxChanged()346 void ApplicationSettings::notifyFilterLevelMaxChanged()
347 {
348     updateValueInConfig(GENERAL_GROUP_KEY, FILTER_LEVEL_MAX, m_filterLevelMax);
349     qDebug() << "filterLevelMax set to: " << m_filterLevelMax;
350 }
351 
notifyKioskModeChanged()352 void ApplicationSettings::notifyKioskModeChanged()
353 {
354     updateValueInConfig(GENERAL_GROUP_KEY, KIOSK_KEY, m_isKioskMode);
355     qDebug() << "notifyKioskMode: " << m_isKioskMode;
356 }
357 
notifySectionVisibleChanged()358 void ApplicationSettings::notifySectionVisibleChanged()
359 {
360     updateValueInConfig(GENERAL_GROUP_KEY, SECTION_VISIBLE, m_sectionVisible);
361     qDebug() << "notifySectionVisible: " << m_sectionVisible;
362 }
363 
notifyWordsetChanged()364 void ApplicationSettings::notifyWordsetChanged()
365 {
366     if (!m_wordset.isEmpty() && DownloadManager::getInstance()->haveLocalResource(m_wordset) && !DownloadManager::getInstance()->isDataRegistered("words")) {
367         // words.rcc is there -> register old file first
368         // then try to update in the background
369         DownloadManager::getInstance()->updateResource(m_wordset);
370     }
371 
372     updateValueInConfig(GENERAL_GROUP_KEY, WORDSET, m_wordset);
373     qDebug() << "notifyWordset: " << m_wordset;
374 }
375 
notifyUseWordsetChanged()376 void ApplicationSettings::notifyUseWordsetChanged()
377 {
378     updateValueInConfig(GENERAL_GROUP_KEY, USE_WORDSET, m_useWordset);
379     qDebug() << "notifyUseWordset: " << m_useWordset;
380 }
381 
notifyDownloadServerUrlChanged()382 void ApplicationSettings::notifyDownloadServerUrlChanged()
383 {
384     updateValueInConfig(ADMIN_GROUP_KEY, DOWNLOAD_SERVER_URL_KEY, m_downloadServerUrl);
385     qDebug() << "downloadServerUrl set to: " << m_downloadServerUrl;
386 }
387 
notifyCachePathChanged()388 void ApplicationSettings::notifyCachePathChanged()
389 {
390     updateValueInConfig(ADMIN_GROUP_KEY, CACHE_PATH_KEY, m_cachePath);
391     qDebug() << "cachePath set to: " << m_cachePath;
392 }
393 
notifyUserDataPathChanged()394 void ApplicationSettings::notifyUserDataPathChanged()
395 {
396     updateValueInConfig(ADMIN_GROUP_KEY, USERDATA_PATH_KEY, m_userDataPath);
397     qDebug() << "userDataPath set to: " << m_userDataPath;
398 }
399 
notifyRendererChanged()400 void ApplicationSettings::notifyRendererChanged()
401 {
402     updateValueInConfig(ADMIN_GROUP_KEY, RENDERER_KEY, m_renderer);
403     qDebug() << "renderer set to: " << m_renderer;
404 }
405 
notifyExeCountChanged()406 void ApplicationSettings::notifyExeCountChanged()
407 {
408     updateValueInConfig(INTERNAL_GROUP_KEY, EXE_COUNT_KEY, m_exeCount);
409     qDebug() << "exeCount set to: " << m_exeCount;
410 }
411 
notifyLastGCVersionRanChanged()412 void ApplicationSettings::notifyLastGCVersionRanChanged()
413 {
414     updateValueInConfig(INTERNAL_GROUP_KEY, LAST_GC_VERSION_RAN, m_lastGCVersionRan);
415     qDebug() << "lastVersionRan set to: " << m_lastGCVersionRan;
416 }
417 
notifyBarHiddenChanged()418 void ApplicationSettings::notifyBarHiddenChanged()
419 {
420     qDebug() << "is bar hidden: " << m_isBarHidden;
421 }
422 
saveBaseFontSize()423 void ApplicationSettings::saveBaseFontSize()
424 {
425     updateValueInConfig(GENERAL_GROUP_KEY, BASE_FONT_SIZE_KEY, m_baseFontSize);
426 }
427 
saveActivityConfiguration(const QString & activity,const QVariantMap & data)428 void ApplicationSettings::saveActivityConfiguration(const QString &activity, const QVariantMap &data)
429 {
430     qDebug() << "save configuration for:" << activity;
431     QMapIterator<QString, QVariant> i(data);
432     while (i.hasNext()) {
433         i.next();
434         updateValueInConfig(activity, i.key(), i.value(), false);
435     }
436     m_config.sync();
437 }
438 
loadActivityConfiguration(const QString & activity)439 QVariantMap ApplicationSettings::loadActivityConfiguration(const QString &activity)
440 {
441     qDebug() << "load configuration for:" << activity;
442     m_config.beginGroup(activity);
443     QStringList keys = m_config.childKeys();
444     QVariantMap data;
445     for (const QString &key: keys) {
446         data[key] = m_config.value(key);
447     }
448     m_config.endGroup();
449     return data;
450 }
451 
setFavorite(const QString & activity,bool favorite)452 void ApplicationSettings::setFavorite(const QString &activity, bool favorite)
453 {
454     updateValueInConfig(FAVORITE_GROUP_KEY, activity, favorite);
455 }
456 
isFavorite(const QString & activity)457 bool ApplicationSettings::isFavorite(const QString &activity)
458 {
459     m_config.beginGroup(FAVORITE_GROUP_KEY);
460     bool favorite = m_config.value(activity, false).toBool();
461     m_config.endGroup();
462     return favorite;
463 }
464 
setCurrentLevels(const QString & activity,const QStringList & level,bool sync)465 void ApplicationSettings::setCurrentLevels(const QString &activity, const QStringList &level, bool sync)
466 {
467     updateValueInConfig(LEVELS_GROUP_KEY, activity, level, sync);
468 }
469 
currentLevels(const QString & activity)470 QStringList ApplicationSettings::currentLevels(const QString &activity)
471 {
472     m_config.beginGroup(LEVELS_GROUP_KEY);
473     QStringList level = m_config.value(activity, QStringList()).toStringList();
474     m_config.endGroup();
475     return level;
476 }
477 
478 template <class T>
updateValueInConfig(const QString & group,const QString & key,const T & value,bool sync)479 void ApplicationSettings::updateValueInConfig(const QString &group,
480                                               const QString &key, const T &value, bool sync)
481 {
482     m_config.beginGroup(group);
483     m_config.setValue(key, value);
484     m_config.endGroup();
485     if (sync) {
486         m_config.sync();
487     }
488 }
489 
sync()490 void ApplicationSettings::sync()
491 {
492     m_config.sync();
493 }
494 
loadActivityProgress(const QString & activity)495 int ApplicationSettings::loadActivityProgress(const QString &activity)
496 {
497     int progress = 0;
498     m_config.beginGroup(activity);
499     progress = m_config.value(PROGRESS_KEY, 0).toInt();
500     m_config.endGroup();
501     qDebug() << "loaded progress for activity" << activity << ":" << progress;
502     return progress;
503 }
504 
saveActivityProgress(const QString & activity,int progress)505 void ApplicationSettings::saveActivityProgress(const QString &activity, int progress)
506 {
507     updateValueInConfig(activity, PROGRESS_KEY, progress);
508 }
509 
useExternalWordset()510 bool ApplicationSettings::useExternalWordset()
511 {
512     return !m_wordset.isEmpty() && DownloadManager::getInstance()->isDataRegistered("words");
513 }
514 
applicationSettingsProvider(QQmlEngine * engine,QJSEngine * scriptEngine)515 QObject *ApplicationSettings::applicationSettingsProvider(QQmlEngine *engine,
516                                                           QJSEngine *scriptEngine)
517 {
518     Q_UNUSED(engine)
519     Q_UNUSED(scriptEngine)
520 
521     ApplicationSettings *appSettings = getInstance();
522     return appSettings;
523 }
524