[Interest] Proxied view not updating live when source model does

Murphy, Sean Sean.Murphy at centauricorp.com
Mon Sep 20 19:15:45 CEST 2021

I'm having an issue where my proxy model and its associated view aren't updating live when changes 
are made in the source model.

My proxy model simply is attempting to invert the rows of the source model. So it inherits from a 
QSortFilterProxyModel and implements mapFromSource() and mapToSource() as follows:

    QModelIndex invertRowsModel::mapFromSource(const QModelIndex &sourceIndex) const
        if(sourceIndex.isValid() && rowCount() > 0)
            return this->index(rowCount() - sourceIndex.row() - 1, sourceIndex.column());

        return QModelIndex();

    QModelIndex invertRowsModel::mapToSource(const QModelIndex &proxyIndex) const
        if(proxyIndex.isValid() && sourceModel() && rowCount() > 0)
            return sourceModel()->index(rowCount() - proxyIndex.row() - 1, proxyIndex.column());

        return QModelIndex();

I load up my source model with some data, connect the models up to their respective views, 
connect the source model to the proxy and launch the application. The original views are 
correct - the proxied rows are flipped when compared to the source model. But then if the 
user makes a change to some of the data in the source model's view, the corresponding index 
in proxy model's view is NOT updated automatically. HOWEVER, if the user then clicks within 
the proxy view, or clicks outside of my application, the proxy model will then repaint and the 
updated information is correctly shown. 

I've attached a minimal example that shows the behavior. Things to note:  
1. When the source model emits its dataChanged(), this seems to trigger a dataChanged() 
  emission in the proxy model as well. The weird (at least to me) thing is that both of those 
  signals have the SAME model index row & column numbers. I would have expected that 
  when the source model emits data changed, that the proxy model would translate the 
  source model's indices into the proper proxy model's indices via the mapFromSource() 
  function and then emit dataChanged() with those indices. I've got debug statements in 
  my example to illustrate that no dataChanged() translation is happening - if the user 
  updates data in row 0 in the source model's view, the proxy model also emits that data 
  changed in its row 0, but that isn't the correct row for the proxy.
2. We discovered that if we connect the proxy model's dataChanged() signal to a custom 
  slot within the proxy model, and have that slot emit layoutChanged() then we can get 
  the live update behavior when the source model updates. This is at line 25 of 
  invertrowsmodel.cpp. It's commented out initially, but if you uncomment it and re-run 
  the app then proxy view does update instantly. Other similar signals would work as well - 
  we just need something triggers the proxy view to refresh the data in the proxied view, 
  but we don't think we should really have to do this...
3. I have a second view attached to the source model and both source model views update 
  each other live - changes in one source model view are instantly updated in the other 
  source model view, but not in the proxy model view without further user interaction 
  (or by emitting that layoutChanged() signal)

Any thoughts as to why the proxy model isn't updating correctly?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: invertRowsModel.zip
Type: application/x-zip-compressed
Size: 5773 bytes
Desc: invertRowsModel.zip
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20210920/7b771ffa/attachment.bin>

More information about the Interest mailing list