1
votes

I've created c++ class with QML attached properties to use it in qml.

Now I want to add attached property to one QQuickItem object and propagate this attached property for all QQuickItem child items (those which returned by QQuickItem::childItems() not by QObject::children()). I can easily iterate over existing QQuickItem child items and add attached properties to them, however I can't find out how to listen for added/removed child items for certain QQuickItem. No signals, no events only overriding QQuickItem::itemChange() method.

How can I listen for adding/removing QQuickItem item children? I've found only QQuickItemChangeListener but this class is from private API.

UPD1: Implementation of attached property:

class MyProp : public QObject {
    Q_OBJECT
    Q_PROPERTY(int prop ...)
    public:
        explicit MyProp(QObject * object = nullptr) : QObject(object) {
            auto item = qobject_cast<QQuickItem *>(object);
            if(item) {
                for(auto child : _item->childItems()) {
                    QObject * attached = qmlAttachedPropertiesObject<MyProp>(child, true);
                    ... // needs to listen here for adding/removing child items
                }
            }
        }

        static MyProp * qmlAttachedProperties(QObject * object) {
            return new MyProp(object);
        }
}

QML_DECLARE_TYPEINFO(MyProp, QML_HAS_ATTACHED_PROPERTIES)
2
Are you sure about your design ? Because duplicating properties in all children sounds weird to me. Do you possibly need a different value in each children ? If not, your parent could have the properties and the children just read them instead of the propagation. - ymoreau
Yes I'm sure about it. For example inside qt code such approach is used in QQuickAttachedObject class. - Kamil Zaripov
This sounds like a very bad solution to a problem that can most likely be resolved in a much easier and more efficient way. For example, adding the value as a context property of an object will allow the entire object branch the object is root of to resolve and access it. - dtech
Well if context property value can be created/changed from qml code it can solve the problem. - Kamil Zaripov
It cannot be created but it can be changed. Also if you declare the property in a QML file in the scope of its root object, that property will be resolvable from all objects in that tree via dynamic scoping, unless it gets shadowed by an identically named one of course. Unlike the context property this solution can be implemented without any C++ whatsoever. - dtech

2 Answers

0
votes

Using QML you have the Item properties data, children and resources :

The children property contains the list of visual children of this item. The resources property contains non-visual resources that you want to reference by name.
[...] the default data property will automatically assign child objects to the children and resources properties as appropriate.

When you add some Item as a child of your object :
myItem->setParentItem(parentQQuickItem);
You can listen to the change in QML code :

MyParentItem
{
    onDataChanged:
    {
        // Parse children and modify them
    }
}

Or use onChildrenChanged for visual items only or onResourcesChangedfor the non-visual items only.

0
votes

There's no way to do this currently, unfortunately. You can vote for and watch this suggestion to be notified of when it's implemented:

https://bugreports.qt.io/browse/QTBUG-74320