From 119d4b93187a0dd3644a62551fa45216b7c8b105 Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Mon, 23 Jul 2018 19:58:11 +0200 Subject: [PATCH] wip further --- .../qmlsettingsgenerator.cpp | 192 ++++++++++-------- .../settingsgenerator/qmlsettingsgenerator.h | 16 +- 2 files changed, 113 insertions(+), 95 deletions(-) diff --git a/tools/settingsgenerator/qmlsettingsgenerator.cpp b/tools/settingsgenerator/qmlsettingsgenerator.cpp index 4aaa025..5b3dba2 100644 --- a/tools/settingsgenerator/qmlsettingsgenerator.cpp +++ b/tools/settingsgenerator/qmlsettingsgenerator.cpp @@ -14,6 +14,7 @@ void QmlSettingsGenerator::process(const QString &inPath) auto settings = readDocument(inPath); if(!settings.name) settings.name = QFileInfo{inPath}.baseName(); + _cppName = settings.name.value(); settings.name.value().prepend(QStringLiteral("QMLTYPE_")); fixTrContext(settings, QFileInfo{inPath}.fileName()); @@ -57,12 +58,13 @@ void QmlSettingsGenerator::writeHeader(const SettingsGeneratorBase::SettingsType } _hdr << "\n"; - writeListTypeClasses(settings); + writeListTypeBaseClass(settings); // create all the qmltype classes + auto keyList = settings.prefix ? QStringList{settings.prefix.value()} : QStringList{}; int offset; QList childOffsets; - std::tie(offset, childOffsets) = writeNodeContentClassesDeclarations(settings); + std::tie(offset, childOffsets) = writeNodeContentClassesDeclarations(settings, keyList); // create the class _hdr << "class " << _prefixName << " : public QObject\n" @@ -70,7 +72,8 @@ void QmlSettingsGenerator::writeHeader(const SettingsGeneratorBase::SettingsType << "\tQ_OBJECT\n\n" << "\tQ_PROPERTY(QtMvvm::ISettingsAccessor *accessor READ accessor CONSTANT FINAL)\n\n"; - writeNodeClassPropertiesDeclarations(settings, childOffsets); + QList> childConstructs; + writeNodeClassPropertiesDeclarations(settings, keyList, childOffsets, childConstructs); _hdr << "public:\n" << "\texplicit " << settings.name.value() << "(QObject *parent = nullptr);\n" @@ -82,77 +85,64 @@ void QmlSettingsGenerator::writeHeader(const SettingsGeneratorBase::SettingsType << "#endif //" << incGuard << '\n'; } -void QmlSettingsGenerator::writeListTypeClasses(const SettingsGeneratorBase::SettingsType &settings) +void QmlSettingsGenerator::writeListTypeBaseClass(const SettingsGeneratorBase::SettingsType &settings) { - // write the list wrapper base class - _hdr << "class " << _prefixName << "_ListType : public QObject\n" - << "{\n" - << "\tQ_OBJECT\n\n" - << "\tQ_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged)\n\n" - << "public:\n" - << "\tclass Accessor {\n" - << "\tpublic:\n" - << "\t\tinline virtual ~Accessor() = default;\n" - << "\t\tvirtual QVariant value() const = 0;\n" - << "\t\tvirtual void setValue(const QVariant &value) = 0;\n" - << "\t};\n\n" - << "\texplicit " << _prefixName << "_ListType(QObject *parent);\n\n" - << "\tQVariant value() const { return _data ? _data->value() : _buffer; }\n" - << "\tvoid setValue(const QVariant &value) { if(_data) _data->setValue(value); else _buffer = value; }\n" - << "\tvoid setAccessor(Accessor *accessor) { _data.reset(accessor); if(_buffer.isValid()) _data->setValue(_buffer); _buffer.clear(); }\n\n" - << "Q_SIGNALS:\n" - << "\tvoid valueChanged(const QVariant &value);\n\n" - << "private:\n" - << "\tQScopedPointer _data;\n" - << "\tQVariant _buffer;\n" - << "};\n\n"; - // write the generic variant _hdr << "template \n" - << "class " << _prefixName << "_ListType_Accessor : public " << _prefixName << "_ListType::Accessor\n" + << "class " << _prefixName << "_ListType : public QObject\n" << "{\n" << "public:\n" + << "\ttemplate \n" << "\tstruct ListData {\n" + << "\t\tstatic_assert(std::is_base_of<" << _prefixName << "_ListType, TList>::value, \"TList must extend " << _prefixName << "_ListType\");\n" << "\t\tQtMvvm::SettingsEntry> &entry;\n" - << "\t\tQList<" << _prefixName << "_ListType> elements;\n" + << "\t\tQList elements;\n" << "\t};\n\n" - << "\t" << _prefixName << "_ListType_Accessor(QtMvvm::SettingsEntry> &entry, int index) : \n" - << "\t\t_entry{entry},\n" - << "\t\t_index{index}\n" + << "\t" << _prefixName << "_ListType(QtMvvm::SettingsEntry> &entry, QObject *parent) : \n" + << "\t\tQObject{parent},\n" + << "\t\t_entry{entry}\n" << "\t{}\n" - << "\tQVariant value() const final { return QVariant::fromValue(_entry.getAt(_index)); }\n" - << "\tvoid setValue(const QVariant &value) final { _entry.setAt(_index, value.template value()); }\n\n" + << "\tT value() const { return _index >= 0 ? _entry.getAt(_index) : _buffer; }\n" + << "\tvoid setValue(const T &value) { if(_index >= 0) _entry.setAt(_index, value); else { _index = -2; _buffer = value; } }\n\n" << "private:\n" << "\tfriend class " << _prefixName << ";\n" << "\tQtMvvm::SettingsEntry> &_entry;\n" - << "\tconst int _index;\n\n" - << "\tstatic void append(QQmlListProperty<" << _prefixName << "_ListType>* list, " << _prefixName << "_ListType* element) {\n" - << "\t\tconst auto data = reinterpret_cast(list->data);\n" + << "\tint _index = -1;\n" + << "\tT _buffer{};\n\n" + << "\ttemplate \n" + << "\tstatic void append(QQmlListProperty *list, TList *element) {\n" + << "\t\tconst auto data = reinterpret_cast*>(list->data);\n" << "\t\tconst auto maxIndex = data->entry.size();\n" << "\t\tfor(auto index = data->elements.size(); index <= maxIndex; index++) {\n" - << "\t\t\t" << _prefixName << "_ListType *elem;\n" + << "\t\t\tTList *elem;\n" << "\t\t\tif(index == maxIndex) {\n" << "\t\t\t\telem = element;\n" << "\t\t\t\telem->setParent(list->object);\n" << "\t\t\t} else\n" - << "\t\t\t\telem = new " << _prefixName << "_ListType{list->object};\n" + << "\t\t\t\telem = new TList{list->object};\n" + << "\t\t\tconst auto copyDefault = elem->_index == -2;\n" + << "\t\t\telem->_index = index;\n" << "\t\t\tdata->elements.append(elem);\n" - << "\t\t\telem->setAccessor(new " << _prefixName << "_ListType_Accessor{data->entry, index});\n" + << "\t\t\tif(copyDefault)\n" + << "\t\t\t\telem->setValue(T{std::move(elem->_buffer)});\n" << "\t\t\tdata->entry.addChangeCallback(elem, [index, elem](int i, const T &d) {\n" << "\t\t\t\tif(i == index)\n" - << "\t\t\t\t\temit elem->valueChanged(QVariant::fromValue(d));\n" + << "\t\t\t\t\temit elem->valueChanged(d);\n" << "\t\t\t});\n" << "\t\t}\n" << "\t}\n\n" - << "\tstatic " << _prefixName << "_ListType *at(QQmlListProperty<" << _prefixName << "_ListType>* list, int index) {\n" - << "\t\tconst auto data = reinterpret_cast(list->data);\n" + << "\ttemplate \n" + << "\tstatic TList *at(QQmlListProperty *list, int index) {\n" + << "\t\tconst auto data = reinterpret_cast*>(list->data);\n" << "\t\treturn data->elements.size() > index ? data->elements.value(index) : nullptr;\n" << "\t}\n\n" - << "\tstatic int count(QQmlListProperty<" << _prefixName << "_ListType>* list) {\n" - << "\t\treturn reinterpret_cast(list->data)->elements.size();\n" + << "\ttemplate \n" + << "\tstatic int count(QQmlListProperty *list) {\n" + << "\t\treturn reinterpret_cast*>(list->data)->elements.size();\n" << "\t}\n\n" - << "\tstatic void clear(QQmlListProperty<" << _prefixName << "_ListType>* list) {\n" - << "\t\tconst auto data = reinterpret_cast(list->data);\n" + << "\ttemplate \n" + << "\tstatic void clear(QQmlListProperty *list) {\n" + << "\t\tconst auto data = reinterpret_cast*>(list->data);\n" << "\t\tfor(auto elem : qAsConst(data->elements))\n" << "\t\t\telem->deleteLater();\n" << "\t\tdata->elements.clear();\n" @@ -161,28 +151,30 @@ void QmlSettingsGenerator::writeListTypeClasses(const SettingsGeneratorBase::Set << "};\n\n"; } -std::tuple> QmlSettingsGenerator::writeNodeContentClassesDeclarations(const SettingsGeneratorBase::NodeContentGroup &node, int offset) +std::tuple> QmlSettingsGenerator::writeNodeContentClassesDeclarations(const SettingsGeneratorBase::NodeContentGroup &node, const QStringList &keyList, int offset) { QList offsetList; for(const auto &cNode : node.contentNodes) { if(nonstd::holds_alternative(cNode)) { - offset = writeNodeClassDeclaration(nonstd::get(cNode), offset); + offset = writeNodeClassDeclaration(nonstd::get(cNode), keyList, offset); offsetList.append(offset - 1); } else if(nonstd::holds_alternative(cNode)) { if(!nonstd::get(cNode).contentNodes.isEmpty()) { - offset = writeNodeClassDeclaration(nonstd::get(cNode), offset); + offset = writeNodeClassDeclaration(nonstd::get(cNode), keyList, offset); offsetList.append(offset - 1); } else offsetList.append(-1); } else if(nonstd::holds_alternative(cNode)) { + offset = writeListEntryListClass(nonstd::get(cNode), keyList, offset); + offsetList.append(offset - 1); //double offset!!! if(!nonstd::get(cNode).contentNodes.isEmpty()) { - offset = writeNodeClassDeclaration(nonstd::get(cNode), offset); + offset = writeNodeClassDeclaration(nonstd::get(cNode), keyList, offset); offsetList.append(offset - 1); } else offsetList.append(-1); } else if(nonstd::holds_alternative(cNode)) { QList subList; - std::tie(offset, subList) = writeNodeContentClassesDeclarations(nonstd::get(cNode), offset); + std::tie(offset, subList) = writeNodeContentClassesDeclarations(nonstd::get(cNode), keyList, offset); offsetList.append(subList); } else Q_UNREACHABLE(); @@ -190,71 +182,93 @@ std::tuple> QmlSettingsGenerator::writeNodeContentClassesDeclara return std::make_tuple(offset, offsetList); } -void QmlSettingsGenerator::writeNodeClassPropertiesDeclarations(const SettingsGeneratorBase::NodeContentGroup &node, QList &childOffsets) +int QmlSettingsGenerator::writeNodeClassDeclaration(const SettingsGeneratorBase::NodeType &node, const QStringList &keyList, int offset) +{ + auto subList = QStringList{keyList} << node.key; + QList childOffsets; + std::tie(offset, childOffsets) = writeNodeContentClassesDeclarations(node, subList, offset); + + _hdr << "class " << _prefixName << "_" << offset << " : public QObject // " << node.key << "\n" + << "{\n" + << "\tQ_OBJECT\n\n"; + + QList> childConstructs; + writeNodeClassPropertiesDeclarations(node, subList, childOffsets, childConstructs); + + _hdr << "\t" << _cppName << " *_settings;\n\n" + << "public:\n" + << "\t" << _name << "_" << offset << "(" << _cppName << " *settings, QObject *parent) : \n" + << "\t\tQObject{parent},\n"; + for(const auto &info : childConstructs) + _hdr << "\t\t_" << info.first << "{new " << _name << "_" << info.second << "{settings, this}},\n"; + _hdr << "\t\t_settings{settings}\n" + << "\t{}\n" + << "};\n\n"; + + return ++offset; +} + +int QmlSettingsGenerator::writeListEntryListClass(const SettingsGeneratorBase::ListEntryType &entry, QStringList keyList, int offset) +{ + const auto &mType = _typeMappings.value(entry.type, entry.type); + _hdr << "class " << _prefixName << "_" << offset << " : public " << _prefixName << "_ListType<" << mType << "> // " << entry.key << "\n" + << "{\n" + << "\tQ_OBJECT\n\n" + << "\tQ_PROPERTY(" << mType << " value READ value WRITE setValue NOTIFY valueChanged)\n\n" + << "public:\n" + << "\texplicit " << _name << "_" << offset << "(QObject *parent = nullptr);\n\n" + << "Q_SIGNALS:\n" + << "\tvoid valueChanged(const " << mType << " &value);\n" + << "};\n\n"; + + return ++offset; +} + +void QmlSettingsGenerator::writeNodeClassPropertiesDeclarations(const SettingsGeneratorBase::NodeContentGroup &node, const QStringList &keyList, QList &childOffsets, QList> &childConstructs) { for(const auto &cNode : node.contentNodes) { if(nonstd::holds_alternative(cNode)) - writeNodePropertyDeclaration(nonstd::get(cNode), childOffsets.takeFirst()); + writeNodePropertyDeclaration(nonstd::get(cNode), childOffsets.takeFirst(), childConstructs); else if(nonstd::holds_alternative(cNode)) - writeEntryPropertyDeclaration(nonstd::get(cNode), childOffsets.takeFirst()); - else if(nonstd::holds_alternative(cNode)) - writeEntryPropertyDeclaration(nonstd::get(cNode), childOffsets.takeFirst()); - else if(nonstd::holds_alternative(cNode)) - writeNodeClassPropertiesDeclarations(nonstd::get(cNode), childOffsets); + writeEntryPropertyDeclaration(nonstd::get(cNode), keyList, childOffsets.takeFirst(), childConstructs); + else if(nonstd::holds_alternative(cNode)) { + childOffsets.takeFirst(); //TODO use... + writeEntryPropertyDeclaration(nonstd::get(cNode), keyList, childOffsets.takeFirst(), childConstructs); + } else if(nonstd::holds_alternative(cNode)) + writeNodeClassPropertiesDeclarations(nonstd::get(cNode), keyList, childOffsets, childConstructs); else Q_UNREACHABLE(); } } -void QmlSettingsGenerator::writeNodePropertyDeclaration(const SettingsGeneratorBase::NodeType &entry, int classIndex, const QString &overwriteName) +void QmlSettingsGenerator::writeNodePropertyDeclaration(const SettingsGeneratorBase::NodeType &entry, int classIndex, QList> &childConstructs, const QString &overwriteName) { const auto &mName = overwriteName.isNull() ? entry.key : overwriteName; _hdr << "\tQ_PROPERTY(" << _name << "_" << classIndex << "* " << mName << " MEMBER _" << mName << " CONSTANT)\n"; - _hdr << "\t" << _name << "_" << classIndex << "* _" << mName << ";\n\n"; + childConstructs.append({mName, classIndex}); } -void QmlSettingsGenerator::writeEntryPropertyDeclaration(const SettingsGeneratorBase::EntryType &entry, int classIndex) +void QmlSettingsGenerator::writeEntryPropertyDeclaration(const SettingsGeneratorBase::EntryType &entry, QStringList keyList, int classIndex, QList> &childConstructs) { + keyList.append(entry.key); const auto &mType = _typeMappings.value(entry.type, entry.type); if(mType != QStringLiteral("void")) { _hdr << "\tQ_PROPERTY(" << mType << " " << entry.key << " READ get_" << entry.key << " WRITE set_" << entry.key - << " NOTIFY notify_" << entry.key << ")\n"; + << " NOTIFY " << entry.key << "_changed)\n"; - _hdr << "\t" << mType << " get_" << entry.key << "() const;\n" - << "\tvoid set_" << entry.key << "(const " << mType << "& value);\n" + _hdr << "\t" << mType << " get_" << entry.key << "() const { return _settings->" << keyList.join(QLatin1Char('.')) << ".get(); }\n" + << "\tvoid set_" << entry.key << "(const " << mType << "& value) { _settings->" << keyList.join(QLatin1Char('.')) << ".set(value); }\n" << "Q_SIGNALS:\n" - << "\tvoid notify_" << entry.key << "();\n" + << "\tvoid " << entry.key << "_changed();\n" << "private:\n\n"; } if(!entry.contentNodes.isEmpty()) - writeNodePropertyDeclaration(entry, classIndex, entry.qmlGroupKey.value_or(entry.key + QStringLiteral("Group"))); -} - -int QmlSettingsGenerator::writeNodeClassDeclaration(const SettingsGeneratorBase::NodeType &node, int offset) -{ - QList childOffsets; - std::tie(offset, childOffsets) = writeNodeContentClassesDeclarations(node, offset); - - _hdr << "class " << _prefixName << "_" << offset << " : public QObject // " << node.key << "\n" - << "{\n" - << "\tQ_OBJECT\n\n"; - - _hdr << "public:\n" - << "\t" << _name << "_" << offset << "(QtMvvm::ISettingsAccessor *accessor, const QString &parentKey, QObject *parent);\n\n" - << "private:\n" - << "\tQtMvvm::ISettingsAccessor *_accessor;\n" - << "\tQString _nodeKey;\n\n"; - - writeNodeClassPropertiesDeclarations(node, childOffsets); - - _hdr << "};\n\n"; - - return ++offset; + writeNodePropertyDeclaration(entry, classIndex, childConstructs, entry.qmlGroupKey.value_or(entry.key + QStringLiteral("Group"))); } void QmlSettingsGenerator::writeSource(const SettingsGeneratorBase::SettingsType &settings) diff --git a/tools/settingsgenerator/qmlsettingsgenerator.h b/tools/settingsgenerator/qmlsettingsgenerator.h index 0e878ec..aec06fb 100644 --- a/tools/settingsgenerator/qmlsettingsgenerator.h +++ b/tools/settingsgenerator/qmlsettingsgenerator.h @@ -19,18 +19,22 @@ private: QTextStream _hdr; QTextStream _src; + QString _cppName; QString _name; QString _prefixName; QHash _typeMappings; void writeHeader(const SettingsType &settings, const QString &inHdrPath); - void writeListTypeClasses(const SettingsType &settings); - std::tuple> writeNodeContentClassesDeclarations(const NodeContentGroup &node, int offset = 0); - void writeNodeClassPropertiesDeclarations(const NodeContentGroup &node, QList &childOffsets); - void writeNodePropertyDeclaration(const NodeType &entry, int classIndex, const QString &overwriteName = {}); - void writeEntryPropertyDeclaration(const EntryType &entry, int classIndex); - int writeNodeClassDeclaration(const NodeType &node, int offset); + void writeListTypeBaseClass(const SettingsType &settings); + + std::tuple> writeNodeContentClassesDeclarations(const NodeContentGroup &node, const QStringList &keyList, int offset = 0); + int writeNodeClassDeclaration(const NodeType &node, const QStringList &keyList, int offset); + int writeListEntryListClass(const ListEntryType &entry, QStringList keyList, int offset); + + void writeNodeClassPropertiesDeclarations(const NodeContentGroup &node, const QStringList &keyList, QList &childOffsets, QList> &childConstructs); + void writeNodePropertyDeclaration(const NodeType &entry, int classIndex, QList> &childConstructs, const QString &overwriteName = {}); + void writeEntryPropertyDeclaration(const EntryType &entry, QStringList keyList, int classIndex, QList> &childConstructs); void writeSource(const SettingsType &settings); };