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#include <algorithm>
24
25static constexpr const char* XMLPLIST_SERIALIZER_VERSION { "1.0" };
26
27void XmlPListSerializer::BeginSerialize(QString &/*sName*/)
28{
29 m_pXmlWriter->setAutoFormatting(true);
30 m_pXmlWriter->setAutoFormattingIndent(4);
31 m_pXmlWriter->writeStartDocument("1.0");
32 m_pXmlWriter->writeDTD(R"(<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">)");
33 m_pXmlWriter->writeStartElement("plist");
34 m_pXmlWriter->writeAttribute("version", "1.0");
35 m_pXmlWriter->writeStartElement("dict"); // top level node
36}
37
39{
40 m_pXmlWriter->writeEndElement(); // "dict"
41 m_pXmlWriter->writeEndElement(); // "plist"
42 m_pXmlWriter->writeEndDocument();
43}
44
46{
47 return "text/x-apple-plist+xml";
48}
49
50void XmlPListSerializer::RenderValue(const QString &sName,
51 const QVariant &vValue,
52 bool needKey)
53{
54 if ( vValue.canConvert<QObject*>())
55 {
56 const QObject *pObject = vValue.value<QObject*>();
57 SerializePListObjectProperties(sName, pObject, needKey);
58 return;
59 }
60
61#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
62 auto type = static_cast<QMetaType::Type>(vValue.type());
63#else
64 auto type = vValue.typeId();
65#endif
66 switch( type )
67 {
68 case QMetaType::QVariantList:
69 {
70 RenderList(sName, vValue.toList());
71 break;
72 }
73
74 case QMetaType::QStringList:
75 {
76 RenderStringList(sName, vValue.toStringList());
77 break;
78 }
79
80 case QMetaType::QVariantMap:
81 {
82 RenderMap(sName, vValue.toMap());
83 break;
84 }
85
86 case QMetaType::QDateTime:
87 {
88 if (vValue.toDateTime().isValid())
89 {
90 if (needKey)
91 m_pXmlWriter->writeTextElement("key", sName);
92 m_pXmlWriter->writeTextElement("date", vValue.toDateTime()
93 .toUTC().toString("yyyy-MM-ddThh:mm:ssZ"));
94 }
95 break;
96 }
97
98 case QMetaType::QByteArray:
99 {
100 if (!vValue.toByteArray().isNull())
101 {
102 if (needKey)
103 m_pXmlWriter->writeTextElement("key", sName);
104 m_pXmlWriter->writeTextElement("data",
105 vValue.toByteArray().toBase64().data());
106 }
107 break;
108 }
109
110 case QMetaType::Bool:
111 {
112 if (needKey)
113 m_pXmlWriter->writeTextElement("key", sName);
114 m_pXmlWriter->writeEmptyElement(vValue.toBool() ?
115 "true" : "false");
116 break;
117 }
118
119 case QMetaType::UInt:
120 case QMetaType::ULongLong:
121 {
122 if (needKey)
123 m_pXmlWriter->writeTextElement("key", sName);
124 m_pXmlWriter->writeTextElement("integer",
125 QString::number(vValue.toULongLong()));
126 break;
127 }
128
129 case QMetaType::Int:
130 case QMetaType::LongLong:
131 case QMetaType::Double:
132 {
133 if (needKey)
134 m_pXmlWriter->writeTextElement("key", sName);
135 m_pXmlWriter->writeTextElement("real",
136 QString("%1").arg(vValue.toDouble(), 0, 'f', 6));
137 break;
138 }
139
140 // anything else will be unrecognised, so wrap in a string
141 case QMetaType::QString:
142 default:
143 {
144 if (needKey)
145 m_pXmlWriter->writeTextElement("key", sName);
146 m_pXmlWriter->writeTextElement("string", vValue.toString());
147 break;
148 }
149 }
150}
151
152void XmlPListSerializer::RenderList(const QString &sName,
153 const QVariantList &list)
154{
155 bool array = true;
156 if (!list.isEmpty())
157 {
158#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
159 auto t = static_cast<QMetaType::Type>(list[0].type());
160 array = std::ranges::all_of(std::as_const(list),
161 [t](const QVariant& v)
162 { return t == static_cast<QMetaType::Type>(v.type()); } );
163#else
164 auto t = list[0].typeId();
165 array = std::ranges::all_of(std::as_const(list),
166 [t](const QVariant& v) { return t == v.typeId(); } );
167#endif
168 }
169
170 QString sItemName = GetItemName(sName);
171 m_pXmlWriter->writeTextElement("key", sName);
172 m_pXmlWriter->writeStartElement(array ? "array" : "dict");
173
174 for (const auto& variant : list)
175 RenderValue(sItemName, variant, !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 for (const QString& str : list)
187 m_pXmlWriter->writeTextElement("string", str);
188
189 m_pXmlWriter->writeEndElement();
190}
191
192void XmlPListSerializer::RenderMap(const QString &sName,
193 const QVariantMap &map)
194{
195 QString sItemName = GetItemName(sName);
196 m_pXmlWriter->writeTextElement("key", sItemName);
197 m_pXmlWriter->writeStartElement("dict");
198
199 for (auto it = map.cbegin(); it != map.cend(); ++it)
200 RenderValue(it.key(), it.value());
201
202 m_pXmlWriter->writeEndElement();
203}
204
205void XmlPListSerializer::BeginObject(const QString &sName,
206 const QObject *pObject)
207{
208 const QMetaObject *pMeta = pObject->metaObject();
209
210 int nIdx = -1;
211
212 if (pMeta)
213 nIdx = pMeta->indexOfClassInfo("version");
214
215 if (nIdx >=0)
216 {
217 m_pXmlWriter->writeTextElement("key", "version");
218 m_pXmlWriter->writeTextElement("string", pMeta->classInfo(nIdx).value());
219 }
220
221 m_pXmlWriter->writeTextElement("key", "serializerversion");
222 m_pXmlWriter->writeTextElement("string", XMLPLIST_SERIALIZER_VERSION);
223
224 m_pXmlWriter->writeTextElement("key", sName);
225 m_pXmlWriter->writeStartElement("dict");
226}
227
228void XmlPListSerializer::EndObject(const QString &/*sName*/,
229 const QObject */*pObject*/)
230{
231 m_pXmlWriter->writeEndElement(); // dict
232}
233
234void XmlPListSerializer::AddProperty(const QString &sName,
235 const QVariant &vValue,
236 const QMetaObject */*pMetaParent*/,
237 const QMetaProperty */*pMetaProp*/)
238{
239 RenderValue(sName, vValue);
240}
241
243 const QObject *pObject,
244 bool needKey )
245{
246 if (!pObject)
247 return;
248
249 if (needKey)
250 {
251 QString sItemName = GetItemName(sName);
252 m_pXmlWriter->writeTextElement("key", sItemName);
253 }
254 m_pXmlWriter->writeStartElement("dict");
255
256 const QMetaObject *pMetaObject = pObject->metaObject();
257
258 int nCount = pMetaObject->propertyCount();
259
260 for (int nIdx=0; nIdx < nCount; ++nIdx)
261 {
262 QMetaProperty metaProperty = pMetaObject->property(nIdx);
263
264 if (metaProperty.isDesignable())
265 {
266 const char *pszPropName = metaProperty.name();
267 QString sPropName(pszPropName);
268
269 if (sPropName.compare("objectName") == 0)
270 continue;
271
272 QVariant value(pObject->property(pszPropName));
273
274 AddProperty(sPropName, value, pMetaObject, &metaProperty);
275 }
276 }
277
278 m_pXmlWriter->writeEndElement();
279}
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