Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. QAbstractListModel example with MVVM pattern

QAbstractListModel example with MVVM pattern

Scheduled Pinned Locked Moved Solved QML and Qt Quick
qmlc++mvvm
1 Posts 1 Posters 576 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    AROH
    wrote on last edited by AROH
    #1

    I am trying to display the list of items that comes from QAbstractListModel on a QML List View using the MVVM pattern. To keep it simple my reading/accessing architecture will be something like this-View(QML-ListView)->ViewModel(C++-Binding Properties defined)->Model(C++ read data from DevicesListModel)->DevicesListModel(QAbstractListModel)class.

    The DevicesListModel receives items from lower layers.

    I am trying with writing a sample but ended up not knowing how to move further, any help in completing the example to achieve the desired result is much helpful.

    DeviceListModel.h

    #ifndef DEVICESLISTMODEL_H
    #define DEVICESLISTMODEL_H
    
    #pragma once
    
    #include <QObject>
    #include <QAbstractListModel>
    
    class QQmlEngine;
    class QJSEngine;
    
    class DevicesListModel : public QAbstractListModel
    {
        Q_OBJECT
        Q_DISABLE_COPY(DevicesListModel)
    public:
    
        enum DeviceModelRoles {
            NameRole = Qt::UserRole + 1,
            AddressRole,
            TypeRole
        };
    
        static QObject *qobject_singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
        {
            Q_UNUSED(engine)
            Q_UNUSED(scriptEngine)
            return new DevicesListModel();
        }
    
        // Basic functionality:
        int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    
        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    
    signals:
        void countChanged(int count);
    
    private slots:
        void devicesChanged(QVariantList devices);
    
    public slots:
    
    private:
        explicit DevicesListModel(QObject *parent = nullptr);
    
        ~DevicesListModel();
    
        QList<QVariantMap> m_device_list;
        QHash<int, QByteArray> m_roles;
    
    };
    
    #endif // DEVICESLISTMODEL_H
    

    DeviceListModel.cpp

    #include "deviceslistmodel.h"
    #include <QDebug>
    
    DevicesListModel::DevicesListModel(QObject *parent) : QAbstractListModel(parent){
    
        //QObject::connect(DeviceDiscovery::instance(), SIGNAL(devicesChanged(QVariantList)), this, SLOT(devicesChanged(QVariantList)));
    
        m_roles[NameRole] = "name";
        m_roles[AddressRole] = "address";
        m_roles[TypeRole] = "type";
    
    }
    
    DevicesListModel::~DevicesListModel()
    {
        m_device_list.clear();
    }
    
    int DevicesListModel::rowCount(const QModelIndex &parent) const
    {
        if (parent.isValid())
            return 0;
    
        return m_device_list.count();
    }
    
    QVariant DevicesListModel::data(const QModelIndex &index, int role) const
    {
        if (!index.isValid())
            return QVariant();
    
        QVariantMap device = m_device_list.at(index.row());
    
        switch (role) {
            case NameRole: {
                return QVariant::fromValue(device["name"].toString());
            }
            case AddressRole: {
                return QVariant::fromValue(device["address"].toString());
            }
            case TypeRole: {
                return QVariant::fromValue(device["type"].toString());
            }
            default: {
                return QVariant::fromValue(QString("Unkown Role"));
            }
        }
    }
    
    void DevicesListModel::devicesChanged(QVariantList devices)
    {
        // Add device
        for (QVariant device: devices) {
            QVariantMap deviceMap = device.toMap();
            QString name = deviceMap["name"].toString();
            QString address = deviceMap["address"].toString();
            QString type = deviceMap["type"].toString();
    
            qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << name << address << type;
    
            if (!m_device_list.contains(deviceMap))
            {
                m_device_list.append(deviceMap);
            }
        }
    
        // Remove device
        for (int i = 0; i < m_device_list.count(); i++) {
    
            if (!devices.contains(QVariant::fromValue(m_device_list[i])))
            {
                m_device_list.removeAt(i);
            }
        }
    
        emit countChanged(m_device_list.count());
    }
    

    DeviceModel.h

    #ifndef DEVICESMODEL_H
    #define DEVICESMODEL_H
    
    #include <QObject>
    
    class DevicesModel : public QObject
    {
        Q_OBJECT
    private:
        QStringList _devicesList;
    
    public:
        virtual ~DevicesModel() {}
        explicit DevicesModel(QObject *parent = nullptr);
    
        //QString getDevicesListModelItems() const {return _devicesList;}
    
        void  readListItemsFromDeviceListModel(){
            //how to read from devicesListModel and Store here, so that View can read the data using properties defined in the deviceViewModel
        }
    
    signals:
    
    public slots:
    };
    
    #endif // DEVICESMODEL_H
    

    DeviceModel.cpp

    #include "devicesmodel.h"

    DevicesModel::DevicesModel(QObject *parent) : QObject(parent)
    {

    }

    DeviceViewModel.h

    #ifndef DEVICEVIEWMODEL_H
    #define DEVICEVIEWMODEL_H
    
    #include <QObject>
    #include <QList>
    #include "devicesmodel.h"
    
    class DeviceViewModel : public QObject
    {
        Q_OBJECT
    
    private:
    
        DevicesModel _devicesModel;
        //Q_PROPERTY(QList devicesListModel READ devicesListModel WRITE setDevicesListModel NOTIFY devicesListModelChanged)
    
        //QList m_devicesListModel;
    
    public:
        explicit DeviceViewModel(const DevicesModel& devicesModel);
    
        virtual ~DeviceViewModel(){}
    
    
    //QList devicesListModel() const;
    
    signals:
    
    //void devicesListModelChanged(QList devicesListModel);
    
    public slots:
    //void setDevicesListModel(QList devicesListModel);
    };
    
    #endif // DEVICEVIEWMODEL_H
    

    DeviceViewModel.cpp

    #include "deviceviewmodel.h"
    
    DeviceViewModel::DeviceViewModel(const DevicesModel& devicesModel)
    {
    
    }
    
    /*QList DeviceViewModel::devicesListModel() const
    {
        return m_devicesListModel;
    }
    
    void DeviceViewModel::setDevicesListModel(QList devicesListModel)
    {
        if (m_devicesListModel == devicesListModel)
            return;
    
        m_devicesListModel = devicesListModel;
        emit devicesListModelChanged(m_devicesListModel);
    }*/
    

    main.cpp

    #include <QGuiApplication>
    #include <QQmlContext>
    #include <QQmlApplicationEngine>
    
    #include "deviceviewmodel.h"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QGuiApplication app(argc, argv);
    
        DevicesModel deviceMod;
        DeviceViewModel deviceViewModell(deviceMod);
    
        QQmlApplicationEngine engine;
        engine.rootContext()->setContextProperty("listModel", &deviceViewModell);
        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
    import QtQuick.Controls 2.2
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        ListView{
            id: devicesView
            anchors.fill: parent.fill
            model: listModel
            delegate: Button{
                text: (listModel.Name+listModel.type+listModel.address)
                //Binding { target: listModel; property: "labelText"; value:  }
    
            }
        }
    }
    

    Thanks in advance !!

    1 Reply Last reply
    0
    • A AROH has marked this topic as solved on

    • Login

    • Login or register to search.
    • First post
      Last post
    0
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Get Qt Extensions
    • Unsolved