00001 #ifndef __Q_IBUS_SERIALIZABLE_H_
00002 #define __Q_IBUS_SERIALIZABLE_H_
00003
00004 #include <QDebug>
00005 #include "qibusobject.h"
00006 #include <QDBusArgument>
00007 #include <QDBusVariant>
00008 #include <QHash>
00009 #include <QMap>
00010
00011 #define INIT_PRIO_HIGH __attribute__((init_priority(1000)))
00012
00013 #define INIT_PRIO_LOW
00014
00015 #define IBUS_SERIALIZABLE \
00016 public: \
00017 static Serializable *newInstance (void); \
00018 static MetaTypeInfo staticMetaTypeInfo; \
00019 virtual const MetaTypeInfo *metaTypeInfo (void) const;
00020
00021 #define IBUS_DECLARE_SERIALIZABLE(classname, name) \
00022 Serializable * \
00023 classname::newInstance (void) \
00024 { \
00025 return (Serializable *) new classname (); \
00026 } \
00027 const Serializable::MetaTypeInfo * \
00028 classname::metaTypeInfo (void) const \
00029 { \
00030 return & (classname::staticMetaTypeInfo); \
00031 } \
00032 Serializable::MetaTypeInfo \
00033 classname::staticMetaTypeInfo INIT_PRIO_LOW (QString(#name), classname::newInstance);
00034
00035 namespace IBus {
00036
00037 class Serializable;
00038 typedef Pointer<Serializable> SerializablePointer;
00039
00040 class Serializable : public Object
00041 {
00042 Q_OBJECT;
00043
00044 template<typename T> friend QDBusVariant & qDBusVariantFromSerializable (const Pointer<T> &p, QDBusVariant & dbus_variant);
00045 template<typename T> friend QDBusVariant qDBusVariantFromSerializable (const Pointer<T> &p);
00046 template<typename T> friend Pointer<T> qDBusVariantToSerializable (const QDBusVariant &variant);
00047
00048 typedef Serializable * (NewInstanceFunc) (void);
00049
00050 protected:
00051 class MetaTypeInfo
00052 {
00053 public:
00054 MetaTypeInfo(const QString &name, NewInstanceFunc _new) : m_className (name) {
00055 Serializable::registerObject (m_className, _new);
00056 }
00057 ~MetaTypeInfo (void) {
00058 Serializable::unregisterObject (m_className);
00059 }
00060 const QString &className (void) const {
00061 return m_className;
00062 }
00063 private:
00064 QString m_className;
00065 };
00066
00067 public:
00068 Serializable () {}
00069 void setAttachment (const QString &key, const SerializablePointer &value);
00070 SerializablePointer getAttachment (const QString &key) const;
00071 SerializablePointer removeAttachment (const QString &key);
00072
00073 protected:
00074 virtual bool serialize (QDBusArgument &argument);
00075 virtual bool deserialize (const QDBusArgument &argument);
00076
00077 private:
00078 QMap <QString, SerializablePointer> m_attachments;
00079
00080
00081 protected:
00082 static void registerObject (const QString &name, NewInstanceFunc _new);
00083 static void unregisterObject (const QString &name);
00084
00085 private:
00086 static SerializablePointer createInstance (const QString &name);
00087 static QHash<QString, NewInstanceFunc *> type_table;
00088
00089 IBUS_SERIALIZABLE
00090 };
00091
00092 template<typename T>
00093 QVariant &
00094 qVariantFromSerializable (const Pointer<T> &p, QVariant & variant = QVariant ())
00095 {
00096 QDBusArgument argument;
00097
00098 argument.beginStructure ();
00099 argument << p->metaTypeInfo ()->className ();
00100 p->serialize (argument);
00101 argument.endStructure ();
00102
00103 variant.setValue (argument);
00104 return variant;
00105 }
00106
00107 template<typename T>
00108 QDBusVariant &
00109 qDBusVariantFromSerializable (const Pointer<T> &p, QDBusVariant &dbus_variant)
00110 {
00111 QVariant variant;
00112 QDBusArgument argument;
00113
00114 argument.beginStructure ();
00115 argument << p->metaTypeInfo ()->className ();
00116 p->serialize (argument);
00117 argument.endStructure ();
00118 variant.setValue (argument);
00119 dbus_variant.setVariant (variant);
00120
00121 return dbus_variant;
00122 }
00123
00124 template<typename T>
00125 QDBusVariant
00126 qDBusVariantFromSerializable (const Pointer<T> &p)
00127 {
00128 QDBusVariant variant;
00129 return qDBusVariantFromSerializable (p, variant);
00130 }
00131
00132 template<typename T>
00133 Pointer<T>
00134 qDBusVariantToSerializable (const QDBusVariant &variant)
00135 {
00136
00137 Pointer<T> p;
00138 QString name;
00139
00140 const QDBusArgument argument = variant.variant().value<QDBusArgument> ();
00141
00142 if (argument.currentType () != QDBusArgument::StructureType) {
00143 return p;
00144 }
00145
00146 argument.beginStructure ();
00147 argument >> name;
00148 p = Serializable::createInstance (name);
00149 if (!p.isNull () && !p->deserialize (argument)) {
00150 p = NULL;
00151 }
00152 argument.endStructure ();
00153
00154 return p;
00155 }
00156
00157 template<typename T>
00158 QDBusArgument& operator<< (QDBusArgument& argument, const Pointer<T> &p)
00159 {
00160 QDBusVariant variant;
00161 argument << qDBusVariantFromSerializable<T> (p, variant);
00162 return argument;
00163 }
00164
00165 template<typename T>
00166 const QDBusArgument& operator>> (const QDBusArgument& argument, Pointer<T> &p)
00167 {
00168 Q_ASSERT ((argument.currentType () == QDBusArgument::VariantType));
00169
00170 QDBusVariant variant;
00171 argument >> variant;
00172
00173 p = qDBusVariantToSerializable<T> (variant);
00174
00175 return argument;
00176 }
00177
00178 };
00179
00180 Q_DECLARE_METATYPE (IBus::SerializablePointer);
00181
00182 #endif