QAbstractListModel need help with data() and setData()



  • Hello,

    I have a QAbstractListModel with own roles for my values that should be editable:
    this is the model:

    #include <QAbstractListModel>
    #include <QStringList>
    #include "datasourceobject.h"
    
    
    class datasourcemodel : public QAbstractListModel
    {
        Q_OBJECT
    public:
        enum datasourceRoles {
            idRole = Qt::UserRole + 1,
            nameRole,
            displaynameRole,
            valueRole
        };
    
        datasourcemodel(QObject *parent = nullptr);
    
        void addDataSourceObject(const DataSourceObject &DataSourceObject);
    
        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);
    
        //Qt::ItemFlags flags(const QModelIndex &index) const;
    
    protected:
        QHash<int, QByteArray> roleNames() const;
    
    private:
        QList<DataSourceObject> m_DataSourceObjects;
    
    };
    
    #include "datasourcemodel.h"
    
    datasourcemodel::datasourcemodel(QObject *parent)
        : QAbstractListModel (parent)
    {
    }
    
    void datasourcemodel::addDataSourceObject(const DataSourceObject &DataSourceObject){
        beginInsertRows(QModelIndex(), rowCount(), rowCount());
        m_DataSourceObjects << DataSourceObject;
        endInsertRows();
    }
    
    int datasourcemodel::rowCount(const QModelIndex & parent) const{
        Q_UNUSED(parent);
        return m_DataSourceObjects.count();
    }
    
    QVariant datasourcemodel::data(const QModelIndex & index, int role) const{
        if(index.row() < 0 || index.row() >= m_DataSourceObjects.count())
            return  QVariant();
    
        const DataSourceObject &dataSourceObject = m_DataSourceObjects[index.row()];
        if (role == idRole)
            return dataSourceObject.id();
        else if (role == nameRole)
            return dataSourceObject.name();
        else if (role == displaynameRole)
            return dataSourceObject.displayname();
        else if (role == valueRole)
            return dataSourceObject.value();
        return QVariant();
    }
    
    bool ::datasourcemodel::setData(const QModelIndex &index, const QVariant &value, int role){
    
        DataSourceObject &dataSourceObject = m_DataSourceObjects[index.row()];
        if(role == idRole){
            dataSourceObject.setid(value.toInt());
            return true;
        }
        else if(role == nameRole){
            dataSourceObject.setname(value.toString());
            return true;
        }
        else if(role == displaynameRole){
            dataSourceObject.setdisplayname(value.toString());
            return true;
        }
        else if(role == valueRole){
            dataSourceObject.setvalue(value.toDouble());
            return true;
        }
        return false;
    
    }
    
    
    QHash<int, QByteArray> datasourcemodel::roleNames() const {
        QHash<int, QByteArray> roles;
        roles[idRole] = "id";
        roles[nameRole] = "name";
        roles[displaynameRole] = "displayname";
        roles[valueRole] = "value";
        return roles;
    }
    

    This is the object thats stored in the model:

    #include "datasourceobject.h"
    
    DataSourceObject::DataSourceObject(const int &id, const QString &name, const QString &displayname, const double &value)
        : m_id(id), m_name(name), m_displayname(displayname), m_value(value)
    {
    
    }
    
    
    int DataSourceObject::id() const
    {
        return m_id;
    }
    
    void DataSourceObject::setid(const int &id)
    {
        if (id != m_id) {
            m_id = id;
            //emit idChanged();
        }
    }
    
    
    QString DataSourceObject::name() const
    {
        return m_name;
    }
    
    void DataSourceObject::setname(const QString &name)
    {
        if (name != m_name) {
            m_name = name;
            //emit nameChanged();
        }
    }
    
    
    QString DataSourceObject::displayname() const
    {
        return m_displayname;
    }
    
    void DataSourceObject::setdisplayname(const QString &displayname)
    {
        if (displayname != m_displayname) {
            m_displayname = displayname;
            //emit displaynameChanged();
        }
    }
    
    
    double DataSourceObject::value() const
    {
        return m_value;
    }
    
    void DataSourceObject::setvalue(const double &value)
    {
        //if(value != m_value) {
            m_value = value;
            //emit valueChanged();
        //}
    }
    

    I can't get datasourcemodel::data and datasourcemodel::setData to work.
    I can't figure out how to tell which role should be edited.


  • Moderators

    @Slash200 said in QAbstractListModel need help with data() and setData():

    I can't figure out how to tell which role should be edited.

    Can you explain this? For editing normally Qt::EditRole is used.



  • @Christian-Ehrlicher

    I probably have a little problem understanding how the role concept works.
    I tried to show a object in with: qWarning() << m_DataSourceModel.data(childIndex, Qt::DisplayRole); where Childindex is my desired object

    But it return QVariant(Invalid)

    Also I tried editing with m_DataSourceModel.setData(childIndex,QVariant(value), Qt::EditRole); but it does not work

    But I don't understand how I edit a value in my Child and how to use

    QHash<int, QByteArray> datasourcemodel::roleNames() const {
        QHash<int, QByteArray> roles;
        roles[idRole] = "id";
        roles[nameRole] = "name";
        roles[displaynameRole] = "displayname";
        roles[valueRole] = "value";
        return roles;
    }
    

    I read this documentation but it's very hard to understand for me


  • Qt Champions 2017

    Are you using the model with Qt or QML ?
    You have defined the roles starting from Qt::userRole + 1. Inside the data function you are returning the data based on this numbers. When you pass Qt::DisplayRole, it is asking for value passing the value as 0(zero). Inside your data(..) function nothing matches for 0. So it returns invalid QVariant.

    Just quickly check this, try like following and see how it works.
    enum datasourceRoles {
    idRole=0,
    nameRole,
    displaynameRole,
    valueRole
    };



  • @dheerendra
    Hi!
    I'm using it as datamodel for QML.

    I removed the "+ 1" in my programm and it's still returning invalid.

    When I change idRole to 0 , the program crashed with a index out of range error


  • Qt Champions 2017

    If you are using for QML, not sure why you are calling the data function directly. Since it is crashing you must be passing some null index to fetch the value. To make your like simple, I have given small example. Try this. See how model works. Based on this modify your program.

    class MyModel : public QAbstractListModel
    {
    public:
    enum datasourceRoles {
    idRole = Qt::UserRole + 1,
    nameRole,
    displaynameRole,
    valueRole
    };
    MyModel();
    QVariant data(const QModelIndex &index, int role) const;
    int rowCount(const QModelIndex &parent) const;
    QModelIndex getIndex(int r, int c, void *p);
    private :
    int a[100];
    };

    QVariant MyModel::data(const QModelIndex &index, int role) const
    {
    int v = a[index.row()];
    QVariant val;
    switch(role){

    case idRole:
         val = v;break;
    case nameRole:
         val = v+10;break;
    case displaynameRole:
        val = v+20;break;
    case valueRole :
        val = v+30;break;
    }
    
    return val;
    

    }

    int MyModel::rowCount(const QModelIndex &parent) const
    {
    return 10;
    }

    QModelIndex MyModel::getIndex(int r, int c, void *p)
    {
    return this->createIndex(r,c,p);
    }

    =====main.cpp====
    MyModel *model1 = new MyModel;
    QModelIndex id1 = model1->getIndex(1,0,0);
    QVariant v1 = model1->data(id1,Qt::UserRole+1);
    QVariant v2 = model1->data(id1,Qt::UserRole+2)
    qDebug() << "-----> " << v1.toInt() <<v2.toInt() << endl;



  • @dheerendra
    I have to modify the data in Qt and display it with QML. thats why I need display and editing in Qt.
    Qt is getting data via network and has to store it in this model(changes the values-variable of the objects-no other variable of the objects)

    With your solution the data isn't displayed corectly in QML and debugging shows values but not the correct ones.


  • Qt Champions 2017

    Can you show your sample in qml ?



  • It is now working.
    I can see the data beeing updatet in den debug output. But the data isn't updated in QML



  • @Slash200 "The dataChanged() signal should be emitted if the data was successfully set." (See QAbstractItemModel::setData)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.