Unsolved 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 errorerror: 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
anddouble
are already registered by default. you need to registerstd::string
withQ_DECLARE_METATYPE(std::string)
andstd::map
withQ_DECLARE_METATYPE_TEMPLATE_2ARG(std::map)
P.S.
sequence_.at(index)
you probably want to checkindex
is in range or usesequence_.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 casesQStandardItemModel
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 goodAnd 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/filesQHelpContentModel
basically only used internally by QtAssistantQStringListModel
to show a list of stringsQSqlQueryModel
(and subclasses) to interact with a dbQStandardItemModel
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 theQAbstractItemModel
interface alone. use QStandardItemModel, build your application around it, if you realise you need to optimise performance you can changeQStandardItemModel
with your own super fast model later by just changing 1 line. No need to think about this optimisation detail from the start