Sort and filter a C++ model via QML functors?

后端 未结 2 1529
失恋的感觉
失恋的感觉 2021-01-20 23:47

I have a polymorphic (as in arbitrary roles) QObject model that is mostly instantiated declaratively from QML, as in this answer, and I would like to be able to hav

2条回答
  •  梦谈多话
    2021-01-21 00:42

    As you mentionned, you could use QJSValue. But that's pretty static. What if you want to use a filter like filter: function(o) { return o.size > slider.value; } with a dynamic slider ? You'll have to manually call invalidateFilter().

    As a more practical alternative, you could instead use QQmlScriptString as a property & QQmlExpression to execute it. Using QQmlExpression allows you to be notified of context changes with setNotifyOnValueChanged.

    Your syntax would change to be like so : filter: o.size > slider.value.

    If you are looking for an out of the box solution, I've implemented this in a library of mine : SortFilterProxyModel on GitHub

    You can take a look at ExpressionFilter & ExpressionSorter, those do the same as what you initially wanted. You can check the complete source code in the repo.

    How to use it :

    import SortFilterProxyModel 0.2
    
    // ...
    
    SortFilterProxyModel {
        sourceModel: model
        filters: ExpressionFilter  { expression: model.size > 3 }
        sorters: ExpressionSorter { expression: modelLeft.size < modelRight.size }
    }
    

    But as @dtech mentionned, the overhead of going back and forth between qml and c++ for each row of the model is quite noticeable. That's why I created more specific filters and sorters. In your case, we would use RangeFilter and RoleSorter :

    import SortFilterProxyModel 0.2
    
    // ...
    
    SortFilterProxyModel {
        sourceModel: model
        filters: RangeFilter  {
            roleName: "size"
            minimumValue > 3
            minimumInclusive: true
        }
        sorters: RoleSorter { roleName: "size" }
    }
    

    Doing like this, we have a nice declarative API and the parameters are only passed once from qml to c++. All the filtering and sorting is then entirely done on the c++ side.

提交回复
热议问题