Skip to content

Commit 89f401d

Browse files
committed
Add Settings class
1 parent ec28963 commit 89f401d

File tree

9 files changed

+404
-0
lines changed

9 files changed

+404
-0
lines changed

src/global/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ set(MODULE_SRC
55
globalmodule.h
66
iappinfo.h
77
ifilepaths.h
8+
isettings.h
89
modularity/ioc.h
910
modularity/modulesioc.h
1011
modularity/imoduleexportinterface.h
@@ -13,6 +14,8 @@ set(MODULE_SRC
1314
internal/appinfo.h
1415
internal/filepaths.cpp
1516
internal/filepaths.h
17+
internal/settings.cpp
18+
internal/settings.h
1619
)
1720

1821
include(${PROJECT_SOURCE_DIR}/build/module.cmake)

src/global/globalmodule.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "globalmodule.h"
66
#include "internal/appinfo.h"
77
#include "internal/filepaths.h"
8+
#include "internal/settings.h"
89

910
using namespace scratchcpp;
1011

@@ -22,4 +23,10 @@ void GlobalModule::registerExports()
2223
modularity::ioc()->registerExport<IAppInfo>(m_appInfo);
2324

2425
modularity::ioc()->registerExport<FilePaths>(FilePaths::instance());
26+
27+
m_settings = std::make_shared<Settings>();
28+
29+
QQmlEngine::setObjectOwnership(m_settings.get(), QQmlEngine::CppOwnership);
30+
qmlRegisterSingletonInstance<Settings>("ScratchCPP.Global", 1, 0, "Settings", m_settings.get());
31+
modularity::ioc()->registerExport<Settings>(m_settings);
2532
}

src/global/globalmodule.h

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace scratchcpp
1010
{
1111

1212
class AppInfo;
13+
class Settings;
1314

1415
class GlobalModule : public modularity::IModuleSetup
1516
{
@@ -20,6 +21,7 @@ class GlobalModule : public modularity::IModuleSetup
2021

2122
private:
2223
std::shared_ptr<AppInfo> m_appInfo;
24+
std::shared_ptr<Settings> m_settings;
2325
};
2426

2527
} // namespace scratchcpp

src/global/internal/settings.cpp

+162
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
3+
#include <QSettings>
4+
#include <QCoreApplication>
5+
#include <QStandardPaths>
6+
#include <QDebug>
7+
8+
#include "settings.h"
9+
#include "ifilepaths.h"
10+
11+
using namespace scratchcpp;
12+
13+
Settings::Settings(QObject *parent) :
14+
QObject(parent),
15+
m_mainSettingsInstance(paths()->configLocation(), QSettings::IniFormat),
16+
m_tmpSettingsInstance(paths()->configLocation() + ".tmp", QSettings::IniFormat)
17+
{
18+
m_settingsInstance = &m_mainSettingsInstance;
19+
}
20+
21+
void Settings::addKey(const QString &moduleName, const QString &keyName, const QVariant &defaultValue)
22+
{
23+
m_defaults.insert({ moduleName, keyName }, defaultValue);
24+
}
25+
26+
void Settings::setValue(const QString &moduleName, const QString &keyName, const QVariant &value)
27+
{
28+
set(moduleName + "/" + keyName, value);
29+
}
30+
31+
QVariant Settings::getValue(const QString &moduleName, const QString &keyName)
32+
{
33+
QPair<QString, QString> key(moduleName, keyName);
34+
QVariant defaultValue;
35+
auto it = m_defaults.find(key);
36+
37+
if (it != m_defaults.cend())
38+
defaultValue = it.value();
39+
40+
return get(moduleName + "/" + keyName, defaultValue);
41+
}
42+
43+
bool Settings::containsKey(const QString &moduleName, const QString &keyName)
44+
{
45+
QPair<QString, QString> key(moduleName, keyName);
46+
return contains(moduleName + "/" + keyName);
47+
}
48+
49+
/*
50+
* Switches to temporary settings. You can decide to saveChanges() or discardChanges() later.
51+
* This is useful for settings dialogs with a discard button.
52+
*/
53+
void Settings::freeze(void)
54+
{
55+
Q_ASSERT(!m_frozen);
56+
m_settingsInstance = &m_tmpSettingsInstance;
57+
copySettings(&m_mainSettingsInstance, m_settingsInstance);
58+
m_frozen = true;
59+
emit stateChanged();
60+
}
61+
62+
// Saves changes to real settings and switches back to them.
63+
void Settings::saveChanges(void)
64+
{
65+
Q_ASSERT(m_frozen);
66+
copySettings(m_settingsInstance, &m_mainSettingsInstance);
67+
m_mainSettingsInstance.sync();
68+
m_settingsInstance = &m_mainSettingsInstance;
69+
m_frozen = false;
70+
emit stateChanged();
71+
emit saved();
72+
}
73+
74+
// Discards changes and switches back to real settings.
75+
void Settings::discardChanges(void)
76+
{
77+
Q_ASSERT(m_frozen);
78+
m_settingsInstance = &m_mainSettingsInstance;
79+
m_frozen = false;
80+
emit stateChanged();
81+
emit discarded();
82+
}
83+
84+
bool Settings::isFrozen(void)
85+
{
86+
return m_frozen;
87+
}
88+
89+
QVariant Settings::get(const QString &key, const QVariant &defaultValue)
90+
{
91+
Q_ASSERT(m_settingsInstance != nullptr);
92+
#ifdef Q_OS_WASM
93+
if (m_settingsInstance->isWritable()) {
94+
if (!m_tempSettingsCopied)
95+
copyTempSettings();
96+
return m_settingsInstance->value(key, defaultValue);
97+
} else {
98+
// Use temporary settings until sandbox is initialized
99+
QSettings settings(paths()->configLocation(), QSettings::IniFormat);
100+
return settings.value(key, defaultValue);
101+
}
102+
#else
103+
return m_settingsInstance->value(key, defaultValue);
104+
#endif // Q_OS_WASM
105+
}
106+
107+
bool Settings::contains(const QString &key)
108+
{
109+
Q_ASSERT(m_settingsInstance != nullptr);
110+
#ifdef Q_OS_WASM
111+
if (m_settingsInstance->isWritable()) {
112+
if (!m_tempSettingsCopied)
113+
copyTempSettings();
114+
return m_settingsInstance->contains(key);
115+
} else {
116+
// Use temporary settings until sandbox is initialized
117+
QSettings settings(paths()->configLocation(), QSettings::IniFormat);
118+
return settings.contains(key);
119+
}
120+
#else
121+
return m_settingsInstance->contains(key);
122+
#endif // Q_OS_WASM
123+
}
124+
125+
void Settings::set(const QString &key, const QVariant &value)
126+
{
127+
Q_ASSERT(m_settingsInstance != nullptr);
128+
#ifdef Q_OS_WASM
129+
if (m_settingsInstance->isWritable()) {
130+
if (!m_tempSettingsCopied)
131+
copyTempSettings();
132+
m_settingsInstance->setValue(key, value);
133+
m_settingsInstance->sync();
134+
} else {
135+
// Use temporary settings until sandbox is initialized
136+
QSettings settings(paths()->configLocation(), QSettings::IniFormat);
137+
settings.setValue(key, value);
138+
}
139+
#else
140+
m_settingsInstance->setValue(key, value);
141+
#endif // Q_OS_WASM
142+
}
143+
144+
void Settings::copySettings(QSettings *source, QSettings *target)
145+
{
146+
#ifndef Q_OS_WASM
147+
target->clear();
148+
#endif
149+
QStringList keys = source->allKeys();
150+
for (int i = 0; i < keys.count(); i++)
151+
target->setValue(keys[i], source->value(keys[i]));
152+
}
153+
154+
#ifdef Q_OS_WASM
155+
void Settings::copyTempSettings(void)
156+
{
157+
QSettings settings(paths()->configLocation(), QSettings::IniFormat);
158+
copySettings(&settings, m_settingsInstance);
159+
m_settingsInstance->sync();
160+
m_tempSettingsCopied = true;
161+
}
162+
#endif // Q_OS_WASM

src/global/internal/settings.h

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
3+
#pragma once
4+
5+
#include <QQmlEngine>
6+
#include <QSettings>
7+
8+
#include "isettings.h"
9+
#include "ifilepaths.h"
10+
11+
class QSettings;
12+
13+
namespace scratchcpp
14+
{
15+
16+
// class IFilePaths;
17+
18+
class Settings
19+
: public QObject
20+
, public ISettings
21+
{
22+
Q_OBJECT
23+
INJECT(IFilePaths, paths)
24+
public:
25+
Settings(QObject *parent = nullptr);
26+
27+
void addKey(const QString &moduleName, const QString &keyName, const QVariant &defaultValue) override;
28+
Q_INVOKABLE void setValue(const QString &moduleName, const QString &keyName, const QVariant &value) override;
29+
Q_INVOKABLE QVariant getValue(const QString &moduleName, const QString &keyName) override;
30+
Q_INVOKABLE bool containsKey(const QString &moduleName, const QString &keyName) override;
31+
Q_INVOKABLE void freeze(void) override;
32+
Q_INVOKABLE void saveChanges(void) override;
33+
Q_INVOKABLE void discardChanges(void) override;
34+
Q_INVOKABLE bool isFrozen(void) override;
35+
36+
signals:
37+
void stateChanged();
38+
void saved();
39+
void discarded();
40+
41+
private:
42+
QVariant get(const QString &key, const QVariant &defaultValue);
43+
bool contains(const QString &key);
44+
void set(const QString &key, const QVariant &value);
45+
46+
static void copySettings(QSettings *source, QSettings *target);
47+
48+
QSettings *m_settingsInstance = nullptr;
49+
QSettings m_mainSettingsInstance;
50+
QSettings m_tmpSettingsInstance;
51+
bool m_frozen = false;
52+
QMap<QPair<QString, QString>, QVariant> m_defaults;
53+
54+
#ifdef Q_OS_WASM
55+
bool m_tempSettingsCopied = false;
56+
void copyTempSettings(void);
57+
#endif // Q_OS_WASM
58+
};
59+
60+
} // namespace scratchcpp

src/global/isettings.h

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
3+
#pragma once
4+
5+
#include <QVariant>
6+
#include "modularity/ioc.h"
7+
8+
#define INIT_SETTINGS_KEY(keyName, defaultValue) modularity::ioc()->resolve<ISettings>()->addKey(QString::fromStdString(moduleName()), keyName, defaultValue)
9+
10+
namespace scratchcpp
11+
{
12+
13+
class ISettings : MODULE_EXPORT_INTERFACE
14+
{
15+
public:
16+
virtual ~ISettings() { }
17+
18+
virtual void addKey(const QString &moduleName, const QString &keyName, const QVariant &defaultValue) = 0;
19+
virtual void setValue(const QString &moduleName, const QString &keyName, const QVariant &value) = 0;
20+
virtual QVariant getValue(const QString &moduleName, const QString &keyName) = 0;
21+
virtual bool containsKey(const QString &moduleName, const QString &keyName) = 0;
22+
23+
virtual void freeze() = 0;
24+
virtual void saveChanges() = 0;
25+
virtual void discardChanges() = 0;
26+
virtual bool isFrozen() = 0;
27+
};
28+
29+
} // namespace scratchcpp

src/global/test/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ set(MODULE_TEST_SRC
22
modularity.cpp
33
setup.cpp
44
appinfo.cpp
5+
settings.cpp
56
fakeexport.h
67
fakedependency.h
78
mocks/moduleexportinterfacemock.h

src/global/test/mocks/filepathsmock.h

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#pragma once
2+
3+
#include <ifilepaths.h>
4+
#include <gmock/gmock.h>
5+
6+
namespace scratchcpp
7+
{
8+
9+
class FilePathsMock : public IFilePaths
10+
{
11+
public:
12+
MOCK_METHOD(QString, configLocation, (), (const, override));
13+
};
14+
15+
} // namespace scratchcpp

0 commit comments

Comments
 (0)