PDA

View Full Version : QSettings custom class serialization problem



sakya
19th December 2011, 11:22
Hi,

I have a problem with class serialization.
I have two classes (one derived from the other)
I provided operator << for the two classes and all works fine if I use the class separately.
I have a problem when I try to use them in a List containing instances of the two classes: it is used always the << operator of the parent class.

Here's an example.
Two classes (Test2 just adds a QString property to Test):

class Test : public QObject
{
Q_OBJECT
public:
explicit Test(QObject *parent = 0);
Test(const Test& test);

QString Field_1;
QString Field_2;
int Field_3;
};

class Test2 : public Test
{
Q_OBJECT
public:
explicit Test2(QObject *parent = 0);
Test2(const Test2& test2);

QString Field_4;
};

Test::Test(QObject *parent) :
QObject(parent)
{
}

Test::Test(const Test& test)
{
Field_1 = test.Field_1;
Field_2 = test.Field_2;
Field_3 = test.Field_3;
}

Test2::Test2(QObject *parent) :
Test(parent)
{
}

Test2::Test2(const Test2& test2) :
Test(test2)
{
Field_4 = test2.Field_4;
}

Q_DECLARE_METATYPE(Test)
QDataStream &operator<<(QDataStream &out, const Test &test)
{
out << test.Field_1 << test.Field_2 << test.Field_3;
return out;
}

QDataStream &operator>>(QDataStream &in, Test &test)
{
in >> test.Field_1 >> test.Field_2 >> test.Field_3;
return in;
}

Q_DECLARE_METATYPE(Test2)
QDataStream &operator<<(QDataStream &out, const Test2 &test)
{
out << test.Field_1 << test.Field_2 << test.Field_3 << test.Field_4;
return out;
}

QDataStream &operator>>(QDataStream &in, Test2 &test)
{
in >> test.Field_1 >> test.Field_2 >> test.Field_3 >> test.Field_4;
return in;
}

If I put in a List instances of the two class in the ini file I always get just a Test serialization:

QSettings settings;

QList<Test*> list;

Test* t = new Test(this);
t->Field_1 = "Field 1";
t->Field_2 = "Field 2";
t->Field_3 = 10;
list.append(t);

Test2* t2 = new Test2(this);
t2->Field_1 = "Field 1";
t2->Field_2 = "Field 2";
t2->Field_3 = 10;
t2->Field_4 = "Field 4";
list.append(t2);

settings.beginWriteArray("tests");
int index = 0;
foreach (Test* o, list){
settings.setArrayIndex(index);
settings.setValue("test", qVariantFromValue(*o));
index++;
}
settings.endArray();
settings.sync();

Is it normal? How can I correctly serialize that Test2 instance?

Many thanks

fullmetalcoder
19th December 2011, 12:00
Is it normal?
Yes.


How can I correctly serialize that Test2 instance?
In this case, it would be fairly easy to tweak the code to serialize properly but a lot more annoying to deserialize. Basically you'd have to move the serialization code to a virtual method of Test and the deserialization to some kind of factory. To distinguish between serialization of different types you'd then need to prefix the serialized data with a id (unique to each supported class).