Unsolved QTableView navigation and QSqlTableModel.editStrategy OnFieldChange
-
Hi,
I have a QTableView with a QSqlTableModel.
The navigation is fine when editstrategy of model is set with OnManualSubmit but I lost focus when I press Tab key when editStaegy is OnFieldChange, which is my need.
I tried many things but nothing works and the only topics I found with that issue had no answers.Can you help me ?
-
I'm not sure I got what your problem is.
try adding
connect(tableModel,&QSqlTableModel::dataChanged,[]()->void{qDebug("Data was submitted!");});
if you see the debug output but the database is not updated, something weird is going on
-
My database is updated, the only problem is the navigation in TableView.
I'd like to start editing the first cell then press tab key and continue with the next cell but when I press tab with the OnFieldChange strategy I don't access to any cell, I loose the TableView focus, probably because it update the database -
Ok, I see where the problem might come from. by "continue with the next cell" you mean the next column in the same row?
If so the problem comes from
QSqlTableModel::selectRow
if (needsAddingToCache) { d->cache[row].refresh(exists, newValues); emit headerDataChanged(Qt::Vertical, row, row); emit dataChanged(createIndex(row, 0), createIndex(row, columnCount() - 1)); }
basically it emits dataChanged for the entire row regardless of how many cells actually changed. to solve it you'll need to add the private side of Qt (
QT += sql-private
) and subclass QSqlTableModel and reimplement QSqlTableModel::selectRow like below:bool QSqlTableModel::selectRow(int row) { Q_D(QSqlTableModel); if (row < 0 || row >= rowCount()) return false; const int table_sort_col = d->sortColumn; d->sortColumn = -1; const QString table_filter = d->filter; d->filter = d->db.driver()->sqlStatement(QSqlDriver::WhereStatement, d->tableName, primaryValues(row), false); static const QString wh = Sql::where() + Sql::sp(); if (d->filter.startsWith(wh, Qt::CaseInsensitive)) d->filter.remove(0, wh.length()); QString stmt; if (!d->filter.isEmpty()) stmt = selectStatement(); d->sortColumn = table_sort_col; d->filter = table_filter; if (stmt.isEmpty()) return false; bool exists; QSqlRecord newValues; { QSqlQuery q(d->db); q.setForwardOnly(true); if (!q.exec(stmt)) return false; exists = q.next(); newValues = q.record(); } bool needsAddingToCache = !exists || d->cache.contains(row); QVector<int> colsChanged; if (!needsAddingToCache) { const QSqlRecord curValues = record(row); needsAddingToCache = curValues.count() != newValues.count(); if (!needsAddingToCache) { // Look for changed values. Primary key fields are customarily first // and probably change less often than other fields, so start at the end. for (int f = curValues.count() - 1; f >= 0; --f) { if (curValues.value(f) != newValues.value(f)) { colsChanged << f; } } } } if (needsAddingToCache) { d->cache[row].refresh(exists, newValues); emit headerDataChanged(Qt::Vertical, row, row); emit dataChanged(createIndex(row, 0), createIndex(row, columnCount() - 1)); } else if(!colsChanged.isEmpty()){ d->cache[row].refresh(exists, newValues); emit headerDataChanged(Qt::Vertical, row, row); for(int singleCol : colsChanged) emit dataChanged(createIndex(row, singleCol), createIndex(row, singleCol)); } return true; }
Edit:
I think this problem is related to https://bugreports.qt.io/browse/QTBUG-47078 too -
Yes, I wanted to mean : "next column in the same row".
I forgot to say that I'm on Qt 4.8, so I haven't : QSqlTableModel::selectRow