Hi Bogdan,

Perhaps I misunderstood, but isn't `QPersistentModelIndex` Qt's current solution to your motivational example of needing to keep a model index beyond the current event loop tick? How does it currently fall short?

My understanding is that `QModelIndex` is intended as a lightweight and cheap to copy reference into a model as it exists at the moment it was created, very much akin to a STL iterator. I think that having it hold arbitrary data, or participate in the ownership of the model data, goes against that.

Best,
Igor

On 01/07/2026 16:02, Bogdan Vatra via Development wrote:
Hello there,

I'd like to propose a new accessor on QModelIndex for Qt 7 and get feedback
from the list:

QVariant QModelIndex::internalData() const;
or
std::any QModelIndex::internalData() const; // as std::any is 1/2 of
sizeof(QVariant).

Why?
QModelIndex currently exposes two ways for a model to attach opaque context to
an index:

   quintptr QModelIndex::internalId() const;
   void *QModelIndex::internalPointer() const;

Both work well for *static* model content, where the model's backing data
lives for as long as the model itself.
They fall short for *dynamic* models, where individual items can be created,
moved, or destroyed independently of any QModelIndex that currently references
them.

Let me give you an example which will randomly crash a QSortFilterProxyModel:

// main loop has a QAbstractItemModel::dataChanged (or any other QAIM signal
which will reset the idx internalPointer) event posted, e.g by another thread
// get an idx
myView->setCurrentIndex(idx);
myView->scrollTo(idx); // At this point there is no way to know if idx is
still valid. It depends on what `myView->setCurrentIndex(idx);` is doing and
there is no way to know if internalPointer is still valid or not. If inside of
that method QCoreApplication::processEvents is called, myView->scrollTo(idx)
gets an invalid idx...

How my proposal fixes this problem?
In a QVariant/std::any we can store a smart pointer and this way the data is
valid all the time. It can still hold a plain quintptr for models that don't
need this, so internalId()/internalPointer() could become thin wrappers around
the same underlying storage instead of needing a member variable of their own.


Cheers,
BogDan.

P.S. It can not go in Qt6 as it will break the ABI ...


--
Development mailing list
[email protected]
https://lists.qt-project.org/listinfo/development

Reply via email to