9 changed files with 431 additions and 159 deletions
@ -1,145 +0,0 @@ |
|||||
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|
||||
<!-- Type definitions --> |
|
||||
<xs:complexType name="IncludeType"> |
|
||||
<xs:simpleContent> |
|
||||
<xs:extension base="xs:string"> |
|
||||
<xs:attribute type="xs:boolean" name="optional" use="optional"/> |
|
||||
</xs:extension> |
|
||||
</xs:simpleContent> |
|
||||
</xs:complexType> |
|
||||
|
|
||||
<xs:complexType name="ElementType" mixed="true"> |
|
||||
<xs:sequence> |
|
||||
<xs:choice maxOccurs="unbounded" minOccurs="0"> |
|
||||
<xs:element type="PropertyType" name="Property"/> |
|
||||
<xs:element type="ElementType" name="Element"/> |
|
||||
</xs:choice> |
|
||||
</xs:sequence> |
|
||||
<xs:attribute type="xs:string" name="type" use="required"/> |
|
||||
<xs:attribute type="xs:boolean" name="tr" use="optional" default="false"/> |
|
||||
<xs:attribute type="xs:boolean" name="ztr" use="optional" default="false"/> |
|
||||
</xs:complexType> |
|
||||
|
|
||||
<xs:complexType name="PropertyType" mixed="true"> |
|
||||
<xs:complexContent> |
|
||||
<xs:extension base="ElementType"> |
|
||||
<xs:attribute type="xs:string" name="key" use="required"/> |
|
||||
</xs:extension> |
|
||||
</xs:complexContent> |
|
||||
</xs:complexType> |
|
||||
|
|
||||
<xs:complexType name="EntryType"> |
|
||||
<xs:sequence> |
|
||||
<xs:choice maxOccurs="unbounded" minOccurs="0"> |
|
||||
<xs:element type="xs:string" name="SearchKey"/> |
|
||||
<xs:element type="PropertyType" name="Property"/> |
|
||||
</xs:choice> |
|
||||
</xs:sequence> |
|
||||
<xs:attribute type="xs:string" name="key" use="required"/> |
|
||||
<xs:attribute type="xs:string" name="type" use="required"/> |
|
||||
<xs:attribute type="xs:string" name="title" use="required"/> |
|
||||
<xs:attribute type="xs:string" name="tooltip" use="optional"/> |
|
||||
<xs:attribute type="xs:string" name="default" use="optional"/> |
|
||||
<xs:attribute type="xs:string" name="frontends" use="optional"/> |
|
||||
<xs:attribute type="xs:string" name="selectors" use="optional"/> |
|
||||
<xs:attribute type="xs:boolean" name="trdefault" use="optional" default="false"/> |
|
||||
<xs:attribute type="xs:boolean" name="ztrdefault" use="optional" default="false"/> |
|
||||
</xs:complexType> |
|
||||
|
|
||||
<xs:complexType name="GroupType"> |
|
||||
<xs:sequence> |
|
||||
<xs:choice maxOccurs="unbounded" minOccurs="0"> |
|
||||
<xs:element type="IncludeType" name="Include"/> |
|
||||
<xs:element type="EntryType" name="Entry"/> |
|
||||
</xs:choice> |
|
||||
</xs:sequence> |
|
||||
<xs:attribute type="xs:string" name="title" use="required"/> |
|
||||
<xs:attribute type="xs:string" name="tooltip" use="optional"/> |
|
||||
<xs:attribute type="xs:string" name="frontends" use="optional"/> |
|
||||
<xs:attribute type="xs:string" name="selectors" use="optional"/> |
|
||||
</xs:complexType> |
|
||||
|
|
||||
<xs:complexType name="SectionType"> |
|
||||
<xs:choice> |
|
||||
<xs:sequence> |
|
||||
<xs:choice maxOccurs="unbounded" minOccurs="0"> |
|
||||
<xs:element type="IncludeType" name="Include"/> |
|
||||
<xs:element type="GroupType" name="Group"/> |
|
||||
</xs:choice> |
|
||||
</xs:sequence> |
|
||||
<xs:sequence> |
|
||||
<xs:choice maxOccurs="unbounded" minOccurs="0"> |
|
||||
<xs:element type="IncludeType" name="Include"/> |
|
||||
<xs:element type="EntryType" name="Entry"/> |
|
||||
</xs:choice> |
|
||||
</xs:sequence> |
|
||||
</xs:choice> |
|
||||
<xs:attribute type="xs:string" name="title" use="required"/> |
|
||||
<xs:attribute type="xs:string" name="icon" use="optional"/> |
|
||||
<xs:attribute type="xs:string" name="tooltip" use="optional"/> |
|
||||
<xs:attribute type="xs:string" name="frontends" use="optional"/> |
|
||||
<xs:attribute type="xs:string" name="selectors" use="optional"/> |
|
||||
</xs:complexType> |
|
||||
|
|
||||
<xs:complexType name="CategoryType"> |
|
||||
<xs:choice> |
|
||||
<xs:sequence> |
|
||||
<xs:choice maxOccurs="unbounded" minOccurs="0"> |
|
||||
<xs:element type="IncludeType" name="Include"/> |
|
||||
<xs:element type="SectionType" name="Section"/> |
|
||||
</xs:choice> |
|
||||
</xs:sequence> |
|
||||
<xs:sequence> |
|
||||
<xs:choice maxOccurs="unbounded" minOccurs="0"> |
|
||||
<xs:element type="IncludeType" name="Include"/> |
|
||||
<xs:element type="GroupType" name="Group"/> |
|
||||
</xs:choice> |
|
||||
</xs:sequence> |
|
||||
<xs:sequence> |
|
||||
<xs:choice maxOccurs="unbounded" minOccurs="0"> |
|
||||
<xs:element type="IncludeType" name="Include"/> |
|
||||
<xs:element type="EntryType" name="Entry"/> |
|
||||
</xs:choice> |
|
||||
</xs:sequence> |
|
||||
</xs:choice> |
|
||||
<xs:attribute type="xs:string" name="title" use="required"/> |
|
||||
<xs:attribute type="xs:string" name="icon" use="optional"/> |
|
||||
<xs:attribute type="xs:string" name="tooltip" use="optional"/> |
|
||||
<xs:attribute type="xs:string" name="frontends" use="optional"/> |
|
||||
<xs:attribute type="xs:string" name="selectors" use="optional"/> |
|
||||
</xs:complexType> |
|
||||
|
|
||||
<xs:complexType name="SettingsConfigType"> |
|
||||
<xs:choice> |
|
||||
<xs:sequence> |
|
||||
<xs:choice maxOccurs="unbounded" minOccurs="0"> |
|
||||
<xs:element type="IncludeType" name="Include"/> |
|
||||
<xs:element type="CategoryType" name="Category"/> |
|
||||
</xs:choice> |
|
||||
</xs:sequence> |
|
||||
<xs:sequence> |
|
||||
<xs:choice maxOccurs="unbounded" minOccurs="0"> |
|
||||
<xs:element type="IncludeType" name="Include"/> |
|
||||
<xs:element type="SectionType" name="Section"/> |
|
||||
</xs:choice> |
|
||||
</xs:sequence> |
|
||||
<xs:sequence> |
|
||||
<xs:choice maxOccurs="unbounded" minOccurs="0"> |
|
||||
<xs:element type="IncludeType" name="Include"/> |
|
||||
<xs:element type="GroupType" name="Group"/> |
|
||||
</xs:choice> |
|
||||
</xs:sequence> |
|
||||
<xs:sequence> |
|
||||
<xs:choice maxOccurs="unbounded" minOccurs="0"> |
|
||||
<xs:element type="IncludeType" name="Include"/> |
|
||||
<xs:element type="EntryType" name="Entry"/> |
|
||||
</xs:choice> |
|
||||
</xs:sequence> |
|
||||
</xs:choice> |
|
||||
<xs:attribute type="xs:boolean" name="allowSearch" use="optional"/> |
|
||||
<xs:attribute type="xs:boolean" name="allowRestore" use="optional"/> |
|
||||
</xs:complexType> |
|
||||
|
|
||||
<!-- root elements--> |
|
||||
<xs:element name="SettingsConfig" type="SettingsConfigType"/> |
|
||||
</xs:schema> |
|
@ -1,5 +1,6 @@ |
|||||
<RCC> |
<RCC> |
||||
<qresource prefix="/schemas"> |
<qresource prefix="/schemas"> |
||||
<file>qsettingsgenerator.xsd</file> |
<file>qsettingsgenerator.xsd</file> |
||||
|
<file>settingsconfig.xsd</file> |
||||
</qresource> |
</qresource> |
||||
</RCC> |
</RCC> |
||||
|
@ -0,0 +1,144 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" |
||||
|
xmlns:qxg="https://skycoder42.de/xml/schemas/QXmlCodeGen"> |
||||
|
<!-- QXG Definitions --> |
||||
|
<qxg:config class="SettingsConfigBase" |
||||
|
stdcompat="true" |
||||
|
schemaUrl="qrc:/schemas/settingsconfig.xsd" |
||||
|
visibility="public"> |
||||
|
<qxg:include>QtCore/QHash</qxg:include> |
||||
|
</qxg:config> |
||||
|
<qxg:method name="finish_group_content" type="GroupContentGroup" asGroup="true"/> |
||||
|
<qxg:method name="finish_section_content" type="SectionContentGroup" asGroup="true"/> |
||||
|
<qxg:method name="finish_category_content" type="CategoryContentGroup" asGroup="true"/> |
||||
|
<qxg:method name="finish_settings_config_content" type="SettingsConfigContentGroup" asGroup="true"/> |
||||
|
|
||||
|
<!-- Basic property-like elements definitions --> |
||||
|
<xs:complexType name="IncludeType"> |
||||
|
<xs:simpleContent> |
||||
|
<xs:extension base="xs:string" qxg:member="includePath"> |
||||
|
<xs:attribute type="xs:boolean" name="optional" default="false" use="optional"/> |
||||
|
</xs:extension> |
||||
|
</xs:simpleContent> |
||||
|
</xs:complexType> |
||||
|
|
||||
|
<xs:complexType name="ElementType" mixed="true" qxg:declare="true" qxg:member="content"> |
||||
|
<xs:sequence> |
||||
|
<xs:element maxOccurs="unbounded" minOccurs="0" type="PropertyType" name="Property" qxg:member="properties"/> |
||||
|
<xs:element maxOccurs="unbounded" minOccurs="0" type="ElementType" name="Element" qxg:member="elements"/> |
||||
|
</xs:sequence> |
||||
|
<xs:attribute type="xs:string" name="type" use="required"/> |
||||
|
<xs:attribute type="xs:boolean" name="tr" use="optional" default="false"/> |
||||
|
<xs:attribute type="xs:boolean" name="ztr" use="optional" default="false"/> |
||||
|
</xs:complexType> |
||||
|
|
||||
|
<xs:complexType name="PropertyType" qxg:declare="true"> |
||||
|
<xs:complexContent> |
||||
|
<xs:extension base="ElementType"> |
||||
|
<xs:attribute type="xs:string" name="key" use="required"/> |
||||
|
</xs:extension> |
||||
|
</xs:complexContent> |
||||
|
</xs:complexType> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<!-- Group Definitions to build the elements from --> |
||||
|
<xs:attributeGroup name="BasicContainerInfo"> |
||||
|
<xs:attribute type="xs:string" name="title" use="optional"/> |
||||
|
<xs:attribute type="xs:string" name="tooltip" use="optional"/> |
||||
|
<xs:attribute type="xs:string" name="frontends" use="optional"/> |
||||
|
<xs:attribute type="xs:string" name="selectors" use="optional"/> |
||||
|
</xs:attributeGroup> |
||||
|
|
||||
|
<xs:attributeGroup name="ExtendedContainerInfo"> |
||||
|
<xs:attributeGroup ref="BasicContainerInfo" qxg:inherit="true"/> |
||||
|
<xs:attribute type="xs:string" name="icon" use="optional"/> |
||||
|
</xs:attributeGroup> |
||||
|
|
||||
|
<xs:group name="GroupContentGroup"> |
||||
|
<xs:sequence> |
||||
|
<xs:choice maxOccurs="unbounded" minOccurs="0" qxg:member="content"> |
||||
|
<xs:element type="IncludeType" name="Include"/> |
||||
|
<xs:element type="EntryType" name="Entry"/> |
||||
|
</xs:choice> |
||||
|
</xs:sequence> |
||||
|
</xs:group> |
||||
|
|
||||
|
<xs:group name="SectionContentGroup"> |
||||
|
<xs:sequence> |
||||
|
<xs:choice maxOccurs="unbounded" minOccurs="0" qxg:member="content"> |
||||
|
<xs:element type="IncludeType" name="Include"/> |
||||
|
<xs:element type="GroupType" name="Group"/> |
||||
|
<xs:element type="EntryType" name="Entry"/> |
||||
|
</xs:choice> |
||||
|
</xs:sequence> |
||||
|
</xs:group> |
||||
|
|
||||
|
<xs:group name="CategoryContentGroup"> |
||||
|
<xs:sequence> |
||||
|
<xs:choice maxOccurs="unbounded" minOccurs="0" qxg:member="content"> |
||||
|
<xs:element type="IncludeType" name="Include"/> |
||||
|
<xs:element type="SectionType" name="Section"/> |
||||
|
<xs:element type="GroupType" name="Group"/> |
||||
|
<xs:element type="EntryType" name="Entry"/> |
||||
|
</xs:choice> |
||||
|
</xs:sequence> |
||||
|
</xs:group> |
||||
|
|
||||
|
<xs:group name="SettingsConfigContentGroup"> |
||||
|
<xs:sequence> |
||||
|
<xs:choice maxOccurs="unbounded" minOccurs="0" qxg:member="content"> |
||||
|
<xs:element type="IncludeType" name="Include"/> |
||||
|
<xs:element type="CategoryType" name="Category"/> |
||||
|
<xs:element type="SectionType" name="Section"/> |
||||
|
<xs:element type="GroupType" name="Group"/> |
||||
|
<xs:element type="EntryType" name="Entry"/> |
||||
|
</xs:choice> |
||||
|
</xs:sequence> |
||||
|
</xs:group> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<!-- Element definitions --> |
||||
|
<xs:complexType name="EntryType" qxg:declare="true"> |
||||
|
<xs:sequence> |
||||
|
<xs:choice maxOccurs="unbounded" minOccurs="0" qxg:unordered="true"> |
||||
|
<xs:element type="xs:string" name="SearchKey" qxg:member="searchKeys"/> |
||||
|
<xs:element type="PropertyType" name="Property" qxg:member="properties"/> |
||||
|
</xs:choice> |
||||
|
</xs:sequence> |
||||
|
<xs:attributeGroup ref="BasicContainerInfo" qxg:inherit="true"/> |
||||
|
<xs:attribute type="xs:string" name="key" use="required"/> |
||||
|
<xs:attribute type="xs:string" name="type" use="required"/> |
||||
|
<xs:attribute type="xs:string" name="default" use="optional" qxg:member="defaultValue"/> |
||||
|
<xs:attribute type="xs:boolean" name="trdefault" use="optional" default="false"/> |
||||
|
</xs:complexType> |
||||
|
|
||||
|
<xs:complexType name="GroupType" qxg:declare="true"> |
||||
|
<xs:group ref="GroupContentGroup" qxg:inherit="true" qxg:method="finish_group_content"/> |
||||
|
<xs:attributeGroup ref="BasicContainerInfo" qxg:inherit="true"/> |
||||
|
</xs:complexType> |
||||
|
|
||||
|
<xs:complexType name="SectionType" qxg:declare="true"> |
||||
|
<xs:group ref="SectionContentGroup" qxg:inherit="true" qxg:method="finish_section_content"/> |
||||
|
<xs:attributeGroup ref="ExtendedContainerInfo" qxg:inherit="true"/> |
||||
|
</xs:complexType> |
||||
|
|
||||
|
<xs:complexType name="CategoryType" qxg:declare="true"> |
||||
|
<xs:group ref="CategoryContentGroup" qxg:inherit="true" qxg:method="finish_category_content"/> |
||||
|
<xs:attributeGroup ref="ExtendedContainerInfo" qxg:inherit="true"/> |
||||
|
</xs:complexType> |
||||
|
|
||||
|
<xs:complexType name="SettingsConfigType" qxg:declare="true"> |
||||
|
<xs:group ref="SettingsConfigContentGroup" qxg:inherit="true" qxg:method="finish_settings_config_content"/> |
||||
|
<xs:attribute type="xs:boolean" name="allowSearch" use="optional" default="true"/> |
||||
|
<xs:attribute type="xs:boolean" name="allowRestore" use="optional" default="true"/> |
||||
|
</xs:complexType> |
||||
|
|
||||
|
<!-- root elements--> |
||||
|
<xs:element name="SettingsConfig" type="SettingsConfigType"/> |
||||
|
<xs:element name="Category" type="CategoryType"/> |
||||
|
<xs:element name="Section" type="SectionType"/> |
||||
|
<xs:element name="Group" type="GroupType"/> |
||||
|
<xs:element name="Entry" type="EntryType"/> |
||||
|
</xs:schema> |
@ -0,0 +1,108 @@ |
|||||
|
#include "settingstranslator.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 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); |
||||
|
finishContents(reader, data.content); |
||||
|
return hasNext; |
||||
|
} |
||||
|
|
||||
|
template<typename TGroup> |
||||
|
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; |
||||
|
} |
||||
|
} |
@ -0,0 +1,21 @@ |
|||||
|
#ifndef SETTINGSTRANSLATOR_H |
||||
|
#define SETTINGSTRANSLATOR_H |
||||
|
|
||||
|
#include "settingsconfig.h" |
||||
|
|
||||
|
class SettingsTranslator : 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 // SETTINGSTRANSLATOR_H
|
Loading…
Reference in new issue