[Interest] QSqlRelationalModel and QDataWidgetMapper: can items in QComboBox be filtered?

Dmitry Teslenko dteslenko at gmail.com
Mon Feb 27 08:51:28 CET 2012


> There's nice qt docs example here:
> http://doc.qt.nokia.com/4.7-snapshot/sql-sqlwidgetmapper.html
> demonstrating QSqlRelationalTable, QDataWidgetMapper and QComboBox.
>
> They setup model:
>        ...
>        query.exec("create table person (id int primary key, "
>                "name varchar(20), address varchar(200), typeid int)");
>        ...
>        query.exec("create table addresstype (id int, description varchar(20))");
>        ...
>         model = new QSqlRelationalTableModel(this);
>     model->setTable("person");
>     model->setEditStrategy(QSqlTableModel::OnManualSubmit);
>
>     typeIndex = model->fieldIndex("typeid");
>
>     model->setRelation(typeIndex,
>            QSqlRelation("addresstype", "id", "description"));
>     model->select();
>
> and then setup mapper:
>     QSqlTableModel *relModel = model->relationModel(typeIndex);
>     typeComboBox->setModel(relModel);
>     typeComboBox->setModelColumn(relModel->fieldIndex("description"));
>
>     mapper = new QDataWidgetMapper(this);
>     mapper->setModel(model);
>     mapper->setItemDelegate(new QSqlRelationalDelegate(this));
>     mapper->addMapping(nameEdit, model->fieldIndex("name"));
>     mapper->addMapping(addressEdit, model->fieldIndex("address"));
>     mapper->addMapping(typeComboBox, typeIndex);
>
>
> Here's the question: is there a way to filter typeComboBox items while
> editing a record? Say, on button click. User clicks button and theres
> types with some property only in typeComboBox.
> I've tried two things:
> 1) calling setFilter on relModel. This somehow "decouples" combobox
> from mapper and no further updates from typeComboBox pass to model.
> 2) setting typeComboBox::setModel() to relModel wrapped in
> QSortFilterProxyModel. This causes invalid values to assigned. Say,
> I picked second item in filtered list and mapper assigned second
> item in not filtered list to model.


I managed to make it work. My solution is QSortFilterProxyModel and
subclassed QComboBox with new user property and these setter-getter:

QVariant MyComboBox::data() const {
	return = model()->data(
		model()->index(currentIndex(), <column-with-id-index>),
		Qt::EditRole
	);
}

void MyComboBox::setData(const QVariant &d) {
	QModelIndexList list = model()->match(
		model()->index(0, modelColumn()/*note this is column-with-name-index*/),
		Qt::EditRole,
		d
	);

	if(list.isEmpty()) {
		setCurrentIndex(-1);
	} else {
		setCurrentIndex(list.at(0).row());
	}
}

Here's some more things I don't quite understand.
1) When I call QDataWidgetMapper setCurrentIndex and mapper populates
widgets with data it calls MyComboBox::setData() passing it name from
related table. Why it's name and not index?

2) When I edit form and pick different items from MyComboBox mapper
performs calls to MyComboBox::setData and passes it index values (not
names this time!).


-- 
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?



More information about the Interest mailing list