Home > Mobile >  How can i overwrite items in a data property
How can i overwrite items in a data property

Time:01-12

I'm trying to make some qml components that are more general but have the flexibility of defaults but for items. Here are some example components

A.qml

import QtQuick 2.15

Rectangle {
    property alias inner: inside.data
    color: "red"
    width: 40
    height: 40
    Item {
        id: inside
    }
}

B.qml

import shared.debug 1.0 as Debug
import QtQuick 2.15

Debug.A {
    inner: Rectangle {
        width: 30
        height: 30
        color: "blue"
    }
}

C.qml

import shared.debug 1.0 as Debug
import QtQuick 2.15

Debug.B {
    inner: Rectangle {
        width: 20
        height: 20
        color: "black"
    }
}

qmldir

module shared.debug
A 1.0 A.qml
B 1.0 B.qml
C 1.0 C.qml

Used here

Column {
  spacing: 10
  Debug.A {}
  Debug.B {}
  Debug.C {}
}

Looks like this

Im looking for a way to make the Debug.C show just the red and black squares, i understand why the blue is showing but i was hoping i could make a straight forward default and then have it be removed and overwritten when used by a child element.

Ive tried to make properties that dont use alias but thats the same problem. Ive also tried just hiding the original content but that feels roundabout in that the original items are still there just not visible.

CodePudding user response:

I would suggest using a Loader instead of an Item in A.qml:

import QtQuick 2.15

Rectangle {
    property alias inner: inside.sourceComponent
    color: "red"
    width: 40
    height: 40
    Loader {
        id: inside
    }
}

Then you can replace that inside field with a Component of your choosing:

B.qml:

Debug.A {
    inner: Component {
        Rectangle {
            width: 30
            height: 30
            color: "blue"
        }
    }
}

CodePudding user response:

The data property is of type list<QtObject>. It seems like binding to it multiple times will append.

Column {
    spacing: 10
    A { Component.onCompleted: console.log("A", inner.length) } // 0
    B { Component.onCompleted: console.log("B", inner.length) } // 1
    C { Component.onCompleted: console.log("C", inner.length) } // 2
}

Similar like making the alias to the data property the default which means all child items of component A would be appended to the list.

component A: Rectangle {
    default property alias inner: inside.data
    color: "red"; width: 80; height: 80
    Item {
        id: inside
    }
}

component B: A {
    Rectangle { width: 40; height: 40; color: "blue" }
}

component C: B {
    Rectangle { width: 20; height: 20; color: "black" }
}

To circumvent this you could make inner an Item and bind it to the data or children property.

DANGER Keep in mind that this is a "hack". You should only use it if you know what you're doing. You can't add any other item into the inner Item because the binding on data will always overwrite it.

component A: Rectangle {
    property Item inner
    color: "red"; width: 80; height: 80
    Item {
        data: [inner]
    }
}

component B: A {
    inner: Rectangle { width: 40; height: 40; color: "blue" }
}

component C: B {
    inner: Rectangle { width: 20; height: 20; color: "black" }
}

Column {
    spacing: 10
    A {}
    B {}
    C {}
}
  • Related