diff --git a/src/mvvmcore/settingsconfigloader.cpp b/src/mvvmcore/settingsconfigloader.cpp index 26af00a..455d7a8 100644 --- a/src/mvvmcore/settingsconfigloader.cpp +++ b/src/mvvmcore/settingsconfigloader.cpp @@ -14,41 +14,46 @@ void SettingsConfigLoader::changeDefaultIcon(const QUrl &defaultIcon) Setup SettingsConfigLoader::loadSetup(const QString &filePath, const QString &frontend, const QFileSelector *selector) const { + auto keyTuple = std::make_tuple(filePath, frontend, selector->allSelectors()); Setup setup; - if(!_cache.contains(filePath)) { + if(!_cache.contains(keyTuple)) { try { + const_cast(this)->setFilters(frontend, selector); auto config = const_cast(this)->readDocument(filePath); + const_cast(this)->resetFilters(); + if(!nonstd::holds_alternative(config)) throw SettingsConfigException{"Root Element of \"" + filePath.toUtf8() + "\" must be a SettingsConfig"}; - _cache.insert(filePath, convertSettings(nonstd::get(config))); + + setup = convertSettings(nonstd::get(config)); + _cache.insert(keyTuple, new Setup{setup}); } catch (Exception &e) { throw SettingsConfigException{e}; } } else - setup = *(_cache.object(filePath)); + setup = *(_cache.object(keyTuple)); - //TODO clearSetup(setup, frontend, selector->allSelectors()); return setup; } -Setup *SettingsConfigLoader::convertSettings(const SettingsConfigType &settings) const +Setup SettingsConfigLoader::convertSettings(const SettingsConfigType &settings) const { - QScopedPointer setup{new Setup{}}; + Setup setup; - setup->allowSearch = settings.allowSearch; - setup->allowRestore = settings.allowRestore; + setup.allowSearch = settings.allowSearch; + setup.allowRestore = settings.allowRestore; for(const auto &element : settings.content) { if(nonstd::holds_alternative(element)) {//holds categories -> read them const auto &category = nonstd::get(element); - setup->categories.append(convertCategory(category, category.content)); + setup.categories.append(convertCategory(category, category.content)); } else { //hold anything else -> create default from all child and thus break - setup->categories.append(convertCategory({}, settings.content)); + setup.categories.append(convertCategory({}, settings.content)); break; } } - return setup.take(); + return setup; } template @@ -58,8 +63,6 @@ Category SettingsConfigLoader::convertCategory(const CategoryType &category, con cat.title = category.title.value_or(tr("General Settings")); cat.icon = category.icon ? QUrl{category.icon.value()} : _defaultIcon; cat.tooltip = category.tooltip.value_or(QString{}); - cat.selectors = category.selectors.value_or(QString{}); - cat.frontends = category.frontends.value_or(QString{}); for(const auto &element : content) { if(nonstd::holds_alternative(element)) {//holds sections -> read them const auto §ion = nonstd::get(element); @@ -79,8 +82,6 @@ Section SettingsConfigLoader::convertSection(const SectionType §ion, const Q sec.title = section.title.value_or(tr("General")); sec.icon = section.icon ? QUrl{section.icon.value()} : QUrl{}; sec.tooltip = section.tooltip.value_or(QString{}); - sec.selectors = section.selectors.value_or(QString{}); - sec.frontends = section.frontends.value_or(QString{}); for(const auto &element : content) { if(nonstd::holds_alternative(element)) {//holds sections -> read them const auto &group = nonstd::get(element); @@ -99,8 +100,6 @@ Group SettingsConfigLoader::convertGroup(const GroupType &group, const QList(element)) {//holds sections -> read them const auto &entry = nonstd::get(element); @@ -135,3 +134,12 @@ QException *SettingsConfigException::clone() const { return new SettingsConfigException{_what}; } + + + +uint qHash(const std::tuple &key, uint seed) +{ + return qHash(std::get<0>(key), seed) ^ + qHash(std::get<1>(key), seed) ^ + qHash(std::get<2>(key), seed); +} diff --git a/src/mvvmcore/settingsconfigloader_p.h b/src/mvvmcore/settingsconfigloader_p.h index 42ba5ca..10a26c9 100644 --- a/src/mvvmcore/settingsconfigloader_p.h +++ b/src/mvvmcore/settingsconfigloader_p.h @@ -23,9 +23,9 @@ public: private: QUrl _defaultIcon; - mutable QCache _cache; + mutable QCache, SettingsElements::Setup> _cache; - SettingsElements::Setup *convertSettings(const SettingsConfigType &settings) const; + SettingsElements::Setup convertSettings(const SettingsConfigType &settings) const; template SettingsElements::Category convertCategory(const CategoryType &category, const QList> &content) const; @@ -52,4 +52,6 @@ private: } +uint qHash(const std::tuple &key, uint seed); + #endif // SETTINGSCONFIGLOADER_P_H diff --git a/src/mvvmcore/settingssetup.h b/src/mvvmcore/settingssetup.h index 6d94e68..b4d68ad 100644 --- a/src/mvvmcore/settingssetup.h +++ b/src/mvvmcore/settingssetup.h @@ -34,7 +34,7 @@ struct Entry QVariantMap properties; //! *[Internal]* A logical string describing the allowed frontends - QString frontends; + QString frontends; //MAJOR remove all //! *[Internal]* A logical string describing the allowed selectors QString selectors; }; diff --git a/src/settingsconfig/settingsconfig.xsd b/src/settingsconfig/settingsconfig.xsd index e65e245..1e57d00 100644 --- a/src/settingsconfig/settingsconfig.xsd +++ b/src/settingsconfig/settingsconfig.xsd @@ -13,15 +13,8 @@ - - - - - - - - + @@ -43,11 +36,15 @@ + + + + + + - - @@ -100,6 +97,15 @@ + + + + + + + + + diff --git a/src/settingsconfig/settingsconfigimpl.cpp b/src/settingsconfig/settingsconfigimpl.cpp index 0be0620..38c059a 100644 --- a/src/settingsconfig/settingsconfigimpl.cpp +++ b/src/settingsconfig/settingsconfigimpl.cpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace { @@ -37,6 +38,23 @@ struct VariantInfo(*it)) { + if(!isUsable(nonstd::get(*it))) { + it = group.erase(it); + continue; + } if(!readGeneralInclude(reader, nonstd::get(*it), it, group)) continue; } + // verify that the contents are all of the same type if(index) { if(index.value() != it->index()) throw XmlException{reader, QStringLiteral("Detected mixture of different child elements. Only includes and a single other type are allowed")}; } else index = it->index(); - ++it; + + //erase if not usable due to selectors + bool visited = false; + nonstd::visit([&](auto &&element){ //TODO use trick if neccessary: https://en.cppreference.com/w/cpp/utility/variant/visit + visited = true; + if(isUsable(element)) + ++it; + else + it = group.erase(it); + }, *it); + Q_ASSERT(visited); } } @@ -89,6 +122,9 @@ template bool SettingsConfigImpl::readGeneralInclude(QXmlStreamReader &reader, IncludeType include, TIter &it, TList &list) { try { + if(_selector) + include.includePath = _selector->select(include.includePath); + //make the path relative if possbile if(dynamic_cast(reader.device())) { QFileInfo docInfo{static_cast(reader.device())->fileName()}; @@ -98,7 +134,7 @@ bool SettingsConfigImpl::readGeneralInclude(QXmlStreamReader &reader, IncludeTyp VariantInfo::convert(reader, *it, readDocument(include.includePath)); return true; } catch(FileException &e) { - if(include.optional) { + if(include.optional || _alwaysOptional) { qWarning() << e.what(); it = list.erase(it); return false; @@ -107,3 +143,32 @@ bool SettingsConfigImpl::readGeneralInclude(QXmlStreamReader &reader, IncludeTyp } } +bool SettingsConfigImpl::isUsable(const SelectableContrainerInfo &element) const +{ + if(!_frontend.isNull() && element.frontends) { + auto fronts = element.frontends.value().split(QLatin1Char('|'), QString::SkipEmptyParts); + if(!fronts.contains(_frontend)) + return false; + } + + if(_selector && element.selectors) { + auto selectors = _selector->allSelectors(); + auto selects = element.selectors.value().split(QLatin1Char('|'), QString::SkipEmptyParts); + for(const auto &select : selects) { + auto sels = select.split(QLatin1Char('&'), QString::SkipEmptyParts); + auto allSelected = true; + for(const auto &sel : sels) { + if(!selectors.contains(sel)) { + allSelected = false; + break; + } + } + if(allSelected) + return true; + } + return false; + } + + return true; +} + diff --git a/src/settingsconfig/settingsconfigimpl.h b/src/settingsconfig/settingsconfigimpl.h index cac452f..881451e 100644 --- a/src/settingsconfig/settingsconfigimpl.h +++ b/src/settingsconfig/settingsconfigimpl.h @@ -3,9 +3,15 @@ #include "settingsconfig.h" +class QFileSelector; + class SettingsConfigImpl : public SettingsConfigBase { protected: + void setFilters(QString frontend, const QFileSelector *selector); + void resetFilters(); + void setIncludesOptional(bool alwaysOptional); + bool finish_group_content(QXmlStreamReader &reader, GroupContentGroup &data, bool hasNext) override; bool finish_section_content(QXmlStreamReader &reader, SectionContentGroup &data, bool hasNext) override; bool finish_category_content(QXmlStreamReader &reader, CategoryContentGroup &data, bool hasNext) override; @@ -16,6 +22,12 @@ private: void finishContents(QXmlStreamReader &reader, TGroup &group); template bool readGeneralInclude(QXmlStreamReader &reader, IncludeType include, TIter &it, TList &list); + + bool isUsable(const SelectableContrainerInfo &element) const; + + QString _frontend; + const QFileSelector *_selector = nullptr; + bool _alwaysOptional = false; }; #endif // SETTINGSCONFIGIMPL_H diff --git a/tools/settingsgenerator/settingstranslator.cpp b/tools/settingsgenerator/settingstranslator.cpp index 2126a3c..25e37ab 100644 --- a/tools/settingsgenerator/settingstranslator.cpp +++ b/tools/settingsgenerator/settingstranslator.cpp @@ -4,7 +4,9 @@ SettingsTranslator::SettingsTranslator(const QString &srcPath) : _srcFile{srcPath}, _src{&_srcFile} -{} +{ + setIncludesOptional(true); +} void SettingsTranslator::process(const QString &inPath) {