1
/****************************************************************************
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
5
** This file is part of the item views module of the Qt Toolkit.
7
** This file may be distributed under the terms of the Q Public License
8
** as defined by Trolltech AS of Norway and appearing in the file
9
** LICENSE.QPL included in the packaging of this file.
11
** This file may be distributed and/or modified under the terms of the
12
** GNU General Public License version 2 as published by the Free Software
13
** Foundation and appearing in the file LICENSE.GPL included in the
14
** packaging of this file.
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
17
** information about Qt Commercial License Agreements.
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
21
** Contact info@trolltech.com if any conditions of this licensing are
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27
****************************************************************************/
29
#include "qstandarditemmodel.h"
34
#include <private/qstandarditemmodel_p.h>
38
\class QStandardItemModel
39
\brief The QStandardItemModel class provides a generic model for storing custom data.
41
QStandardItemModel provides a model that that can be used as a repository
42
for standard Qt data types. Data is written to the model and read back using
43
the standard QAbstractItemModel interface. The way each item of information
44
is referenced depends on how the data is inserted into the model.
46
For performance and flexibility, you may want to subclass QAbstractItemModel
47
to provide support for different kinds of repositories. For example, the
48
QDirModel provides a model interface to the underlying file system, and does
49
not actually store file information internally.
51
\sa \link model-view-programming.html Model/View Programming\endlink QAbstractItemModel
56
Creates an empty model that contains no rows or columns with the given
59
QStandardItemModel::QStandardItemModel(QObject *parent)
60
: QAbstractItemModel(*new QStandardItemModelPrivate(0, 0), parent)
66
Creates a model with \a rows number of rows and \a columns number of columns.
68
QStandardItemModel::QStandardItemModel(int rows, int columns, QObject *parent)
69
: QAbstractItemModel(*new QStandardItemModelPrivate(rows, columns), parent)
78
QStandardItemModel::~QStandardItemModel()
83
Returns a model index for the given \a row, \a column, and \a parent.
85
QModelIndex QStandardItemModel::index(int row, int column, const QModelIndex &parent) const
87
Q_D(const QStandardItemModel);
88
if (hasIndex(row, column, parent)) {
89
if (parent.isValid()) {
90
QStdModelRow *parentRow = d->containedRow(parent, false);
91
return createIndex(row, column, parentRow);
93
return createIndex(row, column, 0);
100
Returns a model index for the parent of the \a child item.
102
QModelIndex QStandardItemModel::parent(const QModelIndex &child) const
104
Q_D(const QStandardItemModel);
105
if (child.isValid() && child.internalPointer()) {
106
QStdModelRow *parentRow = static_cast<QStdModelRow*>(child.internalPointer());
107
QStdModelRow *grandParentRow = parentRow ? parentRow->p : 0;
108
QVector<QStdModelRow*> grandParentChildren = d->topLevelRows;
110
grandParentChildren = grandParentRow->childrenRows;
111
// ### slow, use ptr trick
112
int row = grandParentChildren.indexOf(parentRow);
113
return createIndex(row, 0, grandParentRow);
115
return QModelIndex();
119
Returns the number of rows in the model that contain items with the given
123
int QStandardItemModel::rowCount(const QModelIndex &parent) const
125
Q_D(const QStandardItemModel);
126
QStdModelRow *modelRow = d->containedRow(parent, true);
128
return modelRow->childrenRows.count();
130
return d->topLevelRows.count();
134
Returns the number of columns in the model that contain items with the given
137
int QStandardItemModel::columnCount(const QModelIndex &parent) const
139
Q_D(const QStandardItemModel);
140
QStdModelRow *modelRow = d->containedRow(parent, true);
142
return modelRow->childrenColumns;
144
return d->topLevelColumns;
148
Returns true if the \a parent model index has child items; otherwise returns
151
bool QStandardItemModel::hasChildren(const QModelIndex &parent) const
153
Q_D(const QStandardItemModel);
154
if (parent.isValid()) {
155
QStdModelRow *modelRow = d->containedRow(parent, true);
157
return modelRow->childrenRows.count() && modelRow->childrenColumns;
159
return !d->topLevelRows.isEmpty() && d->topLevelColumns;
165
Returns the data for the given \a index and \a role.
167
QVariant QStandardItemModel::data(const QModelIndex &index, int role) const
169
Q_D(const QStandardItemModel);
170
role = (role == Qt::EditRole ? Qt::DisplayRole : role);
171
if (index.isValid()) {
172
QStdModelRow *modelRow = d->containedRow(index, false);
173
if (modelRow && modelRow->items.count() > index.column()) {
174
QStdModelItem *item = modelRow->items.at(index.column());
176
return item->value(role);
183
Sets the data for the given \a index and \a role to the \a value specified.
185
bool QStandardItemModel::setData(const QModelIndex &index, const QVariant &value, int role)
187
Q_D(const QStandardItemModel);
188
role = (role == Qt::EditRole ? Qt::DisplayRole : role);
189
if (index.isValid()) {
190
QStdModelRow *modelRow = d->containedRow(index, true);
191
int count = modelRow->items.count();
192
// make room for enough items
193
if (count <= index.column())
194
modelRow->items.insert(count, index.column() + 1 - count, 0);
195
// make sure we have a QStdModelItem at the position
196
if (!modelRow->items.at(index.column()))
197
modelRow->items[index.column()] = new QStdModelItem();
198
modelRow->items.at(index.column())->setValue(role, value);
199
emit dataChanged(index, index);
209
QVariant QStandardItemModel::headerData(int section, Qt::Orientation orientation, int role) const
211
Q_D(const QStandardItemModel);
213
|| (orientation == Qt::Horizontal && section >= columnCount())
214
|| (orientation == Qt::Vertical && section >= rowCount()))
217
const QStdModelItem *headerItem = 0;
218
const QVector<QStdModelItem*> &header = (orientation == Qt::Horizontal
219
? d->horizontalHeader : d->verticalHeader);
220
role = (role == Qt::EditRole ? Qt::DisplayRole : role);
221
if (header.size() > section)
222
headerItem = header.at(section);
225
return headerItem->value(role);
227
return QAbstractItemModel::headerData(section, orientation, role);
233
bool QStandardItemModel::setHeaderData(int section, Qt::Orientation orientation,
234
const QVariant &value, int role)
236
Q_D(QStandardItemModel);
238
|| (orientation == Qt::Horizontal && section >= columnCount())
239
|| (orientation == Qt::Vertical && section >= rowCount()))
242
QStdModelItem *headerItem = 0;
243
QVector<QStdModelItem*> &header = (orientation == Qt::Horizontal
244
? d->horizontalHeader : d->verticalHeader);
245
role = (role == Qt::EditRole ? Qt::DisplayRole : role);
246
if (header.size() <= section)
247
header.resize(section + 1);
248
headerItem = header[section];
250
headerItem = new QStdModelItem();
251
header.replace(section, headerItem);
254
headerItem->setValue(role, value);
255
emit headerDataChanged(orientation, section, section);
261
Inserts \a count rows into the model, creating new items as children of
262
the given \a parent. The new rows are inserted before the \a row specified.
264
If \a row is 0, the rows are prepended to any existing rows in the parent.
265
If \a row is rowCount(), the rows are appended to any existing rows in
267
If \a parent has no children, a single column with \a count rows is inserted.
269
Returns true if the rows were successfully inserted; otherwise returns false.
271
bool QStandardItemModel::insertRows(int row, int count, const QModelIndex &parent)
273
Q_D(QStandardItemModel);
277
QVector<QStdModelRow*> &rows = (parent.isValid()) ? d->containedRow(parent, true)->childrenRows
282
else if (row > rows.count())
285
if (!parent.isValid() && d->verticalHeader.size() > row)
286
d->verticalHeader.insert(row, count, 0);
288
beginInsertRows(parent, row, row + count - 1);
290
rows.insert(row, count, 0);
298
Inserts \a count columns into the model, creating new items as children of
299
the given \a parent. The new columns are inserted before the \a column
302
If \a column is 0, the columns are prepended to any existing columns in the
304
If \a column is columnCount(), the columns are appended to any existing
305
columns in the parent.
306
If \a parent has no children, a single row with \a count columns is inserted.
308
Returns true if the columns were successfully inserted; otherwise returns
311
bool QStandardItemModel::insertColumns(int column, int count, const QModelIndex &parent)
313
Q_D(QStandardItemModel);
319
else if (column > columnCount(parent))
320
column = columnCount(parent);
322
beginInsertColumns(parent, column, column + count - 1);
324
QVector<QStdModelRow*> *rows = &d->topLevelRows;
325
// update the column counters
326
if (parent.isValid()) {
327
QStdModelRow *modelRow = d->containedRow(parent, true);
328
modelRow->childrenColumns += count;
329
rows = &modelRow->childrenRows;
331
d->topLevelColumns += count;
332
if (d->horizontalHeader.size() > column)
333
d->horizontalHeader.insert(column, count, 0);
336
// update any item vectors if needed
337
for (int i=0; i<rows->count(); ++i) {
338
QStdModelRow *modelRow = rows->at(i);
339
// only insert if there is a QStdModelRow and QStdModelItems in it
340
if (modelRow && modelRow->items.count()
341
&& modelRow->items.count() > column)
342
modelRow->items.insert(column, count, 0);
351
Removes \a count rows from the model, starting with the given
353
The items removed are children of the item represented by the \a parent
356
Returns true if the rows were successfully removed; otherwise returns
359
bool QStandardItemModel::removeRows(int row, int count, const QModelIndex &parent)
361
Q_D(QStandardItemModel);
362
if (count < 1 || row < 0 || (row + count) > rowCount(parent))
365
beginRemoveRows(parent, row, row + count - 1);
367
QVector<QStdModelRow*> &rows = (parent.isValid()) ? d->containedRow(parent, true)->childrenRows
370
if (!parent.isValid() && d->verticalHeader.count() > row) {
371
int headerCount = qMin(d->verticalHeader.count() - row, count);
372
for (int i=row; i < (row+headerCount); ++i)
373
delete d->verticalHeader.at(i);
374
d->verticalHeader.remove(row, headerCount);
377
// delete QStdModelRows
378
for (int i=row; i<(row+count); ++i)
381
rows.remove(row, count);
389
Removes \a count columns from the model, starting with the given
391
The items removed are children of the item represented by the \a parent
394
Returns true if the columns were successfully removed; otherwise returns
397
bool QStandardItemModel::removeColumns(int column, int count, const QModelIndex &parent)
399
Q_D(QStandardItemModel);
400
if (count < 1 || column < 0 || (column + count) > columnCount(parent))
403
beginRemoveColumns(parent, column, column + count - 1);
405
QVector<QStdModelRow*> *rows = &d->topLevelRows;
406
// update the column counters
407
if (parent.isValid()) {
408
QStdModelRow *modelRow = d->containedRow(parent, true);
409
modelRow->childrenColumns -= count;
410
rows = &modelRow->childrenRows;
412
d->topLevelColumns -= count;
413
if (d->horizontalHeader.count() > column) {
414
int headerCount = qMin(d->horizontalHeader.size() - column, count);
415
for (int i=column; i < (column+headerCount); ++i)
416
delete d->horizontalHeader.at(i);
417
d->horizontalHeader.remove(column, headerCount);
421
// iterate over all child rows and remove if needed
422
for (int i=0; i<rows->count(); ++i) {
423
QStdModelRow *modelRow = rows->at(i);
424
if (modelRow && column < modelRow->items.count()) {
425
// delete the QStdModelItem if any
426
for (int j=column; j<(column+count) && j<modelRow->items.count(); ++j)
427
delete modelRow->items.at(j);
428
// resize item vector
429
modelRow->items.remove(column, qMin(count, modelRow->items.count() - column));
439
Returns the item flags for the given \a index.
441
This model returns returns a combination of flags that
442
enables the item (Qt::ItemIsEnabled), allows it to be
443
selected (Qt::ItemIsSelectable) and edited (Qt::ItemIsEditable).
445
Qt::ItemFlags QStandardItemModel::flags(const QModelIndex &index) const
447
return QAbstractItemModel::flags(index) | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
451
Clears the model, removing all items.
453
void QStandardItemModel::clear()
455
Q_D(QStandardItemModel);
464
QStandardItemModelPrivate::~QStandardItemModelPrivate()
472
QStdModelRow *QStandardItemModelPrivate::containedRow(const QModelIndex &index,
473
bool createIfMissing) const
475
if (!index.isValid())
478
QStdModelRow *parentRow = static_cast<QStdModelRow*>(index.internalPointer());
479
QVector<QStdModelRow*> *rowList = const_cast<QVector<QStdModelRow*> *>(&topLevelRows);
481
rowList = const_cast<QVector<QStdModelRow*> *>(&parentRow->childrenRows);
484
if (createIfMissing && !rowList->at(index.row()))
485
rowList->replace(index.row() , new QStdModelRow(parentRow));
486
return rowList->at(index.row());
492
void QStandardItemModelPrivate::clear()
494
qDeleteAll(topLevelRows);
495
topLevelRows.clear();
496
qDeleteAll(horizontalHeader);
497
horizontalHeader.clear();
498
qDeleteAll(verticalHeader);
499
verticalHeader.clear();