Search code examples
c++qtqmlqqmlcomponentqqmllistproperty

How propagate an attached property to children in Qml?


I wanna make something like Material.accent, where I can change in the parent and children getting the parent property definition.

Here is the way I did at this time, but I can't find any information about it in the documentation. I know it is possible, Material Style uses this method and other things like font property too.

class MyThemeAttached : public QObject {
    Q_OBJECT

    Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
    QML_ANONYMOUS

public:
    explicit MyThemeAttached(QObject* parent = nullptr)
        : QObject(parent)
    , m_color("#FF0000"){}

    QColor color() const;
    void setColor(const QColor color);

signals:
    void backgroundChanged(QColor background);

private:
    QColor m_color;
};


class MyTheme : public QObject
{
    Q_OBJECT
    QML_ATTACHED(MyThemeAttached)
    QML_ELEMENT
public:
    explicit MyTheme(QObject *parent = nullptr);

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


ApplicationWindow {
    id: root
    visible: true
    width: 800
    height: 600
    title: qsTr("Window")
    
    MyCustomProperty.color: "orange"

    Rectangle {
        color: MyCustomProperty.color        
    }
}

Solution

  • Why not look at the code that Material has? I introduce you to Woboq.org.

    Here you can see that the Material theme actually pro-actively pushes the theme on the children:

    void QQuickMaterialStyle::propagateTheme()
    {
        const auto styles = attachedChildren();
        for (QQuickAttachedObject *child : styles) {
            QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(child);
            if (material)
                material->inheritTheme(m_theme);
        }
    }