[SOLVED] Updating single item in CppModel does not update QML
-
Hi!
I've made a simple example which have a data model (class derived from QStandardItemModel). I've connected the model from C++ into the QML using setContextProperty(). Every thing works fine as long as I just "display" the model.
But when I start to update the data in an item it does not update the QML. I've made a simple connection (using Connections element) in QML that connects the models dataChanged signal. I see that signal in the QML when I update the model, but still the Text-element in the ListView delegate will not update.
This is my code:
main.cpp
@#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include "cppmodel.h"
#include "cppmodelitem.h"#include <qqmlengine.h>
#include <qqmlcontext.h>
#include <QtQuick/qquickview.h>int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);CppModel model; model.appendRow(new CppModelItem("Item 1")); model.appendRow(new CppModelItem("Item 2")); model.appendRow(new CppModelItem("Item 3")); QtQuick2ApplicationViewer viewer; viewer.rootContext()->setContextProperty("cppModel", &model); viewer.setMainQmlFile(QStringLiteral("qml/datamodeltest/main.qml")); viewer.showExpanded(); return app.exec();
}
@cppmodel.cpp
@#include "cppmodel.h"
#include "cppmodelitem.h"#include <QDebug>
CppModel::CppModel()
{
CppModelItem dummy("");
this->setItemRoleNames(dummy.roleNames());
}void CppModel::changeItem(int i)
{
if( this->rowCount() > i )
{
qDebug() << "using new data for row" << i;// This will NOT update the QML-Viewer with the new data. // But I can see the dataChanged signal within the QML code. this->item(i, 0)->setData("newData", CppModelItem::NameRole); // Appending row will make the QML-Viewer update //this->appendRow(new CppModelItem("Test")); }
}
@cppmodelitem.cpp
@#include "cppmodelitem.h"CppModelItem::CppModelItem(const QString& name)
{
m_name = name;this->setEditable(true);
}
QHash<int, QByteArray> CppModelItem::roleNames() const
{
QHash<int, QByteArray> names;
names[NameRole] = "name";
return names;
}QVariant CppModelItem::data(int r) const
{
Roles role = (Roles)r;
switch(role)
{
case NameRole:
return m_name;
break;
default:
return QVariant();
}
}
@main.qml
@import QtQuick 2.0Rectangle {
width: 360
height: 360ListView { id: listView anchors.fill: parent delegate: Text { height: 18 width: 360 text: name MouseArea { anchors.fill: parent onClicked: cppModel.changeItem(index) } } model: cppModel } Connections { target: listView.model onDataChanged: { console.log("Changing data") } }
}
@When I run the program I get this debug
@using new data for row 1
Changing data
using new data for row 2
Changing data@To me that says that the C++ function changeItem() is invoked and the connection between C++ and QML is there, but how will I get the Element in the delegate to update?
Thanks!
-
Have you tried emitting a signal to notify that data has changed?
-
I've this Connections
@
Connections {
target: listView.model
onDataChanged: {
console.log("Changing data")
}
}
@And I can see the log "Changing data". And as far as I understand QStandardItemModel will do the emitting of signals by it self, right?
-
I believe you still have to emit the signal yourself. Here is a thread with a similar problem:
http://qt-project.org/forums/viewthread/24294
The "Changing data" you see could have come from a different function that changes the data and not neccessarily from your changeItem function.
(I could always be wrong of course :)) -
Nothing :-(
I've added the following line to my changeItem() function right after the setData() call.
@
emit this->dataChanged(createIndex(i,0), createIndex(i,0));
@The only difference is that I now see to "Chaning data" logs that probably comes from the added the extra emit.
-
Have you had a look at this link?
I believe it does something similar to what you're trying to do:
http://www.developer.nokia.com/Community/Wiki/Using_QStandardItemModel_in_QML
-
Sorry, but I can't see why that link would help.
-
I was thinking you could try out the model they provided to see if it would work with your QML file. Guess I should have been more clearer :)
-
I solved it!
To make it work I implemented my own setData() in CppModelItem, which seems really straight-forward when you think of it!@
void CppModelItem::setData(const QVariant &value, int role)
{
if( role == NameRole )
{
m_name = value.toString();this->model()->dataChanged(this->index(), this->index()); }
}
@In the setData() I call the models dataChanged() with this index and everything works!