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

Using a List<object> to feed a QAbstractListModel



  • Hello!

    I'm building a desktop application and want to persist some data using classes. It's just for temporary data.
    I want to feed a model to delegate data inside a ListView with the class objects
    The issue is I've not been able to update the model and I don't know why. Could anyone help me?

    1. If I load data into the class constructor, it works. :(
    2. If I try to attribute a list and emit change or use beginInsertRows, it doesn't work. :(

    EDIT:

    After 2 days of thinking about it, I decided to change lProduct as a static variable and it worked. But I know that I misunderstanding about the class scope (how I instantiate the model correctly) and it is a signal that I must back to study C++ language.


    main.cpp

        QAbstractListModel *modelDataSession = new DataObjectModel(nullptr);
        engine.rootContext()->setContextProperty("productDataModel", modelDataSession);
    

    dataobjectmodel.h

    #ifndef DATAOBJECTMODEL_H
    #define DATAOBJECTMODEL_H
    
    #include <QObject>
    #include <QAbstractListModel>
    
    class DataObjectModel : public QAbstractListModel
    {
        Q_OBJECT
        Q_ENUMS(MyRoles)
    public:
    
        explicit DataObjectModel(QObject *parent = nullptr);
    
        enum MyRoles {
            ProductId = Qt::UserRole + 1,
            ProductName,
            ProductPhoto,
            ProductPrice,
            ProductQuantity
        };
    
        using QAbstractListModel::QAbstractListModel;
    
        QHash<int, QByteArray> roleNames() const override {
    
             qDebug() << "roleNames";
    
            return {
                { ProductId, "id" },
                { ProductName, "name"    },
                { ProductPhoto, "photo"  },
                { ProductPrice, "price"  },
                { ProductQuantity, "quantity" },
            };
        }
    
        int rowCount(const QModelIndex & parent = QModelIndex()) const override {
            qDebug() << "rowCount Updating datamodel inside data";
    
            if (parent.isValid()) {
                return 0;
            }
            return lProduct.size();
        }
    
        bool setData(const QModelIndex &index, const QVariant &value, int role) override;
        QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
    
        QList<product> getLProduct();
        void setLProduct(QList<product> &listProducts);
    
    private:
        QList<product*> lProduct;
    
    signals:
    
    public slots:
    
        void updateModel();
    };
    
    #endif // DATAOBJECTMODEL_H
    
    

    dataobjectmodel.c

    #include "dataobjectmodel.h"
    
    DataObjectModel::DataObjectModel(QObject *parent) : QAbstractListModel(parent)
    {
        // this works 
        lProduct << new product(1,"nome", "photo.png", 1.45, 10);
        lProduct << new product(2,"nome 2", "photo.png", 1.9, 10);
    }
    
    bool DataObjectModel::setData(const QModelIndex &index, const QVariant &value, int role)
    {
        if (!hasIndex(index.row(), index.column(), index.parent()) || !value.isValid())
            return false;
    
        product item = *lProduct[index.row()];
    
        switch (role) {
        case ProductId:
            item.setId(value.toInt());
            break;
        case ProductName:
            item.setName(value.toString());
            break;
        case ProductPhoto:
            item.setPhoto(value.toString());
            break;
        case ProductPrice:
            item.setPrice(value.toDouble());
            break;
        case ProductQuantity:
            item.setQuantity(value.toInt());
            break;
        default:
            return false;
        }
    
        emit dataChanged(index, index, { role } );
    
        return true;
    }
    
    QVariant DataObjectModel::data(const QModelIndex &index, int role) const
    {
        if (!hasIndex(index.row(), index.column(), index.parent()))
            return {};
    
        const product product = *lProduct[index.row()];
    
        switch (role) {
        case ProductId:
            return product.getId();
        case ProductName:
            return product.getName();
        case ProductPhoto:
            return product.getPhoto();
        case ProductPrice:
            return product.getPrice();
        case ProductQuantity:
            return product.getQuantity();
        default:
            return {};
        }
    
    }
    
    
    void DataObjectModel::setLProduct(QList<product> &listProducts)
    {
        QList<product>::iterator i;
        lProduct.clear();
        beginInsertRows(QModelIndex(), 0, listProducts.length()-1);
        for( i= listProducts.begin(); i != listProducts.end(); i++) {
            qDebug() << "Item " << (*i).getName();
            lProduct << &(*i);
        }
         endInsertRows();
    
         emit dataChanged(QModelIndex(),QModelIndex());
    }
    

  • Lifetime Qt Champion

    Hi and welcome to devnet,

    @carpajr said in Using a List<object> to feed a QAbstractListModel:

    product item = *lProduct[index.row()];

    Looks like you are working on a copy of your object and not the original. Out of curiosity, why are you dereferencing it ?



  • @SGaist said in Using a List<object> to feed a QAbstractListModel:

    Hi and welcome to devnet,

    Thank you, @SGaist !

    @SGaist said in Using a List<object> to feed a QAbstractListModel:

    Looks like you are working on a copy of your object and not the original. Out of curiosity, why are you dereferencing it ?

    I tried everything to understand how this mechanism works. I've removed dereferencing in the variable later.

    The issue seems to be here

    void DataObjectModel::setLProduct(QList<product> &listProducts)
    {
      // I tried before
      // lProduct = listProduct;
    
        QList<product>::iterator i;
        lProduct.clear();
        beginInsertRows(QModelIndex(), 0, listProducts.length()-1);
        for( i= listProducts.begin(); i != listProducts.end(); i++) {
            qDebug() << "Item " << (*i).getName();
            lProduct << (*i);
        }
         endInsertRows();
    
         emit dataChanged(QModelIndex(),QModelIndex());
    }
    

Log in to reply