I am trying to view a list of c++ models in qml by subclassing QAbstractListModel following this tutorial Models and Views: AbstractItemModel Example
Here is my implementation:
Item model class
class User
{
private:
QString m_macAddr;
QString m_firstName;
QString m_lastName;
public:
User();
User(const QString &mac);
QString macAddr() const;
void setMacAddr(QString &mac);
};
User::User()
{}
User::User(const QString &mac){
m_macAddr = mac;
}
QString User::macAddr() const{
return m_macAddr;
}
void User::setMacAddr(QString &mac){
if(mac == m_macAddr)
return;
m_macAddr = mac;
// emit macAddrChanged();
}
QAbstractListModel subclass
class UserListModel : public QAbstractListModel
{
Q_OBJECT
public:
// User model roles
enum roles{
macRole = Qt::UserRole + 1
};
UserListModel(QObject *parent = nullptr);
QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &index) const override;
QModelIndex getIndex(int r, int c, void *p);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
void addUser(const User &user);
private:
QList<User> m_users;
protected:
QHash<int, QByteArray> rolesNames() const;
};
// Class inplementation.
UserListModel::UserListModel(QObject *parent)
: QAbstractListModel(parent)
{
}
void UserListModel::addUser(const User &user){
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_users << user;
endInsertRows();
}
int UserListModel::rowCount(const QModelIndex &parent) const
{
return m_users.count();
}
QVariant UserListModel::data(const QModelIndex &index, int role) const
{
if (index.row() < 0 || index.row() >= rowCount())
return QVariant();
const User &user = m_users[index.row()];
if(role == macRole){
return user.macAddr();
}
return QVariant();
}
QModelIndex UserListModel::index(int row, int column, const QModelIndex &parent) const
{
return parent;
}
QModelIndex UserListModel::parent(const QModelIndex &index) const
{
return index;
}
QModelIndex UserListModel::getIndex(int r, int c, void *p) {
return this->createIndex(r, c, p);
}
QHash<int, QByteArray> UserListModel::rolesNames() const {
QHash<int, QByteArray> roles;
roles[macRole] = "mac";
return roles;
}
main.cpp
QQmlApplicationEngine engine;
QString mac = "12:3e:3w:4r:33";
userlistModel->addUser(User(mac));
userlistModel->addUser(User(mac));
userlistModel->addUser(User(mac));
userlistModel->addUser(User(mac));
engine.rootContext()->setContextProperty("usersModel", userlistModel);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
QModelIndex id = userlistModel->getIndex(1, 0, 0);
QVariant v1 = userlistModel->data(id, Qt::UserRole + 1);
qDebug() << "===========" << v1.toString();
controller::DatabaseService<SqliteDB> *sqliteDb = new controller::DatabaseService<SqliteDB>();
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
QML
ListView{
id: listView
anchors.fill: parent
model:usersModel
delegate: Component { HorizontalListItem{mac: mac}}
}
The Problem is :
In main function I am adding 4 models to the list model but, They are shown in qml without data. althought, I am trying to view mac role.
what I tried
It is not necessary that you override the index, or parent methods, nor do you create the getIndex method. In your case you need to implement the roleNames method:
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QAbstractListModel>
#include <QDebug>
class User
{
QString m_macAddr;
public:
User(){}
User(const QString &mac): m_macAddr(mac){}
QString macAddr() const{return m_macAddr;}
void setMacAddr(QString &mac){m_macAddr = mac;}
};
class UserListModel : public QAbstractListModel
{
public:
enum roles{
macRole = Qt::UserRole + 1
};
explicit UserListModel(QObject *parent = nullptr)
: QAbstractListModel(parent){}
int rowCount(const QModelIndex &parent = QModelIndex()) const override {
if (parent.isValid())
return 0;
return m_users.count();
}
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override {
if (!index.isValid())
return QVariant();
if (index.row() < 0 || index.row() >= rowCount())
return QVariant();
const User &user = m_users[index.row()];
if(role == macRole)
return user.macAddr();
return QVariant();
}
QHash<int, QByteArray> roleNames() const override{
QHash<int, QByteArray> roles;
roles[macRole] = "mac";
return roles;
}
void addUser(const User &user){
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_users << user;
endInsertRows();
}
private:
QList<User> m_users;
};
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
UserListModel userlistModel;
QString mac = "12:3e:3w:4r:33";
userlistModel.addUser(User(mac));
userlistModel.addUser(User(mac));
userlistModel.addUser(User(mac));
userlistModel.addUser(User(mac));
QModelIndex ix = userlistModel.index(1, 0);
QVariant v = userlistModel.data(ix, UserListModel::macRole);
qDebug() << "===========" << v.toString();
engine.rootContext()->setContextProperty("usersModel", &userlistModel);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
main.qml
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ListView{
anchors.fill: parent
model:usersModel
delegate: Component
{
Text{
text: model.mac
}
}
}
}