0
votes

I am trying to make a ListView of n CheckBox items where the top item is a "select/deselect all"-item. When checking the select/deselect all CheckBoxes upon program startup it selects/deselects all the n CheckBoxes, but as soon as I check/uncheck any of the n CheckBoxes and then goes back to pressing the select/deselect all, the previously checked/unchecked CheckBox does not get toggled anymore. I don't understand why it does not work as expected. Code and debug output provided below:

GUI

View:

import QtQuick 2.0
import QtQuick.Controls 1.2

Rectangle {
    id: view

    ScrollView {
        id: scrollView
        anchors.fill: parent

        ListView {
            id: listView
            anchors.fill: parent
            model: myModel
            delegate: Delegate { }
        }
    }

    Model {
        id: myModel

        Component.onCompleted: {
            add("C", "Orange", false)
            add("D", "Red", false)
        }
    }

    function add(name, color, check)
    {
        myModel.append({"name":name, "color":color, "check":check})
    }

    function edit(index, attribute, value)
    {
        myModel.setProperty(index, attribute, value)
    }

    function editMultiple(offset, length, attribute, value)
    {
        for (var i = offset; i < length; i++)
        {
            edit(i, attribute, value)
        }
    }
    function length()
    {
        return myModel.count
    }
}

Delegate:

import QtQuick 2.0
import QtQuick.Controls 1.2

Item {
    id: delegate
    height: 40
    width: 100

    property bool allCheckBoxChecked: false

    CheckBox {
        id: checkBox
        text: name
        anchors {
            fill: parent
            leftMargin: 20
            rightMargin: 20
        }
        checked: check
        onCheckedChanged: {
            if (index === 0)
            {
                allCheckBoxChecked = checkBox.checked
            }
            else
            {
                edit(index, "check", checkBox.checked)
            }
            console.log("Name: " + name + " Color: " + color + " Check: " + check)
        }
    }

    onAllCheckBoxCheckedChanged: {
        console.log("All: " + allCheckBoxChecked)
        if (allCheckBoxChecked)
        {
            editMultiple(0, length(), "check", true)
        }
        else
        {
            editMultiple(0, length(), "check", false)
        }
    }
}

Model:

import QtQuick 2.0

ListModel {
    id: listModel

    ListElement {
        name: "All"
        color: "Black"
        check: false
    }
    ListElement {
        name: "A"
        color: "Blue"
        check: false
    }
    ListElement {
        name: "B"
        color: "Green"
        check: false
    }
}

Debug output:

//Pressing "All".
qml: All: true
qml: Name: A Color: Blue Check: true
qml: Name: B Color: Green Check: true
qml: Name: C Color: Orange Check: true
qml: Name: D Color: Red Check: true
qml: Name: All Color: Black Check: true

//Pressing "All".
qml: All: false
qml: Name: A Color: Blue Check: false
qml: Name: B Color: Green Check: false
qml: Name: C Color: Orange Check: false
qml: Name: D Color: Red Check: false
qml: Name: All Color: Black Check: false

//Pressing "A".
qml: Name: A Color: Blue Check: true

//Pressing "All".
qml: All: true
//A does not get assigned anymore...
qml: Name: B Color: Green Check: true
qml: Name: C Color: Orange Check: true
qml: Name: D Color: Red Check: true
qml: Name: All Color: Black Check: true

//Pressing "All".
qml: All: false
//A does not get assigned anymore...
qml: Name: B Color: Green Check: false
qml: Name: C Color: Orange Check: false
qml: Name: D Color: Red Check: false
qml: Name: All Color: Black Check: false
1

1 Answers

2
votes

A QML property can have a value assigned via static assignment (javascript assignment) or via a binding but not at the same time since static assignment erases bindings.

In your case, when the program starts, all Checkboxes use property bindings. But when you click a CheckBox the static assignment removes these bindings. It means that now a static value is assigned to property checked ( true or false). The possible workaround is to use Qt.binding to generate a property binding in JS, i.e. preserve the original binding. You can read more about that here.