Details
-
Bug
-
Resolution: Unresolved
-
P2: Important
-
6.5.0
-
None
Description
If you need to expose a list through Q_PROPERTY you generally do something like this:
Q_PROPERTY(QList<FooBar> fooBars READ fooBars WRITE setFooBars BINDABLE fooBarsBindable FINAL) [...] QList<FooBar> fooBars() const { return m_fooBars.value(); } void setFooBars(const QList<FooBar> &fooBars) { m_fooBars.setValue(fooBars); } [ ... ] QProperty<QList<FooBar>> m_fooBars;
This works ok-ish if you only read from the list. fooBars() gives you an implicitly shared copy which is cheap. However, if either the original list is updated while you hold the copy or you update the copy, the list is detached, which requires a deep copy. If you then write the list back using the setter, you destroy the original list. If you could modify the original list in place, no detach would happen.
This is a problem in QML since QML exclusively deals with properties exposed through Q_PROPERTY. QML has its own wrapper type for lists of QObject*, QQmlListProperty, but that is not usable outside of QML and has its own problems.
We do, however, have an abstraction over "list-like" data that could be used to modify a list in place: QMetaSequence and QSequentialIterable. Those are not quite sufficient since QMetaSequence only contains the sequence interface, not the actual instance, and QSequentialIterable deals in QVariant for everything it does. What we may want is a sequential iterable that retains the value type of the sequence.
Given such a thing, the solution may be to introduce an additional ITERABLE attribute to Q_PROPERTY that would name a method that returns an iterable for the value type, backed by the original list.
We need some more experimentation here. For example it's not yet clear how to make the value type of the list known to QML at run time (in case the QML code hasn't been compiled to C++).
Attachments
Issue Links
- relates to
-
QTBUG-128358 Reduce unnecessary detaches and copies when handling value types and lists
- Reported