Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Giving a QList<CustomQ_OBJECTclass> to the QML using setContextProperty



  • Hi !

    I have a custom class RoiObject flagged as Q_OBJECT and my QML program has to access to a QList of instances of this type.
    So I tried to set the QList as a Q_PROPERTY :

    Q_PROPERTY(QList<RoiObject> roi_list READ roi_list WRITE roi_list NOTIFY roi_list_changed)
    

    When I run the program, I have the error QMetaProperty::read: Unable to handle unregistered datatype 'QList<RoiObject>' for property RoiModel::roi_list (my getters and setters in RoiModel, the class that instanciates the RoiObjects, are also called roi_list.)

    So I tried to store the RoiModel's into a QVariant

    Q_PROPERTY(QList<QVariant> roi_list READ roi_list WRITE roi_list NOTIFY roi_list_changed)
    

    but as RoiModel is a QAbstractListModel I need to implement

    QVariant RoiModel::data(const QModelIndex &, int) const {
            const RoiObject& w_roiObject = m_roiList[ai_index.row()]; 
            return w_roiObject.get_attribute();
    }
    

    Of course it does not work as i should cast the QVariant to a RoiModel and I can't right ? I tried to use qobject_cast but without surprise it doesn't work.
    What can I do to register my RoiModel : public QAbstractListModel class as a contextProperty and make the getter of the QList<RoiObject> callable by the QML pretty please ?

    |
    |
    |
    |

    I paste here the RoiModel declaration in case you needs it :

    class RoiModel : public QAbstractListModel
    		{
    			Q_OBJECT
    			Q_PROPERTY(QList<QVariant> roi_list READ roi_list WRITE roi_list NOTIFY roi_list_changed)//QList<QVariant<RoiObject>> 
                            //Q_PROPERTY(QList<RoiModel> roi_list READ roi_list WRITE roi_list NOTIFY roi_list_changed)
    			
    		private:
    			RoiModel(const RoiModel&);
    			const RoiModel& operator=(const RoiModel&);
    			//ATTRIBUTS
    			QQuickView* mp_view;
    			QList<QVariant> m_roiList;
    		protected:
    
    		public:
    			static enum t_roiRole
    			{
    				  ColorRole = Qt::UserRole + 1
    				, FovHRole = Qt::UserRole + 2
    				, FovVRole = Qt::UserRole + 3
    				, AzimuthRole = Qt::UserRole + 4
    				, ElevationRole = Qt::UserRole + 5
    				, FactorZoomRole = Qt::UserRole + 6
    				, RcRole = Qt::UserRole + 7
    				, FilterRole = Qt::UserRole + 8
    				, LocalFilterRole = Qt::UserRole + 9
    				, CompressionRole = Qt::UserRole + 10
    				, BitrateRole = Qt::UserRole + 11
    			} mstruct_roles;
    			
    			RoiModel(QQuickView* aip_view, QAbstractListModel* aip_parent = nullptr);
    
    			void roi_list(QList<RoiObject>);
    
    			QList<QVariant> roi_list(void) const;
    	
    			int rowCount(const QModelIndex& air_parent = QModelIndex())const override;
    
    			QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    
    			Q_INVOKABLE void setPosRoi(int ia_id, float ai_azimuth, float ai_elevation);
    		signals:
    			void roi_list_changed(void);
    
    		public slots:
    		
    
    		void onRoiChanged(void);
    		};
    

    and data :

    QVariant RoiModel::data(const QModelIndex & ai_index, int ai_role) const
    {
    	if (ai_index.row() < 0 || ai_index.row() >= m_roiList.size())
    		return QVariant();
    	const RoiObject* wp_roiObject = &m_roiList[ai_index.row()];
    	switch (ai_role)
    	{
    		case t_roiRole::ColorRole:
    			return wp_roiObject->color();
    //etc...
    

  • Lifetime Qt Champion

    Hi,

    Before going down your issue, there's a bigger one to fix. QObject and derived classes are not copyable. You should start by fixing that.



  • @SGaist oh I missed it. Thank you very much.

    I edited my post. data is now using a pointer. I think it was the only copy in this code.
    [edit]
    Ok, I think I did it thanks to your help. The QList<QVariant> doesn't work if I copy the objects and try to use them. However, getting a pointer on a RoiObject from a QVariant seems to work.
    BUT the QML still can't access to the attributes set as Q_PROPERTY in RoiObject.

    onPositionChanged:
    {
                cursorPosElOnROI = roiModel.roi_list[ container.idRoi ].elevation;//cannot read property 'elevation' of undefined
    [...]
    

    Here are the codes relatives to the problem. What can I do to solve it ?

    class RoiObject : public QObject
    {
    	Q_OBJECT
            Q_PROPERTY(float elevation READ elevation WRITE elevation NOTIFY roiUpdated)
    //[...]
    };
    Q_DECLARE_METATYPE(QVector<RoiObject>)
    
    class RoiModel : public QAbstractListModel
    {
    	Q_OBJECT
    	Q_PROPERTY(QList<QVariant> roi_list READ roi_list WRITE roi_list NOTIFY roi_list_changed)
    [...]
    
    QVariant RoiModel::data(const QModelIndex & ai_index, int ai_role) const
    {
    	if (ai_index.row() < 0 || ai_index.row() >= m_roiList.size())
    		return QVariant();
    	const RoiObject* wp_roiObject = m_roiList[ai_index.row()].value<RoiObject*>();
    	switch (ai_role)
    	{
    		case t_roiRole::ColorRole:
    			return wp_roiObject->color();
    [...]
    

Log in to reply