ModifiedRow: use for all edit strategies

Previously ModifiedRow was used only for OnManualSubmit and
a seperate buffer and utility methods were used for OnFieldChange
and OnRowChange.

Also, initialization of the edit buffer is done by ModifiedRow
instead of a helper function.

Change-Id: I3316498e5bb10c416138ca14c3a7f8b143c8e544
Reviewed-by: Yunqiao Yin <charles.yin@nokia.com>
This commit is contained in:
Mark Brand 2011-07-06 09:49:45 +02:00 committed by Qt by Nokia
parent 23457bd6d9
commit 48c68b0546
3 changed files with 139 additions and 255 deletions

View File

@ -265,7 +265,6 @@ public:
mutable QVector<QRelation> relations; mutable QVector<QRelation> relations;
QSqlRecord baseRec; // the record without relations QSqlRecord baseRec; // the record without relations
void clearChanges(); void clearChanges();
void clearEditBuffer();
void clearCache(); void clearCache();
void revertCachedRow(int row); void revertCachedRow(int row);
@ -311,12 +310,6 @@ int QSqlRelationalTableModelPrivate::nameToIndex(const QString &name) const
return idx; return idx;
} }
void QSqlRelationalTableModelPrivate::clearEditBuffer()
{
editBuffer = baseRec;
clearGenerated(editBuffer);
}
/*! /*!
\reimp \reimp
*/ */
@ -445,24 +438,17 @@ QVariant QSqlRelationalTableModel::data(const QModelIndex &index, int role) cons
//when the value at index has been changed or added. //when the value at index has been changed or added.
//At an unmodified index, the underlying model will //At an unmodified index, the underlying model will
//already have the correct display value. //already have the correct display value.
QVariant v; if (d->strategy != OnFieldChange) {
switch (d->strategy) {
case OnFieldChange:
break;
case OnRowChange:
if ((index.row() == d->editIndex || index.row() == d->insertIndex)
&& d->editBuffer.isGenerated(index.column()))
v = d->editBuffer.value(index.column());
break;
case OnManualSubmit:
const QSqlTableModelPrivate::ModifiedRow row = d->cache.value(index.row()); const QSqlTableModelPrivate::ModifiedRow row = d->cache.value(index.row());
if (row.op != QSqlTableModelPrivate::None && row.rec.isGenerated(index.column())) if (row.op != QSqlTableModelPrivate::None && row.rec.isGenerated(index.column())) {
v = row.rec.value(index.column()); if (d->strategy == OnManualSubmit || row.op != QSqlTableModelPrivate::Delete) {
break; QVariant v = row.rec.value(index.column());
}
if (v.isValid()) if (v.isValid())
return relation.dictionary[v.toString()]; return relation.dictionary[v.toString()];
} }
}
}
}
return QSqlTableModel::data(index, role); return QSqlTableModel::data(index, role);
} }

View File

@ -112,52 +112,21 @@ void QSqlTableModelPrivate::initRecordAndPrimaryIndex()
void QSqlTableModelPrivate::clear() void QSqlTableModelPrivate::clear()
{ {
editIndex = -1;
sortColumn = -1; sortColumn = -1;
sortOrder = Qt::AscendingOrder; sortOrder = Qt::AscendingOrder;
tableName.clear(); tableName.clear();
editQuery.clear(); editQuery.clear();
editBuffer.clear();
cache.clear(); cache.clear();
primaryIndex.clear(); primaryIndex.clear();
rec.clear(); rec.clear();
filter.clear(); filter.clear();
} }
void QSqlTableModelPrivate::revertInsertedRow()
{
Q_Q(QSqlTableModel);
if (insertIndex == -1)
return;
q->beginRemoveRows(QModelIndex(), insertIndex, insertIndex);
insertIndex = -1;
q->endRemoveRows();
}
void QSqlTableModelPrivate::clearEditBuffer()
{
editBuffer = rec;
clearGenerated(editBuffer);
}
void QSqlTableModelPrivate::clearCache() void QSqlTableModelPrivate::clearCache()
{ {
cache.clear(); cache.clear();
} }
void QSqlTableModelPrivate::clearGenerated(QSqlRecord &rec)
{
for (int i = rec.count() - 1; i >= 0; i--)
rec.setGenerated(i, false);
}
void QSqlTableModelPrivate::setGeneratedValue(QSqlRecord &rec, int c, QVariant v)
{
rec.setValue(c, v);
rec.setGenerated(c, true);
}
void QSqlTableModelPrivate::revertCachedRow(int row) void QSqlTableModelPrivate::revertCachedRow(int row)
{ {
Q_Q(QSqlTableModel); Q_Q(QSqlTableModel);
@ -443,26 +412,25 @@ QVariant QSqlTableModel::data(const QModelIndex &index, int role) const
// and indexInQuery is not virtual (grrr) so any values we pass to QSQM need // and indexInQuery is not virtual (grrr) so any values we pass to QSQM need
// to handle the insertedRows // to handle the insertedRows
QModelIndex item = indexInQuery(index); QModelIndex item = indexInQuery(index);
const QSqlTableModelPrivate::ModifiedRow row = d->cache.value(index.row());
switch (d->strategy) { switch (d->strategy) {
case OnFieldChange: case OnFieldChange:
case OnRowChange: case OnRowChange:
if (index.row() == d->insertIndex) { if (row.op == QSqlTableModelPrivate::Insert) {
if (item.column() < 0 || item.column() >= d->rec.count()) if (item.column() < 0 || item.column() >= row.rec.count())
return QVariant(); return QVariant();
return d->editBuffer.value(index.column()); return row.rec.value(item.column());
} } else if (row.op == QSqlTableModelPrivate::Update) {
if (d->editIndex == item.row()) { if (row.rec.isGenerated(item.column()))
if (d->editBuffer.isGenerated(item.column())) return row.rec.value(item.column());
return d->editBuffer.value(item.column());
} }
break; break;
case OnManualSubmit: case OnManualSubmit:
if (d->cache.contains(index.row())) { if (row.op == QSqlTableModelPrivate::Insert
const QSqlTableModelPrivate::ModifiedRow row = d->cache.value(index.row()); || (row.op != QSqlTableModelPrivate::None
if (row.rec.isGenerated(item.column()) || row.op == QSqlTableModelPrivate::Insert) && row.rec.isGenerated(item.column())))
return row.rec.value(item.column()); return row.rec.value(item.column());
}
break; break;
} }
@ -477,20 +445,11 @@ QVariant QSqlTableModel::headerData(int section, Qt::Orientation orientation, in
{ {
Q_D(const QSqlTableModel); Q_D(const QSqlTableModel);
if (orientation == Qt::Vertical && role == Qt::DisplayRole) { if (orientation == Qt::Vertical && role == Qt::DisplayRole) {
switch (d->strategy) { const QSqlTableModelPrivate::Op op = d->cache.value(section).op;
case OnFieldChange:
case OnRowChange:
if (d->insertIndex == section)
return QLatin1String("*");
break;
case OnManualSubmit:
QSqlTableModelPrivate::Op op = d->cache.value(section).op;
if (op == QSqlTableModelPrivate::Insert) if (op == QSqlTableModelPrivate::Insert)
return QLatin1String("*"); return QLatin1String("*");
else if (op == QSqlTableModelPrivate::Delete) else if (op == QSqlTableModelPrivate::Delete)
return QLatin1String("!"); return QLatin1String("!");
break;
}
} }
return QSqlQueryModel::headerData(section, orientation, role); return QSqlQueryModel::headerData(section, orientation, role);
} }
@ -511,8 +470,11 @@ bool QSqlTableModel::isDirty(const QModelIndex &index) const
switch (d->strategy) { switch (d->strategy) {
case OnFieldChange: case OnFieldChange:
return false; return false;
case OnRowChange: case OnRowChange: {
return index.row() == d->editIndex && d->editBuffer.isGenerated(index.column()); const QSqlTableModelPrivate::ModifiedRow row = d->cache.value(index.row());
return row.op == QSqlTableModelPrivate::Update
&& row.rec.isGenerated(index.column());
}
case OnManualSubmit: { case OnManualSubmit: {
const QSqlTableModelPrivate::ModifiedRow row = d->cache.value(index.row()); const QSqlTableModelPrivate::ModifiedRow row = d->cache.value(index.row());
return row.op == QSqlTableModelPrivate::Insert return row.op == QSqlTableModelPrivate::Insert
@ -546,31 +508,37 @@ bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, in
bool isOk = true; bool isOk = true;
switch (d->strategy) { switch (d->strategy) {
case OnFieldChange: { case OnFieldChange: {
if (index.row() == d->insertIndex) { QSqlTableModelPrivate::ModifiedRow &row = d->cache[index.row()];
QSqlTableModelPrivate::setGeneratedValue(d->editBuffer, index.column(), value); if (row.op == QSqlTableModelPrivate::Insert) {
row.setValue(index.column(), value);
return true; return true;
} }
d->clearEditBuffer(); row = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Update,
QSqlTableModelPrivate::setGeneratedValue(d->editBuffer, index.column(), value); d->rec,
isOk = updateRowInTable(index.row(), d->editBuffer); d->primaryValues(indexInQuery(index).row()));
row.setValue(index.column(), value);
isOk = updateRowInTable(index.row(), row.rec);
if (isOk) if (isOk)
select(); select();
emit dataChanged(index, index); emit dataChanged(index, index);
break; } break; }
case OnRowChange: case OnRowChange: {
if (index.row() == d->insertIndex) { if (!d->cache.isEmpty() && !d->cache.contains(index.row())) {
QSqlTableModelPrivate::setGeneratedValue(d->editBuffer, index.column(), value);
return true;
}
if (d->editIndex != index.row()) {
if (d->editIndex != -1)
submit(); submit();
d->clearEditBuffer(); d->cache.clear();
} }
QSqlTableModelPrivate::setGeneratedValue(d->editBuffer, index.column(), value); QSqlTableModelPrivate::ModifiedRow &row = d->cache[index.row()];
d->editIndex = index.row(); if (row.op == QSqlTableModelPrivate::Insert) {
row.setValue(index.column(), value);
return true;
} else if (row.op == QSqlTableModelPrivate::None) {
row = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Update,
d->rec,
d->primaryValues(indexInQuery(index).row()));
}
row.setValue(index.column(), value);
emit dataChanged(index, index); emit dataChanged(index, index);
break; break; }
case OnManualSubmit: { case OnManualSubmit: {
QSqlTableModelPrivate::ModifiedRow &row = d->cache[index.row()]; QSqlTableModelPrivate::ModifiedRow &row = d->cache[index.row()];
if (row.op == QSqlTableModelPrivate::None) { if (row.op == QSqlTableModelPrivate::None) {
@ -726,27 +694,6 @@ bool QSqlTableModel::submitAll()
{ {
Q_D(QSqlTableModel); Q_D(QSqlTableModel);
switch (d->strategy) {
case OnFieldChange:
if (d->insertIndex == -1)
return true;
// else fall through
case OnRowChange:
if (d->editBuffer.isEmpty())
return true;
if (d->insertIndex != -1) {
if (!insertRowIntoTable(d->editBuffer))
return false;
d->bottom = d->bottom.sibling(d->bottom.row() + 1, d->bottom.column());
} else {
if (!updateRowInTable(d->editIndex, d->editBuffer))
return false;
}
d->clearEditBuffer();
d->editIndex = -1;
d->insertIndex = -1;
return select();
case OnManualSubmit:
for (QSqlTableModelPrivate::CacheMap::ConstIterator it = d->cache.constBegin(); for (QSqlTableModelPrivate::CacheMap::ConstIterator it = d->cache.constBegin();
it != d->cache.constEnd(); ++it) { it != d->cache.constEnd(); ++it) {
switch (it.value().op) { switch (it.value().op) {
@ -771,8 +718,6 @@ bool QSqlTableModel::submitAll()
d->clearCache(); d->clearCache();
return select(); return select();
} }
return false;
}
/*! /*!
This reimplemented slot is called by the item delegates when the This reimplemented slot is called by the item delegates when the
@ -871,20 +816,9 @@ QSqlTableModel::EditStrategy QSqlTableModel::editStrategy() const
void QSqlTableModel::revertAll() void QSqlTableModel::revertAll()
{ {
Q_D(QSqlTableModel); Q_D(QSqlTableModel);
switch (d->strategy) {
case OnFieldChange:
break;
case OnRowChange:
if (d->editIndex != -1)
revertRow(d->editIndex);
else if (d->insertIndex != -1)
revertRow(d->insertIndex);
break;
case OnManualSubmit:
while (!d->cache.isEmpty()) while (!d->cache.isEmpty())
revertRow(d->cache.constBegin().key()); revertRow(d->cache.constBegin().key());
break;
}
} }
/*! /*!
@ -898,23 +832,7 @@ void QSqlTableModel::revertRow(int row)
return; return;
Q_D(QSqlTableModel); Q_D(QSqlTableModel);
switch (d->strategy) {
case OnFieldChange:
break;
case OnRowChange: {
if (d->editIndex == row) {
d->editBuffer.clear();
int oldIndex = d->editIndex;
d->editIndex = -1;
emit dataChanged(createIndex(oldIndex, 0), createIndex(oldIndex, columnCount()));
} else if (d->insertIndex == row) {
d->revertInsertedRow();
}
break; }
case OnManualSubmit:
d->revertCachedRow(row); d->revertCachedRow(row);
break;
}
} }
/*! /*!
@ -1096,23 +1014,11 @@ bool QSqlTableModel::removeRows(int row, int count, const QModelIndex &parent)
if (parent.isValid() || row < 0 || count <= 0) if (parent.isValid() || row < 0 || count <= 0)
return false; return false;
int initialRowCount = rowCount();
int i; int i;
switch (d->strategy) { for (i = 0; i < count && row + i < rowCount(); ++i) {
case OnFieldChange:
case OnRowChange:
for (i = 0; i < count; ++i) {
if (row + i == d->insertIndex)
d->revertInsertedRow();
else if (!deleteRowFromTable(row + i))
return false;
}
select();
break;
case OnManualSubmit:
for (i = 0; i < count; ++i) {
int idx = row + i; int idx = row + i;
if (idx >= rowCount())
return false;
if (d->cache.value(idx).op == QSqlTableModelPrivate::Insert) { if (d->cache.value(idx).op == QSqlTableModelPrivate::Insert) {
revertRow(idx); revertRow(idx);
// Reverting a row means all the other cache entries have been adjusted downwards // Reverting a row means all the other cache entries have been adjusted downwards
@ -1122,11 +1028,23 @@ bool QSqlTableModel::removeRows(int row, int count, const QModelIndex &parent)
d->cache[idx] = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Delete, d->cache[idx] = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Delete,
QSqlRecord(), QSqlRecord(),
d->primaryValues(indexInQuery(createIndex(idx, 0)).row())); d->primaryValues(indexInQuery(createIndex(idx, 0)).row()));
if (d->strategy == OnManualSubmit)
emit headerDataChanged(Qt::Vertical, idx, idx); emit headerDataChanged(Qt::Vertical, idx, idx);
} }
} }
break;
if (d->strategy != OnManualSubmit && i > 0)
submit();
// historical bug: emit beforeDelete for 1st row beyond end
if (d->strategy != OnManualSubmit) {
if (row + count > initialRowCount)
emit beforeDelete(qMax(initialRowCount, row));
} }
if (i < count)
return false;
return true; return true;
} }
@ -1153,19 +1071,14 @@ bool QSqlTableModel::insertRows(int row, int count, const QModelIndex &parent)
if (row < 0 || count <= 0 || row > rowCount() || parent.isValid()) if (row < 0 || count <= 0 || row > rowCount() || parent.isValid())
return false; return false;
switch (d->strategy) { if (d->strategy != OnManualSubmit && count != 1)
case OnFieldChange:
case OnRowChange:
if (count != 1)
return false; return false;
beginInsertRows(parent, row, row);
d->insertIndex = row;
// ### apply dangling changes...
d->clearEditBuffer();
emit primeInsert(row, d->editBuffer);
break;
case OnManualSubmit:
beginInsertRows(parent, row, row + count - 1); beginInsertRows(parent, row, row + count - 1);
if (d->strategy != OnManualSubmit)
d->cache.empty();
if (!d->cache.isEmpty()) { if (!d->cache.isEmpty()) {
QMap<int, QSqlTableModelPrivate::ModifiedRow>::Iterator it = d->cache.end(); QMap<int, QSqlTableModelPrivate::ModifiedRow>::Iterator it = d->cache.end();
while (it != d->cache.begin() && (--it).key() >= row) { while (it != d->cache.begin() && (--it).key() >= row) {
@ -1181,8 +1094,7 @@ bool QSqlTableModel::insertRows(int row, int count, const QModelIndex &parent)
d->rec); d->rec);
emit primeInsert(row + i, d->cache[row + i].rec); emit primeInsert(row + i, d->cache[row + i].rec);
} }
break;
}
endInsertRows(); endInsertRows();
return true; return true;
} }
@ -1220,15 +1132,11 @@ int QSqlTableModel::rowCount(const QModelIndex &parent) const
return 0; return 0;
int rc = QSqlQueryModel::rowCount(); int rc = QSqlQueryModel::rowCount();
if (d->strategy == OnManualSubmit) {
for (QSqlTableModelPrivate::CacheMap::ConstIterator it = d->cache.constBegin(); for (QSqlTableModelPrivate::CacheMap::ConstIterator it = d->cache.constBegin();
it != d->cache.constEnd(); ++it) { it != d->cache.constEnd(); ++it) {
if (it.value().op == QSqlTableModelPrivate::Insert) if (it.value().op == QSqlTableModelPrivate::Insert)
++rc; ++rc;
} }
} else if (d->insertIndex >= 0) {
++rc;
}
return rc; return rc;
} }
@ -1248,7 +1156,6 @@ QModelIndex QSqlTableModel::indexInQuery(const QModelIndex &item) const
{ {
Q_D(const QSqlTableModel); Q_D(const QSqlTableModel);
const QModelIndex it = QSqlQueryModel::indexInQuery(item); // this adjusts columns only const QModelIndex it = QSqlQueryModel::indexInQuery(item); // this adjusts columns only
if (d->strategy == OnManualSubmit) {
int rowOffset = 0; int rowOffset = 0;
QSqlTableModelPrivate::CacheMap::ConstIterator i = d->cache.constBegin(); QSqlTableModelPrivate::CacheMap::ConstIterator i = d->cache.constBegin();
while (i != d->cache.constEnd() && i.key() <= it.row()) { while (i != d->cache.constEnd() && i.key() <= it.row()) {
@ -1257,11 +1164,6 @@ QModelIndex QSqlTableModel::indexInQuery(const QModelIndex &item) const
++i; ++i;
} }
return createIndex(it.row() - rowOffset, it.column(), it.internalPointer()); return createIndex(it.row() - rowOffset, it.column(), it.internalPointer());
} else {
if (d->insertIndex >= 0 && it.row() >= d->insertIndex)
return createIndex(it.row() - 1, it.column(), it.internalPointer());
}
return it;
} }
/*! /*!

View File

@ -64,29 +64,23 @@ class QSqlTableModelPrivate: public QSqlQueryModelPrivate
public: public:
QSqlTableModelPrivate() QSqlTableModelPrivate()
: editIndex(-1), insertIndex(-1), sortColumn(-1), : sortColumn(-1),
sortOrder(Qt::AscendingOrder), sortOrder(Qt::AscendingOrder),
strategy(QSqlTableModel::OnRowChange) strategy(QSqlTableModel::OnRowChange)
{} {}
void clear(); void clear();
QSqlRecord primaryValues(int index); QSqlRecord primaryValues(int index);
virtual void clearEditBuffer();
virtual void clearCache(); virtual void clearCache();
static void clearGenerated(QSqlRecord &rec);
static void setGeneratedValue(QSqlRecord &rec, int c, QVariant v);
QSqlRecord record(const QVector<QVariant> &values) const; QSqlRecord record(const QVector<QVariant> &values) const;
bool exec(const QString &stmt, bool prepStatement, bool exec(const QString &stmt, bool prepStatement,
const QSqlRecord &rec, const QSqlRecord &whereValues); const QSqlRecord &rec, const QSqlRecord &whereValues);
virtual void revertCachedRow(int row); virtual void revertCachedRow(int row);
void revertInsertedRow();
bool setRecord(int row, const QSqlRecord &record); bool setRecord(int row, const QSqlRecord &record);
virtual int nameToIndex(const QString &name) const; virtual int nameToIndex(const QString &name) const;
void initRecordAndPrimaryIndex(); void initRecordAndPrimaryIndex();
QSqlDatabase db; QSqlDatabase db;
int editIndex;
int insertIndex;
int sortColumn; int sortColumn;
Qt::SortOrder sortOrder; Qt::SortOrder sortOrder;
@ -103,7 +97,11 @@ public:
struct ModifiedRow struct ModifiedRow
{ {
inline ModifiedRow(Op o = None, const QSqlRecord &r = QSqlRecord(), const QSqlRecord &pVals = QSqlRecord()) inline ModifiedRow(Op o = None, const QSqlRecord &r = QSqlRecord(), const QSqlRecord &pVals = QSqlRecord())
: op(o), rec(r), primaryValues(pVals) { clearGenerated(rec); } : op(o), rec(r), primaryValues(pVals)
{
for (int i = rec.count() - 1; i >= 0; --i)
rec.setGenerated(i, false);
}
inline void setValue(int c, const QVariant &v) inline void setValue(int c, const QVariant &v)
{ {
rec.setValue(c, v); rec.setValue(c, v);
@ -114,8 +112,6 @@ public:
QSqlRecord primaryValues; QSqlRecord primaryValues;
}; };
QSqlRecord editBuffer;
typedef QMap<int, ModifiedRow> CacheMap; typedef QMap<int, ModifiedRow> CacheMap;
CacheMap cache; CacheMap cache;
}; };