0

I have an AbstractIndex defining the interface for its Items and the sorting and query algorithms. Further I have several concrete indizes like in the example below a FileIndex. Now I want to serialize the indizes. I guess serializeIndex() works, but I could not test it. In FileIndex::buildIndex() the operator>> of AbstractIndexProvider::Item gets called.I tried to downcast the _index but I get strange compiletime errors. Using boost I could easily declare the type, but I want to drop the boost dependency. So what do I have to do, to let Qt instanciate the correct class in FileIndex::buildIndex()?

class AbstractIndex
{
public:
    class Item;    
    void query(const QString &req, QVector<Item*> *res);

protected:
    virtual void buildIndex()      = 0;
    virtual void serializeIndex() const = 0;    
    QVector<Item*> _index;
};

class AbstractIndexProvider::Item
{
public:    
    QString _name;
    // Several pure virtual functions...

    // Serialization
    friend QDataStream &operator<<(QDataStream &out, AbstractIndexProvider::Item const * const item);
    friend QDataStream &operator>>(QDataStream &in, AbstractIndexProvider::Item *item);
};


/**************************************************************************/
class FileIndex : public AbstractIndexProvider
{
public:
    class Item;

protected:
    void buildIndex()           override;
    void serializeIndex() const override;
};

class FileIndex::Item : public AbstractIndexProvider::Item
{
    friend class FileIndex;

protected:
    QString _path;    
    friend QDataStream &operator<<(QDataStream &out, const FileIndex::Item &item);
    friend QDataStream &operator>>(QDataStream &in, FileIndex::Item &item);
};


/**************************************************************************/
void FileIndex::serializeIndex() const
{
    QFile file(_indexFile);
    if (file.open(QIODevice::ReadWrite| QIODevice::Text))
    {
        QDataStream stream( &file );
        stream << _index;
        return;
    }
}


/**************************************************************************/
void FileIndex::buildIndex()
{
    QFile file(_indexFile);
    if (file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        QDataStream stream( &file );
        stream >> _index;  // WHAT TO DO HERE?
        return;
    }
}
ManuelSchneid3r
  • 15,850
  • 12
  • 65
  • 103

2 Answers2

1
stream >> _index;  // WHAT TO DO HERE?

QVector<Item*> _index; is a QVector and doesn't have a straight forward way to a binary stream.

QDebug has a way to write a QVector. If you want a quick and easy way to and from the filesystem, or a data stream, QByteArray handles really well.

Otherwise, if you want to stick with QVector, iterate through it with either foreach or a standard for loop or a java style iterator or a standard lib style iterator.

Your code might look something like:

QDataStream stream( &file );
for(int i = 0; i< _index.size(); i++)
{
    stream << _index.at(i) << ",";
}
stream << "\n";
return;

http://qt-project.org/doc/qt-5/qlist.html#details

http://qt-project.org/doc/qt-5/containers.html

Some of the more complex examples of inheritance in Qt can be found in: The Model/View Programming and Qt's Graphics View Framework.

http://qt-project.org/doc/qt-5/graphicsview.html

http://qt-project.org/doc/qt-5/model-view-programming.html

http://qt-project.org/doc/qt-5/qabstractitemmodel.html

http://qt-project.org/doc/qt-5/qmodelindex.html

Also have you looked into the QFileInfo class and the filter and sorting options that are built into Qt's filesystem queries?

http://qt-project.org/doc/qt-5/qdiriterator.html

http://qt-project.org/doc/qt-5/qdir.html#entryInfoList

QFileInfoList QDir::entryInfoList(const QStringList & nameFilters, Filters filters = NoFilter, SortFlags sort = NoSort) const

Hope that helps.

phyatt
  • 18,472
  • 5
  • 61
  • 80
1

What you are trying to achieve is to virtualize creation of your objects. There is no out of the box solution for it in Qt. So, if you don't want to use boost, you should implement it yourself.

One way is to add a type identifier for every derived class and register the type-class pair in some factory. When you serialize your objects you should also serialize their type ids. When deserialize you first read type id from your data stream and then create an object using object factory.

Here's some useful links:

http://www.parashift.com/c++-faq/serialize-inherit-no-ptrs.html

http://www.parashift.com/c++-faq/virtual-ctors.html

Best Practice For List of Polymorphic Objects in C++

Community
  • 1
  • 1
hank
  • 9,553
  • 3
  • 35
  • 50