Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-55965

QSqlRelationalDelegate for QDataWidgetMapper incorrectly assumes model of mapped QComboBox is QSqlTableModel

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P4: Low
    • None
    • 5.5.1
    • Widgets: Itemviews
    • 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)

      { currentItem = proxy->mapToSource(proxy->index(combo->currentIndex(), 0)).row(); }

      }

      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);
      }

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            qt.team.quick.subscriptions Qt Quick and Widgets Team
            glenn.aycock Glenn Aycock
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes