Search code examples
c++qtqml

How to index an array in Repeater in Connections function QML


import QtQuick
import QtQuick.Controls 2.15
import QtQuick.Layouts 6.3

Page {
    width: root.width
    height: root.height
    visible: true

    background: Rectangle {
        color: "white"
    }

    Text{
        id: stageText
        anchors.horizontalCenter: parent.horizontalCenter
        topPadding: root.height / 4
        font.pixelSize: 26
        text: ""
        color: "black"
    }

    ColumnLayout {

        width: parent.width
        height: parent.height

        scale: root.width / 1000.0

        RowLayout{

            Layout.alignment: Qt.AlignCenter
            spacing: 0

            id: visualizeRow

            property string myArr : hammingCode.getDataStr();

            Repeater {

                model: visualizeRow.myArr.length

                Rectangle {
                    id: bit

                    width: 50
                    height: 50

                    Text {
                        anchors.centerIn: parent
                        text: visualizeRow.myArr.charAt(index)
                        color: "black"
                    }

                    border.width: 1
                    color: "white"
                }
            }

            Component.onCompleted: {
                stageText.text = "Encoding";
                hammingCode.encodeData(true);
            }
        }
    }

    Connections{
        target: hammingCode

        function onTurnBitOff(index){
            bit[index].color = "black";
        }

        function onTurnBitOn(index){
            bit[index].color = "red";
        }

        //put signals from c++ here that change visual stuff and shit
    }

}

I have a Page which using Repeater creates an array from a string of '0' and '1', it looks like this: Application screenshot

What i would like to do is change the color of a certain rectangle, access a certain rectangle at given index in the Connections functions which are connected to c++ signals.

The code in the functions doesn't work (it says "bit" is undefined), but illustrates what i would like to achieve. How can this be achieved?


Solution

  • Your C++ seems to offer getDataStr() as a method returning a string array. Consider changing it to a property and, reconsider the type. If your data type is an array of "1" and "0" the more efficient type for that should be just integer.

    public:
        Q_PROPERTY(int data READ data WRITE setData NOTIFY dataChanged)
        Q_INVOKABLE void setBit(int index) { setData(data() |= (1 << index)); }
        Q_INVOKABLE void clearBit(int index) { setData(data() &= ~(1 << index)); }
        Q_INVOKABLE void toggleBit(int index) { setData(data() ^= (1 << index)); }
        Q_INVOKABLE bool isSet(index) { return (data() & (1 << index)) != 0; }
    signals:
        void dataChanged();
    protected:
        int m_data;
        int data() const { return m_data; }
        void setData(int data) { if (m_data != data) { m_data = data; dataChanged(); } }
    

    Then, you can use that to populate your Repeater and set both the text and color based on the value returned by isSet(index).

    In the following example, I've mocked the C++ hammingCode implementation with a QtObject lookalike plus I've optimized/replaced the Repeater with a ListView. Note that because the left-most top bit is bit 6, hence why you will see 6-index math in checking the bits:

    import QtQuick
    import QtQuick.Controls
    import QtQuick.Layouts
    Page {
        QtObject {
            id: hammingCode
            property int data: 127
            function setBit(index) { data |= (1 << index); }
            function clearBit(index) { data &= ~(1 << index); }
            function toggleBit(index) { data ^= (1 << index); }
            function isSet(index) { return (data & (1 << index)) != 0; }
        }
        ColumnLayout {
            anchors.centerIn: parent
            spacing: 50
            Label {
                Layout.alignment: Qt.AlignHCenter
                text: qsTr("Hamming Code: %1").arg(hammingCode.data)
            }
            ListView {
                Layout.preferredWidth: 50 * 7
                Layout.preferredHeight: 50
                orientation: ListView.Horizontal
                model: 7
                delegate: Rectangle {
                    property bool bitSet: hammingCode.isSet(6-index)
                    property color bitColor: bitSet ? "red" : "black"
                    width: 50
                    height: 50
                    border.color: bitColor
                    Text {
                        anchors.centerIn: parent
                        text: bitSet ? "1" : "0"
                        color: bitColor
                    }
                    MouseArea {
                        anchors.fill: parent
                        onClicked: hammingCode.toggleBit(6-index)
                    }
                }
            }
        }
    }
    

    You can Try it Online!