diff --git a/src/mvvmcore/isettingsaccessor.cpp b/src/mvvmcore/isettingsaccessor.cpp new file mode 100644 index 0000000..5508c79 --- /dev/null +++ b/src/mvvmcore/isettingsaccessor.cpp @@ -0,0 +1,6 @@ +#include "isettingsaccessor.h" +using namespace QtMvvm; + +ISettingsAccessor::ISettingsAccessor(QObject *parent) : + QObject{parent} +{} diff --git a/src/mvvmcore/isettingsaccessor.h b/src/mvvmcore/isettingsaccessor.h new file mode 100644 index 0000000..35ed182 --- /dev/null +++ b/src/mvvmcore/isettingsaccessor.h @@ -0,0 +1,39 @@ +#ifndef QTMVVM_ISETTINGSACCESSOR_H +#define QTMVVM_ISETTINGSACCESSOR_H + +#include +#include +#include + +#include "QtMvvmCore/qtmvvmcore_global.h" + +namespace QtMvvm { + +class Q_MVVMCORE_EXPORT ISettingsAccessor : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY(ISettingsAccessor) + +public: + ISettingsAccessor(QObject *parent = nullptr); + + virtual bool contains(const QString &key) const = 0; + virtual QVariant load(const QString &key, const QVariant &defaultValue = {}) const = 0; + virtual void save(const QString &key, const QVariant &value) = 0; + virtual void remove(const QString &key) = 0; + +public Q_SLOTS: + virtual void sync() = 0; + +Q_SIGNALS: + void entryChanged(const QString &key, const QVariant &value); + void entryRemoved(const QString &key); +}; + +} + +#define ISettingsAccessorIid "de.skycoder42.qtmvvm.core.ISettingsAccessor" +Q_DECLARE_INTERFACE(QtMvvm::ISettingsAccessor, ISettingsAccessorIid) +Q_DECLARE_METATYPE(QtMvvm::ISettingsAccessor*) + +#endif // QTMVVM_ISETTINGSACCESSOR_H diff --git a/src/mvvmcore/mvvmcore.pro b/src/mvvmcore/mvvmcore.pro index 4212a9f..945f2a2 100644 --- a/src/mvvmcore/mvvmcore.pro +++ b/src/mvvmcore/mvvmcore.pro @@ -22,7 +22,10 @@ HEADERS += \ settingssetuploader_p.h \ settingsviewmodel_p.h \ settingsviewmodel.h \ - injection.h + injection.h \ + isettingsaccessor.h \ + qsettingsaccessor.h \ + settingsentry.h SOURCES += \ viewmodel.cpp \ @@ -33,7 +36,9 @@ SOURCES += \ message.cpp \ ipresenter.cpp \ settingssetuploader.cpp \ - settingsviewmodel.cpp + settingsviewmodel.cpp \ + isettingsaccessor.cpp \ + qsettingsaccessor.cpp TRANSLATIONS += \ translations/qtmvvmcore_de.ts \ diff --git a/src/mvvmcore/qsettingsaccessor.cpp b/src/mvvmcore/qsettingsaccessor.cpp new file mode 100644 index 0000000..f975299 --- /dev/null +++ b/src/mvvmcore/qsettingsaccessor.cpp @@ -0,0 +1,60 @@ +#include "qsettingsaccessor.h" +using namespace QtMvvm; + +namespace QtMvvm { + +class QSettingsAccessorPrivate +{ +public: + QSettingsAccessorPrivate(QSettings *settings); + + QSettings *settings; +}; + +} + +QSettingsAccessor::QSettingsAccessor(QObject *parent) : + QSettingsAccessor{new QSettings{}, parent} +{} + +QSettingsAccessor::QSettingsAccessor(QSettings *settings, QObject *parent) : + ISettingsAccessor{parent}, + d{new QSettingsAccessorPrivate{settings}} +{ + d->settings->setParent(this); +} + +QSettingsAccessor::~QSettingsAccessor() = default; + +bool QSettingsAccessor::contains(const QString &key) const +{ + return d->settings->contains(key); +} + +QVariant QSettingsAccessor::load(const QString &key, const QVariant &defaultValue) const +{ + return d->settings->value(key, defaultValue); +} + +void QSettingsAccessor::save(const QString &key, const QVariant &value) +{ + d->settings->setValue(key, value); + emit entryChanged(key, value); +} + +void QSettingsAccessor::remove(const QString &key) +{ + d->settings->remove(key); + emit entryRemoved(key); +} + +void QSettingsAccessor::sync() +{ + d->settings->sync(); +} + + + +QSettingsAccessorPrivate::QSettingsAccessorPrivate(QSettings *settings) : + settings{settings} +{} diff --git a/src/mvvmcore/qsettingsaccessor.h b/src/mvvmcore/qsettingsaccessor.h new file mode 100644 index 0000000..a44c226 --- /dev/null +++ b/src/mvvmcore/qsettingsaccessor.h @@ -0,0 +1,37 @@ +#ifndef QTMVVM_QSETTINGSACCESSOR_H +#define QTMVVM_QSETTINGSACCESSOR_H + +#include +#include + +#include "QtMvvmCore/qtmvvmcore_global.h" +#include "QtMvvmCore/isettingsaccessor.h" + +namespace QtMvvm { + +class QSettingsAccessorPrivate; +class Q_MVVMCORE_EXPORT QSettingsAccessor : public ISettingsAccessor +{ + Q_OBJECT + Q_INTERFACES(QtMvvm::ISettingsAccessor) + +public: + Q_INVOKABLE explicit QSettingsAccessor(QObject *parent = nullptr); + explicit QSettingsAccessor(QSettings *settings, QObject *parent = nullptr); + ~QSettingsAccessor() override; + + bool contains(const QString &key) const override; + QVariant load(const QString &key, const QVariant &defaultValue) const override; + void save(const QString &key, const QVariant &value) override; + void remove(const QString &key) override; + +public Q_SLOTS: + void sync() override; + +private: + QScopedPointer d; +}; + +} + +#endif // QTMVVM_QSETTINGSACCESSOR_H diff --git a/src/mvvmcore/settingsentry.h b/src/mvvmcore/settingsentry.h new file mode 100644 index 0000000..9fac433 --- /dev/null +++ b/src/mvvmcore/settingsentry.h @@ -0,0 +1,124 @@ +#ifndef QTMVVM_SETTINGSENTRY_H +#define QTMVVM_SETTINGSENTRY_H + +#include "QtMvvmCore/isettingsaccessor.h" + +namespace QtMvvm { + +template +class SettingsEntry +{ + Q_DISABLE_COPY(SettingsEntry) + +public: + SettingsEntry() = default; + + bool isSet() const; + + T get() const; + void set(const T &value); + void reset(); + + SettingsEntry &operator=(const T &value); + operator const T() const; + + void addChangeCallback(const std::function &callback); + void addChangeCallback(QObject *scope, const std::function &callback); + + // internal + void setup(const QString &key, ISettingsAccessor *accessor, const QVariant &defaultValue = {}); + +private: + QString _key; + ISettingsAccessor *_accessor = nullptr; + QVariant _default; +}; + +template <> +class SettingsEntry +{ + Q_DISABLE_COPY(SettingsEntry) + +public: + SettingsEntry() = default; + + // internal + void setup(const QString &, ISettingsAccessor *, const QVariant & = {}) {} +}; + + +// ------------- Generic Implementation ------------- + +template +bool SettingsEntry::isSet() const +{ + return _accessor->contains(_key); +} + +template +T SettingsEntry::get() const +{ + return _accessor->load(_key, _default).template value(); +} + +template +void SettingsEntry::set(const T &value) +{ + _accessor->save(_key, QVariant::fromValue(value)); +} + +template +void SettingsEntry::reset() +{ + _accessor->remove(_key); +} + +template +SettingsEntry &SettingsEntry::operator=(const T &value) +{ + set(value); + return (*this); +} + +template +void SettingsEntry::addChangeCallback(const std::function &callback) +{ + addChangeCallback(_accessor, callback); +} + +template +void SettingsEntry::addChangeCallback(QObject *scope, const std::function &callback) +{ + auto mKey = _key; + auto mDefault = _default; + QObject::connect(_accessor, &ISettingsAccessor::entryChanged, + scope, [mKey, callback](const QString &key, const QVariant &value) { + if(key == mKey) + callback(value.template value()); + }); + QObject::connect(_accessor, &ISettingsAccessor::entryRemoved, + scope, [mKey, mDefault, callback](const QString &key) { + if(key == mKey) + callback(mDefault.template value()); + }); +} + +template +SettingsEntry::operator const T() const +{ + return get(); +} + +template +void SettingsEntry::setup(const QString &key, ISettingsAccessor *accessor, const QVariant &defaultValue) +{ + Q_ASSERT_X(accessor, Q_FUNC_INFO, "You must set a valid accessor before initializing the settings!"); + _key = key; + _accessor = accessor; + _default = defaultValue; +} + +} + + +#endif // QTMVVM_SETTINGSENTRY_H diff --git a/tools/settingsgenerator/main.cpp b/tools/settingsgenerator/main.cpp new file mode 100644 index 0000000..054cc68 --- /dev/null +++ b/tools/settingsgenerator/main.cpp @@ -0,0 +1,8 @@ +#include + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + + return a.exec(); +} diff --git a/tools/settingsgenerator/qsettingsgenerator.xsd b/tools/settingsgenerator/qsettingsgenerator.xsd new file mode 100644 index 0000000..01dad4d --- /dev/null +++ b/tools/settingsgenerator/qsettingsgenerator.xsd @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/settingsgenerator/settingsgenerator.pro b/tools/settingsgenerator/settingsgenerator.pro new file mode 100644 index 0000000..3489a7f --- /dev/null +++ b/tools/settingsgenerator/settingsgenerator.pro @@ -0,0 +1,31 @@ +option(host_build) + +QT = core + +TARGET = qsettingsgenerator +VERSION = $$MODULE_VERSION +COMPANY = Skycoder42 +BUNDLE_PREFIX = de.skycoder42 + +DEFINES += BUILD_QSETTINGSGENERATOR +DEFINES += "TARGET=\\\"$$TARGET\\\"" +DEFINES += "VERSION=\\\"$$VERSION\\\"" +DEFINES += "COMPANY=\\\"$$COMPANY\\\"" +DEFINES += "BUNDLE_PREFIX=\\\"$$BUNDLE_PREFIX\\\"" + +HEADERS += + +SOURCES += \ + main.cpp + +load(qt_tool) + +win32 { + QMAKE_TARGET_PRODUCT = "Qt Settings Builder" + QMAKE_TARGET_COMPANY = $$COMPANY + QMAKE_TARGET_COPYRIGHT = "Felix Barz" +} else:mac { + QMAKE_TARGET_BUNDLE_PREFIX = $${BUNDLE_PREFIX}. +} + +DISTFILES += qsettingsgenerator.xsd diff --git a/tools/tools.pro b/tools/tools.pro new file mode 100644 index 0000000..a5c9f22 --- /dev/null +++ b/tools/tools.pro @@ -0,0 +1,9 @@ +TEMPLATE = subdirs + +SUBDIRS += \ + settingsgenerator + +settingsgenerator.CONFIG += no_lrelease_target + +prepareRecursiveTarget(lrelease) +QMAKE_EXTRA_TARGETS += lrelease