It's very much possible, but you've got a few problems:
- You want to expose your list of Data objects as a QQmlListProperty. This is the proper way to get lists into QML
- If your list is properly exposed as a QQmlListProperty you can just set it as the model of your ListView without doing that weird getModel() hack that you're doing now
- You shouldn't be added items to your list in the getter or else you'll be appending to it every time QML tries to read it.
Once that's resolved, you can update a Data object simply by interacting with the reference to the current model item in your delegate.
Here's a full working example. I've added a MouseArea in the QML that changes the model and also a timer in C++ that also changes the model, to show that changes to either side are instantly reflected in the UI.
main.cpp:
#include <QGuiApplication>
#include <QtQuick>
class Data : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
Data(const QString &n) : _name(n) { }
QString name() const { return _name; }
void setName(const QString &n) {
if (_name == n)
return;
_name = n;
emit nameChanged(n);
}
signals:
void nameChanged(const QString &n);
private:
QString _name;
};
class Parser : public QObject
{
Q_OBJECT
Q_PROPERTY(QQmlListProperty<Data> list READ list CONSTANT)
public:
Parser(QObject *parent = 0) {
_list.append(new Data(QStringLiteral("name 1")));
_list.append(new Data(QStringLiteral("name 2")));
_list.append(new Data(QStringLiteral("name 3")));
startTimer(5000);
}
QQmlListProperty<Data> list() {
return QQmlListProperty<Data>(this, _list);
}
void timerEvent(QTimerEvent *) {
_list[1]->setName(_list[1]->name() + QStringLiteral("C++"));
}
private:
QList<Data*> _list;
};
int main(int argc, char *argv[])
{
QGuiApplication a(argc, argv);
qmlRegisterType<Data>();
QQuickView view;
view.rootContext()->setContextProperty(QStringLiteral("parser"), new Parser);
view.setSource(QUrl("qrc:///qml/main.qml"));
view.showNormal();
return a.exec();
}
#include "main.moc"
main.qml:
import QtQuick 2.0
Rectangle {
width: 800
height: 600
ListView {
id: view1
anchors { top: parent.top; left: parent.left; bottom: parent.bottom }
width: parent.width / 2
spacing: 5
delegate: Item {
height: 30
width: parent.width
Text { text: name }
MouseArea {
anchors.fill: parent
onClicked: model.name += "1";
}
}
model: parser.list
}
ListView {
id: view2
anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
width: parent.width / 2
spacing: 5
delegate: Item {
height: 30
width: parent.width
Text { text: name }
MouseArea {
anchors.fill: parent
onClicked: model.name += "2";
}
}
model: parser.list
}
}