David Stocking
David Stocking

Reputation: 1210

QML Repeater for multiple items without a wrapping Item

I want to make a view that looks something like (I left off a column for brevity)

 __________
| text     |
|__________|
|    |headr|
|____|_____|
|text|item1|
|    |item2|
|    |     |
|text|item3|
|    |item4|
|    |item5|
|    |item6|
|____|_____|

and have been trying to do this with a GridLayout. The problem is that I could have potentially many rows. It just depends on my model. So, I want to be able to have a repeater that will repeat the same n elements. However, it seems to only take one component. I would love to repeat one element but that is not how the GridLayout figures out spacing. So, it seems as if this is impossible except using dynamic object creation.

My code for the actual item trying to be repeated is this

            Text {
                Layout.alignment: Qt.AlignHCenter
                text: abbr
                color: "#545454"
            }
            VerticalRule {
                Layout.fillHeight: true
            }
            ColumnLayout {
                Repeater {
                    model: getModel()
                    Image {}
                }
            }
            VerticalRule {
                Layout.fillHeight: true
            }
            ColumnLayout {
                Repeater {
                    model: getModel()
                    Image {}
                }
            }

So, is there any way to do this easily in qml or am I kind of on my own when it comes to this kind of super specific table ish format.

Upvotes: 5

Views: 5367

Answers (2)

pixelgrease
pixelgrease

Reputation: 2118

Add multiple Items as children to a delegate Item and use JavaScript to reparent them to the GridLayout when the delegate Item is completed.

The OP requests a solution that avoids using a wrapping Item, but a wrapping Item affords the cleanest solution to this problem and supports an arbitrary number of columns. Also, I have never seen a solution using a "wrapping Item" -- this is the page that comes up whenever I search for one.

GridLayout {
    id: grid
    anchors.centerIn: parent
    columns: 2

    Repeater {
        model: [
            { column1: "text1", column2: ["item1","item2"] },
            { column1: "text2", column2: ["item3","item4","item5","item6","item7"] },
            { column1: "text3", column2: ["item8","item9"] },
        ]
        delegate: Item {
            objectName: "wrapping_item"

            property int rowOffset: 4

            Component.onCompleted: {
                // reparent all child elements into the grid
                while (children.length)
                    children[0].parent = grid;
            }

            Text {
                objectName: "first_child"
                Layout.alignment: Qt.AlignRight | Qt.AlignTop
                Layout.column: 0
                Layout.row: index + rowOffset
                text: modelData.column1
            }
            Column {
                objectName: "second_child_containing_more_children"
                Layout.alignment: Qt.AlignLeft
                Layout.column: 1
                Layout.row: index + rowOffset

                Repeater {
                    model: modelData.column2
                    delegate: Text { text: modelData }
                }
            }
        }
    }

    // same header code as in other answer, just moved out of the way
    Text {
        text: "text"
        Layout.columnSpan: 2
    }
    Rectangle {
        height: 2
        color: "blue"
        Layout.row: 1
        Layout.columnSpan: 2
        Layout.fillWidth: true
    }
    Text {
        text: "header"
        Layout.row: 2
        Layout.column: 1
    }
    Rectangle {
        height: 2
        color: "blue"
        Layout.row: 3
        Layout.columnSpan: 2
        Layout.fillWidth: true
    }
}

Screenshot of GridLayout with multiple columns from single Repeater

Upvotes: 0

pixelgrease
pixelgrease

Reputation: 2118

You can do it with the GridLayout; use multiple Repeaters, one for each column in the Gridlayout. The following snippet reproduces your text layout:

GridLayout {
    columns: 2

    Text {
        Layout.columnSpan: 2
        Layout.alignment: Qt.AlignLeft
        text: 'text'
    }
    Rectangle {
        height: 2
        color: "black"
        Layout.row: 1
        Layout.columnSpan: 2
        Layout.fillWidth: true
    }
    Text {
        Layout.column: 1
        Layout.row: 2
        text: 'header'
    }
    Rectangle {
        height: 2
        color: "black"
        Layout.row: 3
        Layout.columnSpan: 2
        Layout.fillWidth: true
    }
    Repeater {
        model: list

        Text {
            Layout.column: 0
            Layout.row: index + 4
            Layout.alignment: Qt.AlignTop
            text: label
        }
    }
    Repeater {
        model: list

        Column {
            Layout.column: 1
            Layout.row: index + 4

            Repeater {
                model: items

                Text { text: item }
            }
        }
    }
    ListModel {
        id: list

        ListElement {
            label: 'text1'
            items: [
                ListElement { item: 'item1' },
                ListElement { item: 'item2' }
            ]
        }
        ListElement {
            label: 'text2'
            items: [
                ListElement { item: 'item3' },
                ListElement { item: 'item4' },
                ListElement { item: 'item5' },
                ListElement { item: 'item6' },
                ListElement { item: 'item7' }
            ]
        }
        ListElement {
            label: 'text3'
            items: [
                ListElement { item: 'item8' },
                ListElement { item: 'item9' }
            ]
        }
    }
}

Screenshot of running code

Upvotes: 7

Related Questions