From a694b9f8d204d6555caf4e30dbd18f536859c5bd Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Sat, 26 Jan 2013 23:09:24 +0100 Subject: fix QSqlTableModel::headerData() for empty query with inserted row QSqlQueryModel::headerData() relied on virtual indexInQuery() to detect whether the requested column at row 0 mapped to an index in the query. This failed when row 0 was a pending insert managed by QSqlTableModel, and therefore not in the query. The only thing that matters here is the column. Task-number: QTBUG-29108 Change-Id: I3e0ae85ba223e444781ec8033386d394bb44f0e8 Reviewed-by: Andy Shaw Reviewed-by: Mark Brand --- src/sql/models/qsqlquerymodel.cpp | 21 +++++++++++---------- src/sql/models/qsqlquerymodel_p.h | 1 + 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'src/sql/models') diff --git a/src/sql/models/qsqlquerymodel.cpp b/src/sql/models/qsqlquerymodel.cpp index 59103b72d3..00fc410ca5 100644 --- a/src/sql/models/qsqlquerymodel.cpp +++ b/src/sql/models/qsqlquerymodel.cpp @@ -95,6 +95,13 @@ void QSqlQueryModelPrivate::initColOffsets(int size) memset(colOffsets.data(), 0, colOffsets.size() * sizeof(int)); } +int QSqlQueryModelPrivate::columnInQuery(int modelColumn) const +{ + if (modelColumn < 0 || modelColumn >= rec.count() || !rec.isGenerated(modelColumn) || modelColumn >= colOffsets.size()) + return -1; + return modelColumn - colOffsets[modelColumn]; +} + /*! \class QSqlQueryModel \brief The QSqlQueryModel class provides a read-only data model for SQL @@ -370,11 +377,7 @@ QVariant QSqlQueryModel::headerData(int section, Qt::Orientation orientation, in val = d->headers.value(section).value(Qt::EditRole); if (val.isValid()) return val; - - // See if it's an inserted column (iiq.column() != -1) - QModelIndex dItem = indexInQuery(createIndex(0, section)); - - if (role == Qt::DisplayRole && d->rec.count() > section && dItem.column() != -1) + if (role == Qt::DisplayRole && d->rec.count() > section && d->columnInQuery(section) != -1) return d->rec.fieldName(section); } return QAbstractItemModel::headerData(section, orientation, role); @@ -668,12 +671,10 @@ bool QSqlQueryModel::removeColumns(int column, int count, const QModelIndex &par QModelIndex QSqlQueryModel::indexInQuery(const QModelIndex &item) const { Q_D(const QSqlQueryModel); - if (item.column() < 0 || item.column() >= d->rec.count() - || !d->rec.isGenerated(item.column()) - || item.column() >= d->colOffsets.size()) + int modelColumn = d->columnInQuery(item.column()); + if (modelColumn < 0) return QModelIndex(); - return createIndex(item.row(), item.column() - d->colOffsets[item.column()], - item.internalPointer()); + return createIndex(item.row(), modelColumn, item.internalPointer()); } QT_END_NAMESPACE diff --git a/src/sql/models/qsqlquerymodel_p.h b/src/sql/models/qsqlquerymodel_p.h index ecf69003f4..a79b62cda1 100644 --- a/src/sql/models/qsqlquerymodel_p.h +++ b/src/sql/models/qsqlquerymodel_p.h @@ -72,6 +72,7 @@ public: void prefetch(int); void initColOffsets(int size); + int columnInQuery(int modelColumn) const; mutable QSqlQuery query; mutable QSqlError error; -- cgit v1.2.3 From 33c212b7d25726b78c4bf630548a76feaab872f0 Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Wed, 30 Jan 2013 00:39:53 +0100 Subject: QSqlTableModel::setData(): fix non-change detection Commit 10ff9de91bedf93852f13a58287afd8831644759 introduced the optimization of ignoring non-changes, but it overshot the mark. It neglected to consider that QVariant's equality operator does not compare the null flag. It also failed to consider that setData() has a useful side effect of setting the generated flag in a column of a pending INSERT. This is important when the application actually wants a NULL to be inserted into the column. Task-number: QTBUG-29217 Change-Id: I1368f7acc21eebfeb5a8d23746fc38f6f30fd395 Reviewed-by: Andy Shaw Reviewed-by: Mark Brand --- src/sql/models/qsqltablemodel.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/sql/models') diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 32dd517a7a..a2a83e6a4b 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -587,7 +587,10 @@ bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, in if (!(flags(index) & Qt::ItemIsEditable)) return false; - if (QSqlTableModel::data(index, role) == value) + const QVariant oldValue = QSqlTableModel::data(index, role); + if (value == oldValue + && value.isNull() == oldValue.isNull() + && d->cache.value(index.row()).op() != QSqlTableModelPrivate::Insert) return true; QSqlTableModelPrivate::ModifiedRow &row = d->cache[index.row()]; -- cgit v1.2.3 From c3ae1c76f349bac2e262929d29163cd9b5d60332 Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Sun, 27 Jan 2013 17:13:24 +0100 Subject: QSqlTableModel: support refreshing inserted rows with auto columns Previously, selectRow() did not work after INSERTing a new row into a table with an automatically populated column. It did not work because the model did not know the primary values for the new row. Newly inserted rows were therefore not refreshed in OnFieldChange and OnRowChange edit strategies. This change provides support for the typical simple case where a single column is populated by the database and can be retrieved with QSqlQuery::lastInsertId(). Task-Number: QTBUG-29102 Change-Id: Ibf0f0ac8661185bde57034ddf40c2178bece4778 Reviewed-by: Andy Shaw Reviewed-by: Lukas Geyer Reviewed-by: Mark Brand --- src/sql/models/qsqltablemodel.cpp | 15 +++++++++++++++ src/sql/models/qsqltablemodel_p.h | 1 + 2 files changed, 16 insertions(+) (limited to 'src/sql/models') diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index a2a83e6a4b..2822c8bb73 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -355,6 +355,16 @@ void QSqlTableModel::setTable(const QString &tableName) if (d->rec.count() == 0) d->error = QSqlError(QLatin1String("Unable to find table ") + d->tableName, QString(), QSqlError::StatementError); + + // Remember the auto index column if there is one now. + // The record that will be obtained from the query after select lacks this feature. + d->autoColumn.clear(); + for (int c = 0; c < d->rec.count(); ++c) { + if (d->rec.field(c).isAutoValue()) { + d->autoColumn = d->rec.fieldName(c); + break; + } + } } /*! @@ -775,6 +785,11 @@ bool QSqlTableModel::submitAll() } if (success) { + if (d->strategy != OnManualSubmit && mrow.op() == QSqlTableModelPrivate::Insert) { + int c = mrow.rec().indexOf(d->autoColumn); + if (c != -1 && !mrow.rec().isGenerated(c)) + mrow.setValue(c, d->editQuery.lastInsertId()); + } mrow.setSubmitted(); if (d->strategy != OnManualSubmit) success = selectRow(row); diff --git a/src/sql/models/qsqltablemodel_p.h b/src/sql/models/qsqltablemodel_p.h index 56db09b7e0..825490ea39 100644 --- a/src/sql/models/qsqltablemodel_p.h +++ b/src/sql/models/qsqltablemodel_p.h @@ -96,6 +96,7 @@ public: QSqlIndex primaryIndex; QString tableName; QString filter; + QString autoColumn; enum Op { None, Insert, Update, Delete }; -- cgit v1.2.3 From 93ed02e3b1718a560fb8028c80e63b511d334410 Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Mon, 4 Feb 2013 02:01:28 +0100 Subject: fix QSqlTableModel:revert() for OnFieldChange revert() should operate in OnFieldChange edit strategy just as submit() does. The reason in Qt 4 for excluding OnFieldChange was that there was no opportunity to revert. The model was refreshed, causing all changes to be lost. In Qt 5 a failed edit remains in the cache until user action, which could be to revert. Change-Id: Ide021c4f83a53834b7ed81f2abfa3aa49317704d Reviewed-by: Mark Brand --- src/sql/models/qsqltablemodel.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/sql/models') diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 2822c8bb73..2e395b0a59 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -839,7 +839,8 @@ bool QSqlTableModel::submit() user canceled editing the current row. Reverts the changes if the model's strategy is set to - OnRowChange. Does nothing for the other edit strategies. + OnRowChange or OnFieldChange. Does nothing for the OnManualSubmit + strategy. Use revertAll() to revert all pending changes for the OnManualSubmit strategy or revertRow() to revert a specific row. @@ -849,7 +850,7 @@ bool QSqlTableModel::submit() void QSqlTableModel::revert() { Q_D(QSqlTableModel); - if (d->strategy == OnRowChange) + if (d->strategy == OnRowChange || d->strategy == OnFieldChange) revertAll(); } -- cgit v1.2.3