Details
-
Bug
-
Resolution: Unresolved
-
P4: Low
-
None
-
5.5.1
-
None
-
Red Hat Enterprise Linux 6.8
Description
I've been experiencing some of the previously reported issues between QSql[Relational]TableModel, QSqlRelationalDelegate, QDataWidgetMapper, and QComboBox (see QTBUG-1086, QTBUG-158, QTBUG-29046, QTBUG-23973, QTBUG-431).
I know code is easier to diagnose, but I can't post it yet. I have partly diagnosed the problem, so I will attempt to explain what I understand.
I have a parent model, which is a QSqlRelationalTableModel. It is connected to a QDataWidgetMapper with a QSqlRelationalDelegate. The editStrategy of parent model is onFieldChange.
Two of the mapped form widgets are QComboBox. All the mapped widgets are updated correctly as you navigate through the parent records.
The source model of the first combo box is a QSqlTableModel, from setRelation() on the parent model. After making a different selection from this combo box, the parent model/database is updated but the combo box is no longer updated for that record.
The model of the second combo box is a QSortFilterProxyModel for the QSqlTablemodel from setRelation() because I wanted to filter its based on the selection of the first combo box. However, selections from this combo box are not (reliably) submitted to the parent model/database and it is also no longer updated.
In troubleshooting, I found that the delegate incorrectly assumes that the index being passed to setModelData() is for the related QSqlTableModel instead of the combo's actual (filtered proxy) model, which results in the wrong values (attempted to be) stored.
Maybe my approach is wrong, but it's still a bad assumption.
Here is a partial solution, which maps the proxied index.
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
if (!index.isValid())
return;
QSqlRelationalTableModel *sqlModel = qobject_cast<QSqlRelationalTableModel *>(model);
QSqlTableModel *childModel = sqlModel ? sqlModel->relationModel(index.column()) : 0;
QComboBox *combo = qobject_cast<QComboBox *>(editor);
if (!sqlModel || !childModel || !combo)
{ QItemDelegate::setModelData(editor, model, index); return; }int currentItem = combo->currentIndex();
// fix for combo box proxy model
QAbstractItemModel *cbMdl = combo->model();
QSortFilterProxyModel *proxy = qobject_cast<QSortFilterProxyModel *>(cbMdl);
if (proxy) {
QSqlTableModel *src = qobject_cast<QSqlTableModel *>(proxy->sourceModel());
if (src)
}
int childColIndex = childModel->fieldIndex(sqlModel->relation(index.column()).displayColumn());
int childEditIndex = childModel->fieldIndex(sqlModel->relation(index.column()).indexColumn());
sqlModel->setData(index,
childModel->data(childModel->index(currentItem, childColIndex), Qt::DisplayRole),
Qt::DisplayRole);
sqlModel->setData(index,
childModel->data(childModel->index(currentItem, childEditIndex), Qt::EditRole),
Qt::EditRole);
}