Home > other >  Get model data by role name
Get model data by role name

Time:01-12

There's a model (currently it's derived from QAbstractItemModel, but it can also be any model that provides named data roles) from which I need to get data, knowing a row/column and a role name. I can get index by row and column:

const index = mYModel.index(row, column);

I can also get data by index and role:

const data = myModel.data(index, role);

I haven't found any way to somehow find out the role by its name. Am I missing something or is this impossible at all?

Here's the pseudocode:

// MyModel.h
class MyModel: public QAbstractItemModel
{
public:
    QHash<int, QByteArray> roleNames() const override
    {
        QHash<int, QByteArray> roleNames;
        roleNames[Qt::UserRole   1] = "someRole";
        return roleNames;
    }
};

// Item.qml
Item {
    ListView {
        model: myModel
        delegate: myDelegate
    }
    
    Button {
        onClicked: {
            const rowIndex = Math.random(myModel.count);
            // here I need to get data for item at
            // row rowIndex, column 0 and role name "someRole"
        }
    }
}

CodePudding user response:

Since your model is used in a ListView, I would use the itemAtIndex function of that ListView:

ListView {
    id: theList
    model: myModel

    delegate: UnknownItem {
        property var theModel: model //have to add this property
    }
}

Button {
    onClicked: {
        let item = theList.itemAtIndex(theList.currentIndex)
        if(item) {
            console.log("clicked", item.theModel.title)
        }
    }
}

Note that this works with integer index, not on the QModelIndex you have in your question.

CodePudding user response:

I don't see any built-in features to do that. So the easiest solution for me is to create a helper class that will retrieve the necessary data from the given model.

Helper class:

class ModelHelper : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QVariant model READ model WRITE setModel)

public:
    explicit ModelHelper(QObject *parent = nullptr)
        : QObject(parent)
    {}

    QVariant model() const
    {
        return m_model;
    }

    void setModel(const QVariant &model)
    {
        m_model = model;
    }

    Q_INVOKABLE QVariant data(int row, const QString &roleName) const
    {
        if (const QAbstractItemModel *model = m_model.value<QAbstractItemModel*>()) {
            const QHash<int, QByteArray> roleNames = model->roleNames();
            for (auto i = roleNames.cbegin(); i != roleNames.cend();   i) {
                if (i.value() == roleName) {
                    return model->data(model->index(row, 0), i.key());
                }
            }
        }

        return QVariant();
    }

private:
    QVariant m_model;
};

//...

qmlRegisterType<ModelHelper>("Test.ModelUtils", 1, 0, "ModelHelper");

How to use:qml

import Test.ModelUtils 1.0

//...

ListModel {
    id: listModel

    ListElement { name: "John" }
    ListElement { name: "Mike" }
}

ModelHelper {
    id: modelHelper
    model: listModel
}

Button {
    text: "Print Data"

    onClicked: {
        const data = [];
        for (let i = 0; i < listModel.count;   i) {
            data.push(modelHelper.data(i, "name"));
        }
        console.log(data);
    }
}
  • Related