[Qt5-feedback] Adding better data access method to QAbstractItemModel?

Andre Somers andre at familiesomers.nl
Tue Jul 12 07:30:42 CEST 2011


Op 11-7-2011 14:43, Stephen Kelly schreef:
> Hi,
>
> Currently in the modelview API there are a lot of individual calls to the
> data() method. These can get expensive when proxy models are added to the
> mix.
>
> I'm thinking of adding a method like this to QAbstractItemModel:
>
> virtual QVariantist rangeData(const QModelIndex&topLeft, const QModelIndex
> &bottomRight, const QList<int>  &roles) const;
>
> with a default implementation like
>
> {
>    QVariantList list;
>    for (int row = topLeft.row(); row<= bottomRight.row(); ++row)
>      for (int col = topLeft.column(); col<= bottomRight.column() ++col)
>        foreach (int role, roles)
>          list<<  index(row, column, topLeft.parent()).data(role);
>    return list;
> }
>
> A model implementation and a proxy implementation can both do better of
> course, which is the whole idea. This change is source incompatible, but the
> itemData method currently in QAIM should maybe be deprecated.
>
> I also want to change the dataChanged signal to
>
> dataChanged(const QModelIndex&topLeft, const QModelIndex&bottomRight,
> QSet<int>  &roles = QSet<int>());
>
> so that it actaully tells you what roles have changed. The extra roles
> argument can be safely ignored, and a signal emission with an empty roles
> set has the same meaning as dataChanged has today.
>
> That means this is source compatible for the emitter but not the receiver,
> ie,
>
> emit dataChanged(foo, bar);
>
> still works, but
>
> connect(model, SIGNAL(dataChanged(QMI,QMI)), SLOT(onDataChanged(QMI,QMI));
>
> Needs to be changed to at least:
>
> connect(model, SIGNAL(dataChanged(QMI,QMI,QSet<int>)),
> SLOT(onDataChanged(QMI,QMI));
>
> The (source compatible) alternative would be to add a roleDataChanged signal
> with the signature I proposed instead of changing dataChanged (and possibly
> deprecating dataChanged).
>
> What are your thoughts? Are small source incompatibilities like that
> acceptible?
>
> Thanks,
>
> Steve.
IMHO, it is always a good idea to think about how the model/view 
interface in Qt can be improved, but I am not sure that this is the 
solution. I have a few doubts, perhaps you can clarify:

1) How is this supposed to work in the context of proxy models? As you 
know, proxy models are able to sort (so continuous blocks all of a 
sudden are not continuous at all anymore) and filter (block sizes 
change!). And we are not talking about proxies that actually modify or 
extend the data then. I don't see how this change is going to make 
implementing those easier or more efficient.

2) How will this work with the all-important tree models?

3) I have some doubts to the ease of use of the flat list of QVariants. 
I think it is *very* easy to make mistakes in using that list. You have 
to start calculating offsets for every piece of data you are after. At 
the very least, I think you should then introduce a class like a 
QItemPackage, that provides these offsets for you in a slightly more 
friendly way than a flat list, so you can at least access the EditRole 
of item (4,8) of parent X with ease. You may base that on a QVariantList 
if you want (why not a QVector<QVariant>?), but I don't think passing 
structured data in a flat list is particulary good API.

4) The data changed signal can be emitted frequently. Isn't constructing 
a QSet for each call an expensive operation?

5) Shouldn't this package of data also contain the flags() data? You 
need that piece of data anyway for rendering, so you end up querying it 
for each model index again. Or should there just be a Qt::FlagsRole be 
introduced that (also) returns this information? Would relying on _that_ 
still be source compatible?

I guess I need to give this more thought. I am not sure if this change 
is worth it.

André



More information about the Qt5-feedback mailing list