Important: Please read the Qt Code of Conduct -

QSortFilterProxyModel setData(), and signals issue [solved]

  • This was kind of done before in this thread:

    I would like to make sure I'm clear on how all of this works. This is my first Model/View project. I actually asked this question on qt-interest and got no help. I've found some stuff out since then.

    I have the following subclassed items: QTableView, QAbstractTableModel, with a QSortFilterProxyModel in between. Also a subaclassed QItemDelegate for painting.

    Entire rows will be either colored specifically based on their criteria (from any number of colums, sometimes a combination) or they will be hidden. This functionality works just fine. The problem comes when I update the criteria in a previously added row.

    An easy example would be a table showing ping data. Imagine I'm pinging 1,000 nodes once per 10 seconds. (This is hypothetical -- let's assume there's no weird latency issues). I have a filter set in place to only show me nodes with a ping time over 10ms. For fun, let's say I have another filter that will color each row based on IP. So if it's the first ping message I'm receiving for a given node, I will need to add this item to my model -- whether or not it is displayed (and a row is added) is up to he proxy.

    The flow would be that I add the item to the model, reimplemented filterAcceptsRow() is called. The ping time is checked against the filter. If ping time is > 10ms, filterAcceptsRow() returns true. The delegate's ::paint() is called. Once again, the ping data (which I've got mapped between the proxy & model) is checked against the filters. The delegate paints it a pretty shade of blue based on it's region. This happens 5 more times. My table would look something like this.

    node1 | 15ms |
    node2 | 15ms |
    node3 | 15ms |
    node4 | 15ms |
    node5 | 15ms |
    node6 | 15ms |

    Next ping message is from node3, with a ping time of 20ms. The model's reimplemented setData() is called, and if successful emits dataChanged( createIndex( row, 0 ), createIndex( row, columnCount() - 1 ) ). The result is fine but the process is not. See below.

    Next ping message is from node3 again, but with a ping time of 9ms. setData() is a again called, and dataChanged() again emitted. However, the proxy is left in the cold. He needs to check the data (ping time, specifically) against the filter to see if the row is kosher, which it no longer is.

    I've tried this a few ways, and none are working for me. The closest I got was model emits row_updated(int), which is connected to the proxy's slot. Calling invalidate() is easy, but it is expensive. Imagine if I had hundreds rows, any of which I wanted to see at one time. invadliating the proxy will run filterAcceptsRow() on each row, every time it's invalidated. Not an option.

    The proxy can run removeRows() and change the underlying data just fine. However, what I do at this point is beyond me. Do I run setData()? Do I reimplement setData()? What do I tell it changed? Technically everything in the viewport from row_that_changed,0 to last_visible_row,columnCount() - 1 needs to be repainted.

    Any ideas? Am I missing the point here? I actually messed around a little with running my subclassed QSortFilterProxy::setData() but it is coredumping when I do it. Not exactly sure why. gdb isn't giving me much info either. It seemsto be happening within Qt's meta calls.

  • Here's an updated to my blog post.

    I can successfully removeRows(), but it seems that I have to manually "shift" everything in my proxy model by running setData() on all rows >= the row which was removed. If I have thousands of rows, that's going to hurt. It also seems to break the idea of the model/view.

    Please correct me if I'm wrong.

  • Hi,

    in general it should work. To analyze this, a small reduced helper project would be useful :-(
    As I do much with Model-View, perhaps I will create one, but I can't guarantee :-)

  • I figured out the problem, finally. I had not reimplemented QSortFilterProxyModel::data() even though I had reimplemented data() on QAbstractTableModel. After doing that, it is now working much more predictably. So, I'm on to other problems. :)

Log in to reply