Browse Source

WIP xmlcodegen integration

pull/2/head
Skycoder42 7 years ago
parent
commit
ce834f1bd8
No known key found for this signature in database GPG Key ID: 8E01AD9EF0578D2B
  1. 2
      .gitignore
  2. 5
      tools/3rdparty/3rdparty.pri
  3. 23
      tools/3rdparty/optional-lite/LICENSE.txt
  4. 1214
      tools/3rdparty/optional-lite/optional.hpp
  5. 23
      tools/3rdparty/variant-lite/LICENSE.txt
  6. 1533
      tools/3rdparty/variant-lite/variant.hpp
  7. 3
      tools/settingsgenerator/main.cpp
  8. 21
      tools/settingsgenerator/qpmx.json
  9. 71
      tools/settingsgenerator/qsettingsgenerator.xsd
  10. 291
      tools/settingsgenerator/settingsgenerator.cpp
  11. 100
      tools/settingsgenerator/settingsgenerator.h
  12. 7
      tools/settingsgenerator/settingsgenerator.pro

2
.gitignore

@ -76,3 +76,5 @@ qpmx.user.json
# ts dummy dirs
.ts-dummy
.qpmx-dev-cache
qpmx.json.user

5
tools/3rdparty/3rdparty.pri

@ -0,0 +1,5 @@
HEADERS += \
$$PWD/optional-lite/optional.hpp \
$$PWD/variant-lite/variant.hpp
INCLUDEPATH += $$PWD/optional-lite $$PWD/variant-lite

23
tools/3rdparty/optional-lite/LICENSE.txt

@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

1214
tools/3rdparty/optional-lite/optional.hpp

File diff suppressed because it is too large

23
tools/3rdparty/variant-lite/LICENSE.txt

@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

1533
tools/3rdparty/variant-lite/variant.hpp

File diff suppressed because it is too large

3
tools/settingsgenerator/main.cpp

@ -44,11 +44,10 @@ int main(int argc, char *argv[])
try {
SettingsGenerator generator {
parser.value(QStringLiteral("in")),
parser.value(QStringLiteral("header")),
parser.value(QStringLiteral("impl"))
};
generator.process();
generator.process(parser.value(QStringLiteral("in")));
return EXIT_SUCCESS;
} catch (const QString &str) {
qCritical() << qUtf8Printable(str);

21
tools/settingsgenerator/qpmx.json

@ -0,0 +1,21 @@
{
"dependencies": [
{
"package": "de.skycoder42.qxmlcodegen",
"provider": "qpm",
"version": "1.0.0"
}
],
"license": {
"file": "",
"name": ""
},
"prcFile": "",
"priFile": "",
"priIncludes": [
],
"publishers": {
},
"qbsFile": "",
"source": false
}

71
tools/settingsgenerator/qsettingsgenerator.xsd

@ -1,32 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:qxg="https://skycoder42.de/QXmlCodeGen"><!-- TODO proper name/url -->
<!-- QXG Definitions -->
<qxg:config class="SettingsGeneratorBase"
stdcompat="true">
<qxg:include>QtCore/QHash</qxg:include>
</qxg:config>
<qxg:method name="read_type_mapping" type="QHash&lt;QString, QString&gt;" asGroup="true"/>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- Type definitions -->
<xs:complexType name="Include">
<xs:complexType name="IncludeType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:extension base="xs:string" qxg:member="include">
<xs:attribute default="false" name="local" type="xs:boolean" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="Import">
<!--xs:complexType name="Import">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute default="true" name="required" type="xs:boolean" use="optional"/>
<xs:attribute name="rootNode" type="xs:string" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:complexType-->
<xs:complexType name="TypeMapping">
<xs:complexType name="TypeMappingEntry">
<xs:attribute name="key" type="xs:string" use="required"/>
<xs:attribute name="type" type="xs:string" use="required"/>
</xs:complexType>
<xs:complexType name="Param">
<xs:group name="TypeMappingGroup">
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="TypeMapping" type="TypeMappingEntry"/>
</xs:sequence>
</xs:group>
<xs:complexType name="ParamType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:extension base="xs:string" qxg:member="value">
<xs:attribute name="key" type="xs:string" use="required"/>
<xs:attribute name="type" type="xs:string" use="required"/>
<xs:attribute default="false" name="asStr" type="xs:boolean" use="optional"/>
@ -34,49 +47,49 @@
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="Backend">
<xs:complexType name="BackendType">
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="Param" type="Param"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="Param" type="ParamType"/>
</xs:sequence>
<xs:attribute name="class" type="xs:string" use="required"/>
<xs:attribute name="class" type="xs:string" use="required" qxg:member="className"/>
</xs:complexType>
<xs:complexType name="Node">
<xs:group name="NodeContentGroup">
<xs:sequence>
<xs:choice maxOccurs="unbounded" minOccurs="0">
<xs:element name="Node" type="Node"/>
<xs:element name="Entry" type="Entry"/>
<xs:element name="Import" type="Import"/>
<xs:choice maxOccurs="unbounded" minOccurs="0" qxg:unordered="true">
<xs:element name="Node" type="NodeType" qxg:member="nodes"/>
<xs:element name="Entry" type="EntryType" qxg:member="entries"/>
<!--xs:element name="Import" type="Import"/-->
</xs:choice>
</xs:sequence>
</xs:group>
<xs:complexType name="NodeType" qxg:declare="true">
<xs:group ref="NodeContentGroup" qxg:inherit="true"/>
<xs:attribute name="key" type="xs:string" use="required"/>
</xs:complexType>
<xs:complexType name="Entry">
<xs:complexType name="EntryType" qxg:declare="true">
<xs:complexContent>
<xs:extension base="Node">
<xs:extension base="NodeType">
<xs:sequence>
<xs:element maxOccurs="1" minOccurs="0" name="Code" type="xs:string"/>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="required"/>
<xs:attribute name="qmlGroupKey" type="xs:string" use="optional"/>
<xs:attribute name="default" type="xs:string" use="optional"/>
<xs:attribute name="default" type="xs:string" use="optional" qxg:member="defaultValue"/>
<xs:attribute default="false" name="tr" type="xs:boolean" use="optional"/>
<xs:attribute name="trContext" type="xs:string" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Settings">
<xs:complexType name="SettingsType">
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="Include" type="Include"/>
<xs:element maxOccurs="1" minOccurs="0" name="Backend" type="Backend"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="TypeMapping" type="TypeMapping"/>
<xs:choice maxOccurs="unbounded" minOccurs="0">
<xs:element name="Node" type="Node"/>
<xs:element name="Entry" type="Entry"/>
<xs:element name="Import" type="Import"/>
</xs:choice>
<xs:element maxOccurs="unbounded" minOccurs="0" name="Include" type="IncludeType" qxg:member="includes"/>
<xs:element maxOccurs="1" minOccurs="0" name="Backend" type="BackendType"/>
<xs:group ref="TypeMappingGroup" qxg:member="typeMappings" qxg:method="read_type_mapping" qxg:methodType="QHash&lt;QString, QString&gt;"/> <!-- TODO should be auto-detected -->
<xs:group ref="NodeContentGroup" qxg:inherit="true"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="optional"/>
<xs:attribute name="prefix" type="xs:string" use="optional"/>
@ -84,5 +97,5 @@
</xs:complexType>
<!-- root elements-->
<xs:element name="Settings" type="Settings"/>
<xs:element name="Settings" type="SettingsType"/>
</xs:schema>

291
tools/settingsgenerator/settingsgenerator.cpp

@ -5,218 +5,39 @@
#define TABS QString{QLatin1Char('\t')}.repeated(intendent)
SettingsGenerator::SettingsGenerator(const QString &inPath, const QString &hdrPath, const QString &srcPath) :
_inFile{inPath},
SettingsGenerator::SettingsGenerator(const QString &hdrPath, const QString &srcPath) :
_hdrFile{hdrPath},
_srcFile{srcPath},
_xml{&_inFile},
_hdr{&_hdrFile},
_src{&_srcFile}
{}
void SettingsGenerator::process()
void SettingsGenerator::process(const QString &inPath)
{
if(!_inFile.open(QIODevice::ReadOnly | QIODevice::Text))
throwFile(_inFile);
if(!_hdrFile.open(QIODevice::WriteOnly | QIODevice::Text))
throwFile(_hdrFile);
if(!_srcFile.open(QIODevice::WriteOnly | QIODevice::Text))
throwFile(_srcFile);
if(!_xml.readNextStartElement())
throwReader(_xml);
if(_xml.name() != QStringLiteral("Settings"))
throwChild(_xml);
auto data = readSettings(_xml);
checkError(_xml);
qDebug() << "Completed parsing xml - it is valid";
data.includes.append({
{false, QStringLiteral("QtCore/QObject")},
{false, QStringLiteral("QtMvvmCore/ISettingsAccessor")},
{false, QStringLiteral("QtMvvmCore/SettingsEntry")},
});
writeHeader(data);
writeSource(data);
}
SettingsGenerator::Include SettingsGenerator::readInclude(QXmlStreamReader &xml)
{
Include include;
include.local = readAttrib<bool>(xml, QStringLiteral("local"), false);
include.include = xml.readElementText();
checkError(xml);
return include;
}
SettingsGenerator::Param SettingsGenerator::readParam(QXmlStreamReader &xml)
{
Param param;
param.key = readAttrib(xml, QStringLiteral("key"), {}, true);
param.type = readAttrib(xml, QStringLiteral("type"), {}, true);
param.asStr = readAttrib<bool>(xml, QStringLiteral("asStr"), false);
param.value = xml.readElementText();
checkError(xml);
return param;
}
QSharedPointer<SettingsGenerator::Backend> SettingsGenerator::readBackend(QXmlStreamReader &xml)
{
auto backend = QSharedPointer<Backend>::create();
backend->className = readAttrib(xml, QStringLiteral("class"), {}, true);
while(xml.readNextStartElement()) {
if(xml.name() == QStringLiteral("Param"))
backend->params.append(readParam(xml));
else
throwChild(xml);
}
checkError(xml);
return backend;
}
QPair<QString, QString> SettingsGenerator::readTypeMapping(QXmlStreamReader &xml)
{
QPair<QString, QString> mapping;
mapping.first = readAttrib(xml, QStringLiteral("key"), {}, true);
mapping.second = readAttrib(xml, QStringLiteral("type"), {}, true);
checkError(xml);
return mapping;
}
SettingsGenerator::Node SettingsGenerator::readNode(QXmlStreamReader &xml)
{
Node node;
node.key = readAttrib(xml, QStringLiteral("key"), {}, true);
while(xml.readNextStartElement()) {
if(xml.name() == QStringLiteral("Node"))
node.subNodes.append(readNode(xml));
else if(xml.name() == QStringLiteral("Entry"))
node.subEntries.append(readEntry(xml));
else if(xml.name() == QStringLiteral("Import"))
node.subImports.append(readImport(xml));
else
throwChild(xml);
}
checkError(xml);
return node;
}
SettingsGenerator::Entry SettingsGenerator::readEntry(QXmlStreamReader &xml)
{
Entry entry;
entry.key = readAttrib(xml, QStringLiteral("key"), {}, true);
entry.type = readAttrib(xml, QStringLiteral("type"), {}, true);
entry.qmlGroupKey = readAttrib(xml, QStringLiteral("qmlGroupKey"));
entry.defaultValue = readAttrib(xml, QStringLiteral("default"));
entry.tr = readAttrib<bool>(xml, QStringLiteral("tr"), false);
entry.trContext = readAttrib(xml, QStringLiteral("trContext"));
while(xml.readNextStartElement()) {
if(xml.name() == QStringLiteral("Code")) {
if(!entry.defaultValue.isNull())
throwChild(xml);
entry.defaultValue = xml.readElementText();
entry.defaultIsCode = true;
checkError(xml);
} else if(xml.name() == QStringLiteral("Node"))
entry.subNodes.append(readNode(xml));
else if(xml.name() == QStringLiteral("Entry"))
entry.subEntries.append(readEntry(xml));
else if(xml.name() == QStringLiteral("Import"))
entry.subImports.append(readImport(xml));
else
throwChild(xml);
}
checkError(xml);
return entry;
}
SettingsGenerator::Import SettingsGenerator::readImport(QXmlStreamReader &xml)
{
auto required = readAttrib<bool>(xml, QStringLiteral("required"), true);
auto rootNode = readAttrib(xml, QStringLiteral("rootNode")).split(QLatin1Char('/'), QString::SkipEmptyParts);
auto path = xml.readElementText();
checkError(xml);
auto pInfo = QFileInfo{static_cast<QFileDevice*>(xml.device())->fileName()}.dir();
QFile subFile{pInfo.absoluteFilePath(path)};
if(!subFile.exists()) {
if(required)
throwReader(xml, QStringLiteral("Failed to find required import file \"%1\"").arg(subFile.fileName()));
else
return {};
}
// TODO add xml patterns...
auto settings = readDocument(inPath);
if(!subFile.open(QIODevice::ReadOnly | QIODevice::Text))
throwFile(subFile);
//TODO implement
QXmlStreamReader reader{&subFile};
if(!reader.readNextStartElement())
throwReader(reader);
if(reader.name() != QStringLiteral("Settings"))
throwChild(reader);
Node subSettings = readSettings(reader);
checkError(reader);
for(const auto &key : rootNode) {
auto found = false;
for(const auto &sNode : qAsConst(subSettings.subNodes)) {
if(sNode.key == key) {
found = true;
subSettings = sNode;
break;
}
}
for(const auto &sNode : qAsConst(subSettings.subEntries)) {
if(sNode.key == key) {
found = true;
subSettings = sNode;
break;
}
}
for(const auto &sNode : qAsConst(subSettings.subImports)) {
if(sNode.key == key) {
found = true;
subSettings = sNode;
break;
}
}
if(!found)
throwReader(xml, QStringLiteral("Unable to find rootNode \"%1\" in loaded document").arg(rootNode.join(QLatin1Char('/'))));
}
if(!_hdrFile.open(QIODevice::WriteOnly | QIODevice::Text))
throw FileException{_hdrFile};
writeHeader(settings);
_hdrFile.close();
return std::move(subSettings);
if(!_srcFile.open(QIODevice::WriteOnly | QIODevice::Text))
throw FileException{_srcFile};
writeSource(settings);
_srcFile.close();
}
SettingsGenerator::Settings SettingsGenerator::readSettings(QXmlStreamReader &xml)
bool SettingsGenerator::read_type_mapping(QXmlStreamReader &reader, QHash<QString, QString> &data, bool hasNext)
{
Settings settings;
settings.name = readAttrib(xml, QStringLiteral("name"), {}, true);
settings.prefix = readAttrib(xml, QStringLiteral("prefix"));
while(xml.readNextStartElement()) {
if(xml.name() == QStringLiteral("Include"))
settings.includes.append(readInclude(xml));
else if(xml.name() == QStringLiteral("Backend"))
settings.backend = readBackend(xml);
else if(xml.name() == QStringLiteral("TypeMapping")) {
auto mapping = readTypeMapping(xml);
settings.typeMapping.insert(mapping.first, mapping.second);
} else if(xml.name() == QStringLiteral("Node"))
settings.subNodes.append(readNode(xml));
else if(xml.name() == QStringLiteral("Entry"))
settings.subEntries.append(readEntry(xml));
else if(xml.name() == QStringLiteral("Import"))
settings.subImports.append(readImport(xml));
else
throwChild(xml);
}
checkError(xml);
return settings;
TypeMappingGroup grp;
hasNext = read_TypeMappingGroup(reader, grp, hasNext);
for(const auto &mapping : qAsConst(grp.typeMapping))
data.insert(mapping.key, mapping.type);
return hasNext;
}
void SettingsGenerator::writeHeader(const Settings &settings)
void SettingsGenerator::writeHeader(const SettingsType &settings)
{
QString incGuard = QFileInfo{_hdrFile.fileName()}
.completeBaseName()
@ -235,15 +56,15 @@ void SettingsGenerator::writeHeader(const Settings &settings)
_hdr << "\n";
// create the class
QString pName = settings.prefix.isEmpty() ? settings.name : (settings.prefix + QLatin1Char(' ') + settings.name);
_hdr << "class " << pName << " : public QObject\n"
auto name = settings.name.value_or(QFileInfo{_hdrFile.fileName()}.baseName());
_hdr << "class " << QString{settings.prefix ? settings.prefix.value() + QLatin1Char(' ') + name : name} << " : public QObject\n"
<< "{\n"
<< "\tQ_OBJECT\n\n"
<< "\tQ_PROPERTY(ISettingsAccessor *accessor READ accessor CONSTANT FINAL)\n\n"
<< "public:\n"
<< "\tQ_INVOKABLE explicit " << settings.name << "(QObject *parent = nullptr);\n"
<< "\texplicit " << settings.name << "(QObject *parent, ISettingsAccessor *accessor);\n\n"
<< "\tstatic " << settings.name << " *instance();\n\n"
<< "\tQ_INVOKABLE explicit " << name << "(QObject *parent = nullptr);\n"
<< "\texplicit " << name << "(QObject *parent, ISettingsAccessor *accessor);\n\n"
<< "\tstatic " << name << " *instance();\n\n"
<< "\tISettingsAccessor *accessor() const;\n\n";
writeNodeElements(settings);
@ -254,81 +75,29 @@ void SettingsGenerator::writeHeader(const Settings &settings)
<< "#endif //" << incGuard << '\n';
}
void SettingsGenerator::writeNodeElements(const SettingsGenerator::Node &node, int intendent)
void SettingsGenerator::writeNodeElements(const NodeContentGroup &node, int intendent)
{
for(const auto &cNode : node.subNodes)
for(const auto &cNode : node.nodes)
writeNode(cNode, intendent);
for(const auto &cEntry : node.subEntries)
for(const auto &cEntry : node.entries)
writeEntry(cEntry, intendent);
}
void SettingsGenerator::writeNode(const SettingsGenerator::Node &node, int intendent)
void SettingsGenerator::writeNode(const NodeType &node, int intendent)
{
_hdr << TABS << "struct {\n";
writeNodeElements(node, intendent + 1);
_hdr << TABS << "} " << node.key << ";\n";
}
void SettingsGenerator::writeEntry(const SettingsGenerator::Entry &entry, int intendent)
void SettingsGenerator::writeEntry(const EntryType &entry, int intendent)
{
_hdr << TABS << "struct : QtMvvm::SettingsEntry<" << entry.type << "> {\n";
writeNodeElements(entry, intendent + 1);
_hdr << TABS << "} " << entry.key << ";\n";
}
void SettingsGenerator::writeSource(const Settings &settings)
void SettingsGenerator::writeSource(const SettingsType &settings)
{
}
void SettingsGenerator::checkError(QXmlStreamReader &xml) const
{
if(xml.hasError())
throwReader(xml);
}
template<typename T>
T SettingsGenerator::readAttrib(QXmlStreamReader &xml, const QString &key, const T &defaultValue, bool required) const
{
if(xml.attributes().hasAttribute(key))
return QVariant(xml.attributes().value(key).toString()).template value<T>();
else if(required)
throwReader(xml, QStringLiteral("Required attribute \"%1\" but was not set").arg(key));
else
return defaultValue;
}
template<>
bool SettingsGenerator::readAttrib<bool>(QXmlStreamReader &xml, const QString &key, const bool &defaultValue, bool required) const
{
if(xml.attributes().hasAttribute(key)) {
if(xml.attributes().value(key) == QStringLiteral("true"))
return true;
else if(xml.attributes().value(key) == QStringLiteral("false"))
return false;
else
throwReader(xml, QStringLiteral("Value of attribute \"%1\" is not a xs:boolean!").arg(key));
} else if(required)
throwReader(xml, QStringLiteral("Required attribute \"%1\" but was not set").arg(key));
else
return defaultValue;
}
void SettingsGenerator::throwFile(const QFileDevice &file) const
{
throw QStringLiteral("%1: %2").arg(file.fileName(), file.errorString());
}
void SettingsGenerator::throwReader(QXmlStreamReader &xml, const QString &overwriteError) const
{
throw QStringLiteral("%1:%2:%3: %4")
.arg(dynamic_cast<QFileDevice*>(xml.device())->fileName())
.arg(xml.lineNumber())
.arg(xml.columnNumber())
.arg(overwriteError.isNull() ? xml.errorString() : overwriteError);
}
void SettingsGenerator::throwChild(QXmlStreamReader &xml)
{
throwReader(xml, QStringLiteral("Unexpected child element: %1").arg(xml.name()));
}

100
tools/settingsgenerator/settingsgenerator.h

@ -2,108 +2,34 @@
#define SETTINGSGENERATOR_H
#include <QFile>
#include <QXmlStreamReader>
#include <QTextStream>
#include <QSharedPointer>
class SettingsGenerator
#include "qsettingsgenerator.h"
class SettingsGenerator : public SettingsGeneratorBase
{
public:
SettingsGenerator(const QString &inPath,
const QString &hdrPath,
SettingsGenerator(const QString &hdrPath,
const QString &srcPath);
void process();
void process(const QString &inPath);
protected:
bool read_type_mapping(QXmlStreamReader &reader, QHash<QString, QString> &data, bool hasNext) override;
private:
QFile _inFile;
QFile _hdrFile;
QFile _srcFile;
QXmlStreamReader _xml;
QTextStream _hdr;
QTextStream _src;
struct Include{
bool local;
QString include;
};
struct Param {
QString key;
QString type;
bool asStr;
QString value;
};
struct Backend {
QString className;
QList<Param> params;
};
struct Entry;
struct Import;
struct Node {
QString key;
QList<Node> subNodes;
QList<Entry> subEntries;
QList<Import> subImports;
};
struct Entry : public Node {
QString type;
QString qmlGroupKey;
QString defaultValue;
bool defaultIsCode = false;
bool tr;
QString trContext;
};
struct Import : public Node {
inline Import() = default;
inline Import(Node &&node) :
Node(std::move(node))
{}
};
struct Settings : public Node {
QString name;
QString prefix;
QString baseKey;
void writeHeader(const SettingsType &settings);
void writeNodeElements(const NodeContentGroup &node, int intendent = 1);
void writeNode(const NodeType &node, int intendent = 1);
void writeEntry(const EntryType &entry, int intendent = 1);
QList<Include> includes;
QSharedPointer<Backend> backend;
QHash<QString, QString> typeMapping;
};
Include readInclude(QXmlStreamReader &xml);
Param readParam(QXmlStreamReader &xml);
QSharedPointer<Backend> readBackend(QXmlStreamReader &xml);
QPair<QString, QString> readTypeMapping(QXmlStreamReader &xml);
Node readNode(QXmlStreamReader &xml);
Entry readEntry(QXmlStreamReader &xml);
Import readImport(QXmlStreamReader &xml);
Settings readSettings(QXmlStreamReader &xml);
void writeHeader(const Settings &settings);
void writeNodeElements(const Node &node, int intendent = 1);
void writeNode(const Node &node, int intendent = 1);
void writeEntry(const Entry &entry, int intendent = 1);
void writeSource(const Settings &settings);
template <typename T = QString>
T readAttrib(QXmlStreamReader &xml, const QString &key, const T &defaultValue = {}, bool required = false) const;
void checkError(QXmlStreamReader &xml) const;
Q_NORETURN void throwFile(const QFileDevice &file) const;
Q_NORETURN void throwReader(QXmlStreamReader &xml, const QString &overwriteError = {}) const;
Q_NORETURN void throwChild(QXmlStreamReader &xml);
void writeSource(const SettingsType &settings);
};
template<>
bool SettingsGenerator::readAttrib<bool>(QXmlStreamReader &xml, const QString &key, const bool &defaultValue, bool required) const;
#endif // SETTINGSGENERATOR_H

7
tools/settingsgenerator/settingsgenerator.pro

@ -20,6 +20,10 @@ SOURCES += \
main.cpp \
settingsgenerator.cpp
XML_SCHEMA_DEFINITIONS += qsettingsgenerator.xsd
include(../3rdparty/3rdparty.pri)
load(qt_tool)
win32 {
@ -30,4 +34,5 @@ win32 {
QMAKE_TARGET_BUNDLE_PREFIX = $${BUNDLE_PREFIX}.
}
DISTFILES += qsettingsgenerator.xsd
!ReleaseBuild:!DebugBuild:!system(qpmx -d $$shell_quote($$_PRO_FILE_PWD_) --qmake-run init $$QPMX_EXTRA_OPTIONS $$shell_quote($$QMAKE_QMAKE) $$shell_quote($$OUT_PWD)): error(qpmx initialization failed. Check the compilation log for details.)
else: include($$OUT_PWD/qpmx_generated.pri)

Loading…
Cancel
Save