mardi 2 mai 2023

How to solve the problem of registered objects in a list that refer to registered objects

I have two model classes. The first class is Vector, the second is SequenceUnit. SequenceUnit stores different types of objects, to identify them there is a type property:

Vector.h

#ifndef VECTOR_H
#define VECTOR_H

#include <QObject>
#include <QPointF>
#include <QVariantList>

class Vector : public QObject {
    Q_OBJECT
    Q_PROPERTY(int index READ index WRITE setIndex NOTIFY changedIndex)
    Q_PROPERTY(QPointF point READ point WRITE setPoint NOTIFY changedPoint)

public:
    explicit Vector(QObject *parent = 0) {}

    int index() {
        return m_index;
    }
    void setIndex(int index) {
        if (m_index == index) {
            return;
        }

        m_index = index;
        emit changedIndex();
    }

    QPointF point() {
        return m_point;
    }
    void setPoint(const QPointF& point) {
        if (m_point == point) {
            return;
        }

        m_point = point;
        emit changedPoint();
    }

signals:
    void changedIndex();
    void changedPoint();

private:
    int m_index = -1;
    QPointF m_point = QPointF(0, 0);
};
#endif // VECTOR_H

SequenceUnit:

#ifndef UNITSEQUENCE_H
#define UNITSEQUENCE_H

#include "Vector.h"
#include <QObject>

class SequenceUnit : public QObject {
    Q_OBJECT
    Q_PROPERTY(QString type READ type WRITE setType NOTIFY typeChanged)
    Q_PROPERTY(QObject* unit READ unit WRITE setUnit NOTIFY unitChanged)

public:
    QString type() {
        return m_type;
    }
    void setType(QString type) {
        if (m_type == type) {
            return;
        }

        emit typeChanged();
        m_type = type;
    }

    QObject* unit() {
        return m_unit;
    }
    void setUnit(QObject* unit) {
        if (m_unit == unit) {
            return;
        }

        emit unitChanged();
        m_unit = unit;
    }

signals:
    void typeChanged();
    void unitChanged();

private:
    QString m_type;
    QObject* m_unit;
};

#endif // UNITSEQUENCE_H

The VectorController and LinkSequence controllers are responsible for creating objects in qml. VectorController for creating vectors. LinkSequence for creating unit objects:

VectorController:

#ifndef VECTORCONTROLLER_H
#define VECTORCONTROLLER_H

#include "Vector.h"

#include <QObject>

class VectorController : public QObject {
    Q_OBJECT

public:
    explicit VectorController(QObject *parent = 0) { };

    Q_INVOKABLE Vector* createVector() {
        return new Vector();
    }
};

#endif // VECTORCONTROLLER_H

LinkSequence:

#ifndef LINKSEQUENCE_H
#define LINKSEQUENCE_H

#include "SequenceUnit.h"

class LinkSequence : public QObject {
    Q_OBJECT

public:
    explicit LinkSequence(QObject *parent = 0) { };

    Q_INVOKABLE SequenceUnit* createUnit() {
        return new SequenceUnit();
    }
};

#endif // LINKSEQUENCE_H

I register all these controllers and methods through main cpp:

qmlRegisterType<Vector>("Model", 1, 0, "Vector");
qmlRegisterType<SequenceUnit>("Model", 1, 0, "Unit");
qmlRegisterType<VectorController>("Controller", 1, 0, "VectorController");
qmlRegisterType<LinkSequence>("Controller", 1, 0, "LinkSequence");

There are errors in main qml. The program crashes after 100 clicks:

import QtQuick 2.15
import QtQuick.Window 2.15
import Model 1.0
import Controller 1.0

Window {
    id: window
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    Item {
        id: root
        width: window.width; height: window.height

        property var points: {
            [Qt.point(75.0, 0.0),
            Qt.point(150.0, 100.0),
            Qt.point(100.0, 200.0),
            Qt.point(50.0, 200.0),
            Qt.point(0.0, 100.0),
            Qt.point(75.0, 0.0)
            ]
        }
        property var handledPoints: {
            let newPoints = points.map((point) => Qt.point(point.x, point.y))

            const sequence = list
            for (let i = 0; i < sequence.length; ++i) {
                if (sequence[i] !== null) {
                    console.log(i, 'not null')
                    const vector = list[i].unit
                    for (let a = 0; a < newPoints.length; ++a) {
                        if (vector.index === (a % (newPoints.length - 1))) {
                            const point = vector.point
                            newPoints[a].x += point.x
                            newPoints[a].y += point.y
                        }
                    }
                } else {
                    console.log(i, 'null')
                }
            }
            return newPoints

//link model:
            property list<Unit> list

            VectorController {
                id: cntr
            }
        LinkSequence {
            id: link
        }


        Repeater {
            anchors.fill: parent
            model: root.handledPoints.length - 1
            Rectangle {
                id: circle
                x: root.handledPoints[index].x - height / 2; y: root.handledPoints[index].y - width/ 2
                width: 20; height: 20;
                radius: 20
                color: 'violet'
                MouseArea {
                    anchors.fill: circle
                    cursorShape: Qt.PointingHandCursor
                    property point pressedPoint; property point positionPoint
                    property var vector;  property var unit
                    onPressed: {
                        pressedPoint = circle.mapToItem(root, mouseX, mouseY)
                        vector = cntr.createVector()
                        vector.index = index
                        const unit = link.createUnit()
                        unit.type = 'vector'
                        unit.unit = vector
                        root.list.push(unit)
                    }
                    onPositionChanged: {
                        positionPoint = circle.mapToItem(root, mouseX, mouseY)
                        vector.point = Qt.point(positionPoint.x - pressedPoint.x,positionPoint.y - pressedPoint.y)
                    }
                }
            }
        }
    }
}

an error appears in the console - "TypeError: Cannot read property 'index' of null" and after one more click the program crashes.

I don't understand why it doesn't work. My task is to combine multiple models into one and then use it on another qml item. That is, get a model that will link to other models:

The model I want to get linkmodel

How do I combine multiple models into one model that will link other models in qml? And what could be the problem with the code?

source code: https://github.com/svirid132/qml-list-problem

Aucun commentaire:

Enregistrer un commentaire