QSortFilterProxyModel doesn't emit rows inserted/removed when it is invalidated



  • Imagine you have a model that contains a list of QDateTime objects. Then you have a QSortFilterModel that filters only the objects that are past ones or future ones.

    Then if you call invalidate() at some point in time where you expect the rowCount() to change, since some of the objects have become past/future ones, the rowsInserted() or rowsRemoved() is not emitted by the QSortFilterProxyModel. A workaround is to subclass the QSortFilterProxyModel instance and make the following helper function:
    @
    void SortFilterProxyModel::forceInvalidate()
    {
    this->beginResetModel();
    this->invalidate();
    this->endResetModel();
    }
    @

    Another way would be to track down the removed and added rows and thus emit the rowsRemoved/rowsInserted signals if needed:
    @
    void SortFilterProxyModel::forceInvalidate()
    {
    // clear the member variables that keep track of removed/added rows
    this->invalidate();
    // check the member variables that keep track of removed/added rows and emit the needed signals
    }
    @

    So, any suggestions why rowsRemoved/rowsInserted are not called?



  • I'm having a similar problem. I have a QSortFilterProxyModel sorting and filtering a QAbstractListModel. I have dynamic sorting turned on and my QML that uses the proxy model will add/remove and sort rows as expected. However, when I attempt to connect to signals rowsInserted or rowsRemoved on the C++ side, the signal never gets emitted. I've tried the connection in a number of different ways, both old style of connecting and new, inside the constructor or in another function, etc.

    I am assuming that QML is using rowsInserted and rowsRemoved when adding/removing rows in the ListView, so I must be doing something wrong in the connecting.

    Here's what I'm doing:
    Neither QAbstractItemModel nor QAbstractProxyModel have a property for the number of rows or columns. I am attempting to inherit QSortFilterProxyModel and add the property. The derived class is attempting to connect to its own base class's signals a so it can send an emit of count changed.

    Here is some code:

    @class CountedSortFilterProxyModel : public QSortFilterProxyModel
    {
    Q_OBJECT

    Q_PROPERTY(int count READ count NOTIFY countChanged)
    

    public:
    explicit CountedSortFilterProxyModel(QAbstractItemModel* sourceModel, QObject *parent = 0)
    {
    setSourceModel(sourceModel);
    connect(this, SIGNAL(rowsInserted(const QModelIndex&, int, int)), this, SLOT(rowsChanged(const QModelIndex&, int, int)));
    connect(this, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), this, SLOT(rowsChanged(const QModelIndex&, int, int)));
    }

    signals:
    void countChanged();

    public slots:
    int count() const {return rowCount();}
    void rowsChanged(const QModelIndex & parent, int start, int end) {emit countChanged();}
    };@

    EDIT:
    I tried the same type connection on a class derived from QAbstractListItem and it catches rowsInserted and rowsRemoved signals just fine. So it's something about QSortFilterProxyModel where it does not emit the signals.



  • I'm having a similar problem. I have a QSortFilterProxyModel sorting and filtering a QAbstractListModel. I have dynamic sorting turned on and my QML that uses the proxy model will add/remove and sort rows as expected. However, when I attempt to connect to signals rowsInserted or rowsRemoved on the C++ side, the signal never gets emitted. I've tried the connection in a number of different ways, both old style of connecting and new, inside the constructor or in another function, etc.

    I am assuming that QML is using rowsInserted and rowsRemoved when adding/removing rows in the ListView, so I must be doing something wrong in the connecting.

    Here's what I'm doing:
    Neither QAbstractItemModel nor QAbstractProxyModel have a property for the number of rows or columns. I am attempting to inherit QSortFilterProxyModel and add the property. The derived class is attempting to connect to its own base class's signals a so it can send an emit of count changed.

    Here is some code:

    @class CountedSortFilterProxyModel : public QSortFilterProxyModel
    {
    Q_OBJECT

    Q_PROPERTY(int count READ count NOTIFY countChanged)
    

    public:
    explicit CountedSortFilterProxyModel(QAbstractItemModel* sourceModel, QObject *parent = 0)
    {
    setSourceModel(sourceModel);
    connect(this, SIGNAL(rowsInserted(const QModelIndex&, int, int)), this, SLOT(rowsChanged(const QModelIndex&, int, int)));
    connect(this, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), this, SLOT(rowsChanged(const QModelIndex&, int, int)));
    }

    signals:
    void countChanged();

    public slots:
    int count() const {return rowCount();}
    void rowsChanged(const QModelIndex & parent, int start, int end) {emit countChanged();}
    };@

    EDIT:
    I tried the same type connection on a class derived from QAbstractListItem and it catches rowsInserted and rowsRemoved signals just fine. So it's something about QSortFilterProxyModel where it does not emit the signals.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.