Better_Software_Header_MobileBetter_Software_Header_Web

Find what you need - explore our website and developer resources

Recursive Instantiation with Qt Quick and JSON

Factory Design Techniques - Part 1

    id: root
    // A JSON representation of a QML layout:
    property var factoryModel: [
        {
            "component": "Button",
        },
        {
            "component": "Button",
        }
    ]
    // Root of our component factory
    Repeater {
        model: root.factoryModel
        delegate: loaderComp
    }
    // Root component of the factory and nodes
    Component {
        id: loaderComp
        Loader {
            id: instantiator
            required property var modelData
            sourceComponent: switch (modelData.component) {
                case "Button":
                return buttonComp;
                case "RowLayout":
                return rowLayoutComp;
                case "Item":
                default: return itemComp;
            }
        }
    }
    // Root component of the factory and nodes
    Component {
        id: loaderComp
        Loader {
            id: instantiator
            required property var modelData
            sourceComponent: switch (modelData.component) {
                case "Button":
                return buttonComp;
                case "RowLayout":
                return rowLayoutComp;
                case "Item":
                default: return itemComp;
            }
            onItemChanged: {
                // Pass children (see explanation below)
                if (typeof(modelData.children) === "object")
                    item.model = modelData.children;

                // Button properties
                switch (modelData.component) {
                    case "Button":
                    // If the model contains certain value, we may assign it:
                    if (typeof(modelData.text) !== "undefined")
                        item.text = modelData.text;
                    break;
                }

                // Item properties
                // Since Item is the parent of all repeatable, we don't need to check
                // if the component supports Item properties before we assign them:
                if (typeof(modelData.x) !== "undefined")
                    loaderComp.x = Number(modelData.x);
                if (typeof(modelData.y) !== "undefined")
                    loaderComp.y = Number(modelData.y);
                // ...
            }
        }
    }
    Component {
        id: itemComp
        Item {
            property alias children: itemRepeater.model
            children: Repeater {
                id: itemRepeater
                delegate: loaderComp
            }
        }
    }
    Component {
        id: buttonComp
        Button {
            property alias children: itemRepeater.model
            children: Repeater {
                id: itemRepeater
                delegate: loaderComp
            }
        }
    }
    Component {
        id: rowLayoutComp
        RowLayout {
            property alias children: itemRepeater.model
            children: Repeater {
                id: itemRepeater
                delegate: loaderComp
            }
        }
    }
    // This model lays out buttons vertically
    property var factoryModel: [
        {
            "component": "RowLayout",
            "children": [
                {
                    "component": "Button",
                    "text": "Button 1"
                },
                {
                    "component": "Button",
                    "text": "Button 2"
                }
            ]
        }
    ]

About KDAB


2 Comments

11 - Apr - 2024

Robert

11 - Apr - 2024

Javier Cordero