6#include <QMetaProperty>
7#if QT_VERSION < QT_VERSION_CHECK(6,11,0)
8#include <QSequentialIterable>
10#include <QMetaSequence>
24 m_writer.writeDTD(R
"(<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">)");
26 m_writer.writeAttribute(
"version",
"1.0");
28 m_writer.writeTextElement(
"key",
"serializerversion");
31 if (name.startsWith(
"V2"))
41 auto *
object = Value.value<QObject*>();
47 auto *
object = Value.value<QObject*>();
50 QVariant isNull =
object->property(
"isNull");
58#
if QT_VERSION < QT_VERSION_CHECK(6,0,0)
59 static_cast<QMetaType::Type
>(Value.type())
61 static_cast<QMetaType::Type
>(Value.typeId())
66 case QMetaType::QVariantList:
AddList(
Name, Value.toList());
break;
67 case QMetaType::QVariantMap:
AddMap(
Name, Value.toMap());
break;
69 case QMetaType::ULongLong:
73 m_writer.writeTextElement(
"integer", QString::number(Value.toULongLong()));
78 case QMetaType::LongLong:
79 case QMetaType::Double:
83 m_writer.writeTextElement(
"real", QString(
"%1").arg(Value.toDouble(), 0,
'f', 6));
86 case QMetaType::Float:
90 m_writer.writeTextElement(
"real", QString(
"%1").arg(Value.toFloat(), 0,
'f', 6));
93 case QMetaType::QByteArray:
95 if (!Value.toByteArray().isNull())
99 m_writer.writeTextElement(
"data", Value.toByteArray().toBase64().data());
103 case QMetaType::Bool:
107 m_writer.writeEmptyElement(Value.toBool() ?
"true" :
"false");
110 case QMetaType::QDateTime:
111 if (Value.toDateTime().isValid())
115 m_writer.writeTextElement(
"date", Value.toDateTime().toUTC().toString(
"yyyy-MM-ddThh:mm:ssZ"));
118 case QMetaType::QString:
122 m_writer.writeTextElement(
"string", Value.toString());
134 const auto * meta = Object->metaObject();
135 if (
int index = meta->indexOfClassInfo(
"Version"); index >= 0)
137 m_writer.writeTextElement(
"key",
"version");
138 m_writer.writeTextElement(
"string", meta->classInfo(index).value());
141 int count = meta->propertyCount();
142 for (
int index = 0; index < count; ++index )
144 QMetaProperty metaproperty = meta->property(index);
146#
if QT_VERSION < QT_VERSION_CHECK(6,0,0)
147 metaproperty.isUser(Object)
149 metaproperty.isUser()
153 const char *rawname = metaproperty.name();
154 QString name(rawname);
155 if (name.compare(
"objectName") == 0)
157 AddProperty(name, Object->property(rawname), meta, &metaproperty);
165 const QMetaObject* MetaObject,
const QMetaProperty *MetaProperty)
169 if (MetaProperty && (MetaProperty->isEnumType() || MetaProperty->isFlagType()))
171 QMetaEnum metaEnum = MetaProperty->enumerator();
172 value = MetaProperty->isFlagType() ? metaEnum.valueToKeys(Value.toInt()).constData() :
173 metaEnum.valueToKey(Value.toInt());
181 m_writer.writeStartElement(
"array");
182#if QT_VERSION < QT_VERSION_CHECK(6,11,0)
183 auto values = Values.value<QSequentialIterable>();
185 auto values = Values.value<QMetaSequence::Iterable>();
187 for (
const auto & value : values)
188 m_writer.writeTextElement(
"string", value.toString());
195 if (!Values.isEmpty())
197#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
198 auto type =
static_cast<QMetaType::Type
>(Values.front().type());
199 auto typesEqual = [
type](
const QVariant& value)
200 {
return (
static_cast<QMetaType::Type
>(value.type()) ==
type); };
202 auto type =
static_cast<QMetaType::Type
>(Values.front().typeId());
203 auto typesEqual = [
type](
const QVariant& value)
204 {
return (
static_cast<QMetaType::Type
>(value.typeId()) ==
type); };
206 array = std::ranges::all_of(std::as_const(Values), typesEqual);
210 m_writer.writeTextElement(
"key", name);
211 m_writer.writeStartElement(array ?
"array" :
"dict");
213 for (
const auto& variant : Values)
221 m_writer.writeTextElement(
"key", itemname);
223 for (
auto it = Map.cbegin(); it != Map.cend(); ++it)
230 QString name =
Name.startsWith(
"Q") ?
Name.mid(1) :
Name;
231 name.remove(
"DTC::");
232 if (name.startsWith(
"V2"))
234 name.remove(QChar(
'*'));
242 if (
int index = MetaObject ? MetaObject->indexOfClassInfo(
Name.toLatin1().constData()) : -1; index >= 0)
244 QStringList infos = QString(MetaObject->classInfo(index).value()).split(
';', Qt::SkipEmptyParts);
246 for (
const QString &
info : std::as_const(infos))
248 if (
info.startsWith(QStringLiteral(
"name=")))
249 if (
auto name =
info.mid(5).trimmed(); !name.isEmpty())
251 if (
info.startsWith(QStringLiteral(
"type=")))
void AddProperty(const QString &Name, const QVariant &Value, const QMetaObject *MetaObject, const QMetaProperty *MetaProperty)
static QString GetItemName(const QString &Name)
void AddStringList(const QString &Name, const QVariant &Values)
void AddList(const QString &Name, const QVariantList &Values)
void AddQObject(const QString &Name, const QObject *Object)
void AddObject(const QString &Name, const QVariant &Value)
MythXMLPListSerialiser(const QString &Name, const QVariant &Value)
void AddValue(const QString &Name, const QVariant &Value, bool NeedKey=true)
static QString GetContentName(const QString &Name, const QMetaObject *MetaObject)
FIXME We shouldn't be doing this on the fly.
QXmlStreamWriter m_writer
void AddMap(const QString &Name, const QVariantMap &Map)
#define XML_PLIST_SERIALIZER_VERSION