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 
20 #include <QMetaClassInfo>
21 #include <QDateTime>
22 
23 #include "xmlplistSerializer.h"
24 
25 static constexpr const char* XMLPLIST_SERIALIZER_VERSION { "1.0" };
26 
27 void 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 
50 void 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 
152 void 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::all_of(list.cbegin(), list.cend(),
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::all_of(list.cbegin(), list.cend(),
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  QListIterator<QVariant> it(list);
175  while (it.hasNext())
176  RenderValue(sItemName, it.next(), !array);
177 
178  m_pXmlWriter->writeEndElement();
179 }
180 
181 void XmlPListSerializer::RenderStringList(const QString &sName,
182  const QStringList &list)
183 {
184  m_pXmlWriter->writeTextElement("key", sName);
185  m_pXmlWriter->writeStartElement("array");
186 
187  QListIterator<QString> it(list);
188  while (it.hasNext())
189  m_pXmlWriter->writeTextElement("string", it.next());
190 
191  m_pXmlWriter->writeEndElement();
192 }
193 
194 void XmlPListSerializer::RenderMap(const QString &sName,
195  const QVariantMap &map)
196 {
197  QString sItemName = GetItemName(sName);
198  m_pXmlWriter->writeTextElement("key", sItemName);
199  m_pXmlWriter->writeStartElement("dict");
200 
201  QMapIterator<QString,QVariant> it(map);
202  while (it.hasNext())
203  {
204  it.next();
205  RenderValue(it.key(), it.value());
206  }
207 
208  m_pXmlWriter->writeEndElement();
209 }
210 
211 void XmlPListSerializer::BeginObject(const QString &sName,
212  const QObject *pObject)
213 {
214  const QMetaObject *pMeta = pObject->metaObject();
215 
216  int nIdx = -1;
217 
218  if (pMeta)
219  nIdx = pMeta->indexOfClassInfo("version");
220 
221  if (nIdx >=0)
222  {
223  m_pXmlWriter->writeTextElement("key", "version");
224  m_pXmlWriter->writeTextElement("string", pMeta->classInfo(nIdx).value());
225  }
226 
227  m_pXmlWriter->writeTextElement("key", "serializerversion");
228  m_pXmlWriter->writeTextElement("string", XMLPLIST_SERIALIZER_VERSION);
229 
230  m_pXmlWriter->writeTextElement("key", sName);
231  m_pXmlWriter->writeStartElement("dict");
232 }
233 
234 void XmlPListSerializer::EndObject(const QString &/*sName*/,
235  const QObject */*pObject*/)
236 {
237  m_pXmlWriter->writeEndElement(); // dict
238 }
239 
240 void XmlPListSerializer::AddProperty(const QString &sName,
241  const QVariant &vValue,
242  const QMetaObject */*pMetaParent*/,
243  const QMetaProperty */*pMetaProp*/)
244 {
245  RenderValue(sName, vValue);
246 }
247 
249  const QObject *pObject,
250  bool needKey )
251 {
252  if (!pObject)
253  return;
254 
255  if (needKey)
256  {
257  QString sItemName = GetItemName(sName);
258  m_pXmlWriter->writeTextElement("key", sItemName);
259  }
260  m_pXmlWriter->writeStartElement("dict");
261 
262  const QMetaObject *pMetaObject = pObject->metaObject();
263 
264  int nCount = pMetaObject->propertyCount();
265 
266  for (int nIdx=0; nIdx < nCount; ++nIdx)
267  {
268  QMetaProperty metaProperty = pMetaObject->property(nIdx);
269 
270  if (metaProperty.isDesignable())
271  {
272  const char *pszPropName = metaProperty.name();
273  QString sPropName(pszPropName);
274 
275  if (sPropName.compare("objectName") == 0)
276  continue;
277 
278  QVariant value(pObject->property(pszPropName));
279 
280  AddProperty(sPropName, value, pMetaObject, &metaProperty);
281  }
282  }
283 
284  m_pXmlWriter->writeEndElement();
285 }
XmlSerializer::m_pXmlWriter
QXmlStreamWriter * m_pXmlWriter
Definition: xmlSerializer.h:37
XmlSerializer::GetItemName
static QString GetItemName(const QString &sName)
Definition: xmlSerializer.cpp:309
XmlPListSerializer::BeginObject
void BeginObject(const QString &sName, const QObject *pObject) override
Definition: xmlplistSerializer.cpp:211
XmlPListSerializer::EndSerialize
void EndSerialize() override
Definition: xmlplistSerializer.cpp:38
XmlPListSerializer::SerializePListObjectProperties
void SerializePListObjectProperties(const QString &sName, const QObject *pObject, bool needKey)
Definition: xmlplistSerializer.cpp:248
XmlPListSerializer::RenderList
void RenderList(const QString &sName, const QVariantList &list)
Definition: xmlplistSerializer.cpp:152
XMLPLIST_SERIALIZER_VERSION
static constexpr const char * XMLPLIST_SERIALIZER_VERSION
Definition: xmlplistSerializer.cpp:25
XmlPListSerializer::AddProperty
void AddProperty(const QString &sName, const QVariant &vValue, const QMetaObject *pMetaParent, const QMetaProperty *pMetaProp) override
Definition: xmlplistSerializer.cpp:240
hardwareprofile.i18n.t
t
Definition: i18n.py:36
XmlPListSerializer::RenderStringList
void RenderStringList(const QString &sName, const QStringList &list)
Definition: xmlplistSerializer.cpp:181
XmlPListSerializer::EndObject
void EndObject(const QString &sName, const QObject *pObject) override
Definition: xmlplistSerializer.cpp:234
XmlPListSerializer::BeginSerialize
void BeginSerialize(QString &sName) override
Definition: xmlplistSerializer.cpp:27
xmlplistSerializer.h
XmlPListSerializer::GetContentType
QString GetContentType() override
Definition: xmlplistSerializer.cpp:45
XmlPListSerializer::RenderMap
void RenderMap(const QString &sName, const QVariantMap &map)
Definition: xmlplistSerializer.cpp:194
XmlPListSerializer::RenderValue
void RenderValue(const QString &sName, const QVariant &vValue, bool needKey=true)
Definition: xmlplistSerializer.cpp:50