From d2f90cc3c4ff5886cd15e44885b83388e936c7c0 Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Sat, 21 Jul 2018 21:53:30 +0200 Subject: [PATCH] added support for list entries --- src/mvvmcore/mvvmcore.pro | 3 +- src/mvvmcore/settingsentry.cpp | 31 ++ src/mvvmcore/settingsentry.h | 423 +++++++++++++++++- .../datasyncsettingsentry.cpp | 2 +- .../settingsgenerator/generatortest.xml | 17 + .../mvvmcore/settingsgenerator/test_de.ts | 2 +- .../settingsgenerator/testbackend.cpp | 7 + .../tst_settingsgenerator.cpp | 51 ++- .../settingsgenerator/qsettingsgenerator.xsd | 19 +- tools/settingsgenerator/settingsgenerator.cpp | 45 +- tools/settingsgenerator/settingsgenerator.h | 4 +- 11 files changed, 588 insertions(+), 16 deletions(-) create mode 100644 src/mvvmcore/settingsentry.cpp diff --git a/src/mvvmcore/mvvmcore.pro b/src/mvvmcore/mvvmcore.pro index ec8dfae..9081a35 100644 --- a/src/mvvmcore/mvvmcore.pro +++ b/src/mvvmcore/mvvmcore.pro @@ -38,7 +38,8 @@ SOURCES += \ settingssetuploader.cpp \ settingsviewmodel.cpp \ isettingsaccessor.cpp \ - qsettingsaccessor.cpp + qsettingsaccessor.cpp \ + settingsentry.cpp TRANSLATIONS += \ translations/qtmvvmcore_de.ts \ diff --git a/src/mvvmcore/settingsentry.cpp b/src/mvvmcore/settingsentry.cpp new file mode 100644 index 0000000..67cb6ad --- /dev/null +++ b/src/mvvmcore/settingsentry.cpp @@ -0,0 +1,31 @@ +#include "settingsentry.h" +using namespace QtMvvm; + +template<> +void QtMvvm::SettingsEntry::set(const QVariant &value) +{ + _accessor->save(_key, value); +} + +template<> +QVariant QtMvvm::SettingsEntry::get() const +{ + return _accessor->load(_key, _default); +} + +template<> +void QtMvvm::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); + }); + QObject::connect(_accessor, &ISettingsAccessor::entryRemoved, + scope, [mKey, mDefault, callback](const QString &key) { + if(key == mKey) + callback(mDefault); + }); +} diff --git a/src/mvvmcore/settingsentry.h b/src/mvvmcore/settingsentry.h index 87ecc78..74acf88 100644 --- a/src/mvvmcore/settingsentry.h +++ b/src/mvvmcore/settingsentry.h @@ -1,6 +1,10 @@ #ifndef QTMVVM_SETTINGSENTRY_H #define QTMVVM_SETTINGSENTRY_H +#include +#include + +#include "QtMvvmCore/qtmvvmcore_global.h" #include "QtMvvmCore/isettingsaccessor.h" namespace QtMvvm { @@ -35,6 +39,175 @@ private: QVariant _default; }; +template +class SettingsEntry> +{ + Q_DISABLE_COPY(SettingsEntry) + +public: + class ListElement + { + Q_DISABLE_COPY(ListElement) + + public: + inline ListElement(ListElement &&other) noexcept = default; + inline ListElement &operator=(ListElement &&other) noexcept = default; + + TType get() const && { return _self->getAt(_index); } + void set(const TType &value) && { _self->setAt(_index, value); } + + inline ListElement &operator=(const TType &value) && { _self->setAt(_index, value); return *this; } + inline operator TType() const && { return _self->getAt(_index); } + + private: + friend class SettingsEntry>; + inline ListElement(SettingsEntry> *self, int index) : _self{self}, _index{index} {} + + SettingsEntry> *_self; + int _index; + }; + + template + class iterator_base; + + class iterator_value + { + public: + TType get() const { return _self->getAt(_index); } + void set(const TType &value) { _self->setAt(_index, value); } + + inline iterator_value &operator=(const TType &value) { _self->setAt(_index, value); return *this; } + inline operator TType() const { return _self->getAt(_index); } + + inline friend void swap(iterator_value& lhs, iterator_value& rhs) { qSwap(lhs._self, rhs._self); qSwap(lhs._index, rhs._index); } + + inline friend bool operator==(const iterator_value &lhs, const iterator_value &rhs) { assert(lhs._self == rhs._self); return lhs._index == rhs._index; } + inline friend bool operator!=(const iterator_value &lhs, const iterator_value &rhs) { assert(lhs._self == rhs._self); return lhs._index != rhs._index; } + inline friend bool operator<(const iterator_value &lhs, const iterator_value &rhs) { assert(lhs._self == rhs._self); return lhs._index < rhs._index; } + inline friend bool operator>(const iterator_value &lhs, const iterator_value &rhs) { assert(lhs._self == rhs._self); return lhs._index > rhs._index; } + inline friend bool operator<=(const iterator_value &lhs, const iterator_value &rhs) { assert(lhs._self == rhs._self); return lhs._index <= rhs._index; } + inline friend bool operator>=(const iterator_value &lhs, const iterator_value &rhs) { assert(lhs._self == rhs._self); return lhs._index >= rhs._index; } + + inline friend iterator_value operator+(const iterator_value &value, int delta) { return iterator_value{value._self, value._index + delta}; } + inline friend iterator_value operator+(int delta, const iterator_value &value) { return iterator_value{value._self, value._index + delta}; } + inline friend iterator_value operator-(const iterator_value &value, int delta) { return iterator_value{value._self, value._index - delta}; } + inline friend int operator-(const iterator_value &lhs, const iterator_value &rhs) { assert(lhs._self == rhs._self); return lhs._index - rhs._index; } + + private: + template + friend class SettingsEntry>::iterator_base; + + inline iterator_value(SettingsEntry> *self, int index) : _self{self}, _index{index} {} + inline iterator_value(const iterator_value &other) = default; + inline iterator_value &operator=(const iterator_value &other) = default; + inline iterator_value(iterator_value &&other) noexcept = default; + inline iterator_value &operator=(iterator_value &&other) noexcept = default; + + SettingsEntry> *_self; + int _index; + }; + + template + class iterator_base + { + public: + using iterator_category = std::random_access_iterator_tag; + using difference_type = int; + using value_type = T; + using pointer = value_type*; + using reference = value_type&; + + inline iterator_base(const iterator_base &other) = default; + inline iterator_base &operator=(const iterator_base &other) = default; + inline iterator_base(iterator_base &&other) noexcept = default; + inline iterator_base &operator=(iterator_base &&other) noexcept = default; + + inline iterator_base &operator++() { ++_value._index; return *this; } + inline iterator_base operator++(int) { return iterator_base{_value._self, _value._index++}; } + inline iterator_base &operator--() { --_value._index; return *this; } + inline iterator_base operator--(int) { return iterator_base{_value._self, _value._index--}; } + + inline const value_type &operator*() const { return _value; } + inline value_type &operator*() { return _value; } + inline const value_type *operator->() const { return &_value; } + inline value_type *operator->() { return &_value; } + inline friend void swap(iterator_base &lhs, iterator_base &rhs) { swap(lhs._value, rhs._value); } + + inline friend bool operator==(const iterator_base &lhs, const iterator_base &rhs) { return lhs._value == rhs._value; } + inline friend bool operator!=(const iterator_base &lhs, const iterator_base &rhs) { return lhs._value != rhs._value; } + inline friend bool operator<(const iterator_base &lhs, const iterator_base &rhs) { return lhs._value < rhs._value; } + inline friend bool operator>(const iterator_base &lhs, const iterator_base &rhs) { return lhs._value > rhs._value; } + inline friend bool operator<=(const iterator_base &lhs, const iterator_base &rhs) { return lhs._value <= rhs._value; } + inline friend bool operator>=(const iterator_base &lhs, const iterator_base &rhs) { return lhs._value >= rhs._value; } + + inline iterator_base &operator+=(difference_type delta) { _value._index += delta; return *this; } + inline friend iterator_base operator+(const iterator_base &iter, difference_type delta) { return iterator_base{iter._value + delta}; } + inline friend iterator_base operator+(difference_type delta, const iterator_base &iter) { return iterator_base{iter._value + delta}; } + inline iterator_base &operator-=(difference_type delta) { _value._index -= delta; return *this; } + inline friend iterator_base operator-(const iterator_base &iter, difference_type delta) { return iterator_base{iter._value - delta}; } + inline friend difference_type operator-(const iterator_base &lhs, const iterator_base &rhs) { return lhs._value - rhs._value; } + + inline value_type operator[](difference_type delta) const { return iterator_value{_value._self, _value._index + delta}; } + + private: + friend class SettingsEntry>; + + inline iterator_base(SettingsEntry> *self, int index) : _value{self, index} {} + inline iterator_base(iterator_value value) : _value{std::move(value)} {} + iterator_value _value; + }; + + using iterator = iterator_base; + using const_iterator = iterator_base; + + SettingsEntry() = default; + + bool isSet() const; + QString key() const; + + QList get() const; + void set(const QList &value); + void reset(bool reInit = true); + + SettingsEntry> &operator=(const QList &value); + operator QList() const; + + int size() const; + TType getAt(int index) const; + void setAt(int index, const TType &value); + void push(const TType &value); + void push(const QList &values); + TType pop(); + void chop(int count); + + ListElement operator[](int index); + const ListElement operator[](int index) const; + SettingsEntry> &operator+=(const TType &value); + SettingsEntry> &operator+=(const QList &values); + + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + const_iterator constBegin() const; + const_iterator constEnd() const; + + void addChangeCallback(const std::function &callback); // index, value + void addChangeCallback(QObject *scope, const std::function &callback); + void addSizeChangeCallback(const std::function &callback); // size + void addSizeChangeCallback(QObject *scope, const std::function &callback); + + // internal + void setup(QString key, ISettingsAccessor *accessor, QVariant defaultValue = {}); + void setupInit(QList init); + +private: + QString _key; + ISettingsAccessor *_accessor = nullptr; + QVariant _default; + QList _init; +}; + template <> class SettingsEntry { @@ -47,7 +220,6 @@ public: inline void setup(const QString &, ISettingsAccessor *, const QVariant & = {}) {} }; - // ------------- Generic Implementation ------------- template @@ -68,12 +240,18 @@ T SettingsEntry::get() const return _accessor->load(_key, _default).template value(); } +template<> +Q_MVVMCORE_EXPORT QVariant SettingsEntry::get() const; + template void SettingsEntry::set(const T &value) { _accessor->save(_key, QVariant::fromValue(value)); } +template<> +Q_MVVMCORE_EXPORT void SettingsEntry::set(const QVariant &value); + template void SettingsEntry::reset() { @@ -87,6 +265,12 @@ SettingsEntry &SettingsEntry::operator=(const T &value) return (*this); } +template +SettingsEntry::operator T() const +{ + return get(); +} + template void SettingsEntry::addChangeCallback(const std::function &callback) { @@ -110,14 +294,237 @@ void SettingsEntry::addChangeCallback(QObject *scope, const std::function +Q_MVVMCORE_EXPORT void SettingsEntry::addChangeCallback(QObject *scope, const std::function &callback); + template -SettingsEntry::operator T() const +void SettingsEntry::setup(QString key, ISettingsAccessor *accessor, QVariant defaultValue) +{ + Q_ASSERT_X(accessor, Q_FUNC_INFO, "You must set a valid accessor before initializing the settings!"); + _key = std::move(key); + _accessor = accessor; + _default = std::move(defaultValue); +} + + +// ------------- Generic Implementation ListEntry ------------- + +template +bool SettingsEntry>::isSet() const +{ + return _accessor->contains(_key + QStringLiteral("/size")); +} + +template +QString SettingsEntry>::key() const +{ + return _key; +} + +template +QList SettingsEntry>::get() const +{ + auto mSize = size(); + QList resList; + resList.reserve(mSize); + for(auto i = 0; i < mSize; ++i) + resList.append(getAt(i)); + return resList; +} + +template +void SettingsEntry>::set(const QList &value) +{ + reset(false); + push(value); +} + +template +void SettingsEntry>::reset(bool reInit) +{ + _accessor->remove(_key); + if(reInit && !_init.isEmpty()) + push(_init); +} + +template +SettingsEntry> &SettingsEntry>::operator=(const QList &value) +{ + set(value); + return *this; +} + +template +SettingsEntry>::operator QList() const { return get(); } -template -void SettingsEntry::setup(QString key, ISettingsAccessor *accessor, QVariant defaultValue) +template +int SettingsEntry>::size() const +{ + return _accessor->load(_key + QStringLiteral("/size"), 0).toInt(); +} + +template +TType SettingsEntry>::getAt(int index) const +{ + return _accessor->load(_key + QStringLiteral("/%1/value").arg(index), _default).template value(); +} + +template +void SettingsEntry>::setAt(int index, const TType &value) +{ + _accessor->save(_key + QStringLiteral("/%1/value").arg(index), QVariant::fromValue(value)); +} + +template +void SettingsEntry>::push(const TType &value) +{ + push(QList{value}); +} + +template +void SettingsEntry>::push(const QList &values) +{ + auto cIndex = size(); + for(const auto &value : values) + setAt(cIndex++, value); + _accessor->save(_key + QStringLiteral("/size"), cIndex); +} + +template +TType QtMvvm::SettingsEntry>::pop() +{ + auto res = getAt(size() - 1); + chop(1); + return res; +} + +template +void QtMvvm::SettingsEntry>::chop(int count) +{ + auto cSize = size(); + auto nSize = qMax(size() - count, 0); + for(auto i = cSize - 1; i >= nSize; --i) + _accessor->remove(_key + QStringLiteral("/%1/value").arg(i)); + _accessor->save(_key + QStringLiteral("/size"), nSize); +} + +template +const typename SettingsEntry>::ListElement SettingsEntry>::operator[](int index) const +{ + return ListElement{this, index}; +} + + +template +typename SettingsEntry>::ListElement SettingsEntry>::operator[](int index) +{ + return ListElement{this, index}; +} + +template +SettingsEntry> &SettingsEntry>::operator+=(const TType &value) +{ + push(value); + return *this; +} + +template +SettingsEntry> &SettingsEntry>::operator+=(const QList &values) +{ + push(values); + return *this; +} + +template +typename SettingsEntry>::iterator SettingsEntry>::begin() +{ + return iterator{this, 0}; +} + +template +typename SettingsEntry>::iterator QtMvvm::SettingsEntry>::end() +{ + return iterator{this, size()}; +} + +template +typename SettingsEntry>::const_iterator SettingsEntry>::begin() const +{ + return constBegin(); +} + +template +typename SettingsEntry>::const_iterator SettingsEntry>::end() const +{ + return constEnd(); +} + +template +typename SettingsEntry>::const_iterator SettingsEntry>::constBegin() const +{ + return const_iterator{const_cast>*>(this), 0}; +} + +template +typename SettingsEntry>::const_iterator SettingsEntry>::constEnd() const +{ + return const_iterator{const_cast>*>(this), size()}; +} + +template +void SettingsEntry>::addChangeCallback(const std::function &callback) +{ + addChangeCallback(_accessor, callback); +} + +template +void SettingsEntry>::addChangeCallback(QObject *scope, const std::function &callback) +{ + QRegularExpression mKey {QStringLiteral("^%1\\/\\d+\\/value$").arg(QRegularExpression::escape(_key))}; + mKey.optimize(); + auto mDefault = _default; + QObject::connect(_accessor, &ISettingsAccessor::entryChanged, + scope, [mKey, callback](const QString &key, const QVariant &value) { + auto match = mKey.match(key); + if(match.hasMatch()) + callback(match.captured(1).toInt(), value.template value()); + }); + QObject::connect(_accessor, &ISettingsAccessor::entryRemoved, + scope, [mKey, mDefault, callback](const QString &key) { + auto match = mKey.match(key); + if(match.hasMatch()) + callback(match.captured(1).toInt(), mDefault); + }); +} + +template +void SettingsEntry>::addSizeChangeCallback(const std::function &callback) +{ + addSizeChangeCallback(_accessor, callback); +} + +template +void SettingsEntry>::addSizeChangeCallback(QObject *scope, const std::function &callback) +{ + QString mKey = _key + QStringLiteral("/size"); + auto mInit = _init; + QObject::connect(_accessor, &ISettingsAccessor::entryChanged, + scope, [mKey, callback](const QString &key, const QVariant &value) { + if(key == mKey) + callback(value.toInt()); + }); + QObject::connect(_accessor, &ISettingsAccessor::entryRemoved, + scope, [mKey, mInit, callback](const QString &key) { + if(key == mKey) + callback(0); //is ok, as in case of a "reinit", the entry changed will be emitted next + }); +} + +template +void SettingsEntry>::setup(QString key, ISettingsAccessor *accessor, QVariant defaultValue) { Q_ASSERT_X(accessor, Q_FUNC_INFO, "You must set a valid accessor before initializing the settings!"); _key = std::move(key); @@ -125,6 +532,14 @@ void SettingsEntry::setup(QString key, ISettingsAccessor *accessor, QVariant _default = std::move(defaultValue); } +template +void QtMvvm::SettingsEntry >::setupInit(QList init) +{ + _init = std::move(init); + if(!isSet()) + push(_init); +} + } diff --git a/src/mvvmdatasynccore/datasyncsettingsentry.cpp b/src/mvvmdatasynccore/datasyncsettingsentry.cpp index 1baf017..02b6579 100644 --- a/src/mvvmdatasynccore/datasyncsettingsentry.cpp +++ b/src/mvvmdatasynccore/datasyncsettingsentry.cpp @@ -1,6 +1,6 @@ #include "datasyncsettingsentry.h" #include -#if QT_HAS_INCLUDE() +#if QT_HAS_INCLUDE() && __cplusplus >= 201703L #include #define QTMVVM_HAS_OPTIONAL #endif diff --git a/tests/auto/mvvmcore/settingsgenerator/generatortest.xml b/tests/auto/mvvmcore/settingsgenerator/generatortest.xml index d877cb7..2caa100 100644 --- a/tests/auto/mvvmcore/settingsgenerator/generatortest.xml +++ b/tests/auto/mvvmcore/settingsgenerator/generatortest.xml @@ -51,4 +51,21 @@ tr="true"/> + + + + + + + "Hello World" + { + "test1", + "test2", + "test3" + } + diff --git a/tests/auto/mvvmcore/settingsgenerator/test_de.ts b/tests/auto/mvvmcore/settingsgenerator/test_de.ts index a7c82dd..0d57e36 100644 --- a/tests/auto/mvvmcore/settingsgenerator/test_de.ts +++ b/tests/auto/mvvmcore/settingsgenerator/test_de.ts @@ -4,7 +4,7 @@ SettingsGeneratorTest - + somet translated text... diff --git a/tests/auto/mvvmcore/settingsgenerator/testbackend.cpp b/tests/auto/mvvmcore/settingsgenerator/testbackend.cpp index 87138dc..8927dcc 100644 --- a/tests/auto/mvvmcore/settingsgenerator/testbackend.cpp +++ b/tests/auto/mvvmcore/settingsgenerator/testbackend.cpp @@ -24,6 +24,13 @@ void TestBackend::save(const QString &key, const QVariant &value) void TestBackend::remove(const QString &key) { + for(auto it = _data.begin(); it != _data.end();) { + if(it.key().startsWith(key + QLatin1Char('/'))) { + it = _data.erase(it); + emit entryRemoved(key); + } else + ++it; + } _data.remove(key); emit entryRemoved(key); } diff --git a/tests/auto/mvvmcore/settingsgenerator/tst_settingsgenerator.cpp b/tests/auto/mvvmcore/settingsgenerator/tst_settingsgenerator.cpp index abd5d81..38e266f 100644 --- a/tests/auto/mvvmcore/settingsgenerator/tst_settingsgenerator.cpp +++ b/tests/auto/mvvmcore/settingsgenerator/tst_settingsgenerator.cpp @@ -39,6 +39,9 @@ void SettingsGeneratorTest::testSettingsGenerator() QCOMPARE(settings->parentNode.parentEntry.key(), QStringLiteral("tests/parentNode/parentEntry")); QCOMPARE(settings->parentNode.parentEntry.nodeWithCodeEntry.key(), QStringLiteral("tests/parentNode/parentEntry/nodeWithCodeEntry")); QCOMPARE(settings->parentNode.parentEntry.leafEntry.key(), QStringLiteral("tests/parentNode/parentEntry/leafEntry")); + QCOMPARE(settings->variantEntry.key(), QStringLiteral("tests/variantEntry")); + QCOMPARE(settings->listEntry.key(), QStringLiteral("tests/listEntry")); + QCOMPARE(settings->listEntry.dummyChild.key(), QStringLiteral("tests/listEntry/dummyChild")); //verify defaults QCOMPARE(settings->emptyEntry.get(), false); @@ -48,21 +51,65 @@ void SettingsGeneratorTest::testSettingsGenerator() QCOMPARE(settings->parentNode.parentEntry.get(), true); QCOMPARE(settings->parentNode.parentEntry.nodeWithCodeEntry.get(), 43); QCOMPARE(settings->parentNode.parentEntry.leafEntry.get(), QStringLiteral("translate me")); + QCOMPARE(settings->variantEntry.get(), QVariant{}); + QByteArrayList iList{"test1", "test2", "test3"}; + QCOMPARE(settings->listEntry.get(), iList); + QCOMPARE(settings->listEntry.dummyChild.get(), false); //verify read/write (just on a single entry, they work all the same) - Q_ASSERT(tBackend->_data.isEmpty()); + auto tKey = QStringLiteral("tests/advancedEntry"); + QVERIFY(!tBackend->_data.contains(tKey)); QString cValue; settings->advancedEntry.addChangeCallback([&](QString value) { cValue = std::move(value); }); QString tValue = QStringLiteral("test42"); - auto tKey = QStringLiteral("tests/advancedEntry"); QCOMPARE(settings->advancedEntry.key(), tKey); settings->advancedEntry = tValue; QCOMPARE(tBackend->_data.value(tKey).toString(), tValue); QCOMPARE(cValue, tValue); QVERIFY(settings->advancedEntry.isSet()); QCOMPARE(settings->advancedEntry, tValue); + + //verify list stuff + QVERIFY(settings->listEntry.isSet()); + QCOMPARE(settings->listEntry.size(), 3); + QCOMPARE(settings->listEntry.getAt(0), "test1"); + QCOMPARE(settings->listEntry[1].get(), "test2"); + QCOMPARE(static_cast(settings->listEntry[2]), "test3"); + QCOMPARE(settings->listEntry.getAt(3), "Hello World"); + + settings->listEntry.push("baum"); + QCOMPARE(settings->listEntry.size(), 4); + QCOMPARE(settings->listEntry.getAt(3), "baum"); + settings->listEntry.setAt(1, "tree"); + settings->listEntry[2] = "eetr"; + QCOMPARE(settings->listEntry.size(), 4); + QCOMPARE(settings->listEntry.getAt(1), "tree"); + QCOMPARE(settings->listEntry.getAt(2), "eetr"); + settings->listEntry += "baum42"; + QCOMPARE(settings->listEntry.size(), 5); + QCOMPARE(settings->listEntry.getAt(4), "baum42"); + QCOMPARE(settings->listEntry.pop(), "baum42"); + QCOMPARE(settings->listEntry.size(), 4); + QCOMPARE(settings->listEntry.getAt(4), "Hello World"); + settings->listEntry.chop(10); + QCOMPARE(settings->listEntry.size(), 0); + QVERIFY(settings->listEntry.isSet()); + + settings->listEntry.reset(false); + QVERIFY(!settings->listEntry.isSet()); + QCOMPARE(settings->listEntry.size(), 0); + settings->listEntry.reset(true); + QVERIFY(settings->listEntry.isSet()); + QCOMPARE(settings->listEntry.size(), 3); + + for(const auto &elem : qAsConst(settings->listEntry)) + qDebug() << elem.get() << static_cast(elem); + for(auto &elem : settings->listEntry) { + elem = "test1"; + elem.set("test2"); + } } void SettingsGeneratorTest::testImportedSettings() diff --git a/tools/settingsgenerator/qsettingsgenerator.xsd b/tools/settingsgenerator/qsettingsgenerator.xsd index 624337b..147a1d4 100644 --- a/tools/settingsgenerator/qsettingsgenerator.xsd +++ b/tools/settingsgenerator/qsettingsgenerator.xsd @@ -14,7 +14,7 @@ - + @@ -22,7 +22,7 @@ - + @@ -43,7 +43,7 @@ - + @@ -53,7 +53,7 @@ - + @@ -61,6 +61,7 @@ + @@ -86,6 +87,16 @@ + + + + + + + + + + diff --git a/tools/settingsgenerator/settingsgenerator.cpp b/tools/settingsgenerator/settingsgenerator.cpp index e077ca6..ae73a0c 100644 --- a/tools/settingsgenerator/settingsgenerator.cpp +++ b/tools/settingsgenerator/settingsgenerator.cpp @@ -198,6 +198,12 @@ SettingsGeneratorBase::NodeContentGroup *SettingsGenerator::findContentGroup(Set *isEntry = true; return &(nonstd::get(cNode)); } + } else if(nonstd::holds_alternative(cNode)) { + if(nonstd::get(cNode).key == key) { + if(isEntry) + *isEntry = true; + return &(nonstd::get(cNode)); + } } else if(nonstd::holds_alternative(cNode)) { auto res = findContentGroup(&(nonstd::get(cNode)), key); if(res) @@ -236,6 +242,11 @@ void SettingsGenerator::fixTrContext(NodeContentGroup &group, const QString &con if(!entry.trContext) entry.trContext = context; fixTrContext(entry, context); + } else if(nonstd::holds_alternative(node)) { + auto &entry = nonstd::get(node); + if(!entry.trContext) + entry.trContext = context; + fixTrContext(entry, context); } else if(nonstd::holds_alternative(node)) fixTrContext(nonstd::get(node), context); } @@ -290,6 +301,8 @@ void SettingsGenerator::writeNodeElementDeclarations(const NodeContentGroup &nod writeNodeDeclaration(nonstd::get(cNode), typeMappings, intendent); else if(nonstd::holds_alternative(cNode)) writeEntryDeclaration(nonstd::get(cNode), typeMappings, intendent); + else if(nonstd::holds_alternative(cNode)) + writeListEntryDeclaration(nonstd::get(cNode), typeMappings, intendent); else if(nonstd::holds_alternative(cNode)) writeNodeElementDeclarations(nonstd::get(cNode), typeMappings, intendent); } @@ -315,6 +328,21 @@ void SettingsGenerator::writeEntryDeclaration(const EntryType &entry, const QHas } } +void SettingsGenerator::writeListEntryDeclaration(const SettingsGeneratorBase::ListEntryType &entry, const QHash &typeMappings, int intendent) +{ + if(entry.contentNodes.isEmpty()) + _hdr << TABS << "QtMvvm::SettingsEntry> " << entry.key << ";\n"; + else { + const QString mType = QStringLiteral("QList<") + typeMappings.value(entry.type, entry.type) + QLatin1Char('>'); + _hdr << TABS << "struct : QtMvvm::SettingsEntry<" << mType << "> { //" << entry.key << "\n"; + writeNodeElementDeclarations(entry, typeMappings, intendent + 1); + _hdr << TABS << "\tinline auto &operator=(const " << mType << " &__value) { SettingsEntry<" << mType << ">::operator=(__value); return *this; }\n"; + _hdr << TABS << "\tinline auto &operator+=(const " << typeMappings.value(entry.type, entry.type) << " &__value) { SettingsEntry<" << mType << ">::operator+=(__value); return *this; }\n"; + _hdr << TABS << "\tinline auto &operator+=(const " << mType << " &__value) { SettingsEntry<" << mType << ">::operator+=(__value); return *this; }\n"; + _hdr << TABS << "} " << entry.key << ";\n"; + } +} + void SettingsGenerator::writeSource(const SettingsType &settings) { _src << "#include \"" << _hdrFile.fileName() << "\"\n"; @@ -387,12 +415,14 @@ void SettingsGenerator::writeNodeElementDefinitions(const SettingsGeneratorBase: writeNodeElementDefinitions(xNode, typeMappings, baseKey, QStringList{keyChain} << xNode.key); } else if(nonstd::holds_alternative(cNode)) writeEntryDefinition(nonstd::get(cNode), typeMappings, baseKey, keyChain); + else if(nonstd::holds_alternative(cNode)) + writeListEntryDefinition(nonstd::get(cNode), typeMappings, baseKey, keyChain); else if(nonstd::holds_alternative(cNode)) writeNodeElementDefinitions(nonstd::get(cNode), typeMappings, baseKey, keyChain); } } -void SettingsGenerator::writeEntryDefinition(const SettingsGeneratorBase::EntryType &entry, const QHash &typeMappings, const optional &baseKey, QStringList keyChain) +void SettingsGenerator::writeEntryDefinition(const SettingsGeneratorBase::EntryType &entry, const QHash &typeMappings, const optional &baseKey, QStringList keyChain, bool skipChildren) { keyChain.append(entry.key); _src << "\t" << keyChain.join(QLatin1Char('.')) @@ -408,5 +438,16 @@ void SettingsGenerator::writeEntryDefinition(const SettingsGeneratorBase::EntryT _src << "}.value<" << typeMappings.value(entry.type, entry.type) << ">()"; } _src << ");\n"; - writeNodeElementDefinitions(entry, typeMappings, baseKey, std::move(keyChain)); + if(!skipChildren) + writeNodeElementDefinitions(entry, typeMappings, baseKey, keyChain); +} + +void SettingsGenerator::writeListEntryDefinition(const SettingsGeneratorBase::ListEntryType &entry, const QHash &typeMappings, const optional &baseKey, QStringList keyChain) +{ + writeEntryDefinition(entry, typeMappings, baseKey, keyChain, entry.init.has_value()); + if(entry.init) { + keyChain.append(entry.key); + _src << "\t" << keyChain.join(QLatin1Char('.')) << ".setupInit(" << entry.init.value().trimmed() << ");\n"; + writeNodeElementDefinitions(entry, typeMappings, baseKey, keyChain); + } } diff --git a/tools/settingsgenerator/settingsgenerator.h b/tools/settingsgenerator/settingsgenerator.h index ca3b4c6..147072d 100644 --- a/tools/settingsgenerator/settingsgenerator.h +++ b/tools/settingsgenerator/settingsgenerator.h @@ -41,10 +41,12 @@ private: void writeNodeElementDeclarations(const NodeContentGroup &node, const QHash &typeMappings, int intendent = 1); void writeNodeDeclaration(const NodeType &node, const QHash &typeMappings, int intendent = 1); void writeEntryDeclaration(const EntryType &entry, const QHash &typeMappings, int intendent = 1); + void writeListEntryDeclaration(const ListEntryType &entry, const QHash &typeMappings, int intendent = 1); void writeSource(const SettingsType &settings); void writeNodeElementDefinitions(const NodeContentGroup &node, const QHash &typeMappings, const optional &baseKey, const QStringList &keyChain = {}); - void writeEntryDefinition(const EntryType &entry, const QHash &typeMappings, const optional &baseKey, QStringList keyChain); + void writeEntryDefinition(const EntryType &entry, const QHash &typeMappings, const optional &baseKey, QStringList keyChain, bool skipChildren = false); + void writeListEntryDefinition(const ListEntryType &entry, const QHash &typeMappings, const optional &baseKey, QStringList keyChain); }; #endif // SETTINGSGENERATOR_H