Emmanuel Touzery
Emmanuel Touzery

Reputation: 9173

qml gridview: special add item at the end

I would like to have QML GridView with at the end of it a special element to add new items. So when the grid reflows that special element at the end reflows exactly like normal elements. I had it coded with a Flow, with inside a Repeater and after it, that special element and it worked great, but I can't get scrollbars with a Flow, so I moved to a GridView.

I tried the footer property of the GridView, but the footer appears under the grid, while I want it on the last row of the grid besides the other items.

To make it clear here is what I want:

[item1] [item2] [item3]
[item4] [ ADD ]

Also, the special element must have a different display an different action on click.

I would like the C++ side not to be aware of that special behaviour. If I must add an item at the end of the model, I would like it add it within the QML so that I don't taint the C++ with that implementation detail.

I tried this:

model: projects.push({name: '+'})

and also various types of append, but that didn't work.

Upvotes: 1

Views: 2349

Answers (2)

BaCaRoZzo
BaCaRoZzo

Reputation: 7682

Glad to read that you solved the issue. After testing your code, I think you can achieve the same result in an easier way.

If you bind the Flow to the Item which contains the ScrollView, the Flow can grow horizontally and you got the vertical scrollbar as required. The working code:

import QtQuick 2.3
import QtQuick.Window 2.0
import QtQuick.Controls 1.2
// import QtQuick.Controls 1.3      // <--- requires Qt >= 5.4

Window {
    id: container
    width: 300
    height: 150
    visible: true

    ScrollView {
        anchors.fill: parent
        //horizontalScrollBarPolicy:  Qt.ScrollBarAlwaysOff  // <--- requires .Controls 1.3

        Flow {
            width: container.width       // width of ScrollView parent
            spacing: 10
            Text { text: "Text"; font.pixelSize: 40 }
            Text { text: "items"; font.pixelSize: 40 }
            Text { text: "flowing"; font.pixelSize: 40 }
            Text { text: "inside"; font.pixelSize: 40 }
            Text { text: "a"; font.pixelSize: 40 }
            Text { text: "Flow"; font.pixelSize: 40 }
            Text { text: "item"; font.pixelSize: 40 }
            Text { text: "yeah"; font.pixelSize: 40 }
            Text { text: "alright"; font.pixelSize: 40 }
            Text { text: "cool"; font.pixelSize: 40 }
            Text { text: "almost"; font.pixelSize: 40 }
            Text { text: "not"; font.pixelSize: 40 }
            Text { text: "epic"; font.pixelSize: 40 }
        }
    }
}

Here, with Qt < 5.4, you got the horizontal scrollbar since the vertical one covers part of the content space. Using controls 1.3 from Qt 5.4 (and the related commented code) solves the issue.


Another way to solve the problem is by using Flickable with custom scrollbars (see here). In this case the code would be:

import QtQuick 2.3
import QtQuick.Window 2.0
import QtQuick.Controls 1.2

Window {
    id: container
    width: 300
    height: 150
    visible: true

    Flickable {
        id: flick
        anchors.fill: parent
        contentHeight: flow.height    // grows according to the size of the Flow

        Flow {
            id: flow
            width: container.width
            spacing: 10
            Text { text: "Text"; font.pixelSize: 40 }
            Text { text: "items"; font.pixelSize: 40 }
            Text { text: "flowing"; font.pixelSize: 40 }
            Text { text: "inside"; font.pixelSize: 40 }
            Text { text: "a"; font.pixelSize: 40 }
            Text { text: "Flow"; font.pixelSize: 40 }
            Text { text: "item"; font.pixelSize: 40 }
            Text { text: "yeah"; font.pixelSize: 40 }
            Text { text: "alright"; font.pixelSize: 40 }
            Text { text: "cool"; font.pixelSize: 40 }
            Text { text: "almost"; font.pixelSize: 40 }
            Text { text: "not"; font.pixelSize: 40 }
            Text { text: "epic"; font.pixelSize: 40 }
        }
    }

    ScrollBar {                 // one of the scrollbars from the linked question
        flickable: flick
    }
}

Upvotes: 1

Emmanuel Touzery
Emmanuel Touzery

Reputation: 9173

I managed to get scrollbars working based on a Flow as suggested by BaCaRoZzo.

However it's a bit complex scheme and I get QML warnings on stdout.

Here's how I did it:

ScrollView {
    anchors.fill: parent
    Flickable {
        contentWidth: parent.width
        contentHeight: flow.implicitHeight
        Flow {
            id: flow
            anchors.fill: parent
            ...
        }
    }
}

If I simply put the Flow in a ScrollView I get only one column in the flow.

This works as far as I can tell, however I get this warning on stdout:

QML Flickable: Binding loop detected for property "contentWidth"

I hope there's a simpler solution, but that's what I have for now...

EDIT: OK I got rid of the warning. I just set width: parent.width instead of contentWidth in the Flickable and it's ok, behaves well and no warnings. I guess I'll stick with that unless someone comes up with a nicer solution.

Upvotes: 0

Related Questions