Qt Model/View Without the Magic
I added sorting to a log viewer with QSortFilterProxyModel, clicked the third visible row, and opened the wrong log entry. The view had done exactly what I asked. I had used a proxy row as an index into the source list.
A proxy has its own indexes and its own order. Once sorting or filtering is active, row 3 in the view says nothing useful about row 3 in the source. The handoff needs to be explicit:
QModelIndex proxyIndex = view->currentIndex();
QModelIndex sourceIndex = proxy->mapToSource(proxyIndex);
if (sourceIndex.isValid())
openEntry(sourceIndex.row());
The reverse direction matters too. When the parser reports a source index that should be selected, mapFromSource() finds its current position in the proxy. Calling view->setCurrentIndex() with the source index may look plausible, but the index still belongs to a different model and should not be handed to that view.
My next bug was staler. I changed a severity threshold stored by the proxy, emitted a signal from the dialog, and nothing disappeared. The filter result was cached. After changing the threshold, the proxy had to invalidate its filtering so that filterAcceptsRow() ran again:
void LogProxy::setMinimumLevel(int level)
{
if (minimumLevel == level)
return;
minimumLevel = level;
invalidateFilter();
}
Resetting the source model also made the screen update, but it was the wrong hammer. It discarded selections and told every attached view that the source structure had vanished when only the proxy’s mapping was stale.
Dynamic sorting has a similar edge. If a source value used by the sort or filter changes, the source must emit dataChanged() for that value. The proxy can then reconsider the affected mapping. Without that notification, asking the proxy to repaint merely gives it another chance to use the same old answer.
Selections and drag-and-drop code are where I now look first for mapping mistakes. Anything crossing the proxy boundary should say which side its index belongs to. That small bit of bookkeeping beats opening the wrong error at two in the morning.