Timmmm
Timmmm

Reputation: 96586

Filtering / sorting a QAbstractListModel in QML

I have a QAbstractListModel-derived C++ class which contains a list of two types of things, e.g. like this:

class MyList : public QAbstractListModel
{
    Q_OBJECT
public:
    MyList();

    int rowCount(const QModelIndex& parent = QModelIndex()) const override
    {
        return mData.size();
    }

    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override
    {
        int i = index.row();
        if (i < 0 || i >= mData.size())
            return QVariant(QVariant::Invalid);

        return QVariant::fromValue(mData[i]);
    }

private:
    QList<Something> mData;
};

Suppose the data has a boolean member so that in QML I can do something like this:

Repeater {
    model: myList
    Text {
        text: model.display.someBoolean ? "yes" : "no"
    }
}

My question is very simple. How do I make the list only show items for which someBoolean is true? I.e. how do I filter the list?

I'm aware of QSortFilterProxyModel but the documentation only mentions C++. Do I have to create a QAbstractItemModel* as a Q_PROPERTY of MyList and then set the QML model to it? Like this?

Repeater {
    model: myList.filteredModel

...

class MyList : public QAbstractListModel
{
    Q_OBJECT
    Q_PROPERTY(QAbstractItemModel* filteredModel READ filteredModel ... etc)
public:

Does anyone have any guidance or examples?

Note: I've seen this question. It doesn't answer the question and doesn't appear to be about QML anyway despite the title.

Upvotes: 3

Views: 5573

Answers (2)

Caleb Huitt - cjhuitt
Caleb Huitt - cjhuitt

Reputation: 14941

If you want a way to do visual filtering, you can have the view's delegate just not draw for items that shouldn't be visible.

Repeater {
    model: myList
    Text {
        text: model.display.someBoolean ? "yes" : "no"
    }
    delegate: {
        visible: model.someBoolean
        height: visible ? 30 /* or whatever height */ : 0
        // other drawing code here.
    }
}

This may have other visual artifacts (for example, if you have alternating row colors based on index, the rows may not alternate properly) but if you want a quick and dirty filter, it works.

Upvotes: 0

DmitryARN
DmitryARN

Reputation: 648

You need to subclass QSortFilterProxyModel and make a filtering inside it as documentation suggests. Then you need to assign the QSortFilterProxyModel object to the required QML object. This is how the QML object will recieve the filtered data.

Upvotes: 3

Related Questions