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