Unsolved QVariantMap in a QAbstractListModel and C++/QML
-
hello, I'm using a QAbstractListModel that contains a QVariantMap (m_map)
class CItem { public: CItem(const QString &name, const QString &url); QString name() const; QString url() const; QVariantMap map() const; void setName(const QString& name); void setUrl(const QString& url); void setMap(const QVariantMap& map); private: QString m_name; QString m_url; QVariantMap m_map; };
class CItemModel : public QAbstractListModel { Q_OBJECT public: enum ItemRoles { NameRole = Qt::UserRole + 1, UrlRole, MapRole }; CItemModel(QObject *parent = 0); void addItem(const CItem &CItem); int rowCount(const QModelIndex & parent = QModelIndex()) const; QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); protected: QHash<int, QByteArray> roleNames() const; private: QList<CItem> m_Items; signals: };
and I want to visualize and modify all the datas QML like that:
ListView { id: listView model : itemModel delegate: ItemDelegate { id: root contentItem: ColumnLayout { RowLayout { id: rowLayout ColumnLayout { id: columnLayout Label { id: text1 text: model.name } Label { id: text2 text: model.url } Label { id: text3 text: model.map["test1"] // it works } // did not work Repeater{ model: map Text { text: model.map["test1"]} }
no problem with model.name and model.url. (text3 is ok too) but I cant' display all data of my qVariantMap and modify it
is it possible? can you explain me the best approach, please ? -
@arctik Hi. The first I notice is that the Repeater does not work with Javascript Objects (Conversion of QVariantMap from C++ side to QML side). Repeater component works with ListModels.
So, maybe there is a better approach, but one way is:
- Declare an empty LisModel in your qml file.
- Load or your QVariantMap (JS Object) into ListModel created for that purpose. Automatically, your repeater is going to load the data.
- In order to modify your QVariantMap, any changes that you do in the ListModel, you are going to call a function that will load data from the ListModel to QVariantMap property from your original model again.
Seems complex and some kind tricky but you can test it.
-
I suspect the problem is that an object isn't one of the options for a Repeater model.
https://doc.qt.io/qt-6/qml-qtquick-repeater.html#model-prop
This property can be set to any of the supported data models:
- A number that indicates the number of delegates to be created by the repeater
- A model (e.g. a ListModel item, or a QAbstractItemModel subclass)
- A string list
- An object list
Using object.keys() or object.values() to create a string list might work.
-
@jeremy_k @oria66 Thanks for your answers, i am looking to go in this direction. one more question: if I change the QVariantMap to a QlistModel, will it be easier? what I don't understand is how to handle nested lists in lists with C ++ / Qml. it is however a case which must happen often, or I miss a point ?
something like qobjectlist-based-model to replace my QVariantMap,
https://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html#qobjectlist-based-modelif it is possible, do i have to do just one setContextProperty() for my CItemModel or do I have to do it for all nested classes ?
thank you very much for your help -
@arctik There's nothing specific or blocking about nested models in C++ or QML. Just return a model for one of the role of your outer model.