Model/View Concept for arbitrary data



  • I have vastly different data types that I want to process by means of Qt. I have ssequential container with points clouds, Containers with tiff-images, containers with QImages etc.

    I have trouble wrapping my head around the model/view concept now. The AbstractItemModel class and its subclasses have you override the data function, to supply a unified generic format for the attached view classes. However, how can I return tiff-images, or other formats, not compatible with QVariant, in this case and does it even make sense to resort to the model/view idea for custom data types stored in custom data structures? After all, I have to find a way to pipe my data to the rather rigid model format



  • @Sewing said in Model/View Concept for arbitrary data:

    not compatible with QVariant

    Nothing is incompatible with QVariant.

    class MyClass{
    int m_val;
    public:
    MyClass(int val=0) : m_val(val){}
    ~MyClass() = default;
    MyClass(const MyClass&)=default;
    MyClass& operator=(const MyClass&)=default;
    int val() const {return m_val;}
    void setVal(int val){m_val=val;}
    }
    Q_DECLARE_METATYPE(MyClass)
    
    int main(){
    const int myClassID = qMetaTypeId<MyClass>();
    MyClass valueToStore{5};
    QVariant variantValue = QVariant::fromValue(valueToStore); // create a QVariant that contains valueToStore
    if(variantValue.userType() == myClassID) // check that variantValue contains a MyClass
    qDebug() << variantValue.value<MyClass>().val(); // extract the MyClass from the QVariant and print its value
    return 0;
    }
    


  • So all I need to do is include the metatype macro?

    And provide a default constructor in any case?



  • So all I need to do is include the metatype macro?

    Yes, unless you type is already a QObject. In that case you can store it directly (as a pointer) without having to add anything


    And provide a default constructor in any case?

    from http://doc.qt.io/qt-5/qmetatype.html#Q_DECLARE_METATYPE:

    a public default constructor, a public copy constructor and a public destructor



  • I am wondering if I have the following

    #pragma once
    #include "myLibs/DataHandler.hpp"
    #include "baseModel.h"
    #include <vector>
    // Q_DECLARE_METATYPE(DataHandler::SubDirectoryHandler)
    
    class AdmaModel : public BaseModel {
      using BaseModel::BaseModel;
    
     public:
      QVariant Data(size_t index) const override {
        return QVariant::fromValue(data_->sequence_.at(index).egoPositionsUTM_);
      }
    };
    

    where egoPositionsUTM_ is a
    std::vector<std::map<std::string, double>> data member in the class DataHandler and inside its nested class SubDirectoryHandler. I get the error

    error: static_assert failed "Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt's meta-object system" Q_STATIC_ASSERT_X(QMetaTypeId2<T>::Defined, "Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt's meta-object system");

    How do I have to use the macro Q_DECLARE_METATYPE here?



  • std::vector and double are already registered by default. you need to register std::string with Q_DECLARE_METATYPE(std::string) and std::map with Q_DECLARE_METATYPE_TEMPLATE_2ARG(std::map)

    P.S.
    sequence_.at(index) you probably want to check index is in range or use sequence_.value(index) to prevent a crash:

    QVariant Data(size_t index) const override {
    if(static_cast<size_t>(data_->sequence.size()) <=index) return QVariant();
        return QVariant::fromValue(data_->sequence_.at(index).egoPositionsUTM_);
      }
    

    P.P.S.
    Are you sure you want to subclass a model? it's one of the most difficult things to do in QtGui and for 99% of the cases QStandardItemModel works just fine



  • Thank you for your help!!!

    I thought about QStandardItemModel, but didnt comprehend it entirely so far.

    My overall intention is to have several parallel models of data (camera, infrared, etc) each providing the specific data associated with the current index, i.e. I have e.g. 10 recordings of an image, 10 instances of a custom struct, 10 pointclouds, etc.

    Now is QStandardItemModel the way to go here? And what is the advantage here as compared to the QAbstractItemModel? That is has already overriden the pure virtuals ?

    I imagine registering a view to every single one of those models for displaying purposes later



  • Now is QStandardItemModel the way to go here?

    I don't see any limit to its use in the case you describe. My suggestion is to use it only via the QAbstractItemModel interface (QAbstractItemModel* model = new QStandardItemModel) so that, if in the future you realise QStandardItemModel is not good enough for you anymore, you can just change 1 line and be good

    And what is the advantage here as compared to the QAbstractItemModel?

    QAbstractItemModel subclasses need a lot of manual work. so much so that Qt provides a test to make sure you remembered to implement everything by hand. If you do not have a solid grasp on how models work I would strongly suggest not subclassing the model interface.



  • thank you for your wise words of advise. I appreciate it a lot!

    So whats the difference of StandardItemModel then to the TableModel and ListModel etc.?

    Why not use StandardItemModel in every situation?



  • there are no concrete, generic TableModels or ListModels provided by Qt.
    Qt provides:

    • QFileSystemModel to show directories/files
    • QHelpContentModel basically only used internally by QtAssistant
    • QStringListModel to show a list of strings
    • QSqlQueryModel (and subclasses) to interact with a db
    • QStandardItemModel to act as a generic container model

    Why not use StandardItemModel in every situation?

    since QStandardItemModel has to be generic, in some situations you can optimise away parts. If your model is flat (table or list) you can probably optimise performance as you don't need a generic recursive way to manage branches of a tree. That's why I suggest to use it via the QAbstractItemModel interface alone. use QStandardItemModel, build your application around it, if you realise you need to optimise performance you can change QStandardItemModel with your own super fast model later by just changing 1 line. No need to think about this optimisation detail from the start


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.