[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&#40;QStringLiteral("qml/datamodeltest/main.qml"&#41;&#41;;
    viewer.showExpanded();
    
    return app.exec&#40;&#41;;
    

    }
    @

    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.0

    Rectangle {
    width: 360
    height: 360

    ListView {
        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!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.