1 /* GCompris - ApplicationSettings.h
2  *
3  * SPDX-FileCopyrightText: 2014 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 #ifndef APPLICATIONSETTINGS_H
12 #define APPLICATIONSETTINGS_H
13 
14 #include <QObject>
15 #include <QQmlEngine>
16 #include <QtGlobal>
17 #include <QDebug>
18 
19 #include <QSettings>
20 #include <QStandardPaths>
21 
22 #include <config.h>
23 
24 #define GC_DEFAULT_LOCALE "system"
25 
26 /**
27  * @class ApplicationSettings
28  * @short Singleton that contains GCompris' persistent settings.
29  * @ingroup infrastructure
30  *
31  * Settings are persisted using QSettings, which stores them in platform
32  * specific locations.
33  *
34  * The settings are subdivided in different groups of settings.
35  *
36  * <em>[General]</em> settings are mostly changeable by users in the DialogConfig
37  * dialog.
38  *
39  * <em>[Admin]</em> and <em>[Internal]</em> settings are not changeable by the
40  * user and used for internal purposes. Should only be changed if you really know
41  * what you are doing.
42  *
43  * The <em>[Favorite]</em> group is auto-generated from the favorite activities
44  * selected by a user.
45  *
46  * The <em>[Levels]</em> group is auto-generated from the levels chosen by
47  * a user (if the activity provides multiple datasets).
48  *
49  * Besides these global settings there is one group for each activity that
50  * stores persistent settings.
51  *
52  * Settings defaults are defined in the source code.
53  *
54  * @sa DialogActivityConfig
55  */
56 class ApplicationSettings : public QObject
57 {
58     Q_OBJECT
59 
60     /* General group */
61 
62     /**
63      * Whether audio voices/speech should be enabled.
64      */
65     Q_PROPERTY(bool isAudioVoicesEnabled READ isAudioVoicesEnabled WRITE setIsAudioVoicesEnabled NOTIFY audioVoicesEnabledChanged)
66 
67     /**
68      * Whether audio effects should be enabled.
69      */
70     Q_PROPERTY(bool isAudioEffectsEnabled READ isAudioEffectsEnabled WRITE setIsAudioEffectsEnabled NOTIFY audioEffectsEnabledChanged)
71 
72     /** Whether background music should be enabled.
73      */
74     Q_PROPERTY(bool isBackgroundMusicEnabled READ isBackgroundMusicEnabled WRITE setIsBackgroundMusicEnabled NOTIFY backgroundMusicEnabledChanged)
75 
76     /**
77 	 * Whether GCompris should run in fullscreen mode.
78 	 */
79     Q_PROPERTY(bool isFullscreen READ isFullscreen WRITE setFullscreen NOTIFY fullscreenChanged)
80 
81     /**
82      * Window Height on Application's Startup
83      */
84     Q_PROPERTY(quint32 previousHeight READ previousHeight WRITE setPreviousHeight NOTIFY previousHeightChanged)
85 
86     /**
87      * Window Width on Application's Startup
88      */
89     Q_PROPERTY(quint32 previousWidth READ previousWidth WRITE setPreviousWidth NOTIFY previousWidthChanged)
90 
91     /**
92      * Whether on-screen keyboard should be enabled per default in activities
93      * that use it.
94      */
95     Q_PROPERTY(bool isVirtualKeyboard READ isVirtualKeyboard WRITE setVirtualKeyboard NOTIFY virtualKeyboardChanged)
96 
97     /**
98      * Locale string for currently active language.
99      */
100     Q_PROPERTY(QString locale READ locale WRITE setLocale NOTIFY localeChanged)
101 
102     /**
103      * Currently selected font.
104      */
105     Q_PROPERTY(QString font READ font WRITE setFont NOTIFY fontChanged)
106 
107     /**
108      * Whether currently active font is a shipped font (or a system font).
109      *
110      * Updated automatically.
111      * @sa font
112      */
113     Q_PROPERTY(bool isEmbeddedFont READ isEmbeddedFont WRITE setIsEmbeddedFont NOTIFY embeddedFontChanged)
114 
115     /**
116      * Font Capitalization
117      *
118      * Force all texts to be rendered in UpperCase, LowerCase or MixedCase (default)
119      * @sa font
120      */
121     Q_PROPERTY(quint32 fontCapitalization READ fontCapitalization WRITE setFontCapitalization NOTIFY fontCapitalizationChanged)
122 
123     /**
124      * Font letter spacing
125      *
126      * Change the letter spacing of all the texts
127      * @sa font
128      */
129     Q_PROPERTY(qreal fontLetterSpacing READ fontLetterSpacing WRITE setFontLetterSpacing NOTIFY fontLetterSpacingChanged)
130 
131     /**
132      * Minimum allowed value for font spacing letter.
133      *
134      * Constant value: +0.0
135      */
136     Q_PROPERTY(qreal fontLetterSpacingMin READ fontLetterSpacingMin CONSTANT)
137 
138     /**
139      * Maximum allowed value for font spacing letter.
140      *
141      * Constant value: +8.0
142      */
143     Q_PROPERTY(qreal fontLetterSpacingMax READ fontLetterSpacingMax CONSTANT)
144 
145     /**
146      * Whether downloads/updates of resource files should be done automatically,
147      * without user-interaction.
148      *
149      * Note, that on Android GCompris currently can't distinguish Wifi
150      * from mobile data connections (cf. Qt ticket #30394).
151      */
152     Q_PROPERTY(bool isAutomaticDownloadsEnabled READ isAutomaticDownloadsEnabled WRITE setIsAutomaticDownloadsEnabled NOTIFY automaticDownloadsEnabledChanged)
153 
154     /**
155      * Minimum value for difficulty level filter.
156      */
157     Q_PROPERTY(quint32 filterLevelMin READ filterLevelMin WRITE setFilterLevelMin NOTIFY filterLevelMinChanged)
158 
159     /**
160      * Maximum value for difficulty level filter.
161      */
162     Q_PROPERTY(quint32 filterLevelMax READ filterLevelMax WRITE setFilterLevelMax NOTIFY filterLevelMaxChanged)
163 
164     /**
165      * Whether kiosk mode is currently active.
166      */
167     Q_PROPERTY(bool isKioskMode READ isKioskMode WRITE setKioskMode NOTIFY kioskModeChanged)
168 
169     /**
170      * Whether the section selection row is visible in the menu view.
171      */
172     Q_PROPERTY(bool sectionVisible READ sectionVisible WRITE setSectionVisible NOTIFY sectionVisibleChanged)
173 
174     /**
175      * The name of the default wordset to use. If empty then the internal sample wordset is used.
176      */
177     Q_PROPERTY(QString wordset READ wordset WRITE setWordset NOTIFY wordsetChanged)
178 
179     /**
180      * Wether the extra word set should be used.
181      */
182     Q_PROPERTY(bool useWordset READ useWordset WRITE setUseWordset NOTIFY useWordsetChanged)
183 
184     /**
185      * Current base font-size used for font scaling.
186      *
187      * This setting is the basis for application-wide font-scaling. A value
188      * of 0 means to use the font-size as set by the application. Other values
189      * between @ref baseFontSizeMin and @ref baseFontSizeMax enforce
190      * font-scaling.
191      *
192      * @sa GCText.fontSize baseFontSizeMin baseFontSizeMax
193      */
194     Q_PROPERTY(int baseFontSize READ baseFontSize WRITE setBaseFontSize NOTIFY baseFontSizeChanged)
195 
196     /**
197      * Stores the background music volume set by the user.
198      */
199     Q_PROPERTY(qreal backgroundMusicVolume READ backgroundMusicVolume WRITE setBackgroundMusicVolume NOTIFY backgroundMusicVolumeChanged)
200 
201     /**
202      * Stores the audio effects volume set by the user.
203      */
204     Q_PROPERTY(qreal audioEffectsVolume READ audioEffectsVolume WRITE setAudioEffectsVolume NOTIFY audioEffectsVolumeChanged)
205 
206     /**
207      * Minimum allowed value for font-scaling.
208      *
209      * Constant value: -7
210      */
211     Q_PROPERTY(int baseFontSizeMin READ baseFontSizeMin CONSTANT)
212 
213     /**
214      * Maximum allowed value for font-scaling.
215      *
216      * Constant value: +7
217      */
218     Q_PROPERTY(int baseFontSizeMax READ baseFontSizeMax CONSTANT)
219 
220     // admin group
221 
222     /**
223      * Base-URL for resource downloads.
224      *
225      * @sa DownloadManager
226      */
227     Q_PROPERTY(QString downloadServerUrl READ downloadServerUrl WRITE setDownloadServerUrl NOTIFY downloadServerUrlChanged)
228 
229     /**
230      * Path where resources are downloaded and stored.
231      *
232      * @sa DownloadManager
233      */
234     Q_PROPERTY(QString cachePath READ cachePath WRITE setCachePath NOTIFY cachePathChanged)
235 
236     /**
237      * Return the platform specific path for storing data shared between apps
238      *
239      * On Android: /storage/emulated/0/GCompris (>= Android 4.2),
240      *             /storage/sdcard0/GCompris (< Android 4.2)
241      * On Linux: $HOME/local/share/GCompris
242      */
243     Q_PROPERTY(QString userDataPath READ userDataPath WRITE setUserDataPath NOTIFY userDataPathChanged)
244 
245     /**
246       * Define the renderer used.
247       * Either openGL or software renderer (only for Qt >= 5.8)
248       */
249     Q_PROPERTY(QString renderer READ renderer WRITE setRenderer NOTIFY rendererChanged)
250 
251     /**
252      * Stores the filtered background music playlist by the user.
253      */
254     Q_PROPERTY(QStringList filteredBackgroundMusic READ filteredBackgroundMusic WRITE setFilteredBackgroundMusic NOTIFY filteredBackgroundMusicChanged)
255 
256     // internal group
257     Q_PROPERTY(quint32 exeCount READ exeCount WRITE setExeCount NOTIFY exeCountChanged)
258 
259     // keep last version ran. If different than ApplicationInfo.GCVersionCode(), it means a new version is running
260     Q_PROPERTY(int lastGCVersionRan READ lastGCVersionRan WRITE setLastGCVersionRan NOTIFY lastGCVersionRanChanged)
261 
262     // no group
263     Q_PROPERTY(bool isBarHidden READ isBarHidden WRITE setBarHidden NOTIFY barHiddenChanged)
264 
265 public:
266     /// @cond INTERNAL_DOCS
267 #if defined(UBUNTUTOUCH)
268     explicit ApplicationSettings(const QString &configPath = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation)
269                                      + "/gcompris/" + GCOMPRIS_APPLICATION_NAME + ".conf",
270                                  QObject *parent = 0);
271 #else
272     explicit ApplicationSettings(const QString &configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation)
273                                      + "/gcompris/" + GCOMPRIS_APPLICATION_NAME + ".conf",
274                                  QObject *parent = 0);
275 #endif
276     virtual ~ApplicationSettings();
277     // It is not recommended to create a singleton of Qml Singleton registered
278     // object but we could not found a better way to let us access ApplicationInfo
279     // on the C++ side. All our test shows that it works.
getInstance()280     static ApplicationSettings *getInstance()
281     {
282         if (!m_instance) {
283             m_instance = new ApplicationSettings();
284         }
285         return m_instance;
286     }
287     static QObject *applicationSettingsProvider(QQmlEngine *engine,
288                                                 QJSEngine *scriptEngine);
289 
isAudioVoicesEnabled()290     bool isAudioVoicesEnabled() const { return m_isAudioVoicesEnabled; }
setIsAudioVoicesEnabled(const bool newMode)291     void setIsAudioVoicesEnabled(const bool newMode)
292     {
293         m_isAudioVoicesEnabled = newMode;
294         emit audioVoicesEnabledChanged();
295     }
296 
isAudioEffectsEnabled()297     bool isAudioEffectsEnabled() const { return m_isAudioEffectsEnabled; }
setIsAudioEffectsEnabled(const bool newMode)298     void setIsAudioEffectsEnabled(const bool newMode)
299     {
300         m_isAudioEffectsEnabled = newMode;
301         emit audioEffectsEnabledChanged();
302     }
303 
isBackgroundMusicEnabled()304     bool isBackgroundMusicEnabled() const { return m_isBackgroundMusicEnabled; }
setIsBackgroundMusicEnabled(const bool newMode)305     void setIsBackgroundMusicEnabled(const bool newMode)
306     {
307         m_isBackgroundMusicEnabled = newMode;
308         emit backgroundMusicEnabledChanged();
309     }
310 
isFullscreen()311     bool isFullscreen() const { return m_isFullscreen; }
setFullscreen(const bool newMode)312     void setFullscreen(const bool newMode)
313     {
314         if (m_isFullscreen != newMode) {
315             m_isFullscreen = newMode;
316             emit fullscreenChanged();
317         }
318     }
319 
previousHeight()320     quint32 previousHeight() const { return m_previousHeight; }
setPreviousHeight(quint32 height)321     void setPreviousHeight(quint32 height)
322     {
323         if (m_previousHeight != height) {
324             m_previousHeight = height;
325             emit previousHeightChanged();
326         }
327     }
328 
previousWidth()329     quint32 previousWidth() const { return m_previousWidth; }
setPreviousWidth(quint32 width)330     void setPreviousWidth(quint32 width)
331     {
332         if (m_previousWidth != width) {
333             m_previousWidth = width;
334             emit previousWidthChanged();
335         }
336     }
337 
isVirtualKeyboard()338     bool isVirtualKeyboard() const { return m_isVirtualKeyboard; }
setVirtualKeyboard(const bool newMode)339     void setVirtualKeyboard(const bool newMode)
340     {
341         m_isVirtualKeyboard = newMode;
342         emit virtualKeyboardChanged();
343     }
344 
locale()345     QString locale() const
346     {
347         return m_locale;
348     }
setLocale(const QString & newLocale)349     void setLocale(const QString &newLocale)
350     {
351         m_locale = newLocale;
352         emit localeChanged();
353     }
354 
font()355     QString font() const { return m_font; }
setFont(const QString & newFont)356     void setFont(const QString &newFont)
357     {
358         m_font = newFont;
359         emit fontChanged();
360     }
361 
isEmbeddedFont()362     bool isEmbeddedFont() const { return m_isEmbeddedFont; }
setIsEmbeddedFont(const bool newIsEmbeddedFont)363     void setIsEmbeddedFont(const bool newIsEmbeddedFont)
364     {
365         m_isEmbeddedFont = newIsEmbeddedFont;
366         emit embeddedFontChanged();
367     }
368 
fontCapitalization()369     quint32 fontCapitalization() const { return m_fontCapitalization; }
setFontCapitalization(quint32 newFontCapitalization)370     void setFontCapitalization(quint32 newFontCapitalization)
371     {
372         m_fontCapitalization = newFontCapitalization;
373         emit fontCapitalizationChanged();
374     }
375 
fontLetterSpacing()376     qreal fontLetterSpacing() const { return m_fontLetterSpacing; }
setFontLetterSpacing(qreal newFontLetterSpacing)377     void setFontLetterSpacing(qreal newFontLetterSpacing)
378     {
379         m_fontLetterSpacing = newFontLetterSpacing;
380         emit fontLetterSpacingChanged();
381     }
382 
fontLetterSpacingMin()383     qreal fontLetterSpacingMin() const { return m_fontLetterSpacingMin; }
fontLetterSpacingMax()384     qreal fontLetterSpacingMax() const { return m_fontLetterSpacingMax; }
385 
386     bool isAutomaticDownloadsEnabled() const;
387     void setIsAutomaticDownloadsEnabled(const bool newIsAutomaticDownloadsEnabled);
388 
filterLevelMin()389     quint32 filterLevelMin() const { return m_filterLevelMin; }
setFilterLevelMin(const quint32 newFilterLevelMin)390     void setFilterLevelMin(const quint32 newFilterLevelMin)
391     {
392         m_filterLevelMin = newFilterLevelMin;
393         emit filterLevelMinChanged();
394     }
395 
filterLevelMax()396     quint32 filterLevelMax() const { return m_filterLevelMax; }
setFilterLevelMax(const quint32 newFilterLevelMax)397     void setFilterLevelMax(const quint32 newFilterLevelMax)
398     {
399         m_filterLevelMax = newFilterLevelMax;
400         emit filterLevelMaxChanged();
401     }
402 
isKioskMode()403     bool isKioskMode() const { return m_isKioskMode; }
setKioskMode(const bool newMode)404     void setKioskMode(const bool newMode)
405     {
406         m_isKioskMode = newMode;
407         emit kioskModeChanged();
408     }
409 
sectionVisible()410     bool sectionVisible() const { return m_sectionVisible; }
setSectionVisible(const bool newMode)411     void setSectionVisible(const bool newMode)
412     {
413         qDebug() << "c++ setSectionVisible=" << newMode;
414         m_sectionVisible = newMode;
415         emit sectionVisibleChanged();
416     }
417 
wordset()418     QString wordset() const { return m_wordset; }
setWordset(const QString & newWordset)419     void setWordset(const QString &newWordset)
420     {
421         m_wordset = newWordset;
422         emit wordsetChanged();
423     }
424 
useWordset()425     bool useWordset() const { return m_useWordset; }
setUseWordset(const bool newMode)426     void setUseWordset(const bool newMode)
427     {
428         m_useWordset = newMode;
429         emit useWordsetChanged();
430     }
431 
downloadServerUrl()432     QString downloadServerUrl() const { return m_downloadServerUrl; }
setDownloadServerUrl(const QString & newDownloadServerUrl)433     void setDownloadServerUrl(const QString &newDownloadServerUrl)
434     {
435         m_downloadServerUrl = newDownloadServerUrl;
436         emit downloadServerUrlChanged();
437     }
438 
cachePath()439     QString cachePath() const { return m_cachePath; }
setCachePath(const QString & newCachePath)440     void setCachePath(const QString &newCachePath)
441     {
442         m_cachePath = newCachePath;
443         emit cachePathChanged();
444     }
445 
userDataPath()446     QString userDataPath() const { return m_userDataPath; }
setUserDataPath(const QString & newUserDataPath)447     void setUserDataPath(const QString &newUserDataPath)
448     {
449         m_userDataPath = newUserDataPath;
450         emit userDataPathChanged();
451     }
exeCount()452     quint32 exeCount() const { return m_exeCount; }
setExeCount(const quint32 newExeCount)453     void setExeCount(const quint32 newExeCount)
454     {
455         m_exeCount = newExeCount;
456         emit exeCountChanged();
457     }
458 
isBarHidden()459     bool isBarHidden() const { return m_isBarHidden; }
setBarHidden(const bool newBarHidden)460     void setBarHidden(const bool newBarHidden)
461     {
462         m_isBarHidden = newBarHidden;
463         emit barHiddenChanged();
464     }
465 
baseFontSize()466     int baseFontSize() const { return m_baseFontSize; }
setBaseFontSize(const int newBaseFontSize)467     void setBaseFontSize(const int newBaseFontSize)
468     {
469         m_baseFontSize = qMax(qMin(newBaseFontSize, baseFontSizeMax()), baseFontSizeMin());
470         emit baseFontSizeChanged();
471     }
472 
baseFontSizeMin()473     int baseFontSizeMin() const { return m_baseFontSizeMin; }
baseFontSizeMax()474     int baseFontSizeMax() const { return m_baseFontSizeMax; }
475 
backgroundMusicVolume()476     qreal backgroundMusicVolume() const { return m_backgroundMusicVolume; }
setBackgroundMusicVolume(const qreal newBackgroundMusicVolume)477     void setBackgroundMusicVolume(const qreal newBackgroundMusicVolume)
478     {
479         m_backgroundMusicVolume = newBackgroundMusicVolume;
480         emit backgroundMusicVolumeChanged();
481     }
482 
audioEffectsVolume()483     qreal audioEffectsVolume() const { return m_audioEffectsVolume; }
setAudioEffectsVolume(const qreal newAudioEffectsVolume)484     void setAudioEffectsVolume(const qreal newAudioEffectsVolume)
485     {
486         m_audioEffectsVolume = newAudioEffectsVolume;
487         emit audioEffectsVolumeChanged();
488     }
489 
lastGCVersionRan()490     int lastGCVersionRan() const { return m_lastGCVersionRan; }
setLastGCVersionRan(const int newLastGCVersionRan)491     void setLastGCVersionRan(const int newLastGCVersionRan)
492     {
493         m_lastGCVersionRan = newLastGCVersionRan;
494         emit lastGCVersionRanChanged();
495     }
496 
renderer()497     QString renderer() const { return m_renderer; }
setRenderer(const QString & newRenderer)498     void setRenderer(const QString &newRenderer)
499     {
500         m_renderer = newRenderer;
501         emit rendererChanged();
502     }
503 
filteredBackgroundMusic()504     QStringList filteredBackgroundMusic() const { return m_filteredBackgroundMusic; }
setFilteredBackgroundMusic(const QStringList & newFilteredBackgroundMusic)505     void setFilteredBackgroundMusic(const QStringList &newFilteredBackgroundMusic)
506     {
507         m_filteredBackgroundMusic = newFilteredBackgroundMusic;
508         emit filteredBackgroundMusicChanged();
509     }
510 
511     /**
512      * Check if we use the external wordset for activity based on lang_api
513      * @returns  true if wordset is loaded
514      *           false if wordset is not loaded
515      */
516     Q_INVOKABLE bool useExternalWordset();
517 
518 protected slots:
519 
520     Q_INVOKABLE void notifyAudioVoicesEnabledChanged();
521     Q_INVOKABLE void notifyAudioEffectsEnabledChanged();
522     Q_INVOKABLE void notifyBackgroundMusicEnabledChanged();
523     Q_INVOKABLE void notifyFullscreenChanged();
524     Q_INVOKABLE void notifyPreviousHeightChanged();
525     Q_INVOKABLE void notifyPreviousWidthChanged();
526     Q_INVOKABLE void notifyVirtualKeyboardChanged();
527     Q_INVOKABLE void notifyLocaleChanged();
528     Q_INVOKABLE void notifyFontChanged();
529     Q_INVOKABLE void notifyFontCapitalizationChanged();
530     Q_INVOKABLE void notifyFontLetterSpacingChanged();
531     Q_INVOKABLE void notifyEmbeddedFontChanged();
532     Q_INVOKABLE void notifyAutomaticDownloadsEnabledChanged();
533     Q_INVOKABLE void notifyFilterLevelMinChanged();
534     Q_INVOKABLE void notifyFilterLevelMaxChanged();
535     Q_INVOKABLE void notifyKioskModeChanged();
536     Q_INVOKABLE void notifySectionVisibleChanged();
537     Q_INVOKABLE void notifyWordsetChanged();
538     Q_INVOKABLE void notifyUseWordsetChanged();
539     Q_INVOKABLE void notifyFilteredBackgroundMusicChanged();
540     Q_INVOKABLE void notifyBackgroundMusicVolumeChanged();
541     Q_INVOKABLE void notifyAudioEffectsVolumeChanged();
542 
543     Q_INVOKABLE void notifyDownloadServerUrlChanged();
544     Q_INVOKABLE void notifyCachePathChanged();
545     Q_INVOKABLE void notifyUserDataPathChanged();
546     Q_INVOKABLE void notifyExeCountChanged();
547 
548     Q_INVOKABLE void notifyLastGCVersionRanChanged();
549     Q_INVOKABLE void notifyRendererChanged();
550 
551     Q_INVOKABLE void notifyBarHiddenChanged();
552 
553 public slots:
554     Q_INVOKABLE bool isFavorite(const QString &activity);
555     Q_INVOKABLE void setFavorite(const QString &activity, bool favorite);
556     Q_INVOKABLE void setCurrentLevels(const QString &activity, const QStringList &level, bool sync = true);
557     Q_INVOKABLE QStringList currentLevels(const QString &activity);
558 
559     Q_INVOKABLE void saveBaseFontSize();
560     /// @endcond
561 
562     /**
563      * Stores per-activity configuration @p data for @p activity.
564      *
565      * @param activity Name of the activity that wants to persist settings.
566      * @param data Map of configuration data so save.
567      */
568     Q_INVOKABLE void saveActivityConfiguration(const QString &activity, const QVariantMap &data);
569 
570     /**
571      * Loads per-activity configuration data for @p activity.
572      *
573      * @param activity Name of the activity that wants to persist settings.
574      * @returns Map of configuration items.
575      */
576     Q_INVOKABLE QVariantMap loadActivityConfiguration(const QString &activity);
577 
578     /**
579      * Loads per-activity progress using the default "progress" key.
580      *
581      * @param activity Name of the activity to load progress for.
582      * @returns Last started level of the activity, 0 if none saved.
583      */
584     Q_INVOKABLE int loadActivityProgress(const QString &activity);
585 
586     /**
587      * Saves per-activity progress using the default "progress" key.
588      *
589      * @param activity Name of the activity that wants to persist settings.
590      * @param progress Last started level to save as progress value.
591      */
592     Q_INVOKABLE void saveActivityProgress(const QString &activity, int progress);
593     /**
594      * Synchronize the changes done in the application in the configuration file.
595      */
596     Q_INVOKABLE void sync();
597 
598 signals:
599     void audioVoicesEnabledChanged();
600     void audioEffectsEnabledChanged();
601     void backgroundMusicEnabledChanged();
602     void fullscreenChanged();
603     void previousHeightChanged();
604     void previousWidthChanged();
605     void virtualKeyboardChanged();
606     void localeChanged();
607     void fontChanged();
608     void fontCapitalizationChanged();
609     void fontLetterSpacingChanged();
610     void embeddedFontChanged();
611     void automaticDownloadsEnabledChanged();
612     void filterLevelMinChanged();
613     void filterLevelMaxChanged();
614     void kioskModeChanged();
615     void sectionVisibleChanged();
616     void wordsetChanged();
617     void useWordsetChanged();
618     void baseFontSizeChanged();
619     void filteredBackgroundMusicChanged();
620     void backgroundMusicVolumeChanged();
621     void audioEffectsVolumeChanged();
622 
623     void downloadServerUrlChanged();
624     void cachePathChanged();
625     void userDataPathChanged();
626 
627     void exeCountChanged();
628 
629     void lastGCVersionRanChanged();
630     void rendererChanged();
631     void barHiddenChanged();
632 
633 protected:
634     static ApplicationSettings *m_instance;
635 
636 private:
637     // Update in configuration the couple {key, value} in the group.
638     template <class T>
639     void updateValueInConfig(const QString &group,
640                              const QString &key, const T &value, bool sync = true);
641 
642     bool m_isAudioVoicesEnabled;
643     bool m_isAudioEffectsEnabled;
644     bool m_isBackgroundMusicEnabled;
645     bool m_isFullscreen;
646     quint32 m_previousHeight;
647     quint32 m_previousWidth;
648     bool m_isVirtualKeyboard;
649     bool m_isAutomaticDownloadsEnabled;
650     bool m_isEmbeddedFont;
651     quint32 m_fontCapitalization;
652     qreal m_fontLetterSpacing;
653     quint32 m_filterLevelMin;
654     quint32 m_filterLevelMax;
655     bool m_defaultCursor;
656     bool m_noCursor;
657     QString m_locale;
658     QString m_font;
659     bool m_isKioskMode;
660     bool m_sectionVisible;
661     QString m_wordset;
662     bool m_useWordset;
663     QStringList m_filteredBackgroundMusic;
664     qreal m_backgroundMusicVolume;
665     qreal m_audioEffectsVolume;
666     int m_baseFontSize;
667     const int m_baseFontSizeMin;
668     const int m_baseFontSizeMax;
669     const qreal m_fontLetterSpacingMin;
670     const qreal m_fontLetterSpacingMax;
671 
672     QString m_downloadServerUrl;
673     QString m_cachePath;
674     QString m_userDataPath;
675 
676     quint32 m_exeCount;
677 
678     int m_lastGCVersionRan;
679     QString m_renderer;
680 
681     bool m_isBarHidden;
682 
683     QSettings m_config;
684 };
685 
686 #endif // APPLICATIONSETTINGS_H
687