~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to src/sql/models/qsqlquerymodel.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the QtSql module of the Qt Toolkit.
 
7
**
 
8
** $QT_BEGIN_LICENSE:LGPL$
 
9
** Commercial License Usage
 
10
** Licensees holding valid commercial Qt licenses may use this file in
 
11
** accordance with the commercial license agreement provided with the
 
12
** Software or, alternatively, in accordance with the terms contained in
 
13
** a written agreement between you and Digia.  For licensing terms and
 
14
** conditions see http://qt.digia.com/licensing.  For further information
 
15
** use the contact form at http://qt.digia.com/contact-us.
 
16
**
 
17
** GNU Lesser General Public License Usage
 
18
** Alternatively, this file may be used under the terms of the GNU Lesser
 
19
** General Public License version 2.1 as published by the Free Software
 
20
** Foundation and appearing in the file LICENSE.LGPL included in the
 
21
** packaging of this file.  Please review the following information to
 
22
** ensure the GNU Lesser General Public License version 2.1 requirements
 
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
24
**
 
25
** In addition, as a special exception, Digia gives you certain additional
 
26
** rights.  These rights are described in the Digia Qt LGPL Exception
 
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
28
**
 
29
** GNU General Public License Usage
 
30
** Alternatively, this file may be used under the terms of the GNU
 
31
** General Public License version 3.0 as published by the Free Software
 
32
** Foundation and appearing in the file LICENSE.GPL included in the
 
33
** packaging of this file.  Please review the following information to
 
34
** ensure the GNU General Public License version 3.0 requirements will be
 
35
** met: http://www.gnu.org/copyleft/gpl.html.
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#include "qsqlquerymodel.h"
 
43
#include "qsqlquerymodel_p.h"
 
44
 
 
45
#include <qdebug.h>
 
46
#include <qsqldriver.h>
 
47
#include <qsqlfield.h>
 
48
 
 
49
QT_BEGIN_NAMESPACE
 
50
 
 
51
#define QSQL_PREFETCH 255
 
52
 
 
53
void QSqlQueryModelPrivate::prefetch(int limit)
 
54
{
 
55
    Q_Q(QSqlQueryModel);
 
56
 
 
57
    if (atEnd || limit <= bottom.row() || bottom.column() == -1)
 
58
        return;
 
59
 
 
60
    QModelIndex newBottom;
 
61
    const int oldBottomRow = qMax(bottom.row(), 0);
 
62
 
 
63
    // try to seek directly
 
64
    if (query.seek(limit)) {
 
65
        newBottom = q->createIndex(limit, bottom.column());
 
66
    } else {
 
67
        // have to seek back to our old position for MS Access
 
68
        int i = oldBottomRow;
 
69
        if (query.seek(i)) {
 
70
            while (query.next())
 
71
                ++i;
 
72
            newBottom = q->createIndex(i, bottom.column());
 
73
        } else {
 
74
            // empty or invalid query
 
75
            newBottom = q->createIndex(-1, bottom.column());
 
76
        }
 
77
        atEnd = true; // this is the end.
 
78
    }
 
79
    if (newBottom.row() >= 0 && newBottom.row() > bottom.row()) {
 
80
        q->beginInsertRows(QModelIndex(), bottom.row() + 1, newBottom.row());
 
81
        bottom = newBottom;
 
82
        q->endInsertRows();
 
83
    } else {
 
84
        bottom = newBottom;
 
85
    }
 
86
}
 
87
 
 
88
QSqlQueryModelPrivate::~QSqlQueryModelPrivate()
 
89
{
 
90
}
 
91
 
 
92
void QSqlQueryModelPrivate::initColOffsets(int size)
 
93
{
 
94
    colOffsets.resize(size);
 
95
    memset(colOffsets.data(), 0, colOffsets.size() * sizeof(int));
 
96
}
 
97
 
 
98
/*!
 
99
    \class QSqlQueryModel
 
100
    \brief The QSqlQueryModel class provides a read-only data model for SQL
 
101
    result sets.
 
102
 
 
103
    \ingroup database
 
104
    \inmodule QtSql
 
105
 
 
106
    QSqlQueryModel is a high-level interface for executing SQL
 
107
    statements and traversing the result set. It is built on top of
 
108
    the lower-level QSqlQuery and can be used to provide data to
 
109
    view classes such as QTableView. For example:
 
110
 
 
111
    \snippet sqldatabase/sqldatabase.cpp 16
 
112
 
 
113
    We set the model's query, then we set up the labels displayed in
 
114
    the view header.
 
115
 
 
116
    QSqlQueryModel can also be used to access a database
 
117
    programmatically, without binding it to a view:
 
118
 
 
119
    \snippet sqldatabase/sqldatabase.cpp 21
 
120
 
 
121
    The code snippet above extracts the \c salary field from record 4 in
 
122
    the result set of the query \c{SELECT * from employee}. Assuming
 
123
    that \c salary is column 2, we can rewrite the last line as follows:
 
124
 
 
125
    \snippet sqldatabase/sqldatabase.cpp 22
 
126
 
 
127
    The model is read-only by default. To make it read-write, you
 
128
    must subclass it and reimplement setData() and flags(). Another
 
129
    option is to use QSqlTableModel, which provides a read-write
 
130
    model based on a single database table.
 
131
 
 
132
    The \l{querymodel} example illustrates how to use
 
133
    QSqlQueryModel to display the result of a query. It also shows
 
134
    how to subclass QSqlQueryModel to customize the contents of the
 
135
    data before showing it to the user, and how to create a
 
136
    read-write model based on QSqlQueryModel.
 
137
 
 
138
    If the database doesn't return the number of selected rows in
 
139
    a query, the model will fetch rows incrementally.
 
140
    See fetchMore() for more information.
 
141
 
 
142
    \sa QSqlTableModel, QSqlRelationalTableModel, QSqlQuery,
 
143
        {Model/View Programming}, {Query Model Example}
 
144
*/
 
145
 
 
146
/*!
 
147
    Creates an empty QSqlQueryModel with the given \a parent.
 
148
 */
 
149
QSqlQueryModel::QSqlQueryModel(QObject *parent)
 
150
    : QAbstractTableModel(*new QSqlQueryModelPrivate, parent)
 
151
{
 
152
}
 
153
 
 
154
/*! \internal
 
155
 */
 
156
QSqlQueryModel::QSqlQueryModel(QSqlQueryModelPrivate &dd, QObject *parent)
 
157
    : QAbstractTableModel(dd, parent)
 
158
{
 
159
}
 
160
 
 
161
/*!
 
162
    Destroys the object and frees any allocated resources.
 
163
 
 
164
    \sa clear()
 
165
*/
 
166
QSqlQueryModel::~QSqlQueryModel()
 
167
{
 
168
}
 
169
 
 
170
/*!
 
171
    \since 4.1
 
172
 
 
173
    Fetches more rows from a database.
 
174
    This only affects databases that don't report back the size of a query
 
175
    (see QSqlDriver::hasFeature()).
 
176
 
 
177
    To force fetching of the entire result set, you can use the following:
 
178
 
 
179
    \snippet code/src_sql_models_qsqlquerymodel.cpp 0
 
180
 
 
181
    \a parent should always be an invalid QModelIndex.
 
182
 
 
183
    \sa canFetchMore()
 
184
*/
 
185
void QSqlQueryModel::fetchMore(const QModelIndex &parent)
 
186
{
 
187
    Q_D(QSqlQueryModel);
 
188
    if (parent.isValid())
 
189
        return;
 
190
    d->prefetch(qMax(d->bottom.row(), 0) + QSQL_PREFETCH);
 
191
}
 
192
 
 
193
/*!
 
194
    \since 4.1
 
195
 
 
196
    Returns true if it is possible to read more rows from the database.
 
197
    This only affects databases that don't report back the size of a query
 
198
    (see QSqlDriver::hasFeature()).
 
199
 
 
200
    \a parent should always be an invalid QModelIndex.
 
201
 
 
202
    \sa fetchMore()
 
203
 */
 
204
bool QSqlQueryModel::canFetchMore(const QModelIndex &parent) const
 
205
{
 
206
    Q_D(const QSqlQueryModel);
 
207
    return (!parent.isValid() && !d->atEnd);
 
208
}
 
209
 
 
210
/*! \internal
 
211
 */
 
212
void QSqlQueryModel::beginInsertRows(const QModelIndex &parent, int first, int last)
 
213
{
 
214
    Q_D(QSqlQueryModel);
 
215
    if (!d->nestedResetLevel)
 
216
        QAbstractTableModel::beginInsertRows(parent, first, last);
 
217
}
 
218
 
 
219
/*! \internal
 
220
 */
 
221
void QSqlQueryModel::endInsertRows()
 
222
{
 
223
    Q_D(QSqlQueryModel);
 
224
    if (!d->nestedResetLevel)
 
225
        QAbstractTableModel::endInsertRows();
 
226
}
 
227
 
 
228
/*! \internal
 
229
 */
 
230
void QSqlQueryModel::beginRemoveRows(const QModelIndex &parent, int first, int last)
 
231
{
 
232
    Q_D(QSqlQueryModel);
 
233
    if (!d->nestedResetLevel)
 
234
        QAbstractTableModel::beginRemoveRows(parent, first, last);
 
235
}
 
236
 
 
237
/*! \internal
 
238
 */
 
239
void QSqlQueryModel::endRemoveRows()
 
240
{
 
241
    Q_D(QSqlQueryModel);
 
242
    if (!d->nestedResetLevel)
 
243
        QAbstractTableModel::endRemoveRows();
 
244
}
 
245
 
 
246
/*! \internal
 
247
 */
 
248
void QSqlQueryModel::beginInsertColumns(const QModelIndex &parent, int first, int last)
 
249
{
 
250
    Q_D(QSqlQueryModel);
 
251
    if (!d->nestedResetLevel)
 
252
        QAbstractTableModel::beginInsertColumns(parent, first, last);
 
253
}
 
254
 
 
255
/*! \internal
 
256
 */
 
257
void QSqlQueryModel::endInsertColumns()
 
258
{
 
259
    Q_D(QSqlQueryModel);
 
260
    if (!d->nestedResetLevel)
 
261
        QAbstractTableModel::endInsertColumns();
 
262
}
 
263
 
 
264
/*! \internal
 
265
 */
 
266
void QSqlQueryModel::beginRemoveColumns(const QModelIndex &parent, int first, int last)
 
267
{
 
268
    Q_D(QSqlQueryModel);
 
269
    if (!d->nestedResetLevel)
 
270
        QAbstractTableModel::beginRemoveColumns(parent, first, last);
 
271
}
 
272
 
 
273
/*! \internal
 
274
 */
 
275
void QSqlQueryModel::endRemoveColumns()
 
276
{
 
277
    Q_D(QSqlQueryModel);
 
278
    if (!d->nestedResetLevel)
 
279
        QAbstractTableModel::endRemoveColumns();
 
280
}
 
281
 
 
282
/*! \internal
 
283
 */
 
284
void QSqlQueryModel::beginResetModel()
 
285
{
 
286
    Q_D(QSqlQueryModel);
 
287
    if (!d->nestedResetLevel)
 
288
        QAbstractTableModel::beginResetModel();
 
289
    ++d->nestedResetLevel;
 
290
}
 
291
 
 
292
/*! \internal
 
293
 */
 
294
void QSqlQueryModel::endResetModel()
 
295
{
 
296
    Q_D(QSqlQueryModel);
 
297
    --d->nestedResetLevel;
 
298
    if (!d->nestedResetLevel)
 
299
        QAbstractTableModel::endResetModel();
 
300
}
 
301
 
 
302
/*! \fn int QSqlQueryModel::rowCount(const QModelIndex &parent) const
 
303
    \since 4.1
 
304
 
 
305
    If the database supports returning the size of a query
 
306
    (see QSqlDriver::hasFeature()), the number of rows of the current
 
307
    query is returned. Otherwise, returns the number of rows
 
308
    currently cached on the client.
 
309
 
 
310
    \a parent should always be an invalid QModelIndex.
 
311
 
 
312
    \sa canFetchMore(), QSqlDriver::hasFeature()
 
313
 */
 
314
int QSqlQueryModel::rowCount(const QModelIndex &index) const
 
315
{
 
316
    Q_D(const QSqlQueryModel);
 
317
    return index.isValid() ? 0 : d->bottom.row() + 1;
 
318
}
 
319
 
 
320
/*! \reimp
 
321
 */
 
322
int QSqlQueryModel::columnCount(const QModelIndex &index) const
 
323
{
 
324
    Q_D(const QSqlQueryModel);
 
325
    return index.isValid() ? 0 : d->rec.count();
 
326
}
 
327
 
 
328
/*!
 
329
    Returns the value for the specified \a item and \a role.
 
330
 
 
331
    If \a item is out of bounds or if an error occurred, an invalid
 
332
    QVariant is returned.
 
333
 
 
334
    \sa lastError()
 
335
*/
 
336
QVariant QSqlQueryModel::data(const QModelIndex &item, int role) const
 
337
{
 
338
    Q_D(const QSqlQueryModel);
 
339
    if (!item.isValid())
 
340
        return QVariant();
 
341
 
 
342
    QVariant v;
 
343
    if (role & ~(Qt::DisplayRole | Qt::EditRole))
 
344
        return v;
 
345
 
 
346
    if (!d->rec.isGenerated(item.column()))
 
347
        return v;
 
348
    QModelIndex dItem = indexInQuery(item);
 
349
    if (dItem.row() > d->bottom.row())
 
350
        const_cast<QSqlQueryModelPrivate *>(d)->prefetch(dItem.row());
 
351
 
 
352
    if (!d->query.seek(dItem.row())) {
 
353
        d->error = d->query.lastError();
 
354
        return v;
 
355
    }
 
356
 
 
357
    return d->query.value(dItem.column());
 
358
}
 
359
 
 
360
/*!
 
361
    Returns the header data for the given \a role in the \a section
 
362
    of the header with the specified \a orientation.
 
363
*/
 
364
QVariant QSqlQueryModel::headerData(int section, Qt::Orientation orientation, int role) const
 
365
{
 
366
    Q_D(const QSqlQueryModel);
 
367
    if (orientation == Qt::Horizontal) {
 
368
        QVariant val = d->headers.value(section).value(role);
 
369
        if (role == Qt::DisplayRole && !val.isValid())
 
370
            val = d->headers.value(section).value(Qt::EditRole);
 
371
        if (val.isValid())
 
372
            return val;
 
373
 
 
374
        // See if it's an inserted column (iiq.column() != -1)
 
375
        QModelIndex dItem = indexInQuery(createIndex(0, section));
 
376
 
 
377
        if (role == Qt::DisplayRole && d->rec.count() > section && dItem.column() != -1)
 
378
            return d->rec.fieldName(section);
 
379
    }
 
380
    return QAbstractItemModel::headerData(section, orientation, role);
 
381
}
 
382
 
 
383
/*!
 
384
    This virtual function is called whenever the query changes. The
 
385
    default implementation does nothing.
 
386
 
 
387
    query() returns the new query.
 
388
 
 
389
    \sa query(), setQuery()
 
390
 */
 
391
void QSqlQueryModel::queryChange()
 
392
{
 
393
    // do nothing
 
394
}
 
395
 
 
396
/*!
 
397
    Resets the model and sets the data provider to be the given \a
 
398
    query. Note that the query must be active and must not be
 
399
    isForwardOnly().
 
400
 
 
401
    lastError() can be used to retrieve verbose information if there
 
402
    was an error setting the query.
 
403
 
 
404
    \note Calling setQuery() will remove any inserted columns.
 
405
 
 
406
    \sa query(), QSqlQuery::isActive(), QSqlQuery::setForwardOnly(), lastError()
 
407
*/
 
408
void QSqlQueryModel::setQuery(const QSqlQuery &query)
 
409
{
 
410
    Q_D(QSqlQueryModel);
 
411
    beginResetModel();
 
412
 
 
413
    QSqlRecord newRec = query.record();
 
414
    bool columnsChanged = (newRec != d->rec);
 
415
 
 
416
    if (d->colOffsets.size() != newRec.count() || columnsChanged)
 
417
        d->initColOffsets(newRec.count());
 
418
 
 
419
    d->bottom = QModelIndex();
 
420
    d->error = QSqlError();
 
421
    d->query = query;
 
422
    d->rec = newRec;
 
423
    d->atEnd = true;
 
424
 
 
425
    if (query.isForwardOnly()) {
 
426
        d->error = QSqlError(QLatin1String("Forward-only queries "
 
427
                                           "cannot be used in a data model"),
 
428
                             QString(), QSqlError::ConnectionError);
 
429
        endResetModel();
 
430
        return;
 
431
    }
 
432
 
 
433
    if (!query.isActive()) {
 
434
        d->error = query.lastError();
 
435
        endResetModel();
 
436
        return;
 
437
    }
 
438
 
 
439
    if (query.driver()->hasFeature(QSqlDriver::QuerySize) && d->query.size() > 0) {
 
440
        d->bottom = createIndex(d->query.size() - 1, d->rec.count() - 1);
 
441
    } else {
 
442
        d->bottom = createIndex(-1, d->rec.count() - 1);
 
443
        d->atEnd = false;
 
444
    }
 
445
 
 
446
 
 
447
    // fetchMore does the rowsInserted stuff for incremental models
 
448
    fetchMore();
 
449
 
 
450
    endResetModel();
 
451
    queryChange();
 
452
}
 
453
 
 
454
/*! \overload
 
455
 
 
456
    Executes the query \a query for the given database connection \a
 
457
    db. If no database (or an invalid database) is specified, the
 
458
    default connection is used.
 
459
 
 
460
    lastError() can be used to retrieve verbose information if there
 
461
    was an error setting the query.
 
462
 
 
463
    Example:
 
464
    \snippet code/src_sql_models_qsqlquerymodel.cpp 1
 
465
 
 
466
    \sa query(), queryChange(), lastError()
 
467
*/
 
468
void QSqlQueryModel::setQuery(const QString &query, const QSqlDatabase &db)
 
469
{
 
470
    setQuery(QSqlQuery(query, db));
 
471
}
 
472
 
 
473
/*!
 
474
    Clears the model and releases any acquired resource.
 
475
*/
 
476
void QSqlQueryModel::clear()
 
477
{
 
478
    Q_D(QSqlQueryModel);
 
479
    d->error = QSqlError();
 
480
    d->atEnd = true;
 
481
    d->query.clear();
 
482
    d->rec.clear();
 
483
    d->colOffsets.clear();
 
484
    d->bottom = QModelIndex();
 
485
    d->headers.clear();
 
486
}
 
487
 
 
488
/*!
 
489
    Sets the caption for a horizontal header for the specified \a role to
 
490
    \a value. This is useful if the model is used to
 
491
    display data in a view (e.g., QTableView).
 
492
 
 
493
    Returns true if \a orientation is Qt::Horizontal and
 
494
    the \a section refers to a valid section; otherwise returns
 
495
    false.
 
496
 
 
497
    Note that this function cannot be used to modify values in the
 
498
    database since the model is read-only.
 
499
 
 
500
    \sa data()
 
501
 */
 
502
bool QSqlQueryModel::setHeaderData(int section, Qt::Orientation orientation,
 
503
                                   const QVariant &value, int role)
 
504
{
 
505
    Q_D(QSqlQueryModel);
 
506
    if (orientation != Qt::Horizontal || section < 0 || columnCount() <= section)
 
507
        return false;
 
508
 
 
509
    if (d->headers.size() <= section)
 
510
        d->headers.resize(qMax(section + 1, 16));
 
511
    d->headers[section][role] = value;
 
512
    emit headerDataChanged(orientation, section, section);
 
513
    return true;
 
514
}
 
515
 
 
516
/*!
 
517
    Returns the QSqlQuery associated with this model.
 
518
 
 
519
    \sa setQuery()
 
520
*/
 
521
QSqlQuery QSqlQueryModel::query() const
 
522
{
 
523
    Q_D(const QSqlQueryModel);
 
524
    return d->query;
 
525
}
 
526
 
 
527
/*!
 
528
    Returns information about the last error that occurred on the
 
529
    database.
 
530
 
 
531
    \sa query()
 
532
*/
 
533
QSqlError QSqlQueryModel::lastError() const
 
534
{
 
535
    Q_D(const QSqlQueryModel);
 
536
    return d->error;
 
537
}
 
538
 
 
539
/*!
 
540
   Protected function which allows derived classes to set the value of
 
541
   the last error that occurred on the database to \a error.
 
542
 
 
543
   \sa lastError()
 
544
*/
 
545
void QSqlQueryModel::setLastError(const QSqlError &error)
 
546
{
 
547
    Q_D(QSqlQueryModel);
 
548
    d->error = error;
 
549
}
 
550
 
 
551
/*!
 
552
    Returns the record containing information about the fields of the
 
553
    current query. If \a row is the index of a valid row, the record
 
554
    will be populated with values from that row.
 
555
 
 
556
    If the model is not initialized, an empty record will be
 
557
    returned.
 
558
 
 
559
    \sa QSqlRecord::isEmpty()
 
560
*/
 
561
QSqlRecord QSqlQueryModel::record(int row) const
 
562
{
 
563
    Q_D(const QSqlQueryModel);
 
564
    if (row < 0)
 
565
        return d->rec;
 
566
 
 
567
    QSqlRecord rec = d->rec;
 
568
    for (int i = 0; i < rec.count(); ++i)
 
569
        rec.setValue(i, data(createIndex(row, i), Qt::EditRole));
 
570
    return rec;
 
571
}
 
572
 
 
573
/*! \overload
 
574
 
 
575
    Returns an empty record containing information about the fields
 
576
    of the current query.
 
577
 
 
578
    If the model is not initialized, an empty record will be
 
579
    returned.
 
580
 
 
581
    \sa QSqlRecord::isEmpty()
 
582
 */
 
583
QSqlRecord QSqlQueryModel::record() const
 
584
{
 
585
    Q_D(const QSqlQueryModel);
 
586
    return d->rec;
 
587
}
 
588
 
 
589
/*!
 
590
    Inserts \a count columns into the model at position \a column. The
 
591
    \a parent parameter must always be an invalid QModelIndex, since
 
592
    the model does not support parent-child relationships.
 
593
 
 
594
    Returns true if \a column is within bounds; otherwise returns false.
 
595
 
 
596
    By default, inserted columns are empty. To fill them with data,
 
597
    reimplement data() and handle any inserted column separately:
 
598
 
 
599
    \snippet sqldatabase/sqldatabase.cpp 23
 
600
 
 
601
    \sa removeColumns()
 
602
*/
 
603
bool QSqlQueryModel::insertColumns(int column, int count, const QModelIndex &parent)
 
604
{
 
605
    Q_D(QSqlQueryModel);
 
606
    if (count <= 0 || parent.isValid() || column < 0 || column > d->rec.count())
 
607
        return false;
 
608
 
 
609
    beginInsertColumns(parent, column, column + count - 1);
 
610
    for (int c = 0; c < count; ++c) {
 
611
        QSqlField field;
 
612
        field.setReadOnly(true);
 
613
        field.setGenerated(false);
 
614
        d->rec.insert(column, field);
 
615
        if (d->colOffsets.size() < d->rec.count()) {
 
616
            int nVal = d->colOffsets.isEmpty() ? 0 : d->colOffsets[d->colOffsets.size() - 1];
 
617
            d->colOffsets.append(nVal);
 
618
            Q_ASSERT(d->colOffsets.size() >= d->rec.count());
 
619
        }
 
620
        for (int i = column + 1; i < d->colOffsets.count(); ++i)
 
621
            ++d->colOffsets[i];
 
622
    }
 
623
    endInsertColumns();
 
624
    return true;
 
625
}
 
626
 
 
627
/*!
 
628
    Removes \a count columns from the model starting from position \a
 
629
    column. The \a parent parameter must always be an invalid
 
630
    QModelIndex, since the model does not support parent-child
 
631
    relationships.
 
632
 
 
633
    Removing columns effectively hides them. It does not affect the
 
634
    underlying QSqlQuery.
 
635
 
 
636
    Returns true if the columns were removed; otherwise returns false.
 
637
 */
 
638
bool QSqlQueryModel::removeColumns(int column, int count, const QModelIndex &parent)
 
639
{
 
640
    Q_D(QSqlQueryModel);
 
641
    if (count <= 0 || parent.isValid() || column < 0 || column >= d->rec.count())
 
642
        return false;
 
643
 
 
644
    beginRemoveColumns(parent, column, column + count - 1);
 
645
 
 
646
    int i;
 
647
    for (i = 0; i < count; ++i)
 
648
        d->rec.remove(column);
 
649
    for (i = column; i < d->colOffsets.count(); ++i)
 
650
        d->colOffsets[i] -= count;
 
651
 
 
652
    endRemoveColumns();
 
653
    return true;
 
654
}
 
655
 
 
656
/*!
 
657
    Returns the index of the value in the database result set for the
 
658
    given \a item in the model.
 
659
 
 
660
    The return value is identical to \a item if no columns or rows
 
661
    have been inserted, removed, or moved around.
 
662
 
 
663
    Returns an invalid model index if \a item is out of bounds or if
 
664
    \a item does not point to a value in the result set.
 
665
 
 
666
    \sa QSqlTableModel::indexInQuery(), insertColumns(), removeColumns()
 
667
*/
 
668
QModelIndex QSqlQueryModel::indexInQuery(const QModelIndex &item) const
 
669
{
 
670
    Q_D(const QSqlQueryModel);
 
671
    if (item.column() < 0 || item.column() >= d->rec.count()
 
672
        || !d->rec.isGenerated(item.column())
 
673
        || item.column() >= d->colOffsets.size())
 
674
        return QModelIndex();
 
675
    return createIndex(item.row(), item.column() - d->colOffsets[item.column()],
 
676
                       item.internalPointer());
 
677
}
 
678
 
 
679
QT_END_NAMESPACE