PDA

View Full Version : how to use >> operator serialize QValueList<T> to QDataStream?



coralbird
16th May 2006, 09:08
Below is the related instruction in qt.


QDataStream & operator<< ( QDataStream & s, const QValueList<T> & l )
This is an overloaded member function, provided for convenience. It behaves essentially like the above function.
Writes a list, l, to the stream s. The type T stored in the list must implement the streaming operator.
QDataStream & operator>> ( QDataStream & s, QValueList<T> & l )
Reads a list, l, from the stream s. The type T stored in the list must implement the streaming operator.



I have realize >> operator in my "T", as below:


class CSysAlarm
{

public:
CSysAlarm(ENUM_INFO_TYPE infoType=COS_INFO);
~CSysAlarm();
QDataStream& operator <<( QDataStream& stream );
// Attributes
public:

ENUM_INFO_TYPE m_enumInfoType;
bool m_bIfAlarm;
uint m_dwAlarmTimes;
bool m_bAutoPrint;
bool m_bIfPop;
bool m_bIfLoop;
bool m_bAllInfo;
QString m_strPathFile;

public:

};

And other code:


QFile file( "hmiset.bin" );
if(file.open(IO_WriteOnly )==false)
return;
QDataStream stream( &file );

How can I do this as title? thanks!

wysota
16th May 2006, 10:55
But what is wrong? Do you get any messages from the compiler or anything?

coralbird
17th May 2006, 01:36
But what is wrong? Do you get any messages from the compiler or anything?


The problem is that i don't know how to realize the function as title.The Key is
that how to use << operator as below:

QDataStream & operator<< ( QDataStream & s, const QValueList<T> & l )

For example:
typedef QValueList<CSysAlarm> CSysAlarmList;

CSysAlarmList m_AlarmCfgList;

<<(stream,m_AlarmCfgList) ?

jacek
17th May 2006, 01:44
QDataStream& operator <<( QDataStream& stream, const CSysAlarm& alarm )
{
...
return stream;
}

QDataStream& operator >>( QDataStream& stream, CSysAlarm& alarm )
{
...
return stream;
}

...

stream << m_AlarmCfgList;

coralbird
17th May 2006, 03:50
QDataStream& operator <<( QDataStream& stream, const CSysAlarm& alarm )
{
...
return stream;
}

QDataStream& operator >>( QDataStream& stream, CSysAlarm& alarm )
{
...
return stream;
}

...

stream << m_AlarmCfgList;

It can work ! Thank wysota and jacek.
does only QValueList supprot serializing?If I have several classes inherited from CSysAlarm,and I have to abandon QValueList ,In which way i can serialize them expendiently like using QValueList?

wysota
17th May 2006, 10:16
All Qt classes which have the operator>>(QDataStream&, ...) and operator<<(QDataStream&, ...) defined support serialisation out of the box. Take a look at the docs.

http://doc.trolltech.com/3.3/datastreamformat.html

coralbird
17th May 2006, 10:39
All Qt classes which have the operator>>(QDataStream&, ...) and operator<<(QDataStream&, ...) defined support serialisation out of the box. Take a look at the docs.

http://doc.trolltech.com/3.3/datastreamformat.html
I understand what the docs mean.I want to find a simple way to solve
the probleb as below:


class a
{
...
};
class b:public a
{
...
}
class c:public a
{
....
}
.....
I can't use QValueList to store a ,b and c ,for QvalueList<a> store class object itself in it,not pointer.Maybe I have to use QPtrList<a> to store them.
In Mfc,using virtual function it is very easy to realize this.

Thanks!

wysota
17th May 2006, 11:13
But what is the problem? You don't have to use a class which has streaming operators implemented to store your data.


QPtrList<MyClass> list;
QDataStream ds(...);
//...
ds << list.size();
for(QPtrList<MyClass>::iterator it = list.begin(); it!=list.end(); ++it){
ds << *(*it);
}

coralbird
18th May 2006, 02:14
But what is the problem? You don't have to use a class which has streaming operators implemented to store your data.


QPtrList<MyClass> list;
QDataStream ds(...);
//...
ds << list.size();
for(QPtrList<MyClass>::iterator it = list.begin(); it!=list.end(); ++it){
ds << *(*it);
}


Thanks , I will test soon .:)
I think qt is using a differant mechanism to serialize than MFC.
and there is still a problem,after storing data like above,how to restore data from QDataStream?

QPtrList<MyClass> list;
QDataStream ds(...)
//...
int nSize;
ds>>nSize;
for(int i=0;i<nSize;i++)
{
//how to write the code?
}
Thanks!

jacek
18th May 2006, 02:28
how to restore data from QDataStream?
Analogically:

for(int i=0;i<nSize;i++)
{
MyClass *ptr = new MyClass();
ds >> *ptr;
list.append( ptr );
}
or
for(int i=0;i<nSize;i++)
{
MyClass *ptr = MyClass::load( ds );
if( ptr != 0 ) {
list.append( ptr );
}
else {
// error
}
}

coralbird
18th May 2006, 03:07
This is my test code and result as below:

class Ca
{
public:
int x;
};
class Cb: public Ca
{
public:
int y;
};
//note:this function is called two times.
QDataStream& operator<<( QDataStream& stream ,const Ca& a1)
{
stream<<a1.x;
return stream;
}
//note:this function is not called.
QDataStream& operator<<( QDataStream& stream ,const Cb& b1)
{
stream<<b1.x;
stream<<b1.y;
return stream;
}
int myTestfunc()
{
QPtrList<Ca> list;
QFile file;
file.setName("test.bin");
if(!file.open(IO_WriteOnly))
return 1;
Ca* pCa=new Ca;
Cb* pCb=new Cb;
list.append(pCa);
list.append(pCb);
QDataStream ds(&file);
ds<<list.count();
for(QPtrList<Ca>::iterator it=list.begin();it!=list.end();++it)
{
ds<<*(*it);
}
return 1;
}
Please give me idea where to modify my code,thanks!

coralbird
18th May 2006, 03:24
Analogically:

for(int i=0;i<nSize;i++)
{
MyClass *ptr = new MyClass();
ds >> *ptr;
list.append( ptr );
}
or
for(int i=0;i<nSize;i++)
{
MyClass *ptr = MyClass::load( ds );
if( ptr != 0 ) {
list.append( ptr );
}
else {
// error
}
}

may it is same as qvaluelist.h realized:

template <class T>
Q_INLINE_TEMPLATES QDataStream& operator>>( QDataStream& s, QValueList<T>& l )
{
l.clear();
Q_UINT32 c;
s >> c;
for( Q_UINT32 i = 0; i < c; ++i )
{
T t;
s >> t;
l.append( t );
if ( s.atEnd() )
break;
}
return s;
}

Now I want to realize several kind clssses serializing.Should I have to record every class's
kind myself,and calss's data ,then according to the kind to restore the data?In fact ,MFC recorded these information.

for(int i=0;i<nSize;i++)
{
int nKind;
ds>>nKind;
if(nKind==Ca::rtti())
{
ca*ptr = new ca();
ds >> *ptr;
list.append( ptr );
}
else if(nKind==Cb::rtti())
{
cb*ptr = new cb();
ds >> *ptr;
list.append( ptr );
}
...


}

jacek
18th May 2006, 15:25
Now I want to realize several kind clssses serializing.Should I have to record every class's kind myself,and calss's data ,then according to the kind to restore the data?In fact ,MFC recorded these information.
You should be able to read your objects using QVariant, if you use these:
int qRegisterMetaType ( const char * typeName )
Registers the type name typeName to the type T. Returns the internal ID used by QMetaType. Any class or struct that has a public constructor, a public copy constructor, and a public destructor can be registered.
After a type has been registered, you can create and destroy objects of that type dynamically at run-time.
This example registers the class MyClass:
qRegisterMetaType<MyClass>("MyClass");
Note: This function is thread-safe.
See also qRegisterMetaTypeStreamOperators(), QMetaType::isRegistered(), and Q_DECLARE_METATYPE().

void qRegisterMetaTypeStreamOperators ( const char * typeName )
Registers the stream operators for the type T called typeName.
Afterward, the type can be streamed using QMetaType::load() and QMetaType::save(). These functions are used when streaming a QVariant.
qRegisterMetaTypeStreamOperator<MyClass>("MyClass");
The stream operators should have the following signatures:
QDataStream &operator<<(QDataStream &out, const MyClass &myObj);
QDataStream &operator>>(QDataStream &in, MyClass &myObj);
Note: This function is thread-safe.
See also qRegisterMetaType(), QMetaType::isRegistered(), and Q_DECLARE_METATYPE().

coralbird
19th May 2006, 02:10
Thank wysoto and jacek for giving me so much help. I will study them soon.:D