Implement QSortFilterProxyModel with own TreeModel?



  • Hi there,

    i have a own TreeModel whis is derived from QAbstractItemModel like in the QT Example (Editable TreeModel)

    Now i want to make my TreeView sortable when i click on the table headers. I figured out that i can reimplement the sort()-function on my own inside my model or i can use QSortFilterProxyModel.

    First what is the better or let's say mor practical way? i Think using QSortFilterProxyModel would be better, because i want to implement a filter function, too, which filtes the content of myTreeView. But i don't know how to integrate the QSortFilterProxyModel into my own Model. So i need there a little bit help from you. Would be great if someone could explain it in detail and maybe provide some small example code.

    Thanks a lot!


  • Qt Champions 2019



  • Thanks for the information. I tried wo work on it a little bit.
    I did a small example like this:

    I implemented the EditableTreeModel form my first post) - the official qt example and then my small code looks like this inside the mainwidow.cpp

    QStringList headers;
    headers << tr("Title") << tr("Description");
    model = new EditableTreeModel(headers, QString("Firtsname\tLastname\t"));
    
    
    QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel;
    proxyModel->setSourceModel(model);
    treeView->setModel(proxyModel);
    treeView->setSortingEnabled(true);
    

    So it works and sorting, too, if i add more data so that more rows where created but i have a problem, when i try to retrieve the data. I created a function which is called on double click inside a TreeView Item:

    void MainWindow::on_treeView_doubleClicked(const QModelIndex &index)
    {
    qDebug() << "on_treeView_doubleClicked called";
    qDebug() << model->data(index, Qt::DisplayRole);
    }
    

    Then i got the following output and error:

    on_treeView_doubleClicked called
    
    Trying to construct an instance of an invalid type, type id: 7890276
    

    So it seems there is a problem with getting the data. So what i'm doing wrong? If i dont use the QSortFilterProxyModel the correct data retrieved.


  • Lifetime Qt Champion

    Hi
    I think you need to use
    http://doc.qt.io/qt-5/qsortfilterproxymodel.html#mapToSource
    to look up data in the model.



  • @mrjj

    i think this was the problem:

    qDebug() << model->data(index, Qt::DisplayRole);
    

    i tried to get the datafrom the source model and not from the proxy model. After changing the line to getting data() from the proxy model it works and i get the right data. If i try to remove the selected row, the row (and data) will be removed from the underlying source model.


  • Lifetime Qt Champion

    @Opa114
    Yes, that also works if you ask the proxy.
    However, the model is unaware of the filtering so thats why
    the given index didnt work with model.



  • @mrjj
    yes i understand what the problem is, but if it works directly with the proxy model it is better for me to work with that.


  • Lifetime Qt Champion

    @Opa114
    Hi, nothing wrong working with the proxy :)



  • @mrjj
    Now i have another problem. I implemented a onDoubleClick Listener, which should return the data. My Treeview is set to expandAll(), because i have some TreeView entries which have children, like this structure:

    - Root 1
        - Child 1
    - Root 2
        - Child 2.1
        - Child 2.2
    - Root 3
    

    When i double click on one of the children my function return everytime the data from Root 1, so when i click on Child 2.2 i got the data from Root 1 and when i click on Child 1 i got the data from Root 1. I think something is worng with the indexes? But how can i solve this?



  • @Opa114 said in Implement QSortFilterProxyModel with own TreeModel?:

    I think something is worng with the indexes?

    Good guess, can you show us your code?



  • @VRonin said in Implement QSortFilterProxyModel with own TreeModel?:

    Good guess, can you show us your code?

    I solved it: I had to pass the parent index (tree structure), so the line should look like this:

    QVariant data = m_proxy->data(m_proxy->index(index.row(), 4, index.parent()));