models/qsqltablemodel.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
1/****************************************************************************-
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtSql module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/****************************************************************************
2** -
3** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -
4** Contact: http://www.qt-project.org/legal -
5** -
6** This file is part of the QtSql module of the Qt Toolkit. -
7** -
8** $QT_BEGIN_LICENSE:LGPL$ -
9** Commercial License Usage -
10** Licensees holding valid commercial Qt licenses may use this file in -
11** accordance with the commercial license agreement provided with the -
12** Software or, alternatively, in accordance with the terms contained in -
13** a written agreement between you and Digia. For licensing terms and -
14** conditions see http://qt.digia.com/licensing. For further information -
15** use the contact form at http://qt.digia.com/contact-us. -
16** -
17** GNU Lesser General Public License Usage -
18** Alternatively, this file may be used under the terms of the GNU Lesser -
19** General Public License version 2.1 as published by the Free Software -
20** Foundation and appearing in the file LICENSE.LGPL included in the -
21** packaging of this file. Please review the following information to -
22** ensure the GNU Lesser General Public License version 2.1 requirements -
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -
24** -
25** In addition, as a special exception, Digia gives you certain additional -
26** rights. These rights are described in the Digia Qt LGPL Exception -
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -
28** -
29** GNU General Public License Usage -
30** Alternatively, this file may be used under the terms of the GNU -
31** General Public License version 3.0 as published by the Free Software -
32** Foundation and appearing in the file LICENSE.GPL included in the -
33** packaging of this file. Please review the following information to -
34** ensure the GNU General Public License version 3.0 requirements will be -
35** met: http://www.gnu.org/copyleft/gpl.html. -
36** -
37** -
38** $QT_END_LICENSE$ -
39** -
40****************************************************************************/ -
41 -
42#include "qsqltablemodel.h" -
43 -
44#include "qsqldriver.h" -
45#include "qsqlerror.h" -
46#include "qsqlfield.h" -
47#include "qsqlindex.h" -
48#include "qsqlquery.h" -
49#include "qsqlrecord.h" -
50#include "qsqlresult.h" -
51 -
52#include "qsqltablemodel_p.h" -
53 -
54#include <qdebug.h> -
55 -
56QT_BEGIN_NAMESPACE -
57 -
58typedef QSqlTableModelSql Sql; -
59 -
60/*! \internal -
61 Populates our record with values. -
62*/ -
63QSqlRecord QSqlTableModelPrivate::record(const QVector<QVariant> &values) const -
64{ -
65 QSqlRecord r = rec; -
66 for (int i = 0; i < r.count() && i < values.count(); ++i) -
67 r.setValue(i, values.at(i)); -
68 return r; -
69} -
70 -
71int QSqlTableModelPrivate::nameToIndex(const QString &name) const -
72{ -
73 return rec.indexOf(strippedFieldName(name)); -
74} -
75 -
76QString QSqlTableModelPrivate::strippedFieldName(const QString &name) const -
77{ -
78 QString fieldname = name; -
79 if (db.driver()->isIdentifierEscaped(fieldname, QSqlDriver::FieldName)) -
80 fieldname = db.driver()->stripDelimiters(fieldname, QSqlDriver::FieldName); -
81 return fieldname; -
82} -
83 -
84int QSqlTableModelPrivate::insertCount(int maxRow) const -
85{ -
86 int cnt = 0; -
87 CacheMap::ConstIterator i = cache.constBegin(); -
88 const CacheMap::ConstIterator e = cache.constEnd(); -
89 for ( ; i != e && (maxRow < 0 || i.key() <= maxRow); ++i) -
90 if (i.value().insert()) -
91 ++cnt; -
92 -
93 return cnt; -
94} -
95 -
96void QSqlTableModelPrivate::initRecordAndPrimaryIndex() -
97{ -
98 rec = db.record(tableName); -
99 primaryIndex = db.primaryIndex(tableName); -
100 initColOffsets(rec.count()); -
101} -
102 -
103void QSqlTableModelPrivate::clear() -
104{ -
105 sortColumn = -1; -
106 sortOrder = Qt::AscendingOrder; -
107 tableName.clear(); -
108 editQuery.clear(); -
109 cache.clear(); -
110 primaryIndex.clear(); -
111 rec.clear(); -
112 filter.clear(); -
113} -
114 -
115void QSqlTableModelPrivate::clearCache() -
116{ -
117 cache.clear(); -
118} -
119 -
120void QSqlTableModelPrivate::revertCachedRow(int row) -
121{ -
122 Q_Q(QSqlTableModel); -
123 ModifiedRow r = cache.value(row); -
124 -
125 switch (r.op()) { -
126 case QSqlTableModelPrivate::None: -
127 Q_ASSERT_X(false, "QSqlTableModelPrivate::revertCachedRow()", "Invalid entry in cache map"); -
128 return; -
129 case QSqlTableModelPrivate::Update: -
130 case QSqlTableModelPrivate::Delete: -
131 if (!r.submitted()) { -
132 cache[row].revert(); -
133 emit q->dataChanged(q->createIndex(row, 0), -
134 q->createIndex(row, q->columnCount() - 1)); -
135 } -
136 break; -
137 case QSqlTableModelPrivate::Insert: { -
138 QMap<int, QSqlTableModelPrivate::ModifiedRow>::Iterator it = cache.find(row); -
139 if (it == cache.end()) -
140 return; -
141 q->beginRemoveRows(QModelIndex(), row, row); -
142 it = cache.erase(it); -
143 while (it != cache.end()) { -
144 int oldKey = it.key(); -
145 const QSqlTableModelPrivate::ModifiedRow oldValue = it.value(); -
146 cache.erase(it); -
147 it = cache.insert(oldKey - 1, oldValue); -
148 ++it; -
149 } -
150 q->endRemoveRows(); -
151 break; } -
152 } -
153} -
154 -
155bool QSqlTableModelPrivate::exec(const QString &stmt, bool prepStatement, -
156 const QSqlRecord &rec, const QSqlRecord &whereValues) -
157{ -
158 if (stmt.isEmpty()) -
159 return false; -
160 -
161 // lazy initialization of editQuery -
162 if (editQuery.driver() != db.driver()) -
163 editQuery = QSqlQuery(db); -
164 -
165 // workaround for In-Process databases - remove all read locks -
166 // from the table to make sure the editQuery succeeds -
167 if (db.driver()->hasFeature(QSqlDriver::SimpleLocking)) -
168 const_cast<QSqlResult *>(query.result())->detachFromResultSet(); -
169 -
170 if (prepStatement) { -
171 if (editQuery.lastQuery() != stmt) { -
172 if (!editQuery.prepare(stmt)) { -
173 error = editQuery.lastError(); -
174 return false; -
175 } -
176 } -
177 int i; -
178 for (i = 0; i < rec.count(); ++i) -
179 if (rec.isGenerated(i)) -
180 editQuery.addBindValue(rec.value(i)); -
181 for (i = 0; i < whereValues.count(); ++i) -
182 if (whereValues.isGenerated(i) && !whereValues.isNull(i)) -
183 editQuery.addBindValue(whereValues.value(i)); -
184 -
185 if (!editQuery.exec()) { -
186 error = editQuery.lastError(); -
187 return false; -
188 } -
189 } else { -
190 if (!editQuery.exec(stmt)) { -
191 error = editQuery.lastError(); -
192 return false; -
193 } -
194 } -
195 return true; -
196} -
197 -
198QSqlRecord QSqlTableModelPrivate::primaryValues(const QSqlRecord &rec, const QSqlRecord &pIndex) -
199{ -
200 QSqlRecord pValues(pIndex); -
201 -
202 for (int i = pValues.count() - 1; i >= 0; --i) -
203 pValues.setValue(i, rec.value(pValues.fieldName(i))); -
204 -
205 return pValues; -
206} -
207 -
208QSqlRecord QSqlTableModelPrivate::primaryValues(int row) const -
209{ -
210 Q_Q(const QSqlTableModel); -
211 -
212 const QSqlRecord &pIndex = primaryIndex.isEmpty() ? rec : primaryIndex; -
213 -
214 ModifiedRow mr = cache.value(row); -
215 if (mr.op() != None) -
216 return mr.primaryValues(pIndex); -
217 else -
218 return primaryValues(q->QSqlQueryModel::record(row), pIndex); -
219} -
220 -
221/*! -
222 \class QSqlTableModel -
223 \brief The QSqlTableModel class provides an editable data model -
224 for a single database table. -
225 -
226 \ingroup database -
227 \inmodule QtSql -
228 -
229 QSqlTableModel is a high-level interface for reading and writing -
230 database records from a single table. It is build on top of the -
231 lower-level QSqlQuery and can be used to provide data to view -
232 classes such as QTableView. For example: -
233 -
234 \snippet sqldatabase/sqldatabase.cpp 24 -
235 -
236 We set the SQL table's name and the edit strategy, then we set up -
237 the labels displayed in the view header. The edit strategy -
238 dictates when the changes done by the user in the view are -
239 actually applied to the database. The possible values are \l -
240 OnFieldChange, \l OnRowChange, and \l OnManualSubmit. -
241 -
242 QSqlTableModel can also be used to access a database -
243 programmatically, without binding it to a view: -
244 -
245 \snippet sqldatabase/sqldatabase.cpp 21 -
246 -
247 The code snippet above extracts the \c salary field from record 4 in -
248 the result set of the query \c{SELECT * from employee}. -
249 -
250 It is possible to set filters using setFilter(), or modify the -
251 sort order using setSort(). At the end, you must call select() to -
252 populate the model with data. -
253 -
254 The \l{tablemodel} example illustrates how to use -
255 QSqlTableModel as the data source for a QTableView. -
256 -
257 QSqlTableModel provides no direct support for foreign keys. Use -
258 the QSqlRelationalTableModel and QSqlRelationalDelegate if you -
259 want to resolve foreign keys. -
260 -
261 \sa QSqlRelationalTableModel, QSqlQuery, {Model/View Programming}, -
262 {Table Model Example}, {Cached Table Example} -
263*/ -
264 -
265/*! -
266 \fn QSqlTableModel::beforeDelete(int row) -
267 -
268 This signal is emitted by deleteRowFromTable() before the \a row -
269 is deleted from the currently active database table. -
270*/ -
271 -
272/*! -
273 \fn void QSqlTableModel::primeInsert(int row, QSqlRecord &record) -
274 -
275 This signal is emitted by insertRows(), when an insertion is -
276 initiated in the given \a row of the currently active database -
277 table. The \a record parameter can be written to (since it is a -
278 reference), for example to populate some fields with default -
279 values and set the generated flags of the fields. Do not try to -
280 edit the record via other means such as setData() or setRecord() -
281 while handling this signal. -
282*/ -
283 -
284/*! -
285 \fn QSqlTableModel::beforeInsert(QSqlRecord &record) -
286 -
287 This signal is emitted by insertRowIntoTable() before a new row is -
288 inserted into the currently active database table. The values that -
289 are about to be inserted are stored in \a record and can be -
290 modified before they will be inserted. -
291*/ -
292 -
293/*! -
294 \fn QSqlTableModel::beforeUpdate(int row, QSqlRecord &record) -
295 -
296 This signal is emitted by updateRowInTable() before the \a row is -
297 updated in the currently active database table with the values -
298 from \a record. -
299 -
300 Note that only values that are marked as generated will be updated. -
301 The generated flag can be set with \l QSqlRecord::setGenerated() -
302 and checked with \l QSqlRecord::isGenerated(). -
303 -
304 \sa QSqlRecord::isGenerated() -
305*/ -
306 -
307/*! -
308 Creates an empty QSqlTableModel and sets the parent to \a parent -
309 and the database connection to \a db. If \a db is not valid, the -
310 default database connection will be used. -
311 -
312 The default edit strategy is \l OnRowChange. -
313*/ -
314QSqlTableModel::QSqlTableModel(QObject *parent, QSqlDatabase db) -
315 : QSqlQueryModel(*new QSqlTableModelPrivate, parent) -
316{ -
317 Q_D(QSqlTableModel); -
318 d->db = db.isValid() ? db : QSqlDatabase::database(); -
319} -
320 -
321/*! \internal -
322*/ -
323QSqlTableModel::QSqlTableModel(QSqlTableModelPrivate &dd, QObject *parent, QSqlDatabase db) -
324 : QSqlQueryModel(dd, parent) -
325{ -
326 Q_D(QSqlTableModel); -
327 d->db = db.isValid() ? db : QSqlDatabase::database(); -
328} -
329 -
330/*! -
331 Destroys the object and frees any allocated resources. -
332*/ -
333QSqlTableModel::~QSqlTableModel() -
334{ -
335} -
336 -
337/*! -
338 Sets the database table on which the model operates to \a -
339 tableName. Does not select data from the table, but fetches its -
340 field information. -
341 -
342 To populate the model with the table's data, call select(). -
343 -
344 Error information can be retrieved with \l lastError(). -
345 -
346 \sa select(), setFilter(), lastError() -
347*/ -
348void QSqlTableModel::setTable(const QString &tableName) -
349{ -
350 Q_D(QSqlTableModel);
executed (the execution status of this line is deduced): QSqlTableModelPrivate * const d = d_func();
-
351 clear();
executed (the execution status of this line is deduced): clear();
-
352 d->tableName = tableName;
executed (the execution status of this line is deduced): d->tableName = tableName;
-
353 d->initRecordAndPrimaryIndex();
executed (the execution status of this line is deduced): d->initRecordAndPrimaryIndex();
-
354 -
355 if (d->rec.count() == 0)
evaluated: d->rec.count() == 0
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:182
1-182
356 d->error = QSqlError(QLatin1String("Unable to find table ") + d->tableName, QString(),
executed: d->error = QSqlError(QLatin1String("Unable to find table ") + d->tableName, QString(), QSqlError::StatementError);
Execution Count:1
1
357 QSqlError::StatementError);
executed: d->error = QSqlError(QLatin1String("Unable to find table ") + d->tableName, QString(), QSqlError::StatementError);
Execution Count:1
1
358 -
359 // Remember the auto index column if there is one now. -
360 // The record that will be obtained from the query after select lacks this feature. -
361 d->autoColumn.clear();
executed (the execution status of this line is deduced): d->autoColumn.clear();
-
362 for (int c = 0; c < d->rec.count(); ++c) {
evaluated: c < d->rec.count()
TRUEFALSE
yes
Evaluation Count:450
yes
Evaluation Count:178
178-450
363 if (d->rec.field(c).isAutoValue()) {
evaluated: d->rec.field(c).isAutoValue()
TRUEFALSE
yes
Evaluation Count:5
yes
Evaluation Count:445
5-445
364 d->autoColumn = d->rec.fieldName(c);
executed (the execution status of this line is deduced): d->autoColumn = d->rec.fieldName(c);
-
365 break;
executed: break;
Execution Count:5
5
366 } -
367 }
executed: }
Execution Count:445
445
368}
executed: }
Execution Count:183
183
369 -
370/*! -
371 Returns the name of the currently selected table. -
372*/ -
373QString QSqlTableModel::tableName() const -
374{ -
375 Q_D(const QSqlTableModel); -
376 return d->tableName; -
377} -
378 -
379/*! -
380 Populates the model with data from the table that was set via setTable(), using the -
381 specified filter and sort condition, and returns true if successful; otherwise -
382 returns false. -
383 -
384 \note Calling select() will revert any unsubmitted changes and remove any inserted columns. -
385 -
386 \sa setTable(), setFilter(), selectStatement() -
387*/ -
388bool QSqlTableModel::select() -
389{ -
390 Q_D(QSqlTableModel); -
391 const QString query = selectStatement(); -
392 if (query.isEmpty()) -
393 return false; -
394 -
395 beginResetModel(); -
396 -
397 d->clearCache(); -
398 -
399 QSqlQuery qu(query, d->db); -
400 setQuery(qu); -
401 -
402 if (!qu.isActive() || lastError().isValid()) { -
403 // something went wrong - revert to non-select state -
404 d->initRecordAndPrimaryIndex(); -
405 endResetModel(); -
406 return false; -
407 } -
408 endResetModel(); -
409 return true; -
410} -
411 -
412/*! -
413 \since 5.0 -
414 -
415 Refreshes \a row in the model with values from the database table row matching -
416 on primary key values. Without a primary key, all column values must match. If -
417 no matching row is found, the model will show an empty row. -
418 -
419 Returns true if successful; otherwise returns false. -
420 -
421 \sa select() -
422*/ -
423bool QSqlTableModel::selectRow(int row) -
424{ -
425 Q_D(QSqlTableModel); -
426 -
427 if (row < 0 || row >= rowCount()) -
428 return false; -
429 -
430 const int table_sort_col = d->sortColumn; -
431 d->sortColumn = -1; -
432 const QString table_filter = d->filter; -
433 d->filter = d->db.driver()->sqlStatement(QSqlDriver::WhereStatement, -
434 d->tableName, -
435 d->primaryValues(row), -
436 false); -
437 static const QString wh = Sql::where() + Sql::sp(); -
438 if (d->filter.startsWith(wh, Qt::CaseInsensitive)) -
439 d->filter.remove(0, wh.length()); -
440 -
441 QString stmt; -
442 -
443 if (!d->filter.isEmpty()) -
444 stmt = selectStatement(); -
445 -
446 d->sortColumn = table_sort_col; -
447 d->filter = table_filter; -
448 -
449 if (stmt.isEmpty()) -
450 return false; -
451 -
452 bool exists; -
453 QSqlRecord newValues; -
454 -
455 { -
456 QSqlQuery q(d->db); -
457 q.setForwardOnly(true); -
458 if (!q.exec(stmt)) -
459 return false; -
460 -
461 exists = q.next(); -
462 newValues = q.record(); -
463 } -
464 -
465 bool needsAddingToCache = !exists || d->cache.contains(row); -
466 -
467 if (!needsAddingToCache) { -
468 const QSqlRecord curValues = record(row); -
469 needsAddingToCache = curValues.count() != newValues.count(); -
470 if (!needsAddingToCache) { -
471 // Look for changed values. Primary key fields are customarily first -
472 // and probably change less often than other fields, so start at the end. -
473 for (int f = curValues.count() - 1; f >= 0; --f) { -
474 if (curValues.value(f) != newValues.value(f)) -
475 needsAddingToCache = true; -
476 break; -
477 } -
478 } -
479 } -
480 -
481 if (needsAddingToCache) { -
482 d->cache[row].refresh(exists, newValues); -
483 emit headerDataChanged(Qt::Vertical, row, row); -
484 emit dataChanged(createIndex(row, 0), createIndex(row, columnCount() - 1)); -
485 } -
486 -
487 return true; -
488} -
489 -
490/*! -
491 \reimp -
492*/ -
493QVariant QSqlTableModel::data(const QModelIndex &index, int role) const -
494{ -
495 Q_D(const QSqlTableModel); -
496 if (!index.isValid() || (role != Qt::DisplayRole && role != Qt::EditRole)) -
497 return QVariant(); -
498 -
499 const QSqlTableModelPrivate::ModifiedRow mrow = d->cache.value(index.row()); -
500 if (mrow.op() != QSqlTableModelPrivate::None) -
501 return mrow.rec().value(index.column()); -
502 -
503 return QSqlQueryModel::data(index, role); -
504} -
505 -
506/*! -
507 \reimp -
508*/ -
509QVariant QSqlTableModel::headerData(int section, Qt::Orientation orientation, int role) const -
510{ -
511 Q_D(const QSqlTableModel); -
512 if (orientation == Qt::Vertical && role == Qt::DisplayRole) { -
513 const QSqlTableModelPrivate::Op op = d->cache.value(section).op(); -
514 if (op == QSqlTableModelPrivate::Insert) -
515 return QLatin1String("*"); -
516 else if (op == QSqlTableModelPrivate::Delete) -
517 return QLatin1String("!"); -
518 } -
519 return QSqlQueryModel::headerData(section, orientation, role); -
520} -
521 -
522/*! -
523 \overload -
524 \since 5.0 -
525 -
526 Returns true if the model contains modified values that have not been -
527 committed to the datase, otherwise false. -
528*/ -
529bool QSqlTableModel::isDirty() const -
530{ -
531 Q_D(const QSqlTableModel); -
532 QSqlTableModelPrivate::CacheMap::ConstIterator i = d->cache.constBegin(); -
533 const QSqlTableModelPrivate::CacheMap::ConstIterator e = d->cache.constEnd(); -
534 for (; i != e; i++) -
535 if (!i.value().submitted()) -
536 return true; -
537 return false; -
538} -
539 -
540/*! -
541 Returns true if the value at the index \a index is dirty, otherwise false. -
542 Dirty values are values that were modified in the model -
543 but not yet written into the database. -
544 -
545 If \a index is invalid or points to a non-existing row, false is returned. -
546*/ -
547bool QSqlTableModel::isDirty(const QModelIndex &index) const -
548{ -
549 Q_D(const QSqlTableModel); -
550 if (!index.isValid()) -
551 return false; -
552 -
553 const QSqlTableModelPrivate::ModifiedRow row = d->cache.value(index.row()); -
554 if (row.submitted()) -
555 return false; -
556 -
557 return row.op() == QSqlTableModelPrivate::Insert -
558 || row.op() == QSqlTableModelPrivate::Delete -
559 || (row.op() == QSqlTableModelPrivate::Update -
560 && row.rec().isGenerated(index.column())); -
561} -
562 -
563/*! -
564 Sets the data for the item \a index for the role \a role to \a -
565 value. -
566 -
567 For edit strategy OnFieldChange, an index may receive a change -
568 only if no other index has a cached change. Changes are -
569 submitted immediately. However, rows that have not yet been -
570 inserted in the database may be freely changed and are not -
571 submitted automatically. Submitted changes are not reverted upon -
572 failure. -
573 -
574 For OnRowChange, an index may receive a change only if no other -
575 row has a cached change. Changes are not submitted automatically. -
576 -
577 Returns true if \a value is equal to the current value. However, -
578 the value will not be submitted to the database. -
579 -
580 Returns true if the value could be set or false on error, for -
581 example if \a index is out of bounds. -
582 -
583 \sa editStrategy(), data(), submit(), submitAll(), revertRow() -
584*/ -
585bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, int role) -
586{ -
587 Q_D(QSqlTableModel);
executed (the execution status of this line is deduced): QSqlTableModelPrivate * const d = d_func();
-
588 if (d->busyInsertingRows)
partially evaluated: d->busyInsertingRows
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:270
0-270
589 return false;
never executed: return false;
0
590 -
591 if (role != Qt::EditRole)
evaluated: role != Qt::EditRole
TRUEFALSE
yes
Evaluation Count:2
yes
Evaluation Count:268
2-268
592 return QSqlQueryModel::setData(index, value, role);
executed: return QSqlQueryModel::setData(index, value, role);
Execution Count:2
2
593 -
594 if (!index.isValid() || index.column() >= d->rec.count() || index.row() >= rowCount())
evaluated: !index.isValid()
TRUEFALSE
yes
Evaluation Count:3
yes
Evaluation Count:265
partially evaluated: index.column() >= d->rec.count()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:265
partially evaluated: index.row() >= rowCount()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:265
0-265
595 return false;
executed: return false;
Execution Count:3
3
596 -
597 if (!(flags(index) & Qt::ItemIsEditable))
evaluated: !(flags(index) & Qt::ItemIsEditable)
TRUEFALSE
yes
Evaluation Count:3
yes
Evaluation Count:262
3-262
598 return false;
executed: return false;
Execution Count:3
3
599 -
600 if (const QVariant oldValue = QSqlTableModel::data(index, role));
executed (the execution status of this line is deduced): const QVariant oldValue = QSqlTableModel::data(index, role);
-
601 if (value == oldValue
evaluated: value == oldValue
TRUEFALSE
yes
Evaluation Count:33
yes
Evaluation Count:229
33-229
602 && value.isNull() == oldValue.isNull()
evaluated: value.isNull() == oldValue.isNull()
TRUEFALSE
yes
Evaluation Count:30
yes
Evaluation Count:3
3-30
603 && d->cache.value(index.row()).op() != QSqlTableModelPrivate::Insert)
evaluated: d->cache.value(index.row()).op() != QSqlTableModelPrivate::Insert
TRUEFALSE
yes
Evaluation Count:23
yes
Evaluation Count:7
7-23
604 return true;
executed: return true;
Execution Count:23
23
605 -
606 QSqlTableModelPrivate::ModifiedRow &row = d->cache[index.row()];
executed (the execution status of this line is deduced): QSqlTableModelPrivate::ModifiedRow &row = d->cache[index.row()];
-
607 -
608 if (row.op() == QSqlTableModelPrivate::None)
evaluated: row.op() == QSqlTableModelPrivate::None
TRUEFALSE
yes
Evaluation Count:47
yes
Evaluation Count:192
47-192
609 row = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Update,
executed: row = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Update, QSqlQueryModel::record(index.row()));
Execution Count:47
47
610 QSqlQueryModel::record(index.row()));
executed: row = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Update, QSqlQueryModel::record(index.row()));
Execution Count:47
47
611 -
612 row.setValue(index.column(), value);
executed (the execution status of this line is deduced): row.setValue(index.column(), value);
-
613 emit dataChanged(index, index);
executed (the execution status of this line is deduced): dataChanged(index, index);
-
614 -
615 if (d->strategy == OnFieldChange && row.op() != QSqlTableModelPrivate::Insert)
evaluated: d->strategy == OnFieldChange
TRUEFALSE
yes
Evaluation Count:15
yes
Evaluation Count:224
evaluated: row.op() != QSqlTableModelPrivate::Insert
TRUEFALSE
yes
Evaluation Count:8
yes
Evaluation Count:7
7-224
616 return submit();
executed: return submit();
Execution Count:8
8
617 -
618 return true;
executed: return true;
Execution Count:231
231
619} -
620 -
621/*! -
622 This function simply calls QSqlQueryModel::setQuery(\a query). -
623 You should normally not call it on a QSqlTableModel. Instead, use -
624 setTable(), setSort(), setFilter(), etc., to set up the query. -
625 -
626 \sa selectStatement() -
627*/ -
628void QSqlTableModel::setQuery(const QSqlQuery &query) -
629{ -
630 QSqlQueryModel::setQuery(query); -
631} -
632 -
633/*! -
634 Updates the given \a row in the currently active database table -
635 with the specified \a values. Returns true if successful; otherwise -
636 returns false. -
637 -
638 This is a low-level method that operates directly on the database -
639 and should not be called directly. Use setData() to update values. -
640 The model will decide depending on its edit strategy when to modify -
641 the database. -
642 -
643 Note that only values that have the generated-flag set are updated. -
644 The generated-flag can be set with QSqlRecord::setGenerated() and -
645 tested with QSqlRecord::isGenerated(). -
646 -
647 \sa QSqlRecord::isGenerated(), setData() -
648*/ -
649bool QSqlTableModel::updateRowInTable(int row, const QSqlRecord &values) -
650{ -
651 Q_D(QSqlTableModel); -
652 QSqlRecord rec(values); -
653 emit beforeUpdate(row, rec); -
654 -
655 const QSqlRecord whereValues = d->primaryValues(row); -
656 const bool prepStatement = d->db.driver()->hasFeature(QSqlDriver::PreparedQueries); -
657 const QString stmt = d->db.driver()->sqlStatement(QSqlDriver::UpdateStatement, d->tableName, -
658 rec, prepStatement); -
659 const QString where = d->db.driver()->sqlStatement(QSqlDriver::WhereStatement, d->tableName, -
660 whereValues, prepStatement); -
661 -
662 if (stmt.isEmpty() || where.isEmpty() || row < 0 || row >= rowCount()) { -
663 d->error = QSqlError(QLatin1String("No Fields to update"), QString(), -
664 QSqlError::StatementError); -
665 return false; -
666 } -
667 -
668 return d->exec(Sql::concat(stmt, where), prepStatement, rec, whereValues); -
669} -
670 -
671 -
672/*! -
673 Inserts the values \a values into the currently active database table. -
674 -
675 This is a low-level method that operates directly on the database -
676 and should not be called directly. Use insertRow() and setData() -
677 to insert values. The model will decide depending on its edit strategy -
678 when to modify the database. -
679 -
680 Returns true if the values could be inserted, otherwise false. -
681 Error information can be retrieved with \l lastError(). -
682 -
683 \sa lastError(), insertRow(), insertRows() -
684*/ -
685bool QSqlTableModel::insertRowIntoTable(const QSqlRecord &values) -
686{ -
687 Q_D(QSqlTableModel); -
688 QSqlRecord rec = values; -
689 emit beforeInsert(rec); -
690 -
691 const bool prepStatement = d->db.driver()->hasFeature(QSqlDriver::PreparedQueries); -
692 const QString stmt = d->db.driver()->sqlStatement(QSqlDriver::InsertStatement, d->tableName, -
693 rec, prepStatement); -
694 -
695 if (stmt.isEmpty()) { -
696 d->error = QSqlError(QLatin1String("No Fields to update"), QString(), -
697 QSqlError::StatementError); -
698 return false; -
699 } -
700 -
701 return d->exec(stmt, prepStatement, rec, QSqlRecord() /* no where values */); -
702} -
703 -
704/*! -
705 Deletes the given \a row from the currently active database table. -
706 -
707 This is a low-level method that operates directly on the database -
708 and should not be called directly. Use removeRow() or removeRows() -
709 to delete values. The model will decide depending on its edit strategy -
710 when to modify the database. -
711 -
712 Returns true if the row was deleted; otherwise returns false. -
713 -
714 \sa removeRow(), removeRows() -
715*/ -
716bool QSqlTableModel::deleteRowFromTable(int row) -
717{ -
718 Q_D(QSqlTableModel); -
719 emit beforeDelete(row); -
720 -
721 const QSqlRecord whereValues = d->primaryValues(row); -
722 const bool prepStatement = d->db.driver()->hasFeature(QSqlDriver::PreparedQueries); -
723 const QString stmt = d->db.driver()->sqlStatement(QSqlDriver::DeleteStatement, -
724 d->tableName, -
725 QSqlRecord(), -
726 prepStatement); -
727 const QString where = d->db.driver()->sqlStatement(QSqlDriver::WhereStatement, -
728 d->tableName, -
729 whereValues, -
730 prepStatement); -
731 -
732 if (stmt.isEmpty() || where.isEmpty()) { -
733 d->error = QSqlError(QLatin1String("Unable to delete row"), QString(), -
734 QSqlError::StatementError); -
735 return false; -
736 } -
737 -
738 return d->exec(Sql::concat(stmt, where), prepStatement, QSqlRecord() /* no new values */, whereValues); -
739} -
740 -
741/*! -
742 Submits all pending changes and returns true on success. -
743 Returns false on error, detailed error information can be -
744 obtained with lastError(). -
745 -
746 In OnManualSubmit, on success the model will be repopulated. -
747 Any views presenting it will lose their selections. -
748 -
749 Note: In OnManualSubmit mode, already submitted changes won't -
750 be cleared from the cache when submitAll() fails. This allows -
751 transactions to be rolled back and resubmitted without -
752 losing data. -
753 -
754 \sa revertAll(), lastError() -
755*/ -
756bool QSqlTableModel::submitAll() -
757{ -
758 Q_D(QSqlTableModel);
executed (the execution status of this line is deduced): QSqlTableModelPrivate * const d = d_func();
-
759 -
760 bool success = true;
executed (the execution status of this line is deduced): bool success = true;
-
761 -
762 foreach (int row, d->cache.keys()) {
executed (the execution status of this line is deduced): for (QForeachContainer<__typeof__(d->cache.keys())> _container_(d->cache.keys()); !_container_.brk && _container_.i != _container_.e; __extension__ ({ ++_container_.brk; ++_container_.i; })) for (int row = *_container_.i;; __extension__ ({--_container_.brk; break;})) {
-
763 // be sure cache *still* contains the row since overriden selectRow() could have called select() -
764 QSqlTableModelPrivate::CacheMap::iterator it = d->cache.find(row);
executed (the execution status of this line is deduced): QSqlTableModelPrivate::CacheMap::iterator it = d->cache.find(row);
-
765 if (it == d->cache.end())
partially evaluated: it == d->cache.end()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:160
0-160
766 continue;
never executed: continue;
0
767 -
768 QSqlTableModelPrivate::ModifiedRow &mrow = it.value();
executed (the execution status of this line is deduced): QSqlTableModelPrivate::ModifiedRow &mrow = it.value();
-
769 if (mrow.submitted())
evaluated: mrow.submitted()
TRUEFALSE
yes
Evaluation Count:36
yes
Evaluation Count:124
36-124
770 continue;
executed: continue;
Execution Count:36
36
771 -
772 switch (mrow.op()) { -
773 case QSqlTableModelPrivate::Insert: -
774 success = insertRowIntoTable(mrow.rec());
executed (the execution status of this line is deduced): success = insertRowIntoTable(mrow.rec());
-
775 break;
executed: break;
Execution Count:53
53
776 case QSqlTableModelPrivate::Update: -
777 success = updateRowInTable(row, mrow.rec());
executed (the execution status of this line is deduced): success = updateRowInTable(row, mrow.rec());
-
778 break;
executed: break;
Execution Count:49
49
779 case QSqlTableModelPrivate::Delete: -
780 success = deleteRowFromTable(row);
executed (the execution status of this line is deduced): success = deleteRowFromTable(row);
-
781 break;
executed: break;
Execution Count:22
22
782 case QSqlTableModelPrivate::None: -
783 Q_ASSERT_X(false, "QSqlTableModel::submitAll()", "Invalid cache operation");
never executed (the execution status of this line is deduced): qt_noop();
-
784 break;
never executed: break;
0
785 } -
786 -
787 if (success) {
evaluated: success
TRUEFALSE
yes
Evaluation Count:117
yes
Evaluation Count:7
7-117
788 if (d->strategy != OnManualSubmit && mrow.op() == QSqlTableModelPrivate::Insert) {
evaluated: d->strategy != OnManualSubmit
TRUEFALSE
yes
Evaluation Count:60
yes
Evaluation Count:57
evaluated: mrow.op() == QSqlTableModelPrivate::Insert
TRUEFALSE
yes
Evaluation Count:23
yes
Evaluation Count:37
23-60
789 int c = mrow.rec().indexOf(d->autoColumn);
executed (the execution status of this line is deduced): int c = mrow.rec().indexOf(d->autoColumn);
-
790 if (c != -1 && !mrow.rec().isGenerated(c))
evaluated: c != -1
TRUEFALSE
yes
Evaluation Count:6
yes
Evaluation Count:17
partially evaluated: !mrow.rec().isGenerated(c)
TRUEFALSE
yes
Evaluation Count:6
no
Evaluation Count:0
0-17
791 mrow.setValue(c, d->editQuery.lastInsertId());
executed: mrow.setValue(c, d->editQuery.lastInsertId());
Execution Count:6
6
792 }
executed: }
Execution Count:23
23
793 mrow.setSubmitted();
executed (the execution status of this line is deduced): mrow.setSubmitted();
-
794 if (d->strategy != OnManualSubmit)
evaluated: d->strategy != OnManualSubmit
TRUEFALSE
yes
Evaluation Count:60
yes
Evaluation Count:57
57-60
795 success = selectRow(row);
executed: success = selectRow(row);
Execution Count:60
60
796 }
executed: }
Execution Count:117
117
797 -
798 if (!success)
evaluated: !success
TRUEFALSE
yes
Evaluation Count:7
yes
Evaluation Count:117
7-117
799 break;
executed: break;
Execution Count:7
7
800 }
executed: }
Execution Count:117
117
801 -
802 if (success) {
evaluated: success
TRUEFALSE
yes
Evaluation Count:118
yes
Evaluation Count:7
7-118
803 if (d->strategy == OnManualSubmit)
evaluated: d->strategy == OnManualSubmit
TRUEFALSE
yes
Evaluation Count:36
yes
Evaluation Count:82
36-82
804 success = select();
executed: success = select();
Execution Count:36
36
805 }
executed: }
Execution Count:118
118
806 -
807 return success;
executed: return success;
Execution Count:125
125
808} -
809 -
810/*! -
811 This reimplemented slot is called by the item delegates when the -
812 user stopped editing the current row. -
813 -
814 Submits the currently edited row if the model's strategy is set -
815 to OnRowChange or OnFieldChange. Does nothing for the OnManualSubmit -
816 strategy. -
817 -
818 Use submitAll() to submit all pending changes for the -
819 OnManualSubmit strategy. -
820 -
821 Returns true on success; otherwise returns false. Use lastError() -
822 to query detailed error information. -
823 -
824 Does not automatically repopulate the model. Submitted rows are -
825 refreshed from the database on success. -
826 -
827 \sa revert(), revertRow(), submitAll(), revertAll(), lastError() -
828*/ -
829bool QSqlTableModel::submit() -
830{ -
831 Q_D(QSqlTableModel); -
832 if (d->strategy == OnRowChange || d->strategy == OnFieldChange) -
833 return submitAll(); -
834 return true; -
835} -
836 -
837/*!-
This reimplemented slot is called by the item delegates when the
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.
Use revertAll() to revert all pending changes for the
OnManualSubmit strategy or revertRow() to revert a specific row.
\sa submit(), submitAll(), revertRow(), revertAll()
*/*!
838 This reimplemented slot is called by the item delegates when the -
839 user canceled editing the current row. -
840 -
841 Reverts the changes if the model's strategy is set to -
842 OnRowChange or OnFieldChange. Does nothing for the OnManualSubmit -
843 strategy. -
844 -
845 Use revertAll() to revert all pending changes for the -
846 OnManualSubmit strategy or revertRow() to revert a specific row. -
847 -
848 \sa submit(), submitAll(), revertRow(), revertAll() -
849*/ -
850void QSqlTableModel::revert() -
851{ -
852 Q_D(QSqlTableModel);
executed (the execution status of this line is deduced): QSqlTableModelPrivate * const d = d_func();
-
853 if (d->strategy == OnRowChange || d->strategy == OnFieldChange)
evaluated: d->strategy == OnRowChange
TRUEFALSE
yes
Evaluation Count:4
yes
Evaluation Count:9
evaluated: d->strategy == OnFieldChange
TRUEFALSE
yes
Evaluation Count:4
yes
Evaluation Count:5
4-9
854 revertAll();
executed: revertAll();
Execution Count:8
8
855}
executed: }
Execution Count:13
13
856 -
857/*! -
858 \enum QSqlTableModel::EditStrategy -
859 -
860 This enum type describes which strategy to choose when editing values in the database. -
861 -
862 \value OnFieldChange All changes to the model will be applied immediately to the database. -
863 \value OnRowChange Changes to a row will be applied when the user selects a different row. -
864 \value OnManualSubmit All changes will be cached in the model until either submitAll() -
865 or revertAll() is called. -
866 -
867 Note: To prevent inserting only partly initialized rows into the database, -
868 \c OnFieldChange will behave like \c OnRowChange for newly inserted rows. -
869 -
870 \sa setEditStrategy() -
871*/ -
872 -
873 -
874/*! -
875 Sets the strategy for editing values in the database to \a -
876 strategy. -
877 -
878 This will revert any pending changes. -
879 -
880 \sa editStrategy(), revertAll() -
881*/ -
882void QSqlTableModel::setEditStrategy(EditStrategy strategy) -
883{ -
884 Q_D(QSqlTableModel); -
885 revertAll(); -
886 d->strategy = strategy; -
887} -
888 -
889/*! -
890 Returns the current edit strategy. -
891 -
892 \sa setEditStrategy() -
893*/ -
894QSqlTableModel::EditStrategy QSqlTableModel::editStrategy() const -
895{ -
896 Q_D(const QSqlTableModel); -
897 return d->strategy; -
898} -
899 -
900/*! -
901 Reverts all pending changes. -
902 -
903 \sa revert(), revertRow(), submitAll() -
904*/ -
905void QSqlTableModel::revertAll() -
906{ -
907 Q_D(QSqlTableModel); -
908 -
909 const QList<int> rows(d->cache.keys()); -
910 for (int i = rows.size() - 1; i >= 0; --i) -
911 revertRow(rows.value(i)); -
912} -
913 -
914/*! -
915 Reverts all changes for the specified \a row. -
916 -
917 \sa revert(), revertAll(), submit(), submitAll() -
918*/ -
919void QSqlTableModel::revertRow(int row) -
920{ -
921 if (row < 0) -
922 return; -
923 -
924 Q_D(QSqlTableModel); -
925 d->revertCachedRow(row); -
926} -
927 -
928/*! -
929 Returns the primary key for the current table, or an empty -
930 QSqlIndex if the table is not set or has no primary key. -
931 -
932 \sa setTable(), setPrimaryKey(), QSqlDatabase::primaryIndex() -
933*/ -
934QSqlIndex QSqlTableModel::primaryKey() const -
935{ -
936 Q_D(const QSqlTableModel); -
937 return d->primaryIndex; -
938} -
939 -
940/*! -
941 Protected method that allows subclasses to set the primary key to -
942 \a key. -
943 -
944 Normally, the primary index is set automatically whenever you -
945 call setTable(). -
946 -
947 \sa primaryKey(), QSqlDatabase::primaryIndex() -
948*/ -
949void QSqlTableModel::setPrimaryKey(const QSqlIndex &key) -
950{ -
951 Q_D(QSqlTableModel); -
952 d->primaryIndex = key; -
953} -
954 -
955/*! -
956 Returns a pointer to the used QSqlDatabase or 0 if no database was set. -
957*/ -
958QSqlDatabase QSqlTableModel::database() const -
959{ -
960 Q_D(const QSqlTableModel); -
961 return d->db; -
962} -
963 -
964/*! -
965 Sorts the data by \a column with the sort order \a order. -
966 This will immediately select data, use setSort() -
967 to set a sort order without populating the model with data. -
968 -
969 \sa setSort(), select(), orderByClause() -
970*/ -
971void QSqlTableModel::sort(int column, Qt::SortOrder order) -
972{ -
973 setSort(column, order); -
974 select(); -
975} -
976 -
977/*! -
978 Sets the sort order for \a column to \a order. This does not -
979 affect the current data, to refresh the data using the new -
980 sort order, call select(). -
981 -
982 \sa select(), orderByClause() -
983*/ -
984void QSqlTableModel::setSort(int column, Qt::SortOrder order) -
985{ -
986 Q_D(QSqlTableModel); -
987 d->sortColumn = column; -
988 d->sortOrder = order; -
989} -
990 -
991/*! -
992 Returns an SQL \c{ORDER BY} clause based on the currently set -
993 sort order. -
994 -
995 \sa setSort(), selectStatement() -
996*/ -
997QString QSqlTableModel::orderByClause() const -
998{ -
999 Q_D(const QSqlTableModel); -
1000 QSqlField f = d->rec.field(d->sortColumn); -
1001 if (!f.isValid()) -
1002 return QString(); -
1003 -
1004 //we can safely escape the field because it would have been obtained from the database -
1005 //and have the correct case -
1006 QString field = d->db.driver()->escapeIdentifier(f.name(), QSqlDriver::FieldName); -
1007 field.prepend(QLatin1Char('.')).prepend(d->tableName); -
1008 field = d->sortOrder == Qt::AscendingOrder ? Sql::asc(field) : Sql::desc(field); -
1009 return Sql::orderBy(field); -
1010} -
1011 -
1012/*! -
1013 Returns the index of the field \a fieldName, or -1 if no corresponding field -
1014 exists in the model. -
1015*/ -
1016int QSqlTableModel::fieldIndex(const QString &fieldName) const -
1017{ -
1018 Q_D(const QSqlTableModel); -
1019 return d->rec.indexOf(fieldName); -
1020} -
1021 -
1022/*! -
1023 Returns the SQL \c SELECT statement used internally to populate -
1024 the model. The statement includes the filter and the \c{ORDER BY} -
1025 clause. -
1026 -
1027 \sa filter(), orderByClause() -
1028*/ -
1029QString QSqlTableModel::selectStatement() const -
1030{ -
1031 Q_D(const QSqlTableModel); -
1032 if (d->tableName.isEmpty()) { -
1033 d->error = QSqlError(QLatin1String("No table name given"), QString(), -
1034 QSqlError::StatementError); -
1035 return QString(); -
1036 } -
1037 if (d->rec.isEmpty()) { -
1038 d->error = QSqlError(QLatin1String("Unable to find table ") + d->tableName, QString(), -
1039 QSqlError::StatementError); -
1040 return QString(); -
1041 } -
1042 -
1043 const QString stmt = d->db.driver()->sqlStatement(QSqlDriver::SelectStatement, -
1044 d->tableName, -
1045 d->rec, -
1046 false); -
1047 if (stmt.isEmpty()) { -
1048 d->error = QSqlError(QLatin1String("Unable to select fields from table ") + d->tableName, -
1049 QString(), QSqlError::StatementError); -
1050 return stmt; -
1051 } -
1052 return Sql::concat(Sql::concat(stmt, Sql::where(d->filter)), orderByClause()); -
1053} -
1054 -
1055/*! -
1056 Removes \a count columns from the \a parent model, starting at -
1057 index \a column. -
1058 -
1059 Returns if the columns were successfully removed; otherwise -
1060 returns false. -
1061 -
1062 \sa removeRows() -
1063*/ -
1064bool QSqlTableModel::removeColumns(int column, int count, const QModelIndex &parent) -
1065{ -
1066 Q_D(QSqlTableModel); -
1067 if (parent.isValid() || column < 0 || column + count > d->rec.count()) -
1068 return false; -
1069 for (int i = 0; i < count; ++i) -
1070 d->rec.remove(column); -
1071 if (d->query.isActive()) -
1072 return select(); -
1073 return true; -
1074} -
1075 -
1076/*! -
1077 Removes \a count rows starting at \a row. Since this model -
1078 does not support hierarchical structures, \a parent must be -
1079 an invalid model index. -
1080 -
1081 When the edit strategy is OnManualSubmit, deletion of rows from -
1082 the database is delayed until submitAll() is called. -
1083 -
1084 For OnFieldChange and OnRowChange, only one row may be deleted -
1085 at a time and only if no other row has a cached change. Deletions -
1086 are submitted immediately to the database. The model retains a -
1087 blank row for successfully deleted row until refreshed with select(). -
1088 -
1089 After failed deletion, the operation is not reverted in the model. -
1090 The application may resubmit or revert. -
1091 -
1092 Inserted but not yet successfully submitted rows in the range to be -
1093 removed are immediately removed from the model. -
1094 -
1095 Before a row is deleted from the database, the beforeDelete() -
1096 signal is emitted. -
1097 -
1098 If row < 0 or row + count > rowCount(), no action is taken and -
1099 false is returned. Returns true if all rows could be removed; -
1100 otherwise returns false. Detailed database error information -
1101 can be retrieved using lastError(). -
1102 -
1103 \sa removeColumns(), insertRows() -
1104*/ -
1105bool QSqlTableModel::removeRows(int row, int count, const QModelIndex &parent) -
1106{ -
1107 Q_D(QSqlTableModel); -
1108 if (parent.isValid() || row < 0 || count <= 0) -
1109 return false; -
1110 else if (row + count > rowCount()) -
1111 return false; -
1112 else if (!count) -
1113 return true; -
1114 -
1115 if (d->strategy != OnManualSubmit) -
1116 if (count > 1 || (d->cache.value(row).submitted() && isDirty())) -
1117 return false; -
1118 -
1119 // Iterate backwards so we don't have to worry about removed rows causing -
1120 // higher cache entries to shift downwards. -
1121 for (int idx = row + count - 1; idx >= row; --idx) { -
1122 QSqlTableModelPrivate::ModifiedRow& mrow = d->cache[idx]; -
1123 if (mrow.op() == QSqlTableModelPrivate::Insert) { -
1124 revertRow(idx); -
1125 } else { -
1126 if (mrow.op() == QSqlTableModelPrivate::None) -
1127 mrow = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Delete, -
1128 QSqlQueryModel::record(idx)); -
1129 else -
1130 mrow.setOp(QSqlTableModelPrivate::Delete); -
1131 if (d->strategy == OnManualSubmit) -
1132 emit headerDataChanged(Qt::Vertical, idx, idx); -
1133 } -
1134 } -
1135 -
1136 if (d->strategy != OnManualSubmit) -
1137 return submit(); -
1138 -
1139 return true; -
1140} -
1141 -
1142/*! -
1143 Inserts \a count empty rows at position \a row. Note that \a -
1144 parent must be invalid, since this model does not support -
1145 parent-child relations. -
1146 -
1147 For edit strategies OnFieldChange and OnRowChange, only one row -
1148 may be inserted at a time and the model may not contain other -
1149 cached changes. -
1150 -
1151 The primeInsert() signal will be emitted for each new row. -
1152 Connect to it if you want to initialize the new row with default -
1153 values. -
1154 -
1155 Does not submit rows, regardless of edit strategy. -
1156 -
1157 Returns false if the parameters are out of bounds or the row cannot be -
1158 inserted; otherwise returns true. -
1159 -
1160 \sa primeInsert(), insertRecord() -
1161*/ -
1162bool QSqlTableModel::insertRows(int row, int count, const QModelIndex &parent) -
1163{ -
1164 Q_D(QSqlTableModel); -
1165 if (row < 0 || count <= 0 || row > rowCount() || parent.isValid()) -
1166 return false; -
1167 -
1168 if (d->strategy != OnManualSubmit) -
1169 if (count != 1 || isDirty()) -
1170 return false; -
1171 -
1172 d->busyInsertingRows = true; -
1173 beginInsertRows(parent, row, row + count - 1); -
1174 -
1175 if (d->strategy != OnManualSubmit) -
1176 d->cache.empty(); -
1177 -
1178 if (!d->cache.isEmpty()) { -
1179 QMap<int, QSqlTableModelPrivate::ModifiedRow>::Iterator it = d->cache.end(); -
1180 while (it != d->cache.begin() && (--it).key() >= row) { -
1181 int oldKey = it.key(); -
1182 const QSqlTableModelPrivate::ModifiedRow oldValue = it.value(); -
1183 d->cache.erase(it); -
1184 it = d->cache.insert(oldKey + count, oldValue); -
1185 } -
1186 } -
1187 -
1188 for (int i = 0; i < count; ++i) { -
1189 d->cache[row + i] = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Insert, -
1190 d->rec); -
1191 emit primeInsert(row + i, d->cache[row + i].recRef()); -
1192 } -
1193 -
1194 endInsertRows(); -
1195 d->busyInsertingRows = false; -
1196 return true; -
1197} -
1198 -
1199/*! -
1200 Inserts the \a record at position \a row. If \a row is negative, -
1201 the record will be appended to the end. Calls insertRows() and -
1202 setRecord() internally. -
1203 -
1204 Returns true if the record could be inserted, otherwise false. -
1205 -
1206 Changes are submitted immediately for OnFieldChange and -
1207 OnRowChange. Failure does not leave a new row in the model. -
1208 -
1209 \sa insertRows(), removeRows(), setRecord() -
1210*/ -
1211bool QSqlTableModel::insertRecord(int row, const QSqlRecord &record) -
1212{ -
1213 if (row < 0) -
1214 row = rowCount(); -
1215 if (!insertRow(row, QModelIndex())) -
1216 return false; -
1217 if (!setRecord(row, record)) { -
1218 revertRow(row); -
1219 return false; -
1220 } -
1221 return true; -
1222} -
1223 -
1224/*! \reimp -
1225*/ -
1226int QSqlTableModel::rowCount(const QModelIndex &parent) const -
1227{ -
1228 Q_D(const QSqlTableModel); -
1229 -
1230 if (parent.isValid()) -
1231 return 0; -
1232 -
1233 return QSqlQueryModel::rowCount() + d->insertCount(); -
1234} -
1235 -
1236/*! -
1237 Returns the index of the value in the database result set for the -
1238 given \a item in the model. -
1239 -
1240 The return value is identical to \a item if no columns or rows -
1241 have been inserted, removed, or moved around. -
1242 -
1243 Returns an invalid model index if \a item is out of bounds or if -
1244 \a item does not point to a value in the result set. -
1245 -
1246 \sa QSqlQueryModel::indexInQuery() -
1247*/ -
1248QModelIndex QSqlTableModel::indexInQuery(const QModelIndex &item) const -
1249{ -
1250 Q_D(const QSqlTableModel); -
1251 if (d->cache.value(item.row()).insert()) -
1252 return QModelIndex(); -
1253 -
1254 const int rowOffset = d->insertCount(item.row()); -
1255 return QSqlQueryModel::indexInQuery(createIndex(item.row() - rowOffset, item.column(), item.internalPointer())); -
1256} -
1257 -
1258/*! -
1259 Returns the currently set filter. -
1260 -
1261 \sa setFilter(), select() -
1262*/ -
1263QString QSqlTableModel::filter() const -
1264{ -
1265 Q_D(const QSqlTableModel); -
1266 return d->filter; -
1267} -
1268 -
1269/*! -
1270 Sets the current filter to \a filter. -
1271 -
1272 The filter is a SQL \c WHERE clause without the keyword \c WHERE -
1273 (for example, \c{name='Josephine')}. -
1274 -
1275 If the model is already populated with data from a database, -
1276 the model re-selects it with the new filter. Otherwise, the filter -
1277 will be applied the next time select() is called. -
1278 -
1279 \sa filter(), select(), selectStatement(), orderByClause() -
1280*/ -
1281void QSqlTableModel::setFilter(const QString &filter) -
1282{ -
1283 Q_D(QSqlTableModel); -
1284 d->filter = filter; -
1285 if (d->query.isActive()) -
1286 select(); -
1287} -
1288 -
1289/*! \reimp -
1290*/ -
1291void QSqlTableModel::clear() -
1292{ -
1293 Q_D(QSqlTableModel); -
1294 d->clear(); -
1295 QSqlQueryModel::clear(); -
1296} -
1297 -
1298/*! \reimp -
1299*/ -
1300Qt::ItemFlags QSqlTableModel::flags(const QModelIndex &index) const -
1301{ -
1302 Q_D(const QSqlTableModel); -
1303 if (index.internalPointer() || index.column() < 0 || index.column() >= d->rec.count() -
1304 || index.row() < 0) -
1305 return 0; -
1306 -
1307 bool editable = true; -
1308 -
1309 if (d->rec.field(index.column()).isReadOnly()) { -
1310 editable = false; -
1311 } -
1312 else { -
1313 const QSqlTableModelPrivate::ModifiedRow mrow = d->cache.value(index.row()); -
1314 if (mrow.op() == QSqlTableModelPrivate::Delete) { -
1315 editable = false; -
1316 } -
1317 else if (d->strategy == OnFieldChange) { -
1318 if (mrow.op() != QSqlTableModelPrivate::Insert) -
1319 if (!isDirty(index) && isDirty()) -
1320 editable = false; -
1321 } -
1322 else if (d->strategy == OnRowChange) { -
1323 if (mrow.submitted() && isDirty()) -
1324 editable = false; -
1325 } -
1326 } -
1327 -
1328 if (!editable) -
1329 return QSqlQueryModel::flags(index); -
1330 else -
1331 return QSqlQueryModel::flags(index) | Qt::ItemIsEditable; -
1332} -
1333 -
1334QSqlRecord QSqlTableModel::record() const -
1335{ -
1336 return QSqlQueryModel::record(); -
1337} -
1338 -
1339/*! -
1340\since 5.0 -
1341 Returns the record at \a row in the model. -
1342 -
1343 If \a row is the index of a valid row, the record -
1344 will be populated with values from that row. -
1345 -
1346 If the model is not initialized, an empty record will be -
1347 returned. -
1348 -
1349 \sa QSqlRecord::isEmpty() -
1350*/ -
1351QSqlRecord QSqlTableModel::record(int row) const -
1352{ -
1353 Q_D(const QSqlTableModel); -
1354 -
1355 // the query gets the values from virtual data() -
1356 QSqlRecord rec = QSqlQueryModel::record(row); -
1357 -
1358 // get generated flags from the cache -
1359 const QSqlTableModelPrivate::ModifiedRow mrow = d->cache.value(row); -
1360 if (mrow.op() != QSqlTableModelPrivate::None) { -
1361 const QSqlRecord crec = mrow.rec(); -
1362 for (int i = 0, cnt = rec.count(); i < cnt; ++i) -
1363 rec.setGenerated(i, crec.isGenerated(i)); -
1364 } -
1365 -
1366 return rec; -
1367} -
1368 -
1369/*! -
1370 Applies \a values to the \a row in the model. The source and -
1371 target fields are mapped by field name, not by position in -
1372 the record. -
1373 -
1374 Note that the generated flags in \a values are preserved -
1375 and determine whether the corresponding fields are used when -
1376 changes are submitted to the database. The caller should -
1377 remember to set the generated flag to FALSE for fields -
1378 where the database is meant to supply the value, such as an -
1379 automatically incremented ID. -
1380 -
1381 For edit strategies OnFieldChange and OnRowChange, a row may -
1382 receive a change only if no other row has a cached change. -
1383 Changes are submitted immediately. Submitted changes are not -
1384 reverted upon failure. -
1385 -
1386 Returns true if all the values could be set; otherwise returns -
1387 false. -
1388 -
1389 \sa record(), editStrategy() -
1390*/ -
1391bool QSqlTableModel::setRecord(int row, const QSqlRecord &values) -
1392{ -
1393 Q_D(QSqlTableModel); -
1394 Q_ASSERT_X(row >= 0, "QSqlTableModel::setRecord()", "Cannot set a record to a row less than 0"); -
1395 if (d->busyInsertingRows) -
1396 return false; -
1397 -
1398 if (row >= rowCount()) -
1399 return false; -
1400 -
1401 if (d->cache.value(row).op() == QSqlTableModelPrivate::Delete) -
1402 return false; -
1403 -
1404 if (d->strategy != OnManualSubmit && d->cache.value(row).submitted() && isDirty()) -
1405 return false; -
1406 -
1407 // Check field names and remember mapping -
1408 typedef QMap<int, int> Map; -
1409 Map map; -
1410 for (int i = 0; i < values.count(); ++i) { -
1411 int idx = d->nameToIndex(values.fieldName(i)); -
1412 if (idx == -1) -
1413 return false; -
1414 map[i] = idx; -
1415 } -
1416 -
1417 QSqlTableModelPrivate::ModifiedRow &mrow = d->cache[row]; -
1418 if (mrow.op() == QSqlTableModelPrivate::None) -
1419 mrow = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Update, -
1420 QSqlQueryModel::record(row)); -
1421 -
1422 Map::const_iterator i = map.constBegin(); -
1423 const Map::const_iterator e = map.constEnd(); -
1424 for ( ; i != e; ++i) { -
1425 // have to use virtual setData() here rather than mrow.setValue() -
1426 EditStrategy strategy = d->strategy; -
1427 d->strategy = OnManualSubmit; -
1428 QModelIndex cIndex = createIndex(row, i.value()); -
1429 setData(cIndex, values.value(i.key())); -
1430 d->strategy = strategy; -
1431 // setData() sets generated to TRUE, but source record should prevail. -
1432 if (!values.isGenerated(i.key())) -
1433 mrow.recRef().setGenerated(i.value(), false); -
1434 } -
1435 -
1436 if (d->strategy != OnManualSubmit) -
1437 return submit(); -
1438 -
1439 return true; -
1440} -
1441 -
1442QT_END_NAMESPACE -
1443 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial