qt xml Serialize funtion
Unsolved
General and Desktop
-
Can you check the serialization function I implemented?
The problem is that I can't get the data stored according to the inheritance relationship.cSerializer.h
#define GET(prefix, name) get_##prefix##_##name #define SET(prefix, name) set_##prefix##_##name /* Create variable */ #define QS_DECLARE_MEMBER(type, name) \ public : \ type name = type(); \ /* Create XML property and methods for primitive type field*/ #define QS_XML_FIELD(type, name) \ Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name)) \ private: \ QDomNode GET(xml, name)() const \ { \ QDomDocument doc; \ QString strname = #name; \ QDomElement element = doc.createElement(strname); \ QDomText valueOfProp = doc.createTextNode(QVariant(name).toString()); \ element.appendChild(valueOfProp); \ doc.appendChild(element); \ return QDomNode(doc); \ } \ void SET(xml, name)(const QDomNode &node) \ { \ if(!node.isNull() && node.isElement()) \ { \ QDomElement domElement = node.toElement(); \ if(domElement.tagName() == #name) \ { \ name = QVariant(domElement.text()).value<type>(); \ } \ } \ } /* Generate XML-property and methods for primitive type objects */ /* This collection must be provide method append(T) (it's can be QList, QVector) */ #define QS_XML_ARRAY(itemType, name) \ Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name)) \ private: \ QDomNode GET(xml, name)() const \ { \ QDomDocument doc; \ QString strname = #name; \ QDomElement arrayXml = doc.createElement(QString(strname)); \ arrayXml.setAttribute("type", "array"); \ \ for(int i = 0; i < name.size(); i++) { \ itemType item = name.at(i); \ QDomElement itemXml = doc.createElement("item"); \ itemXml.setAttribute("type", #itemType); \ itemXml.setAttribute("index", i); \ itemXml.appendChild(doc.createTextNode(QVariant(item).toString())); \ arrayXml.appendChild(itemXml); \ } \ \ doc.appendChild(arrayXml); \ return QDomNode(doc); \ } \ void SET(xml, name)(const QDomNode & node) { \ QDomNode domNode = node.firstChild(); \ name.clear(); \ while(!domNode.isNull()) { \ if(domNode.isElement()) { \ QDomElement domElement = domNode.toElement(); \ name.append(QVariant(domElement.text()).value<itemType>()); \ } \ domNode = domNode.nextSibling(); \ } \ } /* Generate XML-property and methods for some custom class */ /* Custom type must be provide methods fromJson and toJson or inherit from QSerializer */ #define QS_XML_OBJECT(type, name) \ Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name)) \ private: \ QDomNode GET(xml, name)() const \ { \ qDebug() << QString("QS_GET_XML_OBJECT"); \ return name.toXml(); \ } \ void SET(xml, name)(const QDomNode & node) \ { \ qDebug() << QString("QS_SET_XML_OBJECT"); \ name.fromXml(node); \ } /* Generate XML-property and methods for collection of custom type objects */ /* Custom type must be provide methods fromXml and toXml or inherit from QSerializer */ /* This collection must be provide method append(T) (it's can be QList, QVector) */ #define QS_XML_ARRAY_OBJECTS(itemType, name) \ Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name)) \ private: \ QDomNode GET(xml, name)() const { \ QDomDocument doc; \ QDomElement element = doc.createElement(#name); \ element.setAttribute("type", "array"); \ for(int i = 0; i < name.size(); i++) \ element.appendChild(name.at(i).toXml()); \ doc.appendChild(element); \ return QDomNode(doc); \ } \ void SET(xml, name)(const QDomNode & node) { \ name.clear(); \ QDomNodeList nodesList = node.childNodes(); \ for(int i = 0; i < nodesList.size(); i++) { \ itemType tmp; \ tmp.fromXml(nodesList.at(i)); \ name.append(tmp); \ } \ } /* Generate XML-property and methods for dictionary of simple fields (int, bool, QString, ...) */ /* Custom type must be inherit from QSerializer */ /* This collection must be provide method insert(KeyT, ValueT) (it's can be QMap, QHash) */ /* THIS IS FOR QT DICTIONARY TYPES, for example QMap<int, QString>, QMap<int,int>, ...*/ #define QS_XML_QT_DICT(map, name) \ Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name)) \ private: \ QDomNode GET(xml, name)() const { \ QDomDocument doc; \ QDomElement element = doc.createElement(#name); \ element.setAttribute("type", "map"); \ for(auto p = name.begin(); p != name.end(); ++p) \ { \ QDomElement e = doc.createElement("item"); \ e.setAttribute("key", QVariant(p.key()).toString()); \ e.setAttribute("value", QVariant(p.value()).toString()); \ element.appendChild(e); \ } \ doc.appendChild(element); \ return QDomNode(doc); \ } \ void SET(xml, name)(const QDomNode & node) { \ if(!node.isNull() && node.isElement()) \ { \ QDomElement root = node.toElement(); \ if(root.tagName() == #name) \ { \ QDomNodeList childs = root.childNodes(); \ \ for(int i = 0; i < childs.size(); ++i) { \ QDomElement item = childs.at(i).toElement(); \ name.insert(QVariant(item.attributeNode("key").value()).value<map::key_type>(), \ QVariant(item.attributeNode("value").value()).value<map::mapped_type>()); \ } \ } \ } \ } /* Generate XML-property and methods for dictionary of custom type objects */ /* Custom type must be inherit from QSerializer */ /* This collection must be provide method insert(KeyT, ValueT) (it's can be QMap, QHash) */ /* THIS IS FOR QT DICTIONARY TYPES, for example QMap<int, CustomSerializableType> */ #define QS_XML_QT_DICT_OBJECTS(map, name) \ Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name)) \ private: \ QDomNode GET(xml, name)() const { \ QDomDocument doc; \ QDomElement element = doc.createElement(#name); \ element.setAttribute("type", "map"); \ for(auto p = name.begin(); p != name.end(); ++p) \ { \ QDomElement e = doc.createElement("item"); \ e.setAttribute("key", QVariant(p.key()).toString()); \ e.appendChild(p.value().toXml()); \ element.appendChild(e); \ } \ doc.appendChild(element); \ return QDomNode(doc); \ } \ void SET(xml, name)(const QDomNode & node) { \ if(!node.isNull() && node.isElement()) \ { \ QDomElement root = node.toElement(); \ if(root.tagName() == #name) \ { \ QDomNodeList childs = root.childNodes(); \ \ for(int i = 0; i < childs.size(); ++i) { \ QDomElement item = childs.at(i).toElement(); \ map::mapped_type tmp; \ tmp.fromXml(item.firstChild()); \ name.insert(QVariant(item.attributeNode("key").value()).value<map::key_type>(), \ tmp); \ } \ } \ } \ } #define QS_XML_STL_DICT(map, name) \ Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name)) \ private: \ QDomNode GET(xml, name)() const { \ QDomDocument doc; \ QDomElement element = doc.createElement(#name); \ element.setAttribute("type", "map"); \ for(auto p : name) \ { \ QDomElement e = doc.createElement("item"); \ e.setAttribute("key", QVariant(p.first).toString()); \ e.setAttribute("value", QVariant(p.second).toString()); \ element.appendChild(e); \ } \ doc.appendChild(element); \ return QDomNode(doc); \ } \ void SET(xml, name)(const QDomNode & node) { \ if(!node.isNull() && node.isElement()) \ { \ QDomElement root = node.toElement(); \ if(root.tagName() == #name) \ { \ QDomNodeList childs = root.childNodes(); \ \ for(int i = 0; i < childs.size(); ++i) { \ QDomElement item = childs.at(i).toElement(); \ name.insert(std::pair<map::key_type, map::mapped_type>( \ QVariant(item.attributeNode("key").value()).value<map::key_type>(), \ QVariant(item.attributeNode("value").value()).value<map::mapped_type>())); \ } \ } \ } \ } /* Generate XML-property and methods for dictionary of custom type objects */ /* Custom type must be inherit from QSerializer */ /* This collection must be provide method insert(KeyT, ValueT) (it's can be std::map) */ /* THIS IS FOR STL DICTIONARY TYPES, for example std::map<int, CustomSerializableType> */ #define QS_XML_STL_DICT_OBJECTS(map, name) \ Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name)) \ private: \ QDomNode GET(xml, name)() const { \ QDomDocument doc; \ QDomElement element = doc.createElement(#name); \ element.setAttribute("type", "map"); \ for(auto p : name) \ { \ QDomElement e = doc.createElement("item"); \ e.setAttribute("key", QVariant(p.first).toString()); \ e.appendChild(p.second.toXml()); \ element.appendChild(e); \ } \ doc.appendChild(element); \ return QDomNode(doc); \ } \ void SET(xml, name)(const QDomNode & node) { \ if(!node.isNull() && node.isElement()) \ { \ QDomElement root = node.toElement(); \ if(root.tagName() == #name) \ { \ QDomNodeList childs = root.childNodes(); \ \ for(int i = 0; i < childs.size(); ++i) { \ QDomElement item = childs.at(i).toElement(); \ map::mapped_type tmp; \ tmp.fromXml(item.firstChild()); \ name.insert(std::pair<map::key_type, map::mapped_type> ( \ QVariant(item.attributeNode("key").value()).value<map::key_type>(), \ tmp)); \ } \ } \ } \ } /* Create variable */ #define QS_DECLARE_MEMBER(type, name) \ public : \ type name = type(); /* BIND: */ /* generate serializable propertyes JSON and XML for primitive type field */ #define QS_BIND_FIELD(type, name) \ QS_XML_FIELD(type, name) /* BIND: */ /* generate serializable propertyes JSON and XML for collection of primitive type fields */ #define QS_BIND_COLLECTION(itemType, name) \ QS_XML_ARRAY(itemType, name) /* BIND: */ /* generate serializable propertyes JSON and XML for custom type object */ #define QS_BIND_OBJECT(type, name) \ QS_XML_OBJECT(type, name) /* BIND: */ /* generate serializable propertyes JSON and XML for collection of custom type objects */ #define QS_BIND_COLLECTION_OBJECTS(itemType, name) \ QS_XML_ARRAY_OBJECTS(itemType, name) \ /* BIND: */ /* generate serializable propertyes JSON and XML for dictionary with primitive value type for QT DICTIONARY TYPES */ #define QS_BIND_QT_DICT(map, name) \ QS_XML_QT_DICT(map, name) \ /* BIND: */ /* generate serializable propertyes JSON and XML for dictionary of custom type objects for QT DICTIONARY TYPES */ #define QS_BIND_QT_DICT_OBJECTS(map, name) \ QS_XML_QT_DICT_OBJECTS(map,name) \ /* BIND: */ /* generate serializable propertyes JSON and XML for dictionary with primitive value type for STL DICTIONARY TYPES */ #define QS_BIND_STL_DICT(map, name) \ QS_XML_STL_DICT(map, name) \ /* BIND: */ /* generate serializable propertyes JSON and XML for dictionary of custom type objects for STL DICTIONARY TYPES */ #define QS_BIND_STL_DICT_OBJECTS(map, name) \ QS_XML_STL_DICT_OBJECTS(map,name) \ /* CREATE AND BIND: */ /* Make primitive field and generate serializable propertyes */ /* For example: QS_FIELD(int, digit), QS_FIELD(bool, flag) */ #define QS_FIELD(type, name) \ QS_DECLARE_MEMBER(type, name) \ QS_BIND_FIELD(type, name) /* CREATE AND BIND: */ /* Make primitive field and generate serializable propertyes */ /* For example: QS_FIELD(int, digit), QS_FIELD(bool, flag) */ #define QS_FIELD(type, name) \ QS_DECLARE_MEMBER(type, name) \ QS_BIND_FIELD(type, name) \ /* CREATE AND BIND: */ /* Make collection of primitive type objects [collectionType<itemType> name] and generate serializable propertyes for this collection */ /* This collection must be provide method append(T) (it's can be QList, QVector) */ #define QS_COLLECTION(collectionType, itemType, name) \ QS_DECLARE_MEMBER(collectionType<itemType>, name) \ QS_BIND_COLLECTION(itemType, name) \ /* CREATE AND BIND: */ /* Make custom class object and bind serializable propertyes */ /* This class must be inherited from QSerializer */ #define QS_OBJECT(type,name) \ QS_DECLARE_MEMBER(type, name) \ QS_BIND_OBJECT(type, name) \ /* CREATE AND BIND: */ /* Make collection of custom class objects [collectionType<itemType> name] and bind serializable propertyes */ /* This collection must be provide method append(T) (it's can be QList, QVector) */ #define QS_COLLECTION_OBJECTS(collectionType, itemType, name) \ QS_DECLARE_MEMBER(collectionType<itemType>, name) \ QS_BIND_COLLECTION_OBJECTS(itemType, name) \
**** cModelStructure.h ****
class cModelStandardCurve_MeasureData : public cSerializer { Q_GADGET QS_SERIALIZABLE private: QS_FIELD(bool, IsChecked) // 체크박스 상태 QS_COLLECTION(QVector, qreal, vABS) // 흡광도 QS_COLLECTION(QVector, qreal, vConc) // 농도 QS_COLLECTION(QVector, qreal, vDispExp) // 차트 axis? QS_COLLECTION(QVector, qreal, vCalcExp) // 수식 }; class cModelStandardCurve : public cModelCommon { Q_GADGET QS_SERIALIZABLE QS_FIELD(int, nFactor) // 희석배수 QS_FIELD(int, nSTCType) // STC 타입 QS_FIELD(int, nRSQ) // RSQ QS_OBJECT(cModelStandardCurve_MeasureData, cSTC_MeasureData) // 측정결과 QS_OBJECT(cReportOption, cSTC_Reportopt) // 리포트옵션 }; class cModelQuantitation_MeasureData : public cSerializer { Q_GADGET QS_SERIALIZABLE QS_FIELD(bool, IsChecked) // 체크박스 상태 QS_COLLECTION(QVector, qreal, vConc) // 농도 QS_COLLECTION(QVector, qreal, vTRA) // 투과율 QS_COLLECTION(QVector, qreal, vABS) // 흡광도 QS_COLLECTION(QVector, QString, vCellNumber) // 셀번호 QS_FIELD(QString, strSampleName) // 샘플명 QS_FIELD(double, strTemperature) // 온도 }; class cModelQuantitation : public cModelCommon { Q_GADGET QS_SERIALIZABLE QS_OBJECT(cModelQuantitation_MeasureData, cMeasureData) // 측정결과 QS_OBJECT(cReportOption, cReportopt) // 리포트옵션 QS_OBJECT(cModelStandardCurve, cStandardCurve) // STC정보 }; void cSerializer::fromXml(const QDomNode& val) { QDomNode doc = val; const char* className = metaObject()->className(); auto n = doc.firstChildElement(metaObject()->className()); qDebug() << QString("******* %1 *******").arg(className); if (!n.isNull()) { // for (int i = 0; i < metaObject()->propertyCount(); i++) { QDomElement tmp = metaObject()->property(i).readOnGadget(this).value<QDomNode>().firstChildElement(); auto f = n.firstChildElement(tmp.tagName()); qDebug() << QString("%1: %2").arg(tmp.tagName()).arg(f.text().toUtf8().constData()); metaObject()->property(i).writeOnGadget(this, QVariant::fromValue<QDomNode>(f)); } } else { for (int i = 0; i < metaObject()->propertyCount(); i++) { QString name = metaObject()->property(i).name(); auto f = doc.firstChildElement(name); qDebug() << QString("%1: %2").arg(name).arg(f.text().toUtf8().constData()); QString str = f.text(); if (str.isNull()) continue; metaObject()->property(i).writeOnGadget(this, QVariant::fromValue<QDomNode>(f)); } } }
-
https://github.com/smurfomen/QSerializer
The source code can be obtained here.