QML Property Browser



  • I want to create a QML component similar to this http://doc.qt.digia.com/qq/qq18-propertybrowser.html. At the moment I'm returning a QVariantMap with the property name as the key, and the variant as the thing I want to create an editor component for. I know how to create a ListView with type loaded specific components http://cdumez.blogspot.co.nz/2010/11/heterogeneous-list-model-in-qml.html but how do you access the key or value from the map within a ListView

    @
    ListView {
    model: variantmap
    delegate: Text{ text: key??, " ", value??}
    }
    @



  • I didn't try it yet, but the modelData role can be used to access unnamed objects. Maybe the following will work

    @delegate: Text { text: modelData["key"] ...@



  • I don't think a variant map can be used as a model for ListView. I found bug "25195":https://bugreports.qt-project.org/browse/QTBUG-25195 and the response would indicate that what they want me to do is QList<QVariantMap> where each QVariantMap is "key:" keyvalue, "value:" value.
    Unfortunately this is a bit long winded and doesn't fit into what I'm being returned so I'll have to hunt down a way to instead fill a ListView dynamically in QML.



  • Yes that is right, you cannot use the Map as a model, since it is not an array.
    I did some toying around and I came up with converting it to an array in JavaScript to an array and use that as the model for your list.
    Made a test-program and that worked.
    my datamodel.h:
    @
    #ifndef DATAMODEL_H
    #define DATAMODEL_H

    #include <QObject>
    #include <QVariantMap>

    class DataModel : public QObject {
    Q_OBJECT
    Q_PROPERTY(QVariantMap map READ map WRITE setmap NOTIFY mapChanged)
    QVariantMap m_map;

    public:
    explicit DataModel(QObject *parent = 0);

    QVariantMap map() const {
    return m_map;
    }

    signals:
    void mapChanged(QVariantMap arg);

    public slots:
    void setmap(QVariantMap arg) {
    if (m_map != arg) {
    m_map = arg;
    emit mapChanged(arg);
    }
    }
    };
    #endif // DATAMODEL_H
    @

    datamodel.cpp
    @
    #include "datamodel.h"

    DataModel::DataModel(QObject *parent) : QObject(parent) {
    m_map["Bike"] = QString("slow");
    m_map["Car"] = QString("Fast");
    m_map["Motor"] = QString("Scary");
    }
    @

    Registering it in my view:
    @
    DataModel datamodel;
    viewer.rootContext()->setContextProperty("MyModel", &datamodel);
    @

    And finally the QML:
    @
    import QtQuick 1.1

    Rectangle {
    width: 360
    height: 360

    property variant jsModel: []
    
    Component.onCompleted: {
        // Don't know why a temp var is needed
        // otherwise it does not work
        var tempModel = jsModel;
        for (var item in MyModel.map) {
            var o = new Object;
            o.key = item;
            o.value = MyModel.map[item];
            tempModel.push(o);
        }
        jsModel = tempModel
    }
    
    ListView {
        anchors.fill: parent
        model: jsModel
        delegate: Text {text: modelData.key + ":" + modelData.value; height: paintedHeight}
    }
    

    }
    @

    Hope it helps



  • I recall reading that you need the temp variable because jsModel ends up being const so you can't update it directly, you can only set a new version. Incidentally, that leads to the next issue of actually updating the values.

    I think, in order to create this property editor, I need to take the variant map, construct a QAbstractItemModel from the map and use that in a ListView.


Log in to reply
 

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