MythTV master
xmlplistSerializer.cpp
Go to the documentation of this file.
1/* Class XmlPListSerializer
2*
3* Copyright (C) Mark Kendall 2012
4*
5* This program is free software; you can redistribute it and/or modify
6* it under the terms of the GNU General Public License as published by
7* the Free Software Foundation; either version 2 of the License, or
8* (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with this program; if not, write to the Free Software
17* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18*/
19#include "xmlplistSerializer.h"
20
21#include <QMetaClassInfo>
22#include <QDateTime>
23
24static constexpr const char* XMLPLIST_SERIALIZER_VERSION { "1.0" };
25
26void XmlPListSerializer::BeginSerialize(QString &/*sName*/)
27{
28 m_pXmlWriter->setAutoFormatting(true);
29 m_pXmlWriter->setAutoFormattingIndent(4);
30 m_pXmlWriter->writeStartDocument("1.0");
31 m_pXmlWriter->writeDTD(R"(<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">)");
32 m_pXmlWriter->writeStartElement("plist");
33 m_pXmlWriter->writeAttribute("version", "1.0");
34 m_pXmlWriter->writeStartElement("dict"); // top level node
35}
36
38{
39 m_pXmlWriter->writeEndElement(); // "dict"
40 m_pXmlWriter->writeEndElement(); // "plist"
41 m_pXmlWriter->writeEndDocument();
42}
43
45{
46 return "text/x-apple-plist+xml";
47}
48
49void XmlPListSerializer::RenderValue(const QString &sName,
50 const QVariant &vValue,
51 bool needKey)
52{
53 if ( vValue.canConvert<QObject*>())
54 {
55 const QObject *pObject = vValue.value<QObject*>();
56 SerializePListObjectProperties(sName, pObject, needKey);
57 return;
58 }
59
60#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
61 auto type = static_cast<QMetaType::Type>(vValue.type());
62#else
63 auto type = vValue.typeId();
64#endif
65 switch( type )
66 {
67 case QMetaType::QVariantList:
68 {
69 RenderList(sName, vValue.toList());
70 break;
71 }
72
73 case QMetaType::QStringList:
74 {
75 RenderStringList(sName, vValue.toStringList());
76 break;
77 }
78
79 case QMetaType::QVariantMap:
80 {
81 RenderMap(sName, vValue.toMap());
82 break;
83 }
84
85 case QMetaType::QDateTime:
86 {
87 if (vValue.toDateTime().isValid())
88 {
89 if (needKey)
90 m_pXmlWriter->writeTextElement("key", sName);
91 m_pXmlWriter->writeTextElement("date", vValue.toDateTime()
92 .toUTC().toString("yyyy-MM-ddThh:mm:ssZ"));
93 }
94 break;
95 }
96
97 case QMetaType::QByteArray:
98 {
99 if (!vValue.toByteArray().isNull())
100 {
101 if (needKey)
102 m_pXmlWriter->writeTextElement("key", sName);
103 m_pXmlWriter->writeTextElement("data",
104 vValue.toByteArray().toBase64().data());
105 }
106 break;
107 }
108
109 case QMetaType::Bool:
110 {
111 if (needKey)
112 m_pXmlWriter->writeTextElement("key", sName);
113 m_pXmlWriter->writeEmptyElement(vValue.toBool() ?
114 "true" : "false");
115 break;
116 }
117
118 case QMetaType::UInt:
119 case QMetaType::ULongLong:
120 {
121 if (needKey)
122 m_pXmlWriter->writeTextElement("key", sName);
123 m_pXmlWriter->writeTextElement("integer",
124 QString::number(vValue.toULongLong()));
125 break;
126 }
127
128 case QMetaType::Int:
129 case QMetaType::LongLong:
130 case QMetaType::Double:
131 {
132 if (needKey)
133 m_pXmlWriter->writeTextElement("key", sName);
134 m_pXmlWriter->writeTextElement("real",
135 QString("%1").arg(vValue.toDouble(), 0, 'f', 6));
136 break;
137 }
138
139 // anything else will be unrecognised, so wrap in a string
140 case QMetaType::QString:
141 default:
142 {
143 if (needKey)
144 m_pXmlWriter->writeTextElement("key", sName);
145 m_pXmlWriter->writeTextElement("string", vValue.toString());
146 break;
147 }
148 }
149}
150
151void XmlPListSerializer::RenderList(const QString &sName,
152 const QVariantList &list)
153{
154 bool array = true;
155 if (!list.isEmpty())
156 {
157#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
158 auto t = static_cast<QMetaType::Type>(list[0].type());
159 array = std::all_of(list.cbegin(), list.cend(),
160 [t](const QVariant& v)
161 { return t == static_cast<QMetaType::Type>(v.type()); } );
162#else
163 auto t = list[0].typeId();
164 array = std::all_of(list.cbegin(), list.cend(),
165 [t](const QVariant& v) { return t == v.typeId(); } );
166#endif
167 }
168
169 QString sItemName = GetItemName(sName);
170 m_pXmlWriter->writeTextElement("key", sName);
171 m_pXmlWriter->writeStartElement(array ? "array" : "dict");
172
173 QListIterator<QVariant> it(list);
174 while (it.hasNext())
175 RenderValue(sItemName, it.next(), !array);
176
177 m_pXmlWriter->writeEndElement();
178}
179
180void XmlPListSerializer::RenderStringList(const QString &sName,
181 const QStringList &list)
182{
183 m_pXmlWriter->writeTextElement("key", sName);
184 m_pXmlWriter->writeStartElement("array");
185
186 QListIterator<QString> it(list);
187 while (it.hasNext())
188 m_pXmlWriter->writeTextElement("string", it.next());
189
190 m_pXmlWriter->writeEndElement();
191}
192
193void XmlPListSerializer::RenderMap(const QString &sName,
194 const QVariantMap &map)
195{
196 QString sItemName = GetItemName(sName);
197 m_pXmlWriter->writeTextElement("key", sItemName);
198 m_pXmlWriter->writeStartElement("dict");
199
200 QMapIterator<QString,QVariant> it(map);
201 while (it.hasNext())
202 {
203 it.next();
204 RenderValue(it.key(), it.value());
205 }
206
207 m_pXmlWriter->writeEndElement();
208}
209
210void XmlPListSerializer::BeginObject(const QString &sName,
211 const QObject *pObject)
212{
213 const QMetaObject *pMeta = pObject->metaObject();
214
215 int nIdx = -1;
216
217 if (pMeta)
218 nIdx = pMeta->indexOfClassInfo("version");
219
220 if (nIdx >=0)
221 {
222 m_pXmlWriter->writeTextElement("key", "version");
223 m_pXmlWriter->writeTextElement("string", pMeta->classInfo(nIdx).value());
224 }
225
226 m_pXmlWriter->writeTextElement("key", "serializerversion");
227 m_pXmlWriter->writeTextElement("string", XMLPLIST_SERIALIZER_VERSION);
228
229 m_pXmlWriter->writeTextElement("key", sName);
230 m_pXmlWriter->writeStartElement("dict");
231}
232
233void XmlPListSerializer::EndObject(const QString &/*sName*/,
234 const QObject */*pObject*/)
235{
236 m_pXmlWriter->writeEndElement(); // dict
237}
238
239void XmlPListSerializer::AddProperty(const QString &sName,
240 const QVariant &vValue,
241 const QMetaObject */*pMetaParent*/,
242 const QMetaProperty */*pMetaProp*/)
243{
244 RenderValue(sName, vValue);
245}
246
248 const QObject *pObject,
249 bool needKey )
250{
251 if (!pObject)
252 return;
253
254 if (needKey)
255 {
256 QString sItemName = GetItemName(sName);
257 m_pXmlWriter->writeTextElement("key", sItemName);
258 }
259 m_pXmlWriter->writeStartElement("dict");
260
261 const QMetaObject *pMetaObject = pObject->metaObject();
262
263 int nCount = pMetaObject->propertyCount();
264
265 for (int nIdx=0; nIdx < nCount; ++nIdx)
266 {
267 QMetaProperty metaProperty = pMetaObject->property(nIdx);
268
269 if (metaProperty.isDesignable())
270 {
271 const char *pszPropName = metaProperty.name();
272 QString sPropName(pszPropName);
273
274 if (sPropName.compare("objectName") == 0)
275 continue;
276
277 QVariant value(pObject->property(pszPropName));
278
279 AddProperty(sPropName, value, pMetaObject, &metaProperty);
280 }
281 }
282
283 m_pXmlWriter->writeEndElement();
284}
void RenderStringList(const QString &sName, const QStringList &list)
void BeginSerialize(QString &sName) override
void RenderValue(const QString &sName, const QVariant &vValue, bool needKey=true)
void SerializePListObjectProperties(const QString &sName, const QObject *pObject, bool needKey)
void RenderMap(const QString &sName, const QVariantMap &map)
void EndSerialize() override
void EndObject(const QString &sName, const QObject *pObject) override
void BeginObject(const QString &sName, const QObject *pObject) override
void RenderList(const QString &sName, const QVariantList &list)
void AddProperty(const QString &sName, const QVariant &vValue, const QMetaObject *pMetaParent, const QMetaProperty *pMetaProp) override
QString GetContentType() override
QXmlStreamWriter * m_pXmlWriter
Definition: xmlSerializer.h:37
static QString GetItemName(const QString &sName)
static constexpr const char * XMLPLIST_SERIALIZER_VERSION