PDA

View Full Version : QML/C++ Master/Detail ComboBox/Listview



lqsa
19th July 2016, 03:52
On Qt 5.7, Quick Controls 2.0, I have a master ComboBox with a slave ListView. How can the slave change when the user changes the ComboBox selection?

For exemple:

Imagine that I have a list of persons, and every person has a list of cars:
- Person1 - car1, car2, car3
- Person2 - car4
- Person3 - car5, car6, car7, car8
- Person4 - car9, car10
...

The persons must appears on ComboBox and when the users selects a person, the Listview must show person's cars.

I've tried this, but the carsRole is never called on data member, so the ListView doesn't show anything.

QML:


ComboBox {
textRole: "name"
model: personsModel
}
ListView {
model: personsModel.cars
}


C++



enum PersonsRoles {
nameRole = Qt::UserRole + 1,
carsRole
};

QVariant PersonsModel::data(const QModelIndex &index, int role) const
{
int row = index.row();
if ((row < 0) || (row >= _persons.size())) {
return QVariant();
}
switch (role) {
case nameRole:
return _persons.at(row);
case carsRole: {
return QVariant::fromValue(new CarsModel(row));
}
}
return QVariant();
}

QHash<int, QByteArray> PersonsModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[nameRole] = "name";
roles[carsRole] = "cars";
return roles;
}

anda_skoa
19th July 2016, 07:55
Your QML is trying to access the "cars" property on the "peronsModel" object, not the "cars" role on any specific index.

For access to the "cars" role you would need a custom delegate, as it has access to the roles of its index through "model.rolename".

If your PersonsModel instance is only used for that specific combobox, then you could add the property your QML is currently trying to access and have it hold a CarsModel that gets changed whenever the combobox changes its current index.

Alternatively you could have a function that returns the CarsModel for a given index


Q_INVOKABLE CarsModel* carsForRow(int row);

and call that from QML



ListView {
model: personsModel.carsForRow(combo.currentIndex)
}


Cheers,
_

lqsa
20th July 2016, 12:43
Hi, thank you very much, it works well.

Only remarks than to avoid to register the CarsModel on QML engine, the Q_INVOKABLE can return a QVariant:


Q_INVOKABLE QVariant carsForRow(int row);

On the method carsForRow only must to convert the CarsModel* to QVariant:

return QVariant::fromValue(carsModel);

Cheers

anda_skoa
20th July 2016, 14:19
You can also make the method return QObject*

Cheers,
_