MythTV master
mythxmlserialiser.cpp
Go to the documentation of this file.
1// Qt
2#include <QMetaProperty>
3#include <QSequentialIterable>
4
5// MythTV
6#include "mythdate.h"
7#include "http/mythhttpdata.h"
9
10MythXMLSerialiser::MythXMLSerialiser(const QString& Name, const QVariant& Value)
11{
12 m_writer.setDevice(&m_buffer);
13 m_writer.writeStartDocument("1.0");
14 QString name = Name;
15 if (name.startsWith("V2"))
16 name.remove(0,2);
17 AddObject(name, Value);
18 m_writer.writeEndDocument();
19}
20
21void MythXMLSerialiser::AddObject(const QString& Name, const QVariant& Value)
22{
23 m_writer.writeStartElement(Name);
24 if (m_first)
25 {
26 m_writer.writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
27 m_writer.writeAttribute("serializerVersion", XML_SERIALIZER_VERSION);
28 m_first = false;
29 }
30 auto * object = Value.value<QObject*>();
31 AddValue(object ? GetContentName(Name, object->metaObject()) : Name, Value);
32 m_writer.writeEndElement();
33}
34
35void MythXMLSerialiser::AddValue(const QString& Name, const QVariant& Value)
36{
37 if (Value.isNull() || !Value.isValid())
38 {
39 m_writer.writeAttribute("xsi:nil", "true");
40 return;
41 }
42
43 auto * object = Value.value<QObject*>();
44 if (object)
45 {
46 QVariant isNull = object->property("isNull");
47 if (isNull.value<bool>())
48 return;
49 AddQObject(object);
50 return;
51 }
52
53 switch (
54#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
55 static_cast<QMetaType::Type>(Value.type())
56#else
57 static_cast<QMetaType::Type>(Value.typeId())
58#endif
59 )
60 {
61 case QMetaType::QStringList: AddStringList(Value); break;
62 case QMetaType::QVariantList: AddList(Name, Value); break;
63 case QMetaType::QVariantMap: AddMap(Name, Value.toMap()); break;
64 case QMetaType::QDateTime:
65 {
66 QDateTime dt(Value.toDateTime());
67 if (dt.isNull())
68 m_writer.writeAttribute("xsi:nil", "true");
69 else
70 m_writer.writeCharacters(MythDate::toString(dt, MythDate::ISODate));
71 }
72 break;
73 case QMetaType::Double:
74 m_writer.writeCharacters(QString::number(Value.toDouble(),'f',6));
75 break;
76 case QMetaType::Float:
77 m_writer.writeCharacters(QString::number(Value.toFloat(),'f',6));
78 break;
79 default:
80 m_writer.writeCharacters(Value.toString());
81 }
82}
83
84void MythXMLSerialiser::AddQObject(const QObject* Object)
85{
86 if (!Object)
87 return;
88
89 const auto * meta = Object->metaObject();
90 if (int index = meta->indexOfClassInfo("Version"); index >= 0)
91 m_writer.writeAttribute("version", meta->classInfo(index).value());
92
93 int count = meta->propertyCount();
94 for (int index = 0; index < count; ++index )
95 {
96 QMetaProperty metaproperty = meta->property(index);
97 if (
98#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
99 metaproperty.isUser(Object)
100#else
101 metaproperty.isUser()
102#endif
103 )
104 {
105 const char *rawname = metaproperty.name();
106 QString name(rawname);
107 if (name.compare("objectName") == 0)
108 continue;
109 QVariant value(Object->property(rawname));
110 m_writer.writeStartElement(name);
111 AddProperty(name, value, meta, &metaproperty);
112 m_writer.writeEndElement();
113 }
114 }
115}
116
117void MythXMLSerialiser::AddProperty(const QString& Name, const QVariant& Value,
118 const QMetaObject* MetaObject, const QMetaProperty *MetaProperty)
119{
120 // Enum ?
121 if (MetaProperty && (MetaProperty->isEnumType() || MetaProperty->isFlagType()))
122 {
123 QMetaEnum metaEnum = MetaProperty->enumerator();
124 QString value = MetaProperty->isFlagType() ? metaEnum.valueToKeys(Value.toInt()).constData() :
125 metaEnum.valueToKey(Value.toInt());
126 // If couldn't convert to enum name, return raw value
127 m_writer.writeCharacters(value.isEmpty() ? Value.toString() : value);
128 return;
129 }
130
131 AddValue(GetContentName(Name, MetaObject), Value);
132}
133
134void MythXMLSerialiser::AddStringList(const QVariant& Values)
135{
136 auto values = Values.value<QSequentialIterable>();
137 for (const auto & value : values)
138 {
139 m_writer.writeStartElement("String");
140 m_writer.writeCharacters(value.toString());
141 m_writer.writeEndElement();
142 }
143}
144
145void MythXMLSerialiser::AddList(const QString& Name, const QVariant& Values)
146{
147 auto values = Values.value<QSequentialIterable>();
148 for (const auto & value : values)
149 {
150 m_writer.writeStartElement(Name);
151 AddValue(Name, value);
152 m_writer.writeEndElement();
153 }
154}
155
156void MythXMLSerialiser::AddMap(const QString& Name, const QVariantMap& Map)
157{
158 QString itemname = GetItemName(Name);
159 for (auto it = Map.cbegin(); it != Map.cend(); ++it)
160 {
161 m_writer.writeStartElement(itemname);
162 m_writer.writeStartElement("Key");
163 m_writer.writeCharacters(it.key());
164 m_writer.writeEndElement();
165 m_writer.writeStartElement("Value");
166 AddValue(itemname, it.value());
167 m_writer.writeEndElement();
168 m_writer.writeEndElement();
169 }
170}
171
173{
174 QString name = Name.startsWith("Q") ? Name.mid(1) : Name;
175 if (name.startsWith("V2"))
176 name.remove(0,2);
177 name.remove(QChar('*'));
178 return name;
179}
180
182QString MythXMLSerialiser::GetContentName(const QString& Name, const QMetaObject* MetaObject)
183{
184 // Try to read Name or TypeName from classinfo metadata.
185 if (int index = MetaObject ? MetaObject->indexOfClassInfo(Name.toLatin1()) : -1; index >= 0)
186 {
187 QStringList infos = QString(MetaObject->classInfo(index).value()).split(';', Qt::SkipEmptyParts);
188 QString type; // fallback
189 foreach (const QString &info, infos)
190 {
191 if (info.startsWith(QStringLiteral("name=")))
192 if (auto name = info.mid(5).trimmed(); !name.isEmpty())
193 return GetItemName(name);
194 if (info.startsWith(QStringLiteral("type=")))
195 type = info.mid(5).trimmed();
196 }
197 if (!type.isEmpty())
198 return GetItemName(type);
199 }
200
201 // Neither found, so lets use the type name (slightly modified).
202 return GetItemName(Name);
203}
MythXMLSerialiser(const QString &Name, const QVariant &Value)
static QString GetContentName(const QString &Name, const QMetaObject *MetaObject)
FIXME We shouldn't be doing this on the fly.
void AddStringList(const QVariant &Values)
void AddQObject(const QObject *Object)
void AddMap(const QString &Name, const QVariantMap &Map)
void AddObject(const QString &Name, const QVariant &Value)
void AddValue(const QString &Name, const QVariant &Value)
QXmlStreamWriter m_writer
void AddProperty(const QString &Name, const QVariant &Value, const QMetaObject *MetaObject, const QMetaProperty *MetaProperty)
static QString GetItemName(const QString &Name)
void AddList(const QString &Name, const QVariant &Values)
#define XML_SERIALIZER_VERSION
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
@ ISODate
Default UTC.
Definition: mythdate.h:17
dictionary info
Definition: azlyrics.py:7