#include <QObject>
#include <QString>
#include <QFile>
#include <QDebug>
#include <QMap>
#include <QDataStream>
#include <QMetaObject>
#include <QByteArray>
#include <QVariant>
#include <QMetaProperty>
#include <QList>
#include <QMetaType>
#include <QBuffer>
#include <iostream>
{
Q_OBJECT
Q_PROPERTY(QString string READ string WRITE setString
)
public:
Object() {
}
const QString& string() const {
return str;
}
void setString
(const QString &ss
) { str = ss;
}
void dump() const {
std::cout << str.toStdString() << std::endl;
}
private:
};
{
Q_OBJECT
Q_PROPERTY(QObject *object READ object WRITE setObject
)
public:
Parent() {
}
return obj;
}
Q_ASSERT(!oo || qobject_cast<Object*>(oo));
obj = qobject_cast<Object*>(oo);
}
private:
Object *obj;
};
class BaseInterface
{
public:
virtual ~BaseInterface() {}
};
template <typename T>
class Creator : public BaseInterface
{
public:
T *ret = new T;
ret->setObjectName(objectName);
return ret;
}
};
class Factory
{
public:
BaseInterface *i = interfaces.value(className, 0);
assert (i);
return i->create(objectName);
}
static void registerClass
(const QString &className, BaseInterface
*interface
) { if (!interface) {
delete interfaces.value(className, 0);
interfaces.remove(className);
} else {
interfaces[className] = interface;
}
}
static QMap<QString, BaseInterface*> interfaces;
};
QMap<QString, BaseInterface*> Factory::interfaces;
{
QMap<QByteArray, QVariant> properties;
QMap<QByteArray, QByteArray> objectStarProperties;
QMap<QByteArray, QVariantList> listProp;;
const int props = mo->propertyCount();
for (int i=0; i<props; ++i) {
if (prop.
userType() == QMetaType::QObjectStar) { QObject *obj
= qVariantValue<QObject
*>
(prop.
read(o
));
if (obj) {
save(obj, &buf);
objectStarProperties[prop.name()] = buf.buffer();
}
} else if (prop.
userType() == QMetaType::QVariantList) { listProp[prop.name()] = prop.read(o).toList();
} else {
properties[prop.name()] = prop.read(o);
}
}
ds <<
QString::fromLatin1(mo
->className
());
ds << properties;
ds << objectStarProperties;
ds << listProp.size();
QMapIterator<QByteArray, QVariantList> it1( listProp );
while( it1.hasNext() ) {
it1.next();
QVariantList vlist = it1.value();
ds << vlist.size() << it1.key();
}
}
{
QMap<QByteArray, QVariant> properties;
QMap<QByteArray, QByteArray> objectStarProperties;
ds >> className;
ds >> properties;
ds >> objectStarProperties;
int nlists;
ds >> nlists;
QList<int> iList;
QList<QByteArray> propNameList;
for ( int idx=0; idx<nlists; idx++ ) {
int il;
ds >> il >> pnl;
iList.append( il );
propNameList.append( pnl );
}
QObject *o
= Factory
::create(className,
properties.value("objectName").toString());
if (!o) {
qWarning() << "Can't create object of type" << className;
return 0;
}
for (QMap<QByteArray, QVariant>::const_iterator it = properties.begin();
it != properties.end(); ++it) {
if (!o->setProperty(it.key().constData(), it.value())) {
qWarning() << "Can't set" << it.key();
}
}
for (QMap<QByteArray, QByteArray>::const_iterator it =
objectStarProperties.begin();
it != objectStarProperties.end(); ++it) {
buf.setData(it.value());
o->setProperty(it.key(), qVariantFromValue<QObject*>(obj));
}
for ( int idx=0; idx<nlists; idx++ ) {
QVariantList objList;
for (int ii=0; ii<iList[idx]; ++ii) {
objList << qVariantFromValue<QObject*>( oo );
}
o->setProperty( propNameList[idx], objList );
}
return o;
}
#include "main.moc"
int main()
{
Factory::registerClass("Parent", new Creator<Parent>());
Factory::registerClass("Object", new Creator<Object>());
Object *o = new Object;
o->setString("foobar");
Parent *p = new Parent;
p->setObject(o);
qobject_cast<Object*>( p->object() )->dump();
save(p, &file);
file.close();
Q_ASSERT(root);
Parent *pp = qobject_cast<Parent*>(root);
qobject_cast<Object*>( pp->object() )->dump();
return 0;
}
#include <QObject>
#include <QString>
#include <QFile>
#include <QDebug>
#include <QMap>
#include <QDataStream>
#include <QMetaObject>
#include <QByteArray>
#include <QVariant>
#include <QMetaProperty>
#include <QList>
#include <QMetaType>
#include <QBuffer>
#include <iostream>
class Object : public QObject
{
Q_OBJECT
Q_PROPERTY(QString string READ string WRITE setString)
public:
Object() {
}
const QString& string() const {
return str;
}
void setString(const QString &ss) {
str = ss;
}
void dump() const {
std::cout << str.toStdString() << std::endl;
}
private:
QString str;
};
class Parent : public QObject
{
Q_OBJECT
Q_PROPERTY(QObject *object READ object WRITE setObject)
public:
Parent() {
}
QObject * object() const {
return obj;
}
void setObject(QObject * oo) {
Q_ASSERT(!oo || qobject_cast<Object*>(oo));
obj = qobject_cast<Object*>(oo);
}
private:
Object *obj;
};
class BaseInterface
{
public:
virtual ~BaseInterface() {}
virtual QObject *create( const QString &objectName) const = 0;
};
template <typename T>
class Creator : public BaseInterface
{
public:
QObject *create( const QString &objectName) const {
T *ret = new T;
ret->setObjectName(objectName);
return ret;
}
};
class Factory
{
public:
static QObject *create(const QString &className, const QString &objectName) {
BaseInterface *i = interfaces.value(className, 0);
assert (i);
return i->create(objectName);
}
static void registerClass(const QString &className, BaseInterface *interface) {
if (!interface) {
delete interfaces.value(className, 0);
interfaces.remove(className);
} else {
interfaces[className] = interface;
}
}
static QMap<QString, BaseInterface*> interfaces;
};
QMap<QString, BaseInterface*> Factory::interfaces;
static void save(QObject *o, QIODevice *dev)
{
const QMetaObject *mo = o->metaObject();
QMap<QByteArray, QVariant> properties;
QMap<QByteArray, QByteArray> objectStarProperties;
QMap<QByteArray, QVariantList> listProp;;
const int props = mo->propertyCount();
for (int i=0; i<props; ++i) {
const QMetaProperty prop = mo->property(i);
if (prop.userType() == QMetaType::QObjectStar) {
QObject *obj = qVariantValue<QObject*>(prop.read(o));
if (obj) {
QBuffer buf;
buf.open(QIODevice::WriteOnly);
save(obj, &buf);
objectStarProperties[prop.name()] = buf.buffer();
}
} else if (prop.userType() == QMetaType::QVariantList) {
listProp[prop.name()] = prop.read(o).toList();
} else {
properties[prop.name()] = prop.read(o);
}
}
QDataStream ds(dev);
ds << QString::fromLatin1(mo->className());
ds << properties;
ds << objectStarProperties;
ds << listProp.size();
QMapIterator<QByteArray, QVariantList> it1( listProp );
while( it1.hasNext() ) {
it1.next();
QVariantList vlist = it1.value();
ds << vlist.size() << it1.key();
}
}
static QObject *read(QIODevice *dev, QObject *parent = 0)
{
QString className;
QMap<QByteArray, QVariant> properties;
QMap<QByteArray, QByteArray> objectStarProperties;
QDataStream ds(dev);
ds >> className;
ds >> properties;
ds >> objectStarProperties;
int nlists;
ds >> nlists;
QList<int> iList;
QList<QByteArray> propNameList;
for ( int idx=0; idx<nlists; idx++ ) {
int il;
QByteArray pnl;
ds >> il >> pnl;
iList.append( il );
propNameList.append( pnl );
}
QObject *o = Factory::create(className,
properties.value("objectName").toString());
if (!o) {
qWarning() << "Can't create object of type" << className;
return 0;
}
for (QMap<QByteArray, QVariant>::const_iterator it = properties.begin();
it != properties.end(); ++it) {
if (!o->setProperty(it.key().constData(), it.value())) {
qWarning() << "Can't set" << it.key();
}
}
for (QMap<QByteArray, QByteArray>::const_iterator it =
objectStarProperties.begin();
it != objectStarProperties.end(); ++it) {
QBuffer buf;
buf.setData(it.value());
buf.open(QIODevice::ReadOnly);
QObject *obj = read(&buf, 0);
o->setProperty(it.key(), qVariantFromValue<QObject*>(obj));
}
for ( int idx=0; idx<nlists; idx++ ) {
QVariantList objList;
for (int ii=0; ii<iList[idx]; ++ii) {
QObject* oo = read(dev, o);
objList << qVariantFromValue<QObject*>( oo );
}
o->setProperty( propNameList[idx], objList );
}
return o;
}
#include "main.moc"
int main()
{
Factory::registerClass("Parent", new Creator<Parent>());
Factory::registerClass("Object", new Creator<Object>());
Object *o = new Object;
o->setString("foobar");
Parent *p = new Parent;
p->setObject(o);
qobject_cast<Object*>( p->object() )->dump();
QFile file("tt.ss");
file.open(QIODevice::WriteOnly);
save(p, &file);
file.close();
file.open(QIODevice::ReadOnly);
QObject *root = read(&file);
Q_ASSERT(root);
Parent *pp = qobject_cast<Parent*>(root);
qobject_cast<Object*>( pp->object() )->dump();
return 0;
}
To copy to clipboard, switch view to plain text mode
Bookmarks