Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt reimplement QSortFilterProxyModel::data() while model is using internalpointer()

Tags:

qt

I have a written model (myModel) using internalpointer() for his data() implementation. I want to filter a tree (based on myModel) using QSortFilterProxyModel,

I got it to work, only when i try to get any data from the tree my app crashes.

I think its because while calling the tree data, expecting to get the myModel indexModel, i get the myQSortFilterProxyModel indexModel.

myItem *myModel::getItem(const QModelIndex &index) const
{
    if (index.isValid()) {
        myItem *item = static_cast<myItem*>(index.internalPointer());
        if (item) return item;
    }
    return rootItem;
}

myModel data() using internalPointer()

QVariant myModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    if (role != Qt::DisplayRole && role != Qt::EditRole)
        return QVariant();

    myItem *item = getItem(index);

    return item->data(index.column());
}

setting the filter model between myModel ant the tree

void myTree::myInit()
{
...
    myModel *model = new myModel();
    proxyModel = new mySortFilterProxyModel(this);
    proxyModel->setSourceModel(model);
    this->setModel(proxyModel);
...

myTree is QTreeView subclass. I want to use tree->model() to get myModel model

how do I get the source model data?

like image 970
Ron Yano Avatar asked Jul 03 '26 18:07

Ron Yano


1 Answers

This approach won't work with proxy models, for the reason you pointed out. Internalpointer/id should only be accessed in methods that are guaranteed to get indexes passed that belong to the model itself, like data() etc.

A better approach to get an item for an index is pass it via a custom role:

 enum Roles {
     MyItemRole=Qt::UserRole
 };

 QVariant data( const QModelIndex& index, int role ) const {
      ...   
      if ( role == MyItemRole )
          return QVariant::fromValue<MyItem>( item ); 
         //MyItem or MyItem*, depending on whether it can be copied/has
         // value semantics or not
      ...
 }

And in using code:

 const MyItem item = index.data( MyModel::MyItemRole ).value<MyItem>();

You'll need to Q_DECLARE_METATYPE(MyItem) (or MyItem*) in a header and call qRegisterMetaType() at runtime, so that MyItem/MyItem* can be passed as QVariant.

This approach has the advantage that it will work regardless of any proxy models in between, and the code calling data doesn't even have to know about the proxies.

like image 131
Frank Osterfeld Avatar answered Jul 05 '26 07:07

Frank Osterfeld



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!