Функция setData принадлежит классу QSqlTableModel, в классе предке QSqlQueryModel setData нет. QSqlQueryModel
Установка значений происходит непосредственно уже в базу данных через функцию updateRowInTable.
Посмотрим QSqlTableModel::setData(..).
bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
Q_D(QSqlTableModel);
if (role != Qt::EditRole)
return QSqlQueryModel::setData(index, value, role);
if (!index.isValid() || index.column() >= d->rec.count() || index.row() >= rowCount())
return false;
bool isOk = true;
switch (d->strategy) {
case OnFieldChange: {
if (index.row() == d->insertIndex) {
QSqlTableModelPrivate::setGeneratedValue(d->editBuffer, index.column(), value);
return true;
}
d->clearEditBuffer();
QSqlTableModelPrivate::setGeneratedValue(d->editBuffer, index.column(), value);
isOk = updateRowInTable(index.row(), d->editBuffer);
if (isOk)
select();
emit dataChanged(index, index);
break; }
case OnRowChange:
if (index.row() == d->insertIndex) {
QSqlTableModelPrivate::setGeneratedValue(d->editBuffer, index.column(), value);
return true;
}
if (d->editIndex != index.row()) {
if (d->editIndex != -1)
submit();
d->clearEditBuffer();
}
QSqlTableModelPrivate::setGeneratedValue(d->editBuffer, index.column(), value);
d->editIndex = index.row();
emit dataChanged(index, index);
break;
case OnManualSubmit: {
QSqlTableModelPrivate::ModifiedRow &row = d->cache[index.row()];
if (row.op == QSqlTableModelPrivate::None) {
row.op = QSqlTableModelPrivate::Update;
row.rec = d->rec;
QSqlTableModelPrivate::clearGenerated(row.rec);
row.primaryValues = d->primaryValues(indexInQuery(index).row());
}
QSqlTableModelPrivate::setGeneratedValue(row.rec, index.column(), value);
emit dataChanged(index, index);
break; }
}
return isOk;
}
submit при OnRowChange
Очень важным нюансом является наличие вызова функции submit в коде функции setData.
Это как раз тот случай, когда вы оставляете редактирование поля одной строки и переходите к редактированию поля другой строки в режиме стратегии редактирования OnRowChange.
И все бы ничего, но нюанс в том, что после submit слетают все текщие присвоенные индексы. То есть, если вы планировали вызвать еще какой-то второй setData, то в результате первого setData может произойти submit, потом произойдет select и как следствие все ранее определенные индексы (QModelIndex) протухнут. Буквально их row/column станут -1/-1.
Кстати именно это и будет являться признаком, что произошел select. И это можно использовать в своих целях.
Теперь немного анализа кода setData
В зависимости от выбранной стратегии редактирования setData пишет данные в разные хранилища.
OnFieldChange
Может показаться, что при стратегии OnFieldChange данные сразу записываются в базу данных. И это правильно с одной оговоркой: если это не вставка новой строки.
При вставке новой строки и потом редактировании поля этой строки запись в базу сразу может и не произойти. Это зависит от клавиши, которой вы завершаете редактирование.
Например если вы не жмете Enter после редактирования - вызывается submit.
А если вы жмете tab после редактирования и переходите к другому полю этой вставляемой строки, то в функции setData функция submit не вызывется. А данные сохранятся в editBuffer.
OnRowChange
При стратегии OnRowChange данные сохраняются во временном буфере editBuffer (обычный QSqlRecord).
OnManualSubmit
При использовании стратегии OnManualSubmit данные пишутся в кэш модели данных (контейнер cache). То есть данные в базу данных не пишутся, все копится в cache.
Может показаться , что можно записывать данные от роли отличной от EditRole. Но изначально это не так, смотрите роли в модели данных.
Логгируем работу модели данных QSqlRelationalTableModel и ее представления QTableView.Смотрите логирование запросов.
setData вызывается обычно интерактивным элементом управления в QTableView при установке нового значения в поле таблицы.
Например делает ComboBoxDelegate в setModelData индекс [1x6] newValue : 0. То есть тут и вызывается setData модели данных с целью установить новое значение.
В модели данных выпускается сигнал dataChanged (конкретно в QSqlTableModel) , который можно связать со своим слотом, чтобы проверять устанавливаемое значение на валидность. Но на самом деле проверять что-то уже поздно.
Может показаться, что обрабатывая dataChanged можно как сделать submit, так и revert установки нового значения, но по нашему мнегию это поавильное решение.
ComboBoxDelegate::createEditor [1x6] parent objName qt_scrollarea_viewport option " QStyleOption( SO_ViewItem , LeftToRight , QStyle::State( "Active | Enabled | HasFocus" ) , QRect(439,30 90x29) )
"ComboBoxDelegate::updateEditorGeometry [1x6] option " option : QStyleOption( SO_ViewItem , LeftToRight , QStyle::State( "Active | Enabled | HasFocus" ) , QRect(439,30 90x29) )
ComboBoxDelegate::slot_currentIndexChanged commitData currentIndex() : -1
ComboBoxDelegate::slot_currentIndexChanged commitData currentIndex() : 0
"ComboBoxDelegate::setModelData [1x6] newValue : 0"
ComboBoxDelegate::setModelData model->setData(index, newValue, Qt::EditRole)
my_TableView_Purchases::dataChanged return
testCheck::purch_dataChanged
"taxCode" : "0"
testCheck::slot_beforeUpdatePurch field : "taxCode" isGenerated : true newVal QVariant(int, 0)
table_QSqlRelationalTableModel::updateRowInTable row 1 true
testCheck::purch_dataChanged submitAll true
ComboBoxDelegate::setModelData model->setData(index, newValue, Qt::EditRole) : true
table_QSqlRelationalTableModel::updateRowInTable row -1 false
ComboBoxDelegate::setModelData model->submit() false newValue 0
Примечание: setData и submit для установки нового значения использует в итоге те же sql команды типа UPDATE ...