PDA

View Full Version : QDataStream overloading << and >>



volcano
20th July 2019, 08:41
Hi,

I'm trying to override the QDataStream to insert a class into a stream eventually writing it to a file. The >> works however << seems to be broken.

Kindly check and let me know what i'm missing

main


int main(int argc, char *argv[])
{
QApplication a(argc, argv);

WorkClass *w = new WorkClass;
w->setId(1);
w->setWorkname("Hello");

WorkItemClass *wc1 = new WorkItemClass;
wc1->setId(11);
wc1->setData("11");

WorkItemClass *wc2 = new WorkItemClass;
wc2->setId(22);
wc2->setData("22");

w->appendItem(wc1);
w->appendItem(wc2);


QFile file("test.txt");
if(file.open(QIODevice::WriteOnly ))
{
QDataStream stream;
stream.setDevice(&file);
stream << w;
file.close();
}

WorkClass w2;
if(file.open(QIODevice::ReadOnly))
{
QDataStream stream( &file );
stream>>w2;
file.close();
}

return a.exec();
}


workclass.h


class WorkClass;
class WorkItemClass;

class WorkClass : public QObject
{
Q_OBJECT
public:
explicit WorkClass(QObject *parent = nullptr);

QVariant getId() const;
void setId(const QVariant &value);

QString getWorkname() const;
void setWorkname(const QString &value);

QList<WorkItemClass*> getItemList() const;
void appendItem( WorkItemClass *value);


signals:

public slots:

protected:
QVariant id;
QString workname;
QList<WorkItemClass*> itemList;

};
QDataStream &operator>>(QDataStream &stream, WorkClass &work);

QDataStream &operator<<(QDataStream &stream,const WorkClass &work);

class WorkItemClass : public QObject
{
Q_OBJECT
public:
explicit WorkItemClass(QObject *parent = nullptr);

int getId() const;
void setId(int value);

QString getData() const;
void setData(const QString &value);

private:
int id;
QString data;

};


workclass.cpp


QDataStream &operator>>(QDataStream &stream, WorkClass &work)
{
QVariant variant;
QString string;
int count;
int id;

stream >> variant;
work.setId(variant);

stream >> string;
work.setWorkname(string);

stream >> count;
for (int i=0; i <count; i++) {
stream >> id;
stream >> string;
WorkItemClass *w = new WorkItemClass;
w->setId(id);
w->setData(string);
work.appendItem(w);
}

return stream;
}

QDataStream &operator<<(QDataStream& stream, const WorkClass &work)
{
stream << work.getId();
stream << work.getWorkname();


stream << work.getItemList().size();

for(int i =0;i<work.getItemList().count();i++)
{
stream << work.getItemList().at(i)->getId();
stream << work.getItemList().at(i)->getData();
}

return stream;
}



WorkClass::WorkClass(QObject *parent) : QObject(parent)
{

}

QVariant WorkClass::getId() const
{
return id;
}

void WorkClass::setId(const QVariant &value)
{
id = value;
}

QString WorkClass::getWorkname() const
{
return workname;
}

void WorkClass::setWorkname(const QString &value)
{
workname = value;
}

QList<WorkItemClass*> WorkClass::getItemList() const
{
return itemList;
}

void WorkClass::appendItem(WorkItemClass *value)
{
itemList.append(value);
}

WorkItemClass::WorkItemClass(QObject *parent) : QObject (parent)
{

}

int WorkItemClass::getId() const
{
return id;
}

void WorkItemClass::setId(int value)
{
id = value;
}

QString WorkItemClass::getData() const
{
return data;
}

void WorkItemClass::setData(const QString &value)
{
data = value;
}

anda_skoa
20th July 2019, 12:41
The operators are fine.

The issue is that you are not writing your object into the stream but its pointer.



QFile file("test.txt");
if(file.open(QIODevice::WriteOnly ))
{
QDataStream stream;
stream.setDevice(&file);
stream << *w; // dereference the pointer and write the actual object
file.close();
}


As a recommendation: don't use QObject as a base class unless you need it. Here actual "value" type classes would likely better.
Currently you are leaking all entries in itemList

Cheers,
_

volcano
20th July 2019, 13:34
The operators are fine.

The issue is that you are not writing your object into the stream but its pointer.



QFile file("test.txt");
if(file.open(QIODevice::WriteOnly ))
{
QDataStream stream;
stream.setDevice(&file);
stream << *w; // dereference the pointer and write the actual object
file.close();
}




Cheers,
_


Thanks for spotting that for me..


As a recommendation: don't use QObject as a base class unless you need it. Here actual "value" type classes would likely better.
Currently you are leaking all entries in itemList
Will make sure to use QObject only if I need so.
I guess parenting the entries int the itemList will stop the leak. Correct me if i'm mistaken.

anda_skoa
20th July 2019, 13:42
I guess parenting the entries int the itemList will stop the leak. Correct me if i'm mistaken.

Yes, or deleting them in the destructor, see qDeleteAll() for a convenient way to do that.

Not using QObject as a base class would mean you could store the objects directly and not need pointers.

Cheers,
_

volcano
20th July 2019, 13:49
Thanks for the prompt reply


you could store the objects directly and not need pointers.

Implies i could use

WorkClass w;
stream << w;

instead of
WorkClass *w = new WorkClass;
stream << *w.

anda_skoa
20th July 2019, 14:24
Yes and QList<WorkItemClass>

Cheers,
_

volcano
20th July 2019, 14:28
Cool... Thank you
volcano