c++qtqabstractitemmodelqmodelindex

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.


Solution

  • 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().