0

Is it possible to make mutual connection (without loop issue), using Connections, Binding or Qt.binding()?

It is possible to connect, say, SwipeView.currentIndex to TabBar.currentIndex and vise versa. When I page through SwipeView, then current tab of TabBar is also changed and vice versa. There is no binding loop of properties.

How to achieve this in Repeater? When some item created by Repeater became selected (in some sense), then I want to rebind its properties to another standalone item, which operates like editor of the selected item. The state of elements in selected item should depend on the state of items into the editor. But on selection changing I need to initialize items in editor using values from newly selected item.

import QtQuick 2.7
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.3
import Qt.labs.settings 1.0

ApplicationWindow {
    id: root

    property var currentDayOfWeek: { "enabled": false, "time": "08:00" }

    visible: true

    SystemPalette {
        id: palette
    }

    RowLayout { 
        anchors.centerIn: parent 

        Column {
            ButtonGroup { id: weekButtonGroup }

            Repeater {
                model: 7

                RowLayout {
                    Settings {
                        id: dayOfWeekSettings

                        category: Qt.locale("C").standaloneDayName(index, Locale.LongFormat)

                        property bool enabled: false
                        property string time: "08:00"
                    }
                    Label {
                        text: dayOfWeekSettings.time

                        verticalAlignment: Text.AlignVCenter
                        horizontalAlignment: Text.AlignHCenter

                        background: Rectangle {
                            color: dayOfWeekSettings.enabled ? palette.highlight : palette.base
                        }

                        Layout.fillHeight: true
                    }
                    RadioButton {
                        text: Qt.locale().standaloneDayName(index, Locale.LongFormat)

                        onCheckedChanged: {
                            if (checked) {
                                root.currentDayOfWeek = dayOfWeekSettings
                                timeField.text = Qt.binding(function() { return dayOfWeekSettings.time }) // ???
                                enabledCheckBox.checked = Qt.binding(function() { return dayOfWeekSettings.enabled }) // ???
                            }
                        }

                        ButtonGroup.group: weekButtonGroup

                        Layout.fillHeight: true
                    }
                }
            }

            Layout.fillHeight: true
        }
        Column {
            // Editor
            TextField {
                id: timeField

                text: currentDayOfWeek.time // ???

                inputMask: "00:00;_"

                inputMethodHints: Qt.ImhDigitsOnly
            }
            CheckBox {
                id: enabledCheckBox

                checked: currentDayOfWeek.enabled // ???
            }

            Layout.fillHeight: true
        }
    }
}

How to achieve this? Is there canonical way to do this? Above example is not the solution.

Tomilov Anatoliy
  • 15,657
  • 10
  • 64
  • 169
  • Maybe [**this**](https://stackoverflow.com/questions/41232999/two-way-binding-c-model-in-qml/41237532#41237532) answers your question – derM - not here for BOT dreams Aug 05 '17 at 08:05
  • Usually this should be possible, as long as you stick to some rules: Don't change a value upon update. So you should not bidirectional bind an `int` to a `real`, e.g. as here changing to real changes the int, it will be rounded differently, changes the real again e.t.c. Use the `when`-conditions of the binding to avoid such mess. – derM - not here for BOT dreams Aug 05 '17 at 08:09
  • @derM Mentioned answer is great. Now I think I only need one-directional bind. When current item is changed, the editor should be filled with values, saved in current item. Then editor's fields should be bounded (using `Qt.binding()`) to properties to be changed of the current item until another item will be selected as current. – Tomilov Anatoliy Aug 05 '17 at 08:39

1 Answers1

1

The following code works as I want:

import QtQuick 2.7
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.3
import Qt.labs.settings 1.0

ApplicationWindow {
    id: root

    //property var currentDayOfWeek: { "enabled": false, "time": "08:00" }

    visible: true

    SystemPalette {
        id: palette
    }

    RowLayout { 
        anchors.centerIn: parent 

        Column {
            ButtonGroup { id: weekButtonGroup }

            Repeater {
                model: 7

                RowLayout {
                    Settings {
                        id: dayOfWeekSettings

                        category: Qt.locale("C").standaloneDayName(index, Locale.LongFormat)

                        property bool enabled: false
                        property string time: "08:00"

                        Binding on enabled {
                            when: dayOfWeekSettingsCheckBox.checked
                            value: enabledCheckBox.checked
                        }
                        Binding on time {
                            when: dayOfWeekSettingsCheckBox.checked
                            value: timeField.text
                        }
                    }
                    Label {
                        text: dayOfWeekSettings.time

                        verticalAlignment: Text.AlignVCenter
                        horizontalAlignment: Text.AlignHCenter

                        background: Rectangle {
                            color: dayOfWeekSettings.enabled ? palette.highlight : palette.base
                        }

                        Layout.fillHeight: true
                    }
                    RadioButton {
                        id: dayOfWeekSettingsCheckBox

                        text: Qt.locale().standaloneDayName(index, Locale.LongFormat)

                        onCheckedChanged: {
                            if (checked) {
                                //root.currentDayOfWeek = dayOfWeekSettings
                                timeField.text = dayOfWeekSettings.time 
                                enabledCheckBox.checked = dayOfWeekSettings.enabled
                            }
                        } 

                        ButtonGroup.group: weekButtonGroup

                        Layout.fillHeight: true
                    }
                }
            }

            Layout.fillHeight: true
        }
        Column {
            id: editor

            TextField {
                id: timeField

                //text: currentDayOfWeek.time

                inputMask: "00:00;_"

                inputMethodHints: Qt.ImhDigitsOnly
            }
            CheckBox {
                id: enabledCheckBox

                //checked: currentDayOfWeek.enabled
            }

            Layout.fillHeight: true
        }
    }
}

but there is an issue: editor filled with values in onCheckedChanged when checked became true. But what if when: in Bindings shoot first? Is it possible? Should I use delayed?

If I comment out:

timeField.text = dayOfWeekSettings.time 
enabledCheckBox.checked = dayOfWeekSettings.enabled

and uncomment all the commented in above solution, then also all works fine. But the suspicion still persist.

Tomilov Anatoliy
  • 15,657
  • 10
  • 64
  • 169