8 changed files with 181 additions and 124 deletions
@ -0,0 +1,109 @@ |
|||||
|
#include "settingsconfigimpl.h" |
||||
|
|
||||
|
#include <QtCore/QFileInfo> |
||||
|
#include <QtCore/QDir> |
||||
|
#include <QtCore/QDebug> |
||||
|
|
||||
|
namespace { |
||||
|
|
||||
|
using SourceType = SettingsConfigBase::variant<SettingsConfigBase::SettingsConfigType, SettingsConfigBase::CategoryType, SettingsConfigBase::SectionType, SettingsConfigBase::GroupType, SettingsConfigBase::EntryType>; |
||||
|
|
||||
|
template <typename TVariantTarget> |
||||
|
void convertElement(QXmlStreamReader &reader, TVariantTarget &, SourceType &&) |
||||
|
{ |
||||
|
throw SettingsConfigBase::XmlException{reader, QStringLiteral("Unexpected root element in included file")}; |
||||
|
} |
||||
|
|
||||
|
template <typename TVariantTarget, typename TType, typename... TArgs> |
||||
|
void convertElement(QXmlStreamReader &reader, TVariantTarget &target, SourceType &&source) |
||||
|
{ |
||||
|
if(nonstd::holds_alternative<TType>(source)) |
||||
|
target = nonstd::get<TType>(std::move(source)); |
||||
|
else |
||||
|
convertElement<TVariantTarget, TArgs...>(reader, target, std::move(source)); |
||||
|
} |
||||
|
|
||||
|
template <typename T> |
||||
|
struct VariantInfo {}; |
||||
|
|
||||
|
template <typename... TArgs> |
||||
|
struct VariantInfo<QList<SettingsConfigBase::variant<SettingsConfigBase::IncludeType, TArgs...>>> |
||||
|
{ |
||||
|
using TargetType = SettingsConfigBase::variant<SettingsConfigBase::IncludeType, TArgs...>; |
||||
|
static void convert(QXmlStreamReader &reader, TargetType &target, SourceType &&source) { |
||||
|
convertElement<TargetType, TArgs...>(reader, target, std::move(source)); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool SettingsConfigImpl::finish_group_content(QXmlStreamReader &reader, GroupContentGroup &data, bool hasNext) |
||||
|
{ |
||||
|
hasNext = read_GroupContentGroup(reader, data, hasNext); |
||||
|
finishContents(reader, data.content); |
||||
|
return hasNext; |
||||
|
} |
||||
|
|
||||
|
bool SettingsConfigImpl::finish_section_content(QXmlStreamReader &reader, SectionContentGroup &data, bool hasNext) |
||||
|
{ |
||||
|
hasNext = read_SectionContentGroup(reader, data, hasNext); |
||||
|
finishContents(reader, data.content); |
||||
|
return hasNext; |
||||
|
} |
||||
|
|
||||
|
bool SettingsConfigImpl::finish_category_content(QXmlStreamReader &reader, CategoryContentGroup &data, bool hasNext) |
||||
|
{ |
||||
|
hasNext = read_CategoryContentGroup(reader, data, hasNext); |
||||
|
finishContents(reader, data.content); |
||||
|
return hasNext; |
||||
|
} |
||||
|
|
||||
|
bool SettingsConfigImpl::finish_settings_config_content(QXmlStreamReader &reader, SettingsConfigContentGroup &data, bool hasNext) |
||||
|
{ |
||||
|
hasNext = read_SettingsConfigContentGroup(reader, data, hasNext); |
||||
|
finishContents(reader, data.content); |
||||
|
return hasNext; |
||||
|
} |
||||
|
|
||||
|
template<typename TGroup> |
||||
|
void SettingsConfigImpl::finishContents(QXmlStreamReader &reader, TGroup &group) |
||||
|
{ |
||||
|
optional<std::size_t> index; |
||||
|
for(auto it = group.begin(); it != group.end();) { |
||||
|
// convert includes to the actual data
|
||||
|
if(nonstd::holds_alternative<IncludeType>(*it)) { |
||||
|
if(!readGeneralInclude(reader, nonstd::get<IncludeType>(*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; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template<typename TIter, typename TList> |
||||
|
bool SettingsConfigImpl::readGeneralInclude(QXmlStreamReader &reader, IncludeType include, TIter &it, TList &list) |
||||
|
{ |
||||
|
try { |
||||
|
//make the path relative if possbile
|
||||
|
if(dynamic_cast<QFileDevice*>(reader.device())) { |
||||
|
QFileInfo docInfo{static_cast<QFileDevice*>(reader.device())->fileName()}; |
||||
|
include.includePath = docInfo.dir().absoluteFilePath(include.includePath); |
||||
|
} |
||||
|
// read the document
|
||||
|
VariantInfo<TList>::convert(reader, *it, readDocument(include.includePath)); |
||||
|
return true; |
||||
|
} catch(FileException &e) { |
||||
|
if(include.optional) { |
||||
|
qWarning() << e.what(); |
||||
|
it = list.erase(it); |
||||
|
return false; |
||||
|
} else |
||||
|
throw; |
||||
|
} |
||||
|
} |
||||
|
|
@ -0,0 +1,21 @@ |
|||||
|
#ifndef SETTINGSCONFIGIMPL_H |
||||
|
#define SETTINGSCONFIGIMPL_H |
||||
|
|
||||
|
#include "settingsconfig.h" |
||||
|
|
||||
|
class SettingsConfigImpl : public SettingsConfigBase |
||||
|
{ |
||||
|
protected: |
||||
|
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; |
||||
|
bool finish_settings_config_content(QXmlStreamReader &reader, SettingsConfigContentGroup &data, bool hasNext) override; |
||||
|
|
||||
|
private: |
||||
|
template <typename TGroup> |
||||
|
void finishContents(QXmlStreamReader &reader, TGroup &group); |
||||
|
template <typename TIter, typename TList> |
||||
|
bool readGeneralInclude(QXmlStreamReader &reader, IncludeType include, TIter &it, TList &list); |
||||
|
}; |
||||
|
|
||||
|
#endif // SETTINGSCONFIGIMPL_H
|
@ -1,108 +1,19 @@ |
|||||
#include "settingstranslator.h" |
#include "settingstranslator.h" |
||||
|
|
||||
#include <QtCore/QFileInfo> |
SettingsTranslator::SettingsTranslator(const QString &srcPath) : |
||||
#include <QtCore/QDir> |
_srcFile{srcPath}, |
||||
#include <QtCore/QDebug> |
_src{&_srcFile} |
||||
|
{} |
||||
|
|
||||
namespace { |
void SettingsTranslator::process(const QString &inPath) |
||||
|
|
||||
using SourceType = SettingsConfigBase::variant<SettingsConfigBase::SettingsConfigType, SettingsConfigBase::CategoryType, SettingsConfigBase::SectionType, SettingsConfigBase::GroupType, SettingsConfigBase::EntryType>; |
|
||||
|
|
||||
template <typename TVariantTarget> |
|
||||
void convertElement(QXmlStreamReader &reader, TVariantTarget &, SourceType &&) |
|
||||
{ |
|
||||
throw SettingsConfigBase::XmlException{reader, QStringLiteral("Unexpected root element in included file")}; |
|
||||
} |
|
||||
|
|
||||
template <typename TVariantTarget, typename TType, typename... TArgs> |
|
||||
void convertElement(QXmlStreamReader &reader, TVariantTarget &target, SourceType &&source) |
|
||||
{ |
|
||||
if(nonstd::holds_alternative<TType>(source)) |
|
||||
target = nonstd::get<TType>(std::move(source)); |
|
||||
else |
|
||||
convertElement<TVariantTarget, TArgs...>(reader, target, std::move(source)); |
|
||||
} |
|
||||
|
|
||||
template <typename T> |
|
||||
struct VariantInfo {}; |
|
||||
|
|
||||
template <typename... TArgs> |
|
||||
struct VariantInfo<QList<SettingsConfigBase::variant<SettingsConfigBase::IncludeType, TArgs...>>> |
|
||||
{ |
|
||||
using TargetType = SettingsConfigBase::variant<SettingsConfigBase::IncludeType, TArgs...>; |
|
||||
static void convert(QXmlStreamReader &reader, TargetType &target, SourceType &&source) { |
|
||||
convertElement<TargetType, TArgs...>(reader, target, std::move(source)); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
bool SettingsTranslator::finish_group_content(QXmlStreamReader &reader, GroupContentGroup &data, bool hasNext) |
|
||||
{ |
|
||||
hasNext = read_GroupContentGroup(reader, data, hasNext); |
|
||||
finishContents(reader, data.content); |
|
||||
return hasNext; |
|
||||
} |
|
||||
|
|
||||
bool SettingsTranslator::finish_section_content(QXmlStreamReader &reader, SectionContentGroup &data, bool hasNext) |
|
||||
{ |
|
||||
hasNext = read_SectionContentGroup(reader, data, hasNext); |
|
||||
finishContents(reader, data.content); |
|
||||
return hasNext; |
|
||||
} |
|
||||
|
|
||||
bool SettingsTranslator::finish_category_content(QXmlStreamReader &reader, CategoryContentGroup &data, bool hasNext) |
|
||||
{ |
|
||||
hasNext = read_CategoryContentGroup(reader, data, hasNext); |
|
||||
finishContents(reader, data.content); |
|
||||
return hasNext; |
|
||||
} |
|
||||
|
|
||||
bool SettingsTranslator::finish_settings_config_content(QXmlStreamReader &reader, SettingsConfigContentGroup &data, bool hasNext) |
|
||||
{ |
{ |
||||
hasNext = read_SettingsConfigContentGroup(reader, data, hasNext); |
auto settings = readDocument(inPath); |
||||
finishContents(reader, data.content); |
if(!nonstd::holds_alternative<SettingsConfigType>(settings)) |
||||
return hasNext; |
throw XmlException{inPath, 0, 0, QStringLiteral("Expected the root element to be a SettingsConfig element")}; |
||||
|
writeTranslations(nonstd::get<SettingsConfigType>(settings)); |
||||
} |
} |
||||
|
|
||||
template<typename TGroup> |
void SettingsTranslator::writeTranslations(const SettingsConfigBase::SettingsConfigType &settings) |
||||
void SettingsTranslator::finishContents(QXmlStreamReader &reader, TGroup &group) |
|
||||
{ |
{ |
||||
optional<std::size_t> index; |
|
||||
for(auto it = group.begin(); it != group.end();) { |
|
||||
// convert includes to the actual data
|
|
||||
if(nonstd::holds_alternative<IncludeType>(*it)) { |
|
||||
if(!readGeneralInclude(reader, nonstd::get<IncludeType>(*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; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
template<typename TIter, typename TList> |
|
||||
bool SettingsTranslator::readGeneralInclude(QXmlStreamReader &reader, IncludeType include, TIter &it, TList &list) |
|
||||
{ |
|
||||
try { |
|
||||
//make the path relative if possbile
|
|
||||
if(dynamic_cast<QFileDevice*>(reader.device())) { |
|
||||
QFileInfo docInfo{static_cast<QFileDevice*>(reader.device())->fileName()}; |
|
||||
include.includePath = docInfo.dir().absoluteFilePath(include.includePath); |
|
||||
} |
|
||||
// read the document
|
|
||||
VariantInfo<TList>::convert(reader, *it, readDocument(include.includePath)); |
|
||||
return true; |
|
||||
} catch(FileException &e) { |
|
||||
if(include.optional) { |
|
||||
qWarning() << e.what(); |
|
||||
it = list.erase(it); |
|
||||
return false; |
|
||||
} else |
|
||||
throw; |
|
||||
} |
|
||||
} |
} |
||||
|
@ -1,21 +1,23 @@ |
|||||
#ifndef SETTINGSTRANSLATOR_H |
#ifndef SETTINGSTRANSLATOR_H |
||||
#define SETTINGSTRANSLATOR_H |
#define SETTINGSTRANSLATOR_H |
||||
|
|
||||
#include "settingsconfig.h" |
#include <QFile> |
||||
|
#include <QTextStream> |
||||
|
|
||||
class SettingsTranslator : public SettingsConfigBase |
#include "settingsconfigimpl.h" |
||||
|
|
||||
|
class SettingsTranslator : public SettingsConfigImpl |
||||
{ |
{ |
||||
protected: |
public: |
||||
bool finish_group_content(QXmlStreamReader &reader, GroupContentGroup &data, bool hasNext) override; |
SettingsTranslator(const QString &srcPath); |
||||
bool finish_section_content(QXmlStreamReader &reader, SectionContentGroup &data, bool hasNext) override; |
|
||||
bool finish_category_content(QXmlStreamReader &reader, CategoryContentGroup &data, bool hasNext) override; |
void process(const QString &inPath); |
||||
bool finish_settings_config_content(QXmlStreamReader &reader, SettingsConfigContentGroup &data, bool hasNext) override; |
|
||||
|
|
||||
private: |
private: |
||||
template <typename TGroup> |
QFile _srcFile; |
||||
void finishContents(QXmlStreamReader &reader, TGroup &group); |
QTextStream _src; |
||||
template <typename TIter, typename TList> |
|
||||
bool readGeneralInclude(QXmlStreamReader &reader, IncludeType include, TIter &it, TList &list); |
void writeTranslations(const SettingsConfigType &settings); |
||||
}; |
}; |
||||
|
|
||||
#endif // SETTINGSTRANSLATOR_H
|
#endif // SETTINGSTRANSLATOR_H
|
||||
|
Loading…
Reference in new issue