summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMark Brand <mabrand@mabrand.nl>2012-02-15 09:56:23 +0100
committerQt by Nokia <qt-info@nokia.com>2012-03-07 00:01:07 +0100
commitb979956ec46093e5668c2b264f9b68da3cbb0326 (patch)
tree14d05c1fe58c08a29ff8c4bf6703a247c38979b3 /src
parentd7b720dd3ee7a095abe7e283d1bed881268b0f5e (diff)
QSqlTableModel: handle changes between submit and select
Once an insert has been submitted, the cached record behaves like an update. For row bookkeeping, we still have to remember that it was originally inserted and is not in the query rows. Between submitting a delete and selecting, we remove the values from the deleted record. This causes a blank row to be displayed. Read-only flag is set for cells in deleted row. Reverting between submit and select means going back to the last submitted values. When removing rows, it's better to process from highest row numbers to lowest. This avoids complications with higher rows shifting down when lower rows are removed. Change-Id: I8752fa11f7a1b88f2a71b9e03a020ac37e62487f Reviewed-by: Honglei Zhang <honglei.zhang@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/sql/models/qsqltablemodel.cpp52
-rw-r--r--src/sql/models/qsqltablemodel_p.h47
2 files changed, 71 insertions, 28 deletions
diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp
index 24668dd946..9ade5f14d5 100644
--- a/src/sql/models/qsqltablemodel.cpp
+++ b/src/sql/models/qsqltablemodel.cpp
@@ -87,7 +87,7 @@ int QSqlTableModelPrivate::insertCount(int maxRow) const
for (;
i != e && (maxRow < 0 || i.key() <= maxRow);
++i) {
- if (i.value().op() == Insert)
+ if (i.value().insert())
++cnt;
}
@@ -122,19 +122,17 @@ void QSqlTableModelPrivate::revertCachedRow(int row)
Q_Q(QSqlTableModel);
ModifiedRow r = cache.value(row);
- // cannot revert a committed change
- if (r.submitted())
- return;
-
switch (r.op()) {
case QSqlTableModelPrivate::None:
Q_ASSERT_X(false, "QSqlTableModelPrivate::revertCachedRow()", "Invalid entry in cache map");
return;
case QSqlTableModelPrivate::Update:
case QSqlTableModelPrivate::Delete:
- cache.remove(row);
- emit q->dataChanged(q->createIndex(row, 0),
- q->createIndex(row, q->columnCount() - 1));
+ if (!r.submitted()) {
+ cache[row].revert();
+ emit q->dataChanged(q->createIndex(row, 0),
+ q->createIndex(row, q->columnCount() - 1));
+ }
break;
case QSqlTableModelPrivate::Insert: {
QMap<int, QSqlTableModelPrivate::ModifiedRow>::Iterator it = cache.find(row);
@@ -373,7 +371,7 @@ bool QSqlTableModel::select()
while (it != d->cache.constBegin()) {
--it;
// rows must be accounted for
- if (it.value().op() == QSqlTableModelPrivate::Insert) {
+ if (it.value().insert()) {
beginRemoveRows(QModelIndex(), it.key(), it.key());
it = d->cache.erase(it);
endRemoveRows();
@@ -470,11 +468,14 @@ bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, in
if (!index.isValid() || index.column() >= d->rec.count() || index.row() >= rowCount())
return false;
+ if (d->cache.value(index.row()).op() == QSqlTableModelPrivate::Delete)
+ return false;
+
if (d->strategy == OnFieldChange && d->cache.value(index.row()).op() != QSqlTableModelPrivate::Insert) {
- d->cache.clear();
+ revertAll();
} else if (d->strategy == OnRowChange && !d->cache.isEmpty() && !d->cache.contains(index.row())) {
submit();
- d->cache.clear();
+ revertAll();
}
QSqlTableModelPrivate::ModifiedRow &row = d->cache[index.row()];
@@ -759,8 +760,10 @@ void QSqlTableModel::revertAll()
{
Q_D(QSqlTableModel);
- while (!d->cache.isEmpty())
- revertRow(d->cache.constBegin().key());
+ const QList<int> rows(d->cache.keys());
+ for (int i = rows.size() - 1; i >= 0; --i) {
+ revertRow(rows.value(i));
+ }
}
/*!
@@ -967,15 +970,17 @@ bool QSqlTableModel::removeRows(int row, int count, const QModelIndex &parent)
else if (!count)
return true;
- for (int i = 0; i < count; ++i) {
- int idx = row + i;
- if (d->cache.value(idx).op() == QSqlTableModelPrivate::Insert) {
+ // Iterate backwards so we don't have to worry about removed rows causing
+ // higher cache entries to shift downwards.
+ for (int idx = row + count - 1; idx >= row; --idx) {
+ QSqlTableModelPrivate::ModifiedRow& mrow = d->cache[idx];
+ if (mrow.op() == QSqlTableModelPrivate::Insert) {
revertRow(idx);
- // Reverting a row means all the other cache entries have been adjusted downwards
- // so fake this by adjusting row
- --row;
} else {
- d->cache[idx] = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Delete, record(idx));
+ if (mrow.op() == QSqlTableModelPrivate::None)
+ mrow = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Delete, record(idx));
+ else
+ mrow.setOp(QSqlTableModelPrivate::Delete);
if (d->strategy == OnManualSubmit)
emit headerDataChanged(Qt::Vertical, idx, idx);
}
@@ -1158,6 +1163,8 @@ Qt::ItemFlags QSqlTableModel::flags(const QModelIndex &index) const
return 0;
if (d->rec.field(index.column()).isReadOnly())
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+ if (d->cache.value(index.row()).op() == QSqlTableModelPrivate::Delete)
+ return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
}
@@ -1186,8 +1193,11 @@ bool QSqlTableModel::setRecord(int row, const QSqlRecord &values)
if (row >= rowCount())
return false;
+ if (d->cache.value(row).op() == QSqlTableModelPrivate::Delete)
+ return false;
+
if (d->strategy == OnFieldChange && d->cache.value(row).op() != QSqlTableModelPrivate::Insert)
- d->cache.clear();
+ revertAll();
else if (d->strategy == OnRowChange && !d->cache.isEmpty() && !d->cache.contains(row))
submit();
diff --git a/src/sql/models/qsqltablemodel_p.h b/src/sql/models/qsqltablemodel_p.h
index 57051a0e9c..ba2fdf5df3 100644
--- a/src/sql/models/qsqltablemodel_p.h
+++ b/src/sql/models/qsqltablemodel_p.h
@@ -101,18 +101,51 @@ public:
{
public:
inline ModifiedRow(Op o = None, const QSqlRecord &r = QSqlRecord())
- : m_op(o), m_rec(r), m_submitted(false)
- { init_rec(); }
+ : m_op(None), m_db_values(r), m_insert(o == Insert)
+ { setOp(o); }
inline Op op() const { return m_op; }
+ inline void setOp(Op o)
+ {
+ if (o == m_op)
+ return;
+ m_submitted = (o != Insert && o != Delete);
+ m_op = o;
+ m_rec = m_db_values;
+ setGenerated(m_rec, m_op == Delete);
+ }
inline QSqlRecord rec() const { return m_rec; }
inline QSqlRecord& recRef() { return m_rec; }
inline void setValue(int c, const QVariant &v)
{
+ m_submitted = false;
m_rec.setValue(c, v);
m_rec.setGenerated(c, true);
}
inline bool submitted() const { return m_submitted; }
- inline void setSubmitted() { m_submitted = true; }
+ inline void setSubmitted()
+ {
+ m_submitted = true;
+ setGenerated(m_rec, false);
+ if (m_op == Delete) {
+ m_rec.clearValues();
+ }
+ else {
+ m_op = Update;
+ m_db_values = m_rec;
+ setGenerated(m_db_values, true);
+ }
+ }
+ inline bool insert() const { return m_insert; }
+ inline void revert()
+ {
+ if (m_submitted)
+ return;
+ if (m_op == Delete)
+ m_op = Update;
+ m_rec = m_db_values;
+ setGenerated(m_rec, false);
+ m_submitted = true;
+ }
inline QSqlRecord primaryValues(const QSqlRecord& pi) const
{
if (m_op == None || m_op == Insert)
@@ -126,16 +159,16 @@ public:
return values;
}
private:
- void init_rec()
+ inline static void setGenerated(QSqlRecord& r, bool g)
{
- for (int i = m_rec.count() - 1; i >= 0; --i)
- m_rec.setGenerated(i, false);
- m_db_values = m_rec;
+ for (int i = r.count() - 1; i >= 0; --i)
+ r.setGenerated(i, g);
}
Op m_op;
QSqlRecord m_rec;
QSqlRecord m_db_values;
bool m_submitted;
+ bool m_insert;
};
typedef QMap<int, ModifiedRow> CacheMap;