qsqltablemodel.cpp

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

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9