Browse Source

added xml include logic

pull/2/head
Skycoder42 7 years ago
parent
commit
446f0e01b3
  1. 2
      src/mvvmcore/qtmvvmcore_global.cpp
  2. 204
      src/mvvmsettingscore/settingssetuploader.cpp
  3. 12
      src/mvvmsettingscore/settingssetuploader_p.h
  4. 9
      src/mvvmsettingscore/settingsviewmodel.cpp

2
src/mvvmcore/qtmvvmcore_global.cpp

@ -3,7 +3,7 @@
namespace QtMvvm { namespace QtMvvm {
#ifdef QT_NO_DEBUG #ifdef QT_NO_DEBUG //TODO always info only
Q_LOGGING_CATEGORY(mvvmLoggingCat, "qtmvvm", QtInfoMsg) Q_LOGGING_CATEGORY(mvvmLoggingCat, "qtmvvm", QtInfoMsg)
#else #else
Q_LOGGING_CATEGORY(mvvmLoggingCat, "qtmvvm", QtDebugMsg) Q_LOGGING_CATEGORY(mvvmLoggingCat, "qtmvvm", QtDebugMsg)

204
src/mvvmsettingscore/settingssetuploader.cpp

@ -1,5 +1,9 @@
#include "settingssetuploader_p.h" #include "settingssetuploader_p.h"
#include <QtCore/QCoreApplication> #include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QtMvvmCore/private/qtmvvm_logging_p.h>
using namespace QtMvvm; using namespace QtMvvm;
using namespace QtMvvm::SettingsElements; using namespace QtMvvm::SettingsElements;
@ -26,7 +30,7 @@ SettingsSetup SettingsSetupLoader::loadSetup(const QString &filePath, const QStr
{ {
SettingsSetup setup; SettingsSetup setup;
if(!_cache.contains(filePath)) { if(!_cache.contains(filePath)) {
QFile file(filePath); QFile file(QDir::cleanPath(filePath));
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
throw SettingsXmlException(file); throw SettingsXmlException(file);
@ -39,10 +43,16 @@ SettingsSetup SettingsSetupLoader::loadSetup(const QString &filePath, const QStr
setup.allowRestore = reader.boolValue("allowRestore"); setup.allowRestore = reader.boolValue("allowRestore");
if(reader.readNextStartElement()) { if(reader.readNextStartElement()) {
if(reader.name() == QStringLiteral("Category")) { if(reader.name() == QStringLiteral("Category") ||
do reader.name() == QStringLiteral("Include")) {
setup.categories.append(readCategory(reader)); do {
while(reader.readNextStartElement()); if(reader.name() == QStringLiteral("Include")) {
SettingsCategory category;
if(readCategoryInclude(reader, category))
setup.categories.append(category);
} else
setup.categories.append(readCategory(reader));
} while(reader.readNextStartElement());
} else } else
setup.categories.append(readDefaultCategory(reader)); setup.categories.append(readDefaultCategory(reader));
} }
@ -89,14 +99,8 @@ SettingsCategory SettingsSetupLoader::readCategory(QXmlStreamReader &reader) con
category.frontends = reader.stringValue("frontends"); category.frontends = reader.stringValue("frontends");
category.selectors = reader.stringValue("selectors"); category.selectors = reader.stringValue("selectors");
if(reader.readNextStartElement()) { if(reader.readNextStartElement())
if(reader.name() == QStringLiteral("Section")) { readCategoryChildren(reader, category);
do
category.sections.append(readSection(reader));
while(reader.readNextStartElement());
} else
category.sections.append(readDefaultSection(reader));
}
testXmlValid(reader); testXmlValid(reader);
return category; return category;
@ -106,17 +110,27 @@ SettingsCategory SettingsSetupLoader::readDefaultCategory(QXmlStreamReader &read
{ {
testXmlValid(reader); testXmlValid(reader);
auto category = createDefaultCategory(); auto category = createDefaultCategory();
if(reader.name() == QStringLiteral("Section")) { readCategoryChildren(reader, category);
do
category.sections.append(readSection(reader));
while(reader.readNextStartElement());
} else
category.sections.append(readDefaultSection(reader));
testXmlValid(reader); testXmlValid(reader);
return category; return category;
} }
void SettingsSetupLoader::readCategoryChildren(QXmlStreamReader &reader, SettingsCategory &category) const
{
if(reader.name() == QStringLiteral("Section") ||
reader.name() == QStringLiteral("Include")) {
do {
if(reader.name() == QStringLiteral("Include")) {
SettingsSection section;
if(readSectionInclude(reader, section))
category.sections.append(section);
} else
category.sections.append(readSection(reader));
} while(reader.readNextStartElement());
} else
category.sections.append(readDefaultSection(reader));
}
SettingsSection SettingsSetupLoader::readSection(QXmlStreamReader &reader) const SettingsSection SettingsSetupLoader::readSection(QXmlStreamReader &reader) const
{ {
testXmlValid(reader); testXmlValid(reader);
@ -134,14 +148,8 @@ SettingsSection SettingsSetupLoader::readSection(QXmlStreamReader &reader) const
section.frontends = reader.stringValue("frontends"); section.frontends = reader.stringValue("frontends");
section.selectors = reader.stringValue("selectors"); section.selectors = reader.stringValue("selectors");
if(reader.readNextStartElement()) { if(reader.readNextStartElement())
if(reader.name() == QStringLiteral("Group")) { readSectionChildren(reader, section);
do
section.groups.append(readGroup(reader));
while(reader.readNextStartElement());
} else
section.groups.append(readDefaultGroup(reader));
}
testXmlValid(reader); testXmlValid(reader);
return section; return section;
@ -151,16 +159,25 @@ SettingsSection SettingsSetupLoader::readDefaultSection(QXmlStreamReader &reader
{ {
testXmlValid(reader); testXmlValid(reader);
auto section = createDefaultSection(); auto section = createDefaultSection();
readSectionChildren(reader, section);
testXmlValid(reader);
return section;
}
if(reader.name() == QStringLiteral("Group")) { void SettingsSetupLoader::readSectionChildren(QXmlStreamReader &reader, SettingsSection &section) const
do {
section.groups.append(readGroup(reader)); if(reader.name() == QStringLiteral("Group") ||
while(reader.readNextStartElement()); reader.name() == QStringLiteral("Include")) {
do {
if(reader.name() == QStringLiteral("Include")) {
SettingsGroup group;
if(readGroupInclude(reader, group))
section.groups.append(group);
} else
section.groups.append(readGroup(reader));
} while(reader.readNextStartElement());
} else } else
section.groups.append(readDefaultGroup(reader)); section.groups.append(readDefaultGroup(reader));
testXmlValid(reader);
return section;
} }
SettingsGroup SettingsSetupLoader::readGroup(QXmlStreamReader &reader) const SettingsGroup SettingsSetupLoader::readGroup(QXmlStreamReader &reader) const
@ -177,14 +194,8 @@ SettingsGroup SettingsSetupLoader::readGroup(QXmlStreamReader &reader) const
group.frontends = reader.stringValue("frontends"); group.frontends = reader.stringValue("frontends");
group.selectors = reader.stringValue("selectors"); group.selectors = reader.stringValue("selectors");
if(reader.readNextStartElement()) { if(reader.readNextStartElement())
if(reader.name() == QStringLiteral("Entry")) { readGroupChildren(reader, group);
do
group.entries.append(readEntry(reader));
while(reader.readNextStartElement());
} else
throwElement(reader, "Entry");
}
testXmlValid(reader); testXmlValid(reader);
return group; return group;
@ -194,21 +205,33 @@ SettingsGroup SettingsSetupLoader::readDefaultGroup(QXmlStreamReader &reader) co
{ {
testXmlValid(reader); testXmlValid(reader);
SettingsGroup group; SettingsGroup group;
readGroupChildren(reader, group);
if(reader.name() == QStringLiteral("Entry")) {
do
group.entries.append(readEntry(reader));
while(reader.readNextStartElement());
} else
throwElement(reader, "Entry");
testXmlValid(reader); testXmlValid(reader);
return group; return group;
} }
void SettingsSetupLoader::readGroupChildren(QXmlStreamReader &reader, SettingsGroup &group) const
{
if(reader.name() == QStringLiteral("Entry") ||
reader.name() == QStringLiteral("Include")) {
do {
if(reader.name() == QStringLiteral("Include")) {
SettingsEntry entry;
if(readEntryInclude(reader, entry))
group.entries.append(entry);
} else
group.entries.append(readEntry(reader));
} while(reader.readNextStartElement());
} else
throwXmlError(reader, QStringLiteral("Unexpected element type <%1>").arg(reader.name()).toUtf8());
}
SettingsEntry SettingsSetupLoader::readEntry(QXmlStreamReader &reader) const SettingsEntry SettingsSetupLoader::readEntry(QXmlStreamReader &reader) const
{ {
testXmlValid(reader); testXmlValid(reader);
if(reader.name() != QStringLiteral("Entry"))
throwElement(reader, "Entry");
SettingsEntry entry; SettingsEntry entry;
if(!reader.hasValue("key")) if(!reader.hasValue("key"))
@ -226,9 +249,10 @@ SettingsEntry SettingsSetupLoader::readEntry(QXmlStreamReader &reader) const
entry.selectors = reader.stringValue("selectors"); entry.selectors = reader.stringValue("selectors");
while(reader.readNextStartElement()) { while(reader.readNextStartElement()) {
if(reader.name() == QStringLiteral("SearchKey")) if(reader.name() == QStringLiteral("SearchKey")) {
entry.searchKeys.append(trctx(reader.readElementText())); entry.searchKeys.append(trctx(reader.readElementText()));
else if(reader.name() == QStringLiteral("Property")) { testXmlValid(reader);
} else if(reader.name() == QStringLiteral("Property")) {
auto prop = readProperty(reader); auto prop = readProperty(reader);
entry.properties.insert(std::get<0>(prop), std::get<1>(prop)); entry.properties.insert(std::get<0>(prop), std::get<1>(prop));
} else } else
@ -303,12 +327,80 @@ QVariant SettingsSetupLoader::readElement(QXmlStreamReader &reader) const
mVariant = trctx(reader.readElementText()); mVariant = trctx(reader.readElementText());
else else
mVariant = reader.readElementText(); mVariant = reader.readElementText();
testXmlValid(reader);
if(!mVariant.convert(typeId)) if(!mVariant.convert(typeId))
throwXmlError(reader, "Failed to convert element data to type: " + type.toUtf8()); throwXmlError(reader, "Failed to convert element data to type: " + type.toUtf8());
return mVariant; return mVariant;
} }
bool SettingsSetupLoader::readCategoryInclude(QXmlStreamReader &reader, SettingsCategory &category) const
{
return readInclude(reader, [this, &category](QXmlStreamReader &reader){
category = readCategory(reader);
}, QStringLiteral("Category"));
}
bool SettingsSetupLoader::readSectionInclude(QXmlStreamReader &reader, SettingsSection &section) const
{
return readInclude(reader, [this, &section](QXmlStreamReader &reader){
section = readSection(reader);
}, QStringLiteral("Section"));
}
bool SettingsSetupLoader::readGroupInclude(QXmlStreamReader &reader, SettingsGroup &group) const
{
return readInclude(reader, [this, &group](QXmlStreamReader &reader){
group = readGroup(reader);
}, QStringLiteral("Group"));
}
bool SettingsSetupLoader::readEntryInclude(QXmlStreamReader &reader, SettingsEntry &entry) const
{
return readInclude(reader, [this, &entry](QXmlStreamReader &reader){
entry = readEntry(reader);
}, QStringLiteral("Entry"));
}
bool SettingsSetupLoader::readInclude(QXmlStreamReader &reader, const std::function<void(QXmlStreamReader &)> &readFn, const QString &typeName) const
{
testXmlValid(reader);
if(reader.name() != QStringLiteral("Include"))
throwElement(reader, "Include");
auto optional = reader.boolValue("optional");
auto fileName = reader.readElementText();
testXmlValid(reader);
if(reader.readNextStartElement())
throwXmlError(reader, "The <Include> Element must not have any child elements");
try {
auto dir = QDir::current();
auto dev = qobject_cast<QFileDevice*>(reader.device());
if(dev)
dir = QFileInfo(dev->fileName()).dir();
QFile incFile(QDir::cleanPath(dir.absoluteFilePath(fileName)));
if(!incFile.open(QIODevice::ReadOnly | QIODevice::Text))
throw SettingsXmlException(incFile);
QXmlStreamReader incReader(&incFile);
if(!incReader.readNextStartElement() || incReader.name() != typeName)
throwXmlError(reader, QStringLiteral("Expected element of type <%1>").arg(typeName).toUtf8());
readFn(incReader);
testXmlValid(reader);
incFile.close();
return true;
} catch(SettingsXmlException &e) {
if(optional) {
logInfo() << "Skipped include file:" << e.what();
return false;
} else
throw;
}
}
void SettingsSetupLoader::clearSetup(SettingsSetup &setup, const QString &frontend, const QStringList &selectors) const void SettingsSetupLoader::clearSetup(SettingsSetup &setup, const QString &frontend, const QStringList &selectors) const
{ {
for(auto it = setup.categories.begin(); it != setup.categories.end();) { for(auto it = setup.categories.begin(); it != setup.categories.end();) {
@ -382,7 +474,11 @@ bool SettingsSetupLoader::isUsable(const T &configElement, const QString &fronte
SettingsXmlException::SettingsXmlException(const QXmlStreamReader &reader) : SettingsXmlException::SettingsXmlException(const QXmlStreamReader &reader) :
SettingsLoaderException(), SettingsLoaderException(),
_what(QStringLiteral("XML Error at %1:%2. Error: %3") _what(QStringLiteral("XML Error in file \"%1\", line %2, column %3. Error: %4")
.arg([&](){
auto dev = qobject_cast<QFileDevice*>(reader.device());
return dev ? dev->fileName() : QStringLiteral("<unknown>");
}())
.arg(reader.lineNumber()) .arg(reader.lineNumber())
.arg(reader.columnNumber()) .arg(reader.columnNumber())
.arg(reader.errorString()) .arg(reader.errorString())

12
src/mvvmsettingscore/settingssetuploader_p.h

@ -31,15 +31,18 @@ private:
mutable QCache<QString, SettingsElements::SettingsSetup> _cache; mutable QCache<QString, SettingsElements::SettingsSetup> _cache;
//functions to read the settings XML //Functions to read the settings XML
SettingsElements::SettingsCategory readCategory(QXmlStreamReader &reader) const; SettingsElements::SettingsCategory readCategory(QXmlStreamReader &reader) const;
SettingsElements::SettingsCategory readDefaultCategory(QXmlStreamReader &reader) const; SettingsElements::SettingsCategory readDefaultCategory(QXmlStreamReader &reader) const;
void readCategoryChildren(QXmlStreamReader &reader, SettingsElements::SettingsCategory &category) const;
SettingsElements::SettingsSection readSection(QXmlStreamReader &reader) const; SettingsElements::SettingsSection readSection(QXmlStreamReader &reader) const;
SettingsElements::SettingsSection readDefaultSection(QXmlStreamReader &reader) const; SettingsElements::SettingsSection readDefaultSection(QXmlStreamReader &reader) const;
void readSectionChildren(QXmlStreamReader &reader, SettingsElements::SettingsSection &section) const;
SettingsElements::SettingsGroup readGroup(QXmlStreamReader &reader) const; SettingsElements::SettingsGroup readGroup(QXmlStreamReader &reader) const;
SettingsElements::SettingsGroup readDefaultGroup(QXmlStreamReader &reader) const; SettingsElements::SettingsGroup readDefaultGroup(QXmlStreamReader &reader) const;
void readGroupChildren(QXmlStreamReader &reader, SettingsElements::SettingsGroup &group) const;
SettingsElements::SettingsEntry readEntry(QXmlStreamReader &reader) const; SettingsElements::SettingsEntry readEntry(QXmlStreamReader &reader) const;
@ -49,6 +52,13 @@ private:
std::tuple<QString, QVariant> readProperty(QXmlStreamReader &reader) const; std::tuple<QString, QVariant> readProperty(QXmlStreamReader &reader) const;
QVariant readElement(QXmlStreamReader &reader) const; QVariant readElement(QXmlStreamReader &reader) const;
//Functions to read included files
bool readCategoryInclude(QXmlStreamReader &reader, SettingsElements::SettingsCategory &category) const;
bool readSectionInclude(QXmlStreamReader &reader, SettingsElements::SettingsSection &section) const;
bool readGroupInclude(QXmlStreamReader &reader, SettingsElements::SettingsGroup &group) const;
bool readEntryInclude(QXmlStreamReader &reader, SettingsElements::SettingsEntry &entry) const;
bool readInclude(QXmlStreamReader &reader, const std::function<void(QXmlStreamReader&)> &readFn, const QString &typeName) const;
//Functions to filter the elements //Functions to filter the elements
void clearSetup(SettingsElements::SettingsSetup &setup, const QString &frontend, const QStringList &selectors) const; void clearSetup(SettingsElements::SettingsSetup &setup, const QString &frontend, const QStringList &selectors) const;
void clearCategory(SettingsElements::SettingsCategory &category, const QString &frontend, const QStringList &selectors) const; void clearCategory(SettingsElements::SettingsCategory &category, const QString &frontend, const QStringList &selectors) const;

9
src/mvvmsettingscore/settingsviewmodel.cpp

@ -48,8 +48,13 @@ ISettingsSetupLoader *SettingsViewModel::settingsSetupLoader() const
SettingsElements::SettingsSetup SettingsViewModel::loadSetup(const QString &frontend) const SettingsElements::SettingsSetup SettingsViewModel::loadSetup(const QString &frontend) const
{ {
QFileSelector selector; try {
return d->setupLoader->loadSetup(d->setupFile, frontend, &selector); QFileSelector selector;
return d->setupLoader->loadSetup(d->setupFile, frontend, &selector);
} catch(SettingsLoaderException &e) {
logCritical() << "Failed to load settings setup:" << e.what();
return {};
}
} }
QSettings *SettingsViewModel::settings() const QSettings *SettingsViewModel::settings() const

Loading…
Cancel
Save