scx
scx

Reputation: 3937

Return custom user type from QAbstractItemModel

I have a QAbstractItemModel that wraps some custom data (a vector of pointers). I use this model with a QSortFilterProxyModel, QTreeView and such.

When connecting some other logic to the selectionChange signal, I need the user data. Not some view of it, the pointer itself.

I've added a special case to the data method. QVariant data(const QModelIndex &index, int role) const override

When I pass in -1 as a role, I return a pointer to my user type in the variant. It is quite hacky, there has to be a better "official" way to do this.

How does one return the underlying model data from a QModelIndex and such? Thank you.

Upvotes: 0

Views: 1687

Answers (2)

Dmitry
Dmitry

Reputation: 3143

Your current way is in fact quite close to what Qt proposes to use: you are passing -1 as a role to tell the model to return your custom data while Qt encourages you to use another value for the role: Qt::ItemDataRole enumeration ends with Qt::UserRole item equal to 0x0100. As the documentation says, it is the first role that can be used for application-specific purposes. So instead of passing -1 to the model you could pass Qt::UserRole. Should you ever need to use some other kind of application-specific data, use Qt::UserRole + 1 as a role. For others you can use Qt::UserRole + N.

There's, however, another way: as one of the comments points out, if you definitely know which model is used in the view, you can simply cast QAbstractItemModel to your particular model and use some model-specific API to extract the data you need:

void MyView::selectionChanged(const QItemSelection & selected, const QItemSelection & deselect)
{
    MyModel * myModel = qobject_cast<MyModel*>(model());
    if (!myModel) {
        // Whoops, something went wrong, not the right model!
        <...> // process it somehow
        return;
    }

    <...> // Use myModel to retrieve the required data using convenient model-specific API
}

If you need to get the model from QModelIndex, just use qobject_cast as shown above on QModelIndex::model().

Upvotes: 2

dtech
dtech

Reputation: 49289

The only hacky thing about it is that you are passing an integer explicitly. I use models that return pointers to the actual object all the time, simply by dedicating a particular dataObject role, or however you chose to name it.

Upvotes: 0

Related Questions