I want to display a single item and it's roles in the GUI from a QAbstractItemModel. In the manual I can only find how to display the whole model.
Displaying a single item is working, but the data in the GUI isn't updated when the data in the model is changed.
The model emits dataChanged() in the setData() function.
Object in Model:
#ifndef DATASOURCEOBJECT_H
#define DATASOURCEOBJECT_H
#include <QString>
#include <QVariantMap>
class DataSourceObject
{
public:
DataSourceObject(const int &id=0, const QString &name="", const QString &displayname="", const double &value=0.0);
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);
double value() const;
void setValue(double value);
QVariantMap toMap() const;
private:
int m_id;
QString m_name;
QString m_unit;
double m_value;
};
#endif // DATASOURCEOBJECT_H
Model Header:
#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(const 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;
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
Model cpp:
#include "datasourcemodel.h"
DataSourceModel::DataSourceModel(QObject *parent)
: QAbstractListModel(parent)
{
}
QVariantMap DataSourceModel::get(int row) const
{
return m_DataSourceObjects[row].toMap();
}
void DataSourceModel::addDataSourceObject(const 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();
const 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;
}
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;
}
I tried to access a single item in QML like this:
Text {
text: dataSourceModel.data(dataSourceModel.index(88,0),259).toFixed(decimalplaces)
}
This shows the data's role 259(valueRole), but the text isn't updated when changed.
I tried to derive the object inside the model from QObject, to use Q_INVOKABLE, but when derived from QOBject, I can't compile it.C:\Qt\5.10.0\mingw53_32\include\QtCore\qlist.h:435: Fehler: use of deleted function 'DataSourceObject::DataSourceObject(const DataSourceObject&)' if (QTypeInfo::isLarge || QTypeInfo::isStatic) n->v = new T(t);
^
dataSourceModel.data(dataSourceModel.index(88,0),259)
259 corresponds to the role? – bardaoQ_PROPERTY
as inQ_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
in yourDataSourceModel
. Also do the same for the rest of your variables. That would create the binding for you when you access your value withdata.modelData.name
... – bardaoDataSourceObject
like in doc.qt.io/qt-5/qtqml-cppintegration-exposecppattributes.html – bardao