0
votes

I have QVariantMap (not QObject, because property names are not predefined). And I inject QVariantMap into QML root context to use property values for binding.

The problem is that when I change QVariantMap or even when I change QVariantMap and call setContextProperty for updated object, or when I update (with fromValue) object returned by contextProperty nothing happens. So this looks like one time binding.

So, what is the right way in inject Map or Map into QML context in observable way, so that changing item in the map will be reflected in QML?

2

2 Answers

4
votes

To expose C++ map to the QML, without creating QObject-derived class, you can use QQmlPropertyMap.

main.cpp

// create our data
QQmlPropertyMap ownerData;
ownerData.insert("name", QVariant(QString("John Smith")));
ownerData.insert("phone", QVariant(QString("555-5555")));
// expose it to the UI layer
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("owner", &ownerData);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

main.qml

Window {
    Text { text: owner.name + " " + owner.phone }
}

The binding is dynamic - whenever a key's value is updated, anything bound to that key will be updated as well. Don't need call setContextProperty every time when you change QQmlPropertyMap.

0
votes

You could create a QObject that has QVariantMap property and set that object as the contextObject (see http://doc.qt.io/qt-5/qqmlcontext.html#details for documentation on contextObject). In you QML you can just use "map" property globally and it should update when you call MyVariantMap::setMap().

class MyVariantMap : public QObject {
    Q_OBJECT
    Q_PROPERTY(QVariantMap map READ map WRITE setMap NOTIFY mapChanged)

public:
    QVariantMap map() const { return Map; }
    void setMap(QVariantMap map) {
       if(Map != map) {
           Map = map;
           emit mapChanged()
       }
    }

signals:
 void mapChanged();

private:
    QVariantMap Map;

};