Доступ к элементу QAbstractItemModel через Pointer получает NULL после нескольких чтений - PullRequest
0 голосов
/ 22 апреля 2019

Мне нужно получить доступ к элементам напрямую из QAbstractListModel из QML.Я понял это, вернув адрес из функции из модели: Функция Q_INVOKABLE DataSourceObject * dataPointer (const QModelIndex & index);

#ifndef DATASOURCEMODEL_H
#define DATASOURCEMODEL_H

#include "datasourceobject.h"
#include <QAbstractListModel>

class DataSourceModel : public QAbstractListModel
{
    Q_OBJECT

public:
    enum datasourceRoles {
        idRole = Qt::UserRole ,
        nameRole,
        unitRole,
        valueRole
    };

    explicit DataSourceModel(QObject *parent = nullptr);
    void addDataSourceObject(DataSourceObject *dataSourceObject);
    Q_INVOKABLE QVariantMap get(int row) const;

    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    Q_INVOKABLE QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    bool setData(const QModelIndex &index, const QVariant &value,
                 int role = Qt::EditRole) override;
    Q_INVOKABLE DataSourceObject *dataPointer(const QModelIndex &index);
    Qt::ItemFlags flags(const QModelIndex& index) const override;
    QHash<int, QByteArray> roleNames() const override;
    //bool checkIndex(const QModelIndex &index) const;

private:
    QList<DataSourceObject*> m_DataSourceObjects;
};

#endif // DATASOURCEMODEL_H

#include "datasourcemodel.h"
#include <qdebug.h>

DataSourceModel::DataSourceModel(QObject *parent)
    : QAbstractListModel(parent)
{
}

QVariantMap DataSourceModel::get(int row) const
{
    return m_DataSourceObjects[row]->toMap();
}

void DataSourceModel::addDataSourceObject(DataSourceObject *dataSourceObject)
{
    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    m_DataSourceObjects << dataSourceObject;
    endInsertRows();
}
int DataSourceModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;
    return m_DataSourceObjects.count();
}

QVariant DataSourceModel::data(const QModelIndex &index, int role) const
{
    if(index.row() < 0 || index.row() >= m_DataSourceObjects.count() || !index.isValid())
        return  QVariant();

    DataSourceObject *dataSourceObject = m_DataSourceObjects[index.row()];
    if (role == idRole)
        return dataSourceObject->id();
    else if (role == nameRole) {
        return dataSourceObject->name();
    }
    else if (role == unitRole) {
        return dataSourceObject->unit();
    }
    else if (role == valueRole)
        return dataSourceObject->value();
    return QVariant();
}

bool DataSourceModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    DataSourceObject *dataSourceObject = m_DataSourceObjects[index.row()];
    if (data(index, role) != value) {
        if(role == idRole)
            dataSourceObject->setId(value.toInt());
        else if(role == nameRole)
            dataSourceObject->setName(value.toString());
        else if(role == unitRole)
            dataSourceObject->setUnit(value.toString());
        else if(role == valueRole)
            dataSourceObject->setValue(value.toDouble());
        emit dataChanged(index, index, QVector<int>() << role);
        return true;
    }
    return false;
}

DataSourceObject *DataSourceModel::dataPointer(const QModelIndex &index)
{
    qDebug() << m_DataSourceObjects[index.row()];
    return m_DataSourceObjects[index.row()];
}

Qt::ItemFlags DataSourceModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return Qt::NoItemFlags;

    return Qt::ItemIsEditable; // FIXME: Implement me!
}

QHash<int, QByteArray> DataSourceModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[idRole] = "id";
    roles[nameRole] = "name";
    roles[unitRole] = "unit";
    roles[valueRole] = "value";
    return  roles;
}

Я могу получить доступ к элементу иэто свойства из QML, и графический интерфейс автоматически обновляется с помощью Q_PROPERTY в графическом интерфейсе.

text: dataSourceModel.dataPointer(dataSourceModel.index(88,0)).value

Object:

#ifndef DATASOURCEOBJECT_H
#define DATASOURCEOBJECT_H

#include <QString>
#include <QVariantMap>

class DataSourceObject : public QObject
{
    Q_OBJECT

    Q_PROPERTY(double value READ value WRITE setValue NOTIFY valueChanged)

public:

    explicit DataSourceObject(QObject *parent = nullptr);
    DataSourceObject(const QJsonObject &obj);
    int id() const;
    void setId(int id);

    QString name() const;
    void setName(const QString &name);

    QString unit() const;
    void setUnit(const QString &unit);

    Q_INVOKABLE double value() const;
    void setValue(double value);
    QVariantMap toMap() const;

signals:
    void valueChanged();


private:
    int m_id;
    QString m_name;
    QString m_unit;
    double m_value;
};

#endif // DATASOURCEOBJECT_H

Свойство "value" элементов get изменяется во время выполнения в фоновом режиме,Примерно после 80 изменений свойств указатель, указывающий на объект, возвращает NULL.Поэтому я предполагаю, что элемент в модели изменил свой адрес.Как я могу помешать модели изменить адреса своего элемента.Но также, когда я снова вызываю Q_INVOKABLE DataSourceObject * dataPointer (const QModelIndex & index); , чтобы снова получить адрес, возвращается «старый» адрес, но вместо «DataSourceObject» возвращается «QObject»

...