Commit f0dafc13 authored by Wouter's avatar Wouter

QVariant conversions

Lists now changed to QList<> subclasses to allow this. All the others
also implemented. Basic tests seem to show it works.
parent f5aa65ba
......@@ -6,4 +6,32 @@
*/{% with class.itemType.type as type %}{% include "typedeclaration.inc" %}{% endwith %}
{% endif %}
typedef QList<{{ class.itemType.signature }}> {{ class.className }};
class {{ class.className }}: public QList<{{ class.itemType.signature }}>
{
public:
{{ class.className }}()
: QList<{{ class.itemType.signature }}>()
{
}
{{ class.className }}(const QList<{{ class.itemType.signature }}>& other)
: QList<{{ class.itemType.signature }}>(other)
{
}
#ifdef Q_COMPILER_INITIALIZER_LISTS
{{ class.className }}(std::initializer_list<{{ class.itemType.signature }}> args)
: QList<{{ class.itemType.signature }}>(args)
{
}
#endif
QVariant toVariant() const;
static {{ class.className }} fromVariant(const QVariant& value, bool* ok = NULL);
operator QVariant() const
{
return toVariant();
}
};
// -----------------------------------------------------------------------------
// ARRAY {{ class.itemType.type.fullName }}
// -----------------------------------------------------------------------------
{% load grantleecodegen %}
{% if class.itemType.type.isAnonymous %}
{% with class.itemType.type as type %}
......@@ -10,3 +8,54 @@
{% include "typedefinition.inc" %}
{% endwith %}
{% endif %}
QVariant {{ class.fullName }}::toVariant() const
{
QVariantList result;
Q_FOREACH(const {{ class.itemType.type.fullName }}& item, *this) {
result << item;
}
return result;
}
{{ class.fullName }} {{ class.fullName }}::fromVariant(const QVariant& value, bool* ok)
{
// First try immediate conversion
if (value.canConvert<{{class.fullName}}>())
{
if (ok != NULL) {
*ok = true;
}
return value.value<{{class.fullName}}>();
}
// Convert to list
bool valuesOk = true;
{{ class.fullName }} result;
if (value.canConvert(QMetaType::QVariantList)) {
Q_FOREACH(const QVariant& itemValue, value.toList()) {
{% switch class.itemType.type.metaType %}
{% default %}
{{ class.itemType.type.fullName }} itemResult = {{ class.itemType.type.fullName }}::fromVariant(itemValue, &valuesOk);
if (valuesOk) {
result << itemResult;
}
else {
break;
}
{% case "type" %}
if (itemValue.canConvert<{{ class.itemType.type.fullName }}>()) {
{{ class.itemType.type.fullName }} itemResult = itemValue.value<{{ class.itemType.type.fullName }}>();
}
{% endswitch %}
}
}
if (ok != NULL) {
*ok = valuesOk;
}
return result;
}
......@@ -60,10 +60,14 @@ class {{ class.className }}
{# Default public data-loader #}
public:
virtual void load(const QVariantMap &data);
virtual void load(const QVariantMap& data);
{% if not class.isQObject %}
static {{ class.className }} fromVariant(const QVariant& value, bool* ok = NULL);
{% endif %}
private:
void loadOwnData(const QVariantMap &data);
void loadOwnData(const QVariantMap& data);
{# QVariant conversion #}
public:
......
......@@ -47,9 +47,43 @@
// QVariant conversion
QVariant {{ class.fullName }}::toVariant() const {
// TODO
return QVariant();
QVariantMap result;
{% for field in class.fields %}
{% if field.type.isPointer %}
if ({{ field.name }}) {
result["{{ field.originalName }}"] = *{{field.name}};
}
{% else %}
result["{{ field.originalName }}"] = {{field.name}};
{% endif %}
{% endfor %}
return result;
};
{% if not class.isQObject %}
{{ class.fullName }} {{ class.fullName }}::fromVariant(const QVariant& value, bool* ok) {
// First try immediate conversion
if (value.canConvert<{{class.fullName}}>()) {
if (ok != NULL) {
*ok = true;
}
return value.value<{{class.fullName}}>();
}
bool canConvert = value.canConvert<QVariantMap>();
if (ok != NULL) {
*ok = canConvert;
}
if (canConvert)
{
return {{ class.className }}(value.toMap());
}
return {{ class.className }}();
}
{% endif %}
{% case "RpcMethod" %}
{% if not member.isInline %}{% if not member.isPureVirtual %}
......
......@@ -25,6 +25,7 @@
{% block includes %}
#include <QtCore/QMetaType>
#include <QtCore/QVariant>
{% with class.headerDependencies as dependencies %}{% include "includes.inc" %}{% endwith %}
{% endblock %}
......@@ -45,9 +46,7 @@ namespace {{ class.namespaces|join:"::" }} {
{% for embeddedType in class.embeddedTypes %}
{% if embeddedType.isIntrospected %}
{% ifnotequal embeddedType.metaType "array" %}{# Arrays are typedef-ed QLists; they should not be registered. #}
Q_DECLARE_METATYPE({{ embeddedType.fullName }});
{% endifnotequal %}
Q_DECLARE_METATYPE({{ embeddedType.fullName }});
{% endif %}
{% endfor %}
{% endblock %}
......
......@@ -50,7 +50,7 @@ public:
*
* This is done as a static method instead of constructor to avoid ambiguities.
*/
static {{ class.className }} fromVariant(const QVariant &value);
static {{ class.className }} fromVariant(const QVariant &value, bool *ok = NULL);
virtual QVariant toVariant() const;
......
......@@ -49,9 +49,58 @@
{% endfor %}
}
{{ class.fullName }} {{ class.fullName }}::fromVariant(const QVariant &value)
{{ class.fullName }} {{ class.fullName }}::fromVariant(const QVariant &value, bool* ok)
{
// TODO
// First try immediate conversion
if (value.canConvert<{{class.fullName}}>())
{
if (ok != NULL) {
*ok = true;
}
return value.value<{{class.fullName}}>();
}
// Otherwise, inspect
{% for variant in class.variants %}
{% switch variant.metaType %}
{% default %}
{
bool variantOk = false;
{{ variant.className }} result = {{ variant.className }}::fromVariant(value, &variantOk);
if (variantOk) {
if (ok != NULL) {
*ok = true;
}
return {{ class.fullName }}(result);
}
}
{% case "type" %}
{% ifequal variant.fullName "void" %}
if (value.isNull() ||
(value.canConvert(QMetaType::QVariantList) && value.toList().isEmpty()) ||
(value.canConvert(QMetaType::QVariantMap) && value.toMap().isEmpty()))
{
if (ok != NULL) {
*ok = true;
}
{{ class.fullName }} result;
result.m_tag = {{ forloop.counter }};
return result;
}
{% else %}
if (value.canConvert<{{ variant.fullName }}>()) {
if (ok != NULL) {
*ok = true;
}
return {{ class.fullName }}(value.value<{{ variant.fullName }}>());
}
{% endifequal %}
{% endswitch %}
{% endfor %}
if (ok != NULL) {
*ok = false;
}
return {{ class.fullName }}();
}
......@@ -60,8 +109,6 @@ QVariant {{ class.fullName }}::toVariant() const
switch(m_tag) {
{% for variant in class.variants %}
case {{ forloop.counter }}:
// {{ variant.metaType }}
// {{ variant.fullName }}
{% switch variant.metaType %}
{% default %}
{% ifequal variant.fullName "void" %}
......@@ -74,7 +121,7 @@ QVariant {{ class.fullName }}::toVariant() const
{
QVariantList resultList;
Q_FOREACH(const {{ variant.itemType.type.fullName }}& m_{{ variant.className }}Item, *m_{{ variant.className }}) {
resultList << m_{{ variant.className }}Item;
resultList << m_{{ variant.className }}Item;
}
return resultList;
}
......
......@@ -50,7 +50,7 @@ public:
*
* @param value The value to apply.
*/
static {{ class.className }} fromVariant(const QVariant &value);
static {{ class.className }} fromVariant(const QVariant& value, bool* ok = NULL);
/**
* Check if a value is valid.
......
......@@ -31,20 +31,27 @@
}
{% endifequal %}
{{ class.fullName }} {{ class.fullName }}::fromVariant(const QVariant &value)
{{ class.fullName }} {{ class.fullName }}::fromVariant(const QVariant& value, bool* ok)
{
{% switch class.sourceType %}
{{ class.fullName }} result = {% switch class.sourceType %}
{% case "integer" %}
return {{ class.fullName }}(value.toInt());
{{ class.fullName }}(value.toInt());
{% case "number" %}
return {{ class.fullName }}(value.toFloat());
{{ class.fullName }}(value.toFloat());
{% case "string" %}
return {{ class.fullName }}(value.toString());
{{ class.fullName }}(value.toString());
{% case "boolean" %}
return {{ class.fullName }}(value.toBool());
{{ class.fullName }}(value.toBool());
{% default %}
{{ class.fullName }}();
// Unsupported wrapped type initializer {{ class.sourceType }}!
{% endswitch %}
if (ok != NULL) {
*ok = result.isValid();
}
return result;
}
bool {{ class.fullName }}::isValid()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment