0

I'm having trouble finding a good way to display the items of a std::map in QML. We're using a MVVM pattern in our application. The std::map contains file paths and is a member of a configuration class in the model. Now I'm trying to show all entries of the map in QML, probably using a ListView item. Currently we just have a couple of file paths in the configuration, so these are exposed as Q_PROPERTYies to the view model and then further to QML. But, of course, the number of paths can and will grow, thus my idea using a std::map for this. It won't be necessary to have it 'growable' at runtime, at least not in the forseeable future. But writing lots and lots of Q_PROPERTYies doesn't seem the right way for me.

Furhter question: How would I access/display the items of the map in a QML ListView - I can't figure it out and I can't find anything helpful online.

Ramkrishna Sharma
  • 6,961
  • 3
  • 42
  • 51
DenverCoder21
  • 879
  • 3
  • 16
  • 34

2 Answers2

2

Another option than @ddriver suggested would be to create a list of QObject-derived types like:

class ConfigObject: public QObject
{
    Q_PROPERTY(QString key READ key)
    Q_PROPERTY(QString value READ value)
    // ... getters and key and value members
};

fill a QList with them and provide them as a model for ListView either via

QVariantList configModel;
// ... fill it with ConfigObjects from std::map
engine.rootContext()->setContextProperty("configModel", &configModel); //QQmlApplicationEngine here

or a property of some class:

Q_PROPERTY(QVariant configModel READ configModel NOTIFY configModelChanged)

Then you should be able to use it via modelData.key and modelData.value in your ListView delegate.

ListView {
    model: configModel // in case of using context
    delegate: Item {
        ...
        Text {
            text: modelData.key
        }
        Text {
            text: modelData.value
        }
    }
}
rightaway717
  • 2,631
  • 3
  • 29
  • 43
1

You should implement a model adapter for std::map by extending a QAbstractListModel, then you can use that as the model for a QML ListView. Implementing the right set of model roles will allow you to access the map element members without the need to use Q_PROPERTY which also requires a QObject derived datatype. Then you only need to expose the model to QML, as a context property for example.

Keep in mind the map is a sorted container, so if you modify the model you should properly reflect the index of insertion and deletion.

So you will have:

std::map -> YourCustomListModel -> ListView

dtech
  • 47,916
  • 17
  • 112
  • 190
  • Makes a lot of sense, I found bits and pieces that indicated to this solution, but couldn't put them together, thanks! Chose @rightaway717 's answer since it also has some code. – DenverCoder21 Mar 03 '16 at 15:04
  • You will eventually run into a situation that calls for creating your own model. I have posted an implementation of a generic QML object model here, the only difference is this one uses QList instead of std::map for storage: http://stackoverflow.com/questions/35160909/how-to-create-a-generic-object-model-for-use-in-qml/35161903#35161903 – dtech Mar 03 '16 at 15:07