1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). |
4 | ** Contact: http://www.qt-project.org/legal |
5 | ** |
6 | ** This file is part of the QtGui 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 "qstandarditemmodel.h" |
43 | |
44 | #ifndef QT_NO_STANDARDITEMMODEL |
45 | |
46 | #include <QtCore/qdatetime.h> |
47 | #include <QtCore/qlist.h> |
48 | #include <QtCore/qmap.h> |
49 | #include <QtCore/qpair.h> |
50 | #include <QtCore/qvariant.h> |
51 | #include <QtCore/qvector.h> |
52 | #include <QtCore/qstringlist.h> |
53 | #include <QtCore/qbitarray.h> |
54 | #include <QtCore/qmimedata.h> |
55 | |
56 | #include <private/qstandarditemmodel_p.h> |
57 | #include <qdebug.h> |
58 | |
59 | QT_BEGIN_NAMESPACE |
60 | |
61 | class QStandardItemModelLessThan |
62 | { |
63 | public: |
64 | inline QStandardItemModelLessThan() |
65 | { } |
66 | |
67 | inline bool operator()(const QPair<QStandardItem*, int> &l, |
68 | const QPair<QStandardItem*, int> &r) const |
69 | { |
70 | return *(l.first) < *(r.first); |
71 | } |
72 | }; |
73 | |
74 | class QStandardItemModelGreaterThan |
75 | { |
76 | public: |
77 | inline QStandardItemModelGreaterThan() |
78 | { } |
79 | |
80 | inline bool operator()(const QPair<QStandardItem*, int> &l, |
81 | const QPair<QStandardItem*, int> &r) const |
82 | { |
83 | return *(r.first) < *(l.first); |
84 | } |
85 | }; |
86 | |
87 | /*! |
88 | \internal |
89 | */ |
90 | QStandardItemPrivate::~QStandardItemPrivate() |
91 | { |
92 | QVector<QStandardItem*>::const_iterator it; |
93 | for (it = children.constBegin(); it != children.constEnd(); ++it) { |
94 | QStandardItem *child = *it; |
95 | if (child) |
96 | child->d_func()->setModel(0); |
97 | delete child; |
98 | } |
99 | children.clear(); |
100 | if (parent && model) |
101 | parent->d_func()->childDeleted(q_func()); |
102 | } |
103 | |
104 | /*! |
105 | \internal |
106 | */ |
107 | QPair<int, int> QStandardItemPrivate::position() const |
108 | { |
109 | if (QStandardItem *par = parent) { |
110 | int idx = par->d_func()->childIndex(q_func()); |
111 | if (idx == -1) |
112 | return QPair<int, int>(-1, -1); |
113 | return QPair<int, int>(idx / par->columnCount(), idx % par->columnCount()); |
114 | } |
115 | // ### support header items? |
116 | return QPair<int, int>(-1, -1); |
117 | } |
118 | |
119 | /*! |
120 | \internal |
121 | */ |
122 | void QStandardItemPrivate::setChild(int row, int column, QStandardItem *item, |
123 | bool emitChanged) |
124 | { |
125 | Q_Q(QStandardItem); |
126 | if (item == q) { |
127 | qWarning("QStandardItem::setChild: Can't make an item a child of itself %p" , |
128 | item); |
129 | return; |
130 | } |
131 | if ((row < 0) || (column < 0)) |
132 | return; |
133 | if (rows <= row) |
134 | q->setRowCount(row + 1); |
135 | if (columns <= column) |
136 | q->setColumnCount(column + 1); |
137 | int index = childIndex(row, column); |
138 | Q_ASSERT(index != -1); |
139 | QStandardItem *oldItem = children.at(index); |
140 | if (item == oldItem) |
141 | return; |
142 | if (item) { |
143 | if (item->d_func()->parent == 0) { |
144 | item->d_func()->setParentAndModel(q, model); |
145 | } else { |
146 | qWarning("QStandardItem::setChild: Ignoring duplicate insertion of item %p" , |
147 | item); |
148 | return; |
149 | } |
150 | } |
151 | if (oldItem) |
152 | oldItem->d_func()->setModel(0); |
153 | delete oldItem; |
154 | children.replace(index, item); |
155 | if (emitChanged && model) |
156 | model->d_func()->itemChanged(item); |
157 | } |
158 | |
159 | |
160 | /*! |
161 | \internal |
162 | */ |
163 | void QStandardItemPrivate::changeFlags(bool enable, Qt::ItemFlags f) |
164 | { |
165 | Q_Q(QStandardItem); |
166 | Qt::ItemFlags flags = q->flags(); |
167 | if (enable) |
168 | flags |= f; |
169 | else |
170 | flags &= ~f; |
171 | q->setFlags(flags); |
172 | } |
173 | |
174 | /*! |
175 | \internal |
176 | */ |
177 | void QStandardItemPrivate::childDeleted(QStandardItem *child) |
178 | { |
179 | int index = childIndex(child); |
180 | Q_ASSERT(index != -1); |
181 | children.replace(index, 0); |
182 | } |
183 | |
184 | /*! |
185 | \internal |
186 | */ |
187 | void QStandardItemPrivate::setItemData(const QMap<int, QVariant> &roles) |
188 | { |
189 | Q_Q(QStandardItem); |
190 | |
191 | //let's build the vector of new values |
192 | QVector<QWidgetItemData> newValues; |
193 | QMap<int, QVariant>::const_iterator it; |
194 | for (it = roles.begin(); it != roles.end(); ++it) { |
195 | QVariant value = it.value(); |
196 | if (value.isValid()) { |
197 | int role = it.key(); |
198 | role = (role == Qt::EditRole) ? Qt::DisplayRole : role; |
199 | QWidgetItemData wid(role,it.value()); |
200 | newValues.append(wid); |
201 | } |
202 | } |
203 | |
204 | if (values!=newValues) { |
205 | values=newValues; |
206 | if (model) |
207 | model->d_func()->itemChanged(q); |
208 | } |
209 | } |
210 | |
211 | /*! |
212 | \internal |
213 | */ |
214 | const QMap<int, QVariant> QStandardItemPrivate::itemData() const |
215 | { |
216 | QMap<int, QVariant> result; |
217 | QVector<QWidgetItemData>::const_iterator it; |
218 | for (it = values.begin(); it != values.end(); ++it) |
219 | result.insert((*it).role, (*it).value); |
220 | return result; |
221 | } |
222 | |
223 | /*! |
224 | \internal |
225 | */ |
226 | void QStandardItemPrivate::sortChildren(int column, Qt::SortOrder order) |
227 | { |
228 | Q_Q(QStandardItem); |
229 | if (column >= columnCount()) |
230 | return; |
231 | |
232 | QVector<QPair<QStandardItem*, int> > sortable; |
233 | QVector<int> unsortable; |
234 | |
235 | sortable.reserve(rowCount()); |
236 | unsortable.reserve(rowCount()); |
237 | |
238 | for (int row = 0; row < rowCount(); ++row) { |
239 | QStandardItem *itm = q->child(row, column); |
240 | if (itm) |
241 | sortable.append(QPair<QStandardItem*,int>(itm, row)); |
242 | else |
243 | unsortable.append(row); |
244 | } |
245 | |
246 | if (order == Qt::AscendingOrder) { |
247 | QStandardItemModelLessThan lt; |
248 | qStableSort(sortable.begin(), sortable.end(), lt); |
249 | } else { |
250 | QStandardItemModelGreaterThan gt; |
251 | qStableSort(sortable.begin(), sortable.end(), gt); |
252 | } |
253 | |
254 | QModelIndexList changedPersistentIndexesFrom, changedPersistentIndexesTo; |
255 | QVector<QStandardItem*> sorted_children(children.count()); |
256 | for (int i = 0; i < rowCount(); ++i) { |
257 | int r = (i < sortable.count() |
258 | ? sortable.at(i).second |
259 | : unsortable.at(i - sortable.count())); |
260 | for (int c = 0; c < columnCount(); ++c) { |
261 | QStandardItem *itm = q->child(r, c); |
262 | sorted_children[childIndex(i, c)] = itm; |
263 | if (model) { |
264 | QModelIndex from = model->createIndex(r, c, q); |
265 | if (model->d_func()->persistent.indexes.contains(from)) { |
266 | QModelIndex to = model->createIndex(i, c, q); |
267 | changedPersistentIndexesFrom.append(from); |
268 | changedPersistentIndexesTo.append(to); |
269 | } |
270 | } |
271 | } |
272 | } |
273 | |
274 | children = sorted_children; |
275 | |
276 | if (model) { |
277 | model->changePersistentIndexList(changedPersistentIndexesFrom, changedPersistentIndexesTo); |
278 | } |
279 | |
280 | QVector<QStandardItem*>::iterator it; |
281 | for (it = children.begin(); it != children.end(); ++it) { |
282 | if (*it) |
283 | (*it)->d_func()->sortChildren(column, order); |
284 | } |
285 | } |
286 | |
287 | /*! |
288 | \internal |
289 | set the model of this item and all its children |
290 | */ |
291 | void QStandardItemPrivate::setModel(QStandardItemModel *mod) |
292 | { |
293 | if (children.isEmpty()) { |
294 | if (model) |
295 | model->d_func()->invalidatePersistentIndex(model->indexFromItem(q_ptr)); |
296 | model = mod; |
297 | } else { |
298 | QStack<QStandardItem*> stack; |
299 | stack.push(q_ptr); |
300 | while (!stack.isEmpty()) { |
301 | QStandardItem *itm = stack.pop(); |
302 | if (itm->d_func()->model) { |
303 | itm->d_func()->model->d_func()->invalidatePersistentIndex(itm->d_func()->model->indexFromItem(itm)); |
304 | } |
305 | itm->d_func()->model = mod; |
306 | const QVector<QStandardItem*> &childList = itm->d_func()->children; |
307 | for (int i = 0; i < childList.count(); ++i) { |
308 | QStandardItem *chi = childList.at(i); |
309 | if (chi) |
310 | stack.push(chi); |
311 | } |
312 | } |
313 | } |
314 | } |
315 | |
316 | /*! |
317 | \internal |
318 | */ |
319 | QStandardItemModelPrivate::QStandardItemModelPrivate() |
320 | : root(new QStandardItem), |
321 | itemPrototype(0), |
322 | sortRole(Qt::DisplayRole) |
323 | { |
324 | root->setFlags(Qt::ItemIsDropEnabled); |
325 | } |
326 | |
327 | /*! |
328 | \internal |
329 | */ |
330 | QStandardItemModelPrivate::~QStandardItemModelPrivate() |
331 | { |
332 | delete itemPrototype; |
333 | qDeleteAll(columnHeaderItems); |
334 | qDeleteAll(rowHeaderItems); |
335 | } |
336 | |
337 | /*! |
338 | \internal |
339 | */ |
340 | void QStandardItemModelPrivate::init() |
341 | { |
342 | Q_Q(QStandardItemModel); |
343 | QObject::connect(q, SIGNAL(dataChanged(QModelIndex,QModelIndex)), |
344 | q, SLOT(_q_emitItemChanged(QModelIndex,QModelIndex))); |
345 | } |
346 | |
347 | /*! |
348 | \internal |
349 | */ |
350 | void QStandardItemModelPrivate::_q_emitItemChanged(const QModelIndex &topLeft, |
351 | const QModelIndex &bottomRight) |
352 | { |
353 | Q_Q(QStandardItemModel); |
354 | QModelIndex parent = topLeft.parent(); |
355 | for (int row = topLeft.row(); row <= bottomRight.row(); ++row) { |
356 | for (int column = topLeft.column(); column <= bottomRight.column(); ++column) { |
357 | QModelIndex index = q->index(row, column, parent); |
358 | if (QStandardItem *item = itemFromIndex(index)) |
359 | emit q->itemChanged(item); |
360 | } |
361 | } |
362 | } |
363 | |
364 | /*! |
365 | \internal |
366 | */ |
367 | bool QStandardItemPrivate::insertRows(int row, const QList<QStandardItem*> &items) |
368 | { |
369 | Q_Q(QStandardItem); |
370 | if ((row < 0) || (row > rowCount())) |
371 | return false; |
372 | int count = items.count(); |
373 | if (model) |
374 | model->d_func()->rowsAboutToBeInserted(q, row, row + count - 1); |
375 | if (rowCount() == 0) { |
376 | if (columnCount() == 0) |
377 | q->setColumnCount(1); |
378 | children.resize(columnCount() * count); |
379 | rows = count; |
380 | } else { |
381 | rows += count; |
382 | int index = childIndex(row, 0); |
383 | if (index != -1) |
384 | children.insert(index, columnCount() * count, 0); |
385 | } |
386 | for (int i = 0; i < items.count(); ++i) { |
387 | QStandardItem *item = items.at(i); |
388 | item->d_func()->model = model; |
389 | item->d_func()->parent = q; |
390 | int index = childIndex(i + row, 0); |
391 | children.replace(index, item); |
392 | } |
393 | if (model) |
394 | model->d_func()->rowsInserted(q, row, count); |
395 | return true; |
396 | } |
397 | |
398 | bool QStandardItemPrivate::insertRows(int row, int count, const QList<QStandardItem*> &items) |
399 | { |
400 | Q_Q(QStandardItem); |
401 | if ((count < 1) || (row < 0) || (row > rowCount())) |
402 | return false; |
403 | if (model) |
404 | model->d_func()->rowsAboutToBeInserted(q, row, row + count - 1); |
405 | if (rowCount() == 0) { |
406 | children.resize(columnCount() * count); |
407 | rows = count; |
408 | } else { |
409 | rows += count; |
410 | int index = childIndex(row, 0); |
411 | if (index != -1) |
412 | children.insert(index, columnCount() * count, 0); |
413 | } |
414 | if (!items.isEmpty()) { |
415 | int index = childIndex(row, 0); |
416 | int limit = qMin(items.count(), columnCount() * count); |
417 | for (int i = 0; i < limit; ++i) { |
418 | QStandardItem *item = items.at(i); |
419 | if (item) { |
420 | if (item->d_func()->parent == 0) { |
421 | item->d_func()->setParentAndModel(q, model); |
422 | } else { |
423 | qWarning("QStandardItem::insertRows: Ignoring duplicate insertion of item %p" , |
424 | item); |
425 | item = 0; |
426 | } |
427 | } |
428 | children.replace(index, item); |
429 | ++index; |
430 | } |
431 | } |
432 | if (model) |
433 | model->d_func()->rowsInserted(q, row, count); |
434 | return true; |
435 | } |
436 | |
437 | /*! |
438 | \internal |
439 | */ |
440 | bool QStandardItemPrivate::insertColumns(int column, int count, const QList<QStandardItem*> &items) |
441 | { |
442 | Q_Q(QStandardItem); |
443 | if ((count < 1) || (column < 0) || (column > columnCount())) |
444 | return false; |
445 | if (model) |
446 | model->d_func()->columnsAboutToBeInserted(q, column, column + count - 1); |
447 | if (columnCount() == 0) { |
448 | children.resize(rowCount() * count); |
449 | columns = count; |
450 | } else { |
451 | columns += count; |
452 | int index = childIndex(0, column); |
453 | for (int row = 0; row < rowCount(); ++row) { |
454 | children.insert(index, count, 0); |
455 | index += columnCount(); |
456 | } |
457 | } |
458 | if (!items.isEmpty()) { |
459 | int limit = qMin(items.count(), rowCount() * count); |
460 | for (int i = 0; i < limit; ++i) { |
461 | QStandardItem *item = items.at(i); |
462 | if (item) { |
463 | if (item->d_func()->parent == 0) { |
464 | item->d_func()->setParentAndModel(q, model); |
465 | } else { |
466 | qWarning("QStandardItem::insertColumns: Ignoring duplicate insertion of item %p" , |
467 | item); |
468 | item = 0; |
469 | } |
470 | } |
471 | int r = i / count; |
472 | int c = column + (i % count); |
473 | int index = childIndex(r, c); |
474 | children.replace(index, item); |
475 | } |
476 | } |
477 | if (model) |
478 | model->d_func()->columnsInserted(q, column, count); |
479 | return true; |
480 | } |
481 | |
482 | /*! |
483 | \internal |
484 | */ |
485 | void QStandardItemModelPrivate::itemChanged(QStandardItem *item) |
486 | { |
487 | Q_Q(QStandardItemModel); |
488 | if (item->d_func()->parent == 0) { |
489 | // Header item |
490 | int idx = columnHeaderItems.indexOf(item); |
491 | if (idx != -1) { |
492 | emit q->headerDataChanged(Qt::Horizontal, idx, idx); |
493 | } else { |
494 | idx = rowHeaderItems.indexOf(item); |
495 | if (idx != -1) |
496 | emit q->headerDataChanged(Qt::Vertical, idx, idx); |
497 | } |
498 | } else { |
499 | // Normal item |
500 | QModelIndex index = q->indexFromItem(item); |
501 | emit q->dataChanged(index, index); |
502 | } |
503 | } |
504 | |
505 | /*! |
506 | \internal |
507 | */ |
508 | void QStandardItemModelPrivate::rowsAboutToBeInserted(QStandardItem *parent, |
509 | int start, int end) |
510 | { |
511 | Q_Q(QStandardItemModel); |
512 | QModelIndex index = q->indexFromItem(parent); |
513 | q->beginInsertRows(index, start, end); |
514 | } |
515 | |
516 | /*! |
517 | \internal |
518 | */ |
519 | void QStandardItemModelPrivate::columnsAboutToBeInserted(QStandardItem *parent, |
520 | int start, int end) |
521 | { |
522 | Q_Q(QStandardItemModel); |
523 | QModelIndex index = q->indexFromItem(parent); |
524 | q->beginInsertColumns(index, start, end); |
525 | } |
526 | |
527 | /*! |
528 | \internal |
529 | */ |
530 | void QStandardItemModelPrivate::rowsAboutToBeRemoved(QStandardItem *parent, |
531 | int start, int end) |
532 | { |
533 | Q_Q(QStandardItemModel); |
534 | QModelIndex index = q->indexFromItem(parent); |
535 | q->beginRemoveRows(index, start, end); |
536 | } |
537 | |
538 | /*! |
539 | \internal |
540 | */ |
541 | void QStandardItemModelPrivate::columnsAboutToBeRemoved(QStandardItem *parent, |
542 | int start, int end) |
543 | { |
544 | Q_Q(QStandardItemModel); |
545 | QModelIndex index = q->indexFromItem(parent); |
546 | q->beginRemoveColumns(index, start, end); |
547 | } |
548 | |
549 | /*! |
550 | \internal |
551 | */ |
552 | void QStandardItemModelPrivate::rowsInserted(QStandardItem *parent, |
553 | int row, int count) |
554 | { |
555 | Q_Q(QStandardItemModel); |
556 | if (parent == root.data()) |
557 | rowHeaderItems.insert(row, count, 0); |
558 | q->endInsertRows(); |
559 | } |
560 | |
561 | /*! |
562 | \internal |
563 | */ |
564 | void QStandardItemModelPrivate::columnsInserted(QStandardItem *parent, |
565 | int column, int count) |
566 | { |
567 | Q_Q(QStandardItemModel); |
568 | if (parent == root.data()) |
569 | columnHeaderItems.insert(column, count, 0); |
570 | q->endInsertColumns(); |
571 | } |
572 | |
573 | /*! |
574 | \internal |
575 | */ |
576 | void QStandardItemModelPrivate::rowsRemoved(QStandardItem *parent, |
577 | int row, int count) |
578 | { |
579 | Q_Q(QStandardItemModel); |
580 | if (parent == root.data()) { |
581 | for (int i = row; i < row + count; ++i) { |
582 | QStandardItem *oldItem = rowHeaderItems.at(i); |
583 | if (oldItem) |
584 | oldItem->d_func()->setModel(0); |
585 | delete oldItem; |
586 | } |
587 | rowHeaderItems.remove(row, count); |
588 | } |
589 | q->endRemoveRows(); |
590 | } |
591 | |
592 | /*! |
593 | \internal |
594 | */ |
595 | void QStandardItemModelPrivate::columnsRemoved(QStandardItem *parent, |
596 | int column, int count) |
597 | { |
598 | Q_Q(QStandardItemModel); |
599 | if (parent == root.data()) { |
600 | for (int i = column; i < column + count; ++i) { |
601 | QStandardItem *oldItem = columnHeaderItems.at(i); |
602 | if (oldItem) |
603 | oldItem->d_func()->setModel(0); |
604 | delete oldItem; |
605 | } |
606 | columnHeaderItems.remove(column, count); |
607 | } |
608 | q->endRemoveColumns(); |
609 | } |
610 | |
611 | /*! |
612 | \class QStandardItem |
613 | \brief The QStandardItem class provides an item for use with the |
614 | QStandardItemModel class. |
615 | \since 4.2 |
616 | \ingroup model-view |
617 | |
618 | Items usually contain text, icons, or checkboxes. |
619 | |
620 | Each item can have its own background brush which is set with the |
621 | setBackground() function. The current background brush can be found with |
622 | background(). The text label for each item can be rendered with its own |
623 | font and brush. These are specified with the setFont() and setForeground() |
624 | functions, and read with font() and foreground(). |
625 | |
626 | By default, items are enabled, editable, selectable, checkable, and can be |
627 | used both as the source of a drag and drop operation and as a drop target. |
628 | Each item's flags can be changed by calling setFlags(). Checkable items |
629 | can be checked and unchecked with the setCheckState() function. The |
630 | corresponding checkState() function indicates whether the item is |
631 | currently checked. |
632 | |
633 | You can store application-specific data in an item by calling setData(). |
634 | |
635 | Each item can have a two-dimensional table of child items. This makes it |
636 | possible to build hierarchies of items. The typical hierarchy is the tree, |
637 | in which case the child table is a table with a single column (a list). |
638 | |
639 | The dimensions of the child table can be set with setRowCount() and |
640 | setColumnCount(). Items can be positioned in the child table with |
641 | setChild(). Get a pointer to a child item with child(). New rows and |
642 | columns of children can also be inserted with insertRow() and |
643 | insertColumn(), or appended with appendRow() and appendColumn(). When |
644 | using the append and insert functions, the dimensions of the child table |
645 | will grow as needed. |
646 | |
647 | An existing row of children can be removed with removeRow() or takeRow(); |
648 | correspondingly, a column can be removed with removeColumn() or |
649 | takeColumn(). |
650 | |
651 | An item's children can be sorted by calling sortChildren(). |
652 | |
653 | \section1 Subclassing |
654 | |
655 | When subclassing QStandardItem to provide custom items, it is possible to |
656 | define new types for them so that they can be distinguished from the base |
657 | class. The type() function should be reimplemented to return a new type |
658 | value equal to or greater than \l UserType. |
659 | |
660 | Reimplement data() and setData() if you want to perform custom handling of |
661 | data queries and/or control how an item's data is represented. |
662 | |
663 | Reimplement clone() if you want QStandardItemModel to be able to create |
664 | instances of your custom item class on demand (see |
665 | QStandardItemModel::setItemPrototype()). |
666 | |
667 | Reimplement read() and write() if you want to control how items are |
668 | represented in their serialized form. |
669 | |
670 | Reimplement \l{operator<()} if you want to control the semantics of item |
671 | comparison. \l{operator<()} determines the sorted order when sorting items |
672 | with sortChildren() or with QStandardItemModel::sort(). |
673 | |
674 | \sa QStandardItemModel, {Item View Convenience Classes}, {Model/View Programming} |
675 | */ |
676 | |
677 | /*! |
678 | \enum QStandardItem::ItemType |
679 | |
680 | This enum describes the types that are used to describe standard items. |
681 | |
682 | \value Type The default type for standard items. |
683 | \value UserType The minimum value for custom types. Values below UserType are |
684 | reserved by Qt. |
685 | |
686 | You can define new user types in QStandardItem subclasses to ensure that |
687 | custom items are treated specially; for example, when items are sorted. |
688 | |
689 | \sa type() |
690 | */ |
691 | |
692 | /*! |
693 | Constructs an item. |
694 | */ |
695 | QStandardItem::QStandardItem() |
696 | : d_ptr(new QStandardItemPrivate) |
697 | { |
698 | Q_D(QStandardItem); |
699 | d->q_ptr = this; |
700 | } |
701 | |
702 | /*! |
703 | Constructs an item with the given \a text. |
704 | */ |
705 | QStandardItem::QStandardItem(const QString &text) |
706 | : d_ptr(new QStandardItemPrivate) |
707 | { |
708 | Q_D(QStandardItem); |
709 | d->q_ptr = this; |
710 | setText(text); |
711 | } |
712 | |
713 | /*! |
714 | Constructs an item with the given \a icon and \a text. |
715 | */ |
716 | QStandardItem::QStandardItem(const QIcon &icon, const QString &text) |
717 | : d_ptr(new QStandardItemPrivate) |
718 | { |
719 | Q_D(QStandardItem); |
720 | d->q_ptr = this; |
721 | setIcon(icon); |
722 | setText(text); |
723 | } |
724 | |
725 | /*! |
726 | Constructs an item with \a rows rows and \a columns columns of child items. |
727 | */ |
728 | QStandardItem::QStandardItem(int rows, int columns) |
729 | : d_ptr(new QStandardItemPrivate) |
730 | { |
731 | Q_D(QStandardItem); |
732 | d->q_ptr = this; |
733 | setRowCount(rows); |
734 | setColumnCount(columns); |
735 | } |
736 | |
737 | /*! |
738 | \internal |
739 | */ |
740 | QStandardItem::QStandardItem(QStandardItemPrivate &dd) |
741 | : d_ptr(&dd) |
742 | { |
743 | Q_D(QStandardItem); |
744 | d->q_ptr = this; |
745 | } |
746 | |
747 | /*! |
748 | Constructs a copy of \a other. Note that model() is |
749 | not copied. |
750 | |
751 | This function is useful when reimplementing clone(). |
752 | */ |
753 | QStandardItem::QStandardItem(const QStandardItem &other) |
754 | : d_ptr(new QStandardItemPrivate) |
755 | { |
756 | Q_D(QStandardItem); |
757 | d->q_ptr = this; |
758 | operator=(other); |
759 | } |
760 | |
761 | /*! |
762 | Assigns \a other's data and flags to this item. Note that |
763 | type() and model() are not copied. |
764 | |
765 | This function is useful when reimplementing clone(). |
766 | */ |
767 | QStandardItem &QStandardItem::operator=(const QStandardItem &other) |
768 | { |
769 | Q_D(QStandardItem); |
770 | d->values = other.d_func()->values; |
771 | return *this; |
772 | } |
773 | |
774 | /*! |
775 | Destructs the item. |
776 | This causes the item's children to be destructed as well. |
777 | */ |
778 | QStandardItem::~QStandardItem() |
779 | { |
780 | } |
781 | |
782 | /*! |
783 | Returns the item's parent item, or 0 if the item has no parent. |
784 | |
785 | \sa child() |
786 | */ |
787 | QStandardItem *QStandardItem::parent() const |
788 | { |
789 | Q_D(const QStandardItem); |
790 | if (!d->model || (d->model->d_func()->root.data() != d->parent)) |
791 | return d->parent; |
792 | return 0; |
793 | } |
794 | |
795 | /*! |
796 | Sets the item's data for the given \a role to the specified \a value. |
797 | |
798 | If you subclass QStandardItem and reimplement this function, your |
799 | reimplementation should call emitDataChanged() if you do not call |
800 | the base implementation of setData(). This will ensure that e.g. |
801 | views using the model are notified of the changes. |
802 | |
803 | \note The default implementation treats Qt::EditRole and Qt::DisplayRole |
804 | as referring to the same data. |
805 | |
806 | \sa Qt::ItemDataRole, data(), setFlags() |
807 | */ |
808 | void QStandardItem::setData(const QVariant &value, int role) |
809 | { |
810 | Q_D(QStandardItem); |
811 | role = (role == Qt::EditRole) ? Qt::DisplayRole : role; |
812 | QVector<QWidgetItemData>::iterator it; |
813 | for (it = d->values.begin(); it != d->values.end(); ++it) { |
814 | if ((*it).role == role) { |
815 | if (value.isValid()) { |
816 | if ((*it).value.type() == value.type() && (*it).value == value) |
817 | return; |
818 | (*it).value = value; |
819 | } else { |
820 | d->values.erase(it); |
821 | } |
822 | if (d->model) |
823 | d->model->d_func()->itemChanged(this); |
824 | return; |
825 | } |
826 | } |
827 | d->values.append(QWidgetItemData(role, value)); |
828 | if (d->model) |
829 | d->model->d_func()->itemChanged(this); |
830 | } |
831 | |
832 | /*! |
833 | Returns the item's data for the given \a role, or an invalid |
834 | QVariant if there is no data for the role. |
835 | |
836 | \note The default implementation treats Qt::EditRole and Qt::DisplayRole |
837 | as referring to the same data. |
838 | */ |
839 | QVariant QStandardItem::data(int role) const |
840 | { |
841 | Q_D(const QStandardItem); |
842 | role = (role == Qt::EditRole) ? Qt::DisplayRole : role; |
843 | QVector<QWidgetItemData>::const_iterator it; |
844 | for (it = d->values.begin(); it != d->values.end(); ++it) { |
845 | if ((*it).role == role) |
846 | return (*it).value; |
847 | } |
848 | return QVariant(); |
849 | } |
850 | |
851 | /*! |
852 | \since 4.4 |
853 | |
854 | Causes the model associated with this item to emit a |
855 | \l{QAbstractItemModel::dataChanged()}{dataChanged}() signal for this |
856 | item. |
857 | |
858 | You normally only need to call this function if you have subclassed |
859 | QStandardItem and reimplemented data() and/or setData(). |
860 | |
861 | \sa setData() |
862 | */ |
863 | void QStandardItem::emitDataChanged() |
864 | { |
865 | Q_D(QStandardItem); |
866 | if (d->model) |
867 | d->model->d_func()->itemChanged(this); |
868 | } |
869 | |
870 | /*! |
871 | Sets the item flags for the item to \a flags. |
872 | |
873 | The item flags determine how the user can interact with the item. |
874 | This is often used to disable an item. |
875 | |
876 | \sa flags(), setData() |
877 | */ |
878 | void QStandardItem::setFlags(Qt::ItemFlags flags) |
879 | { |
880 | setData((int)flags, Qt::UserRole - 1); |
881 | } |
882 | |
883 | /*! |
884 | Returns the item flags for the item. |
885 | |
886 | The item flags determine how the user can interact with the item. |
887 | |
888 | By default, items are enabled, editable, selectable, checkable, and can be |
889 | used both as the source of a drag and drop operation and as a drop target. |
890 | |
891 | \sa setFlags() |
892 | */ |
893 | Qt::ItemFlags QStandardItem::flags() const |
894 | { |
895 | QVariant v = data(Qt::UserRole - 1); |
896 | if (!v.isValid()) |
897 | return (Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable |
898 | |Qt::ItemIsDragEnabled|Qt::ItemIsDropEnabled); |
899 | return Qt::ItemFlags(v.toInt()); |
900 | } |
901 | |
902 | /*! |
903 | \fn QString QStandardItem::text() const |
904 | |
905 | Returns the item's text. This is the text that's presented to the user |
906 | in a view. |
907 | |
908 | \sa setText() |
909 | */ |
910 | |
911 | /*! |
912 | \fn void QStandardItem::setText(const QString &text) |
913 | |
914 | Sets the item's text to the \a text specified. |
915 | |
916 | \sa text(), setFont(), setForeground() |
917 | */ |
918 | |
919 | /*! |
920 | \fn QIcon QStandardItem::icon() const |
921 | |
922 | Returns the item's icon. |
923 | |
924 | \sa setIcon(), {QAbstractItemView::iconSize}{iconSize} |
925 | */ |
926 | |
927 | /*! |
928 | \fn void QStandardItem::setIcon(const QIcon &icon) |
929 | |
930 | Sets the item's icon to the \a icon specified. |
931 | */ |
932 | |
933 | /*! |
934 | \fn QString QStandardItem::statusTip() const |
935 | |
936 | Returns the item's status tip. |
937 | |
938 | \sa setStatusTip(), toolTip(), whatsThis() |
939 | */ |
940 | |
941 | /*! |
942 | \fn void QStandardItem::setStatusTip(const QString &statusTip) |
943 | |
944 | Sets the item's status tip to the string specified by \a statusTip. |
945 | |
946 | \sa statusTip(), setToolTip(), setWhatsThis() |
947 | */ |
948 | |
949 | /*! |
950 | \fn QString QStandardItem::toolTip() const |
951 | |
952 | Returns the item's tooltip. |
953 | |
954 | \sa setToolTip(), statusTip(), whatsThis() |
955 | */ |
956 | |
957 | /*! |
958 | \fn void QStandardItem::setToolTip(const QString &toolTip) |
959 | |
960 | Sets the item's tooltip to the string specified by \a toolTip. |
961 | |
962 | \sa toolTip(), setStatusTip(), setWhatsThis() |
963 | */ |
964 | |
965 | /*! |
966 | \fn QString QStandardItem::whatsThis() const |
967 | |
968 | Returns the item's "What's This?" help. |
969 | |
970 | \sa setWhatsThis(), toolTip(), statusTip() |
971 | */ |
972 | |
973 | /*! |
974 | \fn void QStandardItem::setWhatsThis(const QString &whatsThis) |
975 | |
976 | Sets the item's "What's This?" help to the string specified by \a whatsThis. |
977 | |
978 | \sa whatsThis(), setStatusTip(), setToolTip() |
979 | */ |
980 | |
981 | /*! |
982 | \fn QFont QStandardItem::font() const |
983 | |
984 | Returns the font used to render the item's text. |
985 | |
986 | \sa setFont() |
987 | */ |
988 | |
989 | /*! |
990 | \fn void QStandardItem::setFont(const QFont &font) |
991 | |
992 | Sets the font used to display the item's text to the given \a font. |
993 | |
994 | \sa font() setText() setForeground() |
995 | */ |
996 | |
997 | /*! |
998 | \fn QBrush QStandardItem::background() const |
999 | |
1000 | Returns the brush used to render the item's background. |
1001 | |
1002 | \sa foreground() setBackground() |
1003 | */ |
1004 | |
1005 | /*! |
1006 | \fn void QStandardItem::setBackground(const QBrush &brush) |
1007 | |
1008 | Sets the item's background brush to the specified \a brush. |
1009 | |
1010 | \sa background() setForeground() |
1011 | */ |
1012 | |
1013 | /*! |
1014 | \fn QBrush QStandardItem::foreground() const |
1015 | |
1016 | Returns the brush used to render the item's foreground (e.g. text). |
1017 | |
1018 | \sa setForeground() background() |
1019 | */ |
1020 | |
1021 | /*! |
1022 | \fn void QStandardItem::setForeground(const QBrush &brush) |
1023 | |
1024 | Sets the brush used to display the item's foreground (e.g. text) to the |
1025 | given \a brush. |
1026 | |
1027 | \sa foreground() setBackground() setFont() |
1028 | */ |
1029 | |
1030 | /*! |
1031 | \fn int QStandardItem::textAlignment() const |
1032 | |
1033 | Returns the text alignment for the item's text. |
1034 | */ |
1035 | |
1036 | /*! |
1037 | \fn void QStandardItem::setTextAlignment(Qt::Alignment alignment) |
1038 | |
1039 | Sets the text alignment for the item's text to the \a alignment |
1040 | specified. |
1041 | |
1042 | \sa textAlignment() |
1043 | */ |
1044 | |
1045 | /*! |
1046 | \fn QSize QStandardItem::sizeHint() const |
1047 | |
1048 | Returns the size hint set for the item, or an invalid QSize if no |
1049 | size hint has been set. |
1050 | |
1051 | If no size hint has been set, the item delegate will compute the |
1052 | size hint based on the item data. |
1053 | |
1054 | \sa setSizeHint() |
1055 | */ |
1056 | |
1057 | /*! |
1058 | \fn void QStandardItem::setSizeHint(const QSize &size) |
1059 | |
1060 | Sets the size hint for the item to be \a size. |
1061 | If no size hint is set, the item delegate will compute the |
1062 | size hint based on the item data. |
1063 | |
1064 | \sa sizeHint() |
1065 | */ |
1066 | |
1067 | /*! |
1068 | \fn Qt::CheckState QStandardItem::checkState() const |
1069 | |
1070 | Returns the checked state of the item. |
1071 | |
1072 | \sa setCheckState(), isCheckable() |
1073 | */ |
1074 | |
1075 | /*! |
1076 | \fn void QStandardItem::setCheckState(Qt::CheckState state) |
1077 | |
1078 | Sets the check state of the item to be \a state. |
1079 | |
1080 | \sa checkState(), setCheckable() |
1081 | */ |
1082 | |
1083 | /*! |
1084 | \fn QString QStandardItem::accessibleText() const |
1085 | |
1086 | Returns the item's accessible text. |
1087 | |
1088 | The accessible text is used by assistive technologies (i.e. for users who |
1089 | cannot use conventional means of interaction). |
1090 | |
1091 | \sa setAccessibleText(), accessibleDescription() |
1092 | */ |
1093 | |
1094 | /*! |
1095 | \fn void QStandardItem::setAccessibleText(const QString &accessibleText) |
1096 | |
1097 | Sets the item's accessible text to the string specified by \a accessibleText. |
1098 | |
1099 | The accessible text is used by assistive technologies (i.e. for users who |
1100 | cannot use conventional means of interaction). |
1101 | |
1102 | \sa accessibleText(), setAccessibleDescription() |
1103 | */ |
1104 | |
1105 | /*! |
1106 | \fn QString QStandardItem::accessibleDescription() const |
1107 | |
1108 | Returns the item's accessible description. |
1109 | |
1110 | The accessible description is used by assistive technologies (i.e. for |
1111 | users who cannot use conventional means of interaction). |
1112 | |
1113 | \sa setAccessibleDescription(), accessibleText() |
1114 | */ |
1115 | |
1116 | /*! |
1117 | \fn void QStandardItem::setAccessibleDescription(const QString &accessibleDescription) |
1118 | |
1119 | Sets the item's accessible description to the string specified by \a |
1120 | accessibleDescription. |
1121 | |
1122 | The accessible description is used by assistive technologies (i.e. for |
1123 | users who cannot use conventional means of interaction). |
1124 | |
1125 | \sa accessibleDescription(), setAccessibleText() |
1126 | */ |
1127 | |
1128 | /*! |
1129 | Sets whether the item is enabled. If \a enabled is true, the item is enabled, |
1130 | meaning that the user can interact with the item; if \a enabled is false, the |
1131 | user cannot interact with the item. |
1132 | |
1133 | This flag takes precedence over the other item flags; e.g. if an item is not |
1134 | enabled, it cannot be selected by the user, even if the Qt::ItemIsSelectable |
1135 | flag has been set. |
1136 | |
1137 | \sa isEnabled(), Qt::ItemIsEnabled, setFlags() |
1138 | */ |
1139 | void QStandardItem::setEnabled(bool enabled) |
1140 | { |
1141 | Q_D(QStandardItem); |
1142 | d->changeFlags(enabled, Qt::ItemIsEnabled); |
1143 | } |
1144 | |
1145 | /*! |
1146 | \fn bool QStandardItem::isEnabled() const |
1147 | |
1148 | Returns whether the item is enabled. |
1149 | |
1150 | When an item is enabled, the user can interact with it. The possible |
1151 | types of interaction are specified by the other item flags, such as |
1152 | isEditable() and isSelectable(). |
1153 | |
1154 | The default value is true. |
1155 | |
1156 | \sa setEnabled(), flags() |
1157 | */ |
1158 | |
1159 | /*! |
1160 | Sets whether the item is editable. If \a editable is true, the item can be |
1161 | edited by the user; otherwise, the user cannot edit the item. |
1162 | |
1163 | How the user can edit items in a view is determined by the view's edit |
1164 | triggers; see QAbstractItemView::editTriggers. |
1165 | |
1166 | \sa isEditable(), setFlags() |
1167 | */ |
1168 | void QStandardItem::setEditable(bool editable) |
1169 | { |
1170 | Q_D(QStandardItem); |
1171 | d->changeFlags(editable, Qt::ItemIsEditable); |
1172 | } |
1173 | |
1174 | /*! |
1175 | \fn bool QStandardItem::isEditable() const |
1176 | |
1177 | Returns whether the item can be edited by the user. |
1178 | |
1179 | When an item is editable (and enabled), the user can edit the item by |
1180 | invoking one of the view's edit triggers; see |
1181 | QAbstractItemView::editTriggers. |
1182 | |
1183 | The default value is true. |
1184 | |
1185 | \sa setEditable(), flags() |
1186 | */ |
1187 | |
1188 | /*! |
1189 | Sets whether the item is selectable. If \a selectable is true, the item |
1190 | can be selected by the user; otherwise, the user cannot select the item. |
1191 | |
1192 | You can control the selection behavior and mode by manipulating their |
1193 | view properties; see QAbstractItemView::selectionMode and |
1194 | QAbstractItemView::selectionBehavior. |
1195 | |
1196 | \sa isSelectable(), setFlags() |
1197 | */ |
1198 | void QStandardItem::setSelectable(bool selectable) |
1199 | { |
1200 | Q_D(QStandardItem); |
1201 | d->changeFlags(selectable, Qt::ItemIsSelectable); |
1202 | } |
1203 | |
1204 | /*! |
1205 | \fn bool QStandardItem::isSelectable() const |
1206 | |
1207 | Returns whether the item is selectable by the user. |
1208 | |
1209 | The default value is true. |
1210 | |
1211 | \sa setSelectable(), flags() |
1212 | */ |
1213 | |
1214 | /*! |
1215 | Sets whether the item is user-checkable. If \a checkable is true, the |
1216 | item can be checked by the user; otherwise, the user cannot check |
1217 | the item. |
1218 | |
1219 | The item delegate will render a checkable item with a check box next to the |
1220 | item's text. |
1221 | |
1222 | \sa isCheckable(), setCheckState(), setTristate() |
1223 | */ |
1224 | void QStandardItem::setCheckable(bool checkable) |
1225 | { |
1226 | Q_D(QStandardItem); |
1227 | if (checkable && !isCheckable()) { |
1228 | // make sure there's data for the checkstate role |
1229 | if (!data(Qt::CheckStateRole).isValid()) |
1230 | setData(Qt::Unchecked, Qt::CheckStateRole); |
1231 | } |
1232 | d->changeFlags(checkable, Qt::ItemIsUserCheckable); |
1233 | } |
1234 | |
1235 | /*! |
1236 | \fn bool QStandardItem::isCheckable() const |
1237 | |
1238 | Returns whether the item is user-checkable. |
1239 | |
1240 | The default value is false. |
1241 | |
1242 | \sa setCheckable(), checkState(), isTristate() |
1243 | */ |
1244 | |
1245 | /*! |
1246 | Sets whether the item is tristate. If \a tristate is true, the |
1247 | item is checkable with three separate states; otherwise, the item |
1248 | is checkable with two states. (Note that this also requires that |
1249 | the item is checkable; see isCheckable().) |
1250 | |
1251 | \sa isTristate(), setCheckable(), setCheckState() |
1252 | */ |
1253 | void QStandardItem::setTristate(bool tristate) |
1254 | { |
1255 | Q_D(QStandardItem); |
1256 | d->changeFlags(tristate, Qt::ItemIsTristate); |
1257 | } |
1258 | |
1259 | /*! |
1260 | \fn bool QStandardItem::isTristate() const |
1261 | |
1262 | Returns whether the item is tristate; that is, if it's checkable with three |
1263 | separate states. |
1264 | |
1265 | The default value is false. |
1266 | |
1267 | \sa setTristate(), isCheckable(), checkState() |
1268 | */ |
1269 | |
1270 | #ifndef QT_NO_DRAGANDDROP |
1271 | |
1272 | /*! |
1273 | Sets whether the item is drag enabled. If \a dragEnabled is true, the item |
1274 | can be dragged by the user; otherwise, the user cannot drag the item. |
1275 | |
1276 | Note that you also need to ensure that item dragging is enabled in the view; |
1277 | see QAbstractItemView::dragEnabled. |
1278 | |
1279 | \sa isDragEnabled(), setDropEnabled(), setFlags() |
1280 | */ |
1281 | void QStandardItem::setDragEnabled(bool dragEnabled) |
1282 | { |
1283 | Q_D(QStandardItem); |
1284 | d->changeFlags(dragEnabled, Qt::ItemIsDragEnabled); |
1285 | } |
1286 | |
1287 | /*! |
1288 | \fn bool QStandardItem::isDragEnabled() const |
1289 | |
1290 | Returns whether the item is drag enabled. An item that is drag enabled can |
1291 | be dragged by the user. |
1292 | |
1293 | The default value is true. |
1294 | |
1295 | Note that item dragging must be enabled in the view for dragging to work; |
1296 | see QAbstractItemView::dragEnabled. |
1297 | |
1298 | \sa setDragEnabled(), isDropEnabled(), flags() |
1299 | */ |
1300 | |
1301 | /*! |
1302 | Sets whether the item is drop enabled. If \a dropEnabled is true, the item |
1303 | can be used as a drop target; otherwise, it cannot. |
1304 | |
1305 | Note that you also need to ensure that drops are enabled in the view; see |
1306 | QWidget::acceptDrops(); and that the model supports the desired drop actions; |
1307 | see QAbstractItemModel::supportedDropActions(). |
1308 | |
1309 | \sa isDropEnabled(), setDragEnabled(), setFlags() |
1310 | */ |
1311 | void QStandardItem::setDropEnabled(bool dropEnabled) |
1312 | { |
1313 | Q_D(QStandardItem); |
1314 | d->changeFlags(dropEnabled, Qt::ItemIsDropEnabled); |
1315 | } |
1316 | |
1317 | /*! |
1318 | \fn bool QStandardItem::isDropEnabled() const |
1319 | |
1320 | Returns whether the item is drop enabled. When an item is drop enabled, it |
1321 | can be used as a drop target. |
1322 | |
1323 | The default value is true. |
1324 | |
1325 | \sa setDropEnabled(), isDragEnabled(), flags() |
1326 | */ |
1327 | |
1328 | #endif // QT_NO_DRAGANDDROP |
1329 | |
1330 | /*! |
1331 | Returns the row where the item is located in its parent's child table, or |
1332 | -1 if the item has no parent. |
1333 | |
1334 | \sa column(), parent() |
1335 | */ |
1336 | int QStandardItem::row() const |
1337 | { |
1338 | Q_D(const QStandardItem); |
1339 | QPair<int, int> pos = d->position(); |
1340 | return pos.first; |
1341 | } |
1342 | |
1343 | /*! |
1344 | Returns the column where the item is located in its parent's child table, |
1345 | or -1 if the item has no parent. |
1346 | |
1347 | \sa row(), parent() |
1348 | */ |
1349 | int QStandardItem::column() const |
1350 | { |
1351 | Q_D(const QStandardItem); |
1352 | QPair<int, int> pos = d->position(); |
1353 | return pos.second; |
1354 | } |
1355 | |
1356 | /*! |
1357 | Returns the QModelIndex associated with this item. |
1358 | |
1359 | When you need to invoke item functionality in a QModelIndex-based API (e.g. |
1360 | QAbstractItemView), you can call this function to obtain an index that |
1361 | corresponds to the item's location in the model. |
1362 | |
1363 | If the item is not associated with a model, an invalid QModelIndex is |
1364 | returned. |
1365 | |
1366 | \sa model(), QStandardItemModel::itemFromIndex() |
1367 | */ |
1368 | QModelIndex QStandardItem::index() const |
1369 | { |
1370 | Q_D(const QStandardItem); |
1371 | return d->model ? d->model->indexFromItem(this) : QModelIndex(); |
1372 | } |
1373 | |
1374 | /*! |
1375 | Returns the QStandardItemModel that this item belongs to. |
1376 | |
1377 | If the item is not a child of another item that belongs to the model, this |
1378 | function returns 0. |
1379 | |
1380 | \sa index() |
1381 | */ |
1382 | QStandardItemModel *QStandardItem::model() const |
1383 | { |
1384 | Q_D(const QStandardItem); |
1385 | return d->model; |
1386 | } |
1387 | |
1388 | /*! |
1389 | Sets the number of child item rows to \a rows. If this is less than |
1390 | rowCount(), the data in the unwanted rows is discarded. |
1391 | |
1392 | \sa rowCount(), setColumnCount() |
1393 | */ |
1394 | void QStandardItem::setRowCount(int rows) |
1395 | { |
1396 | int rc = rowCount(); |
1397 | if (rc == rows) |
1398 | return; |
1399 | if (rc < rows) |
1400 | insertRows(qMax(rc, 0), rows - rc); |
1401 | else |
1402 | removeRows(qMax(rows, 0), rc - rows); |
1403 | } |
1404 | |
1405 | /*! |
1406 | Returns the number of child item rows that the item has. |
1407 | |
1408 | \sa setRowCount(), columnCount() |
1409 | */ |
1410 | int QStandardItem::rowCount() const |
1411 | { |
1412 | Q_D(const QStandardItem); |
1413 | return d->rowCount(); |
1414 | } |
1415 | |
1416 | /*! |
1417 | Sets the number of child item columns to \a columns. If this is less than |
1418 | columnCount(), the data in the unwanted columns is discarded. |
1419 | |
1420 | \sa columnCount(), setRowCount() |
1421 | */ |
1422 | void QStandardItem::setColumnCount(int columns) |
1423 | { |
1424 | int cc = columnCount(); |
1425 | if (cc == columns) |
1426 | return; |
1427 | if (cc < columns) |
1428 | insertColumns(qMax(cc, 0), columns - cc); |
1429 | else |
1430 | removeColumns(qMax(columns, 0), cc - columns); |
1431 | } |
1432 | |
1433 | /*! |
1434 | Returns the number of child item columns that the item has. |
1435 | |
1436 | \sa setColumnCount(), rowCount() |
1437 | */ |
1438 | int QStandardItem::columnCount() const |
1439 | { |
1440 | Q_D(const QStandardItem); |
1441 | return d->columnCount(); |
1442 | } |
1443 | |
1444 | /*! |
1445 | Inserts a row at \a row containing \a items. If necessary, the column |
1446 | count is increased to the size of \a items. |
1447 | |
1448 | \sa insertRows(), insertColumn() |
1449 | */ |
1450 | void QStandardItem::insertRow(int row, const QList<QStandardItem*> &items) |
1451 | { |
1452 | Q_D(QStandardItem); |
1453 | if (row < 0) |
1454 | return; |
1455 | if (columnCount() < items.count()) |
1456 | setColumnCount(items.count()); |
1457 | d->insertRows(row, 1, items); |
1458 | } |
1459 | |
1460 | /*! |
1461 | Inserts \a items at \a row. The column count wont be changed. |
1462 | |
1463 | \sa insertRow(), insertColumn() |
1464 | */ |
1465 | void QStandardItem::insertRows(int row, const QList<QStandardItem*> &items) |
1466 | { |
1467 | Q_D(QStandardItem); |
1468 | if (row < 0) |
1469 | return; |
1470 | d->insertRows(row, items); |
1471 | } |
1472 | |
1473 | /*! |
1474 | Inserts a column at \a column containing \a items. If necessary, |
1475 | the row count is increased to the size of \a items. |
1476 | |
1477 | \sa insertColumns(), insertRow() |
1478 | */ |
1479 | void QStandardItem::insertColumn(int column, const QList<QStandardItem*> &items) |
1480 | { |
1481 | Q_D(QStandardItem); |
1482 | if (column < 0) |
1483 | return; |
1484 | if (rowCount() < items.count()) |
1485 | setRowCount(items.count()); |
1486 | d->insertColumns(column, 1, items); |
1487 | } |
1488 | |
1489 | /*! |
1490 | Inserts \a count rows of child items at row \a row. |
1491 | |
1492 | \sa insertRow(), insertColumns() |
1493 | */ |
1494 | void QStandardItem::insertRows(int row, int count) |
1495 | { |
1496 | Q_D(QStandardItem); |
1497 | if (rowCount() < row) { |
1498 | count += row - rowCount(); |
1499 | row = rowCount(); |
1500 | } |
1501 | d->insertRows(row, count, QList<QStandardItem*>()); |
1502 | } |
1503 | |
1504 | /*! |
1505 | Inserts \a count columns of child items at column \a column. |
1506 | |
1507 | \sa insertColumn(), insertRows() |
1508 | */ |
1509 | void QStandardItem::insertColumns(int column, int count) |
1510 | { |
1511 | Q_D(QStandardItem); |
1512 | if (columnCount() < column) { |
1513 | count += column - columnCount(); |
1514 | column = columnCount(); |
1515 | } |
1516 | d->insertColumns(column, count, QList<QStandardItem*>()); |
1517 | } |
1518 | |
1519 | /*! |
1520 | \fn void QStandardItem::appendRow(const QList<QStandardItem*> &items) |
1521 | |
1522 | Appends a row containing \a items. If necessary, the column count is |
1523 | increased to the size of \a items. |
1524 | |
1525 | \sa insertRow() |
1526 | */ |
1527 | |
1528 | /*! |
1529 | \fn void QStandardItem::appendRows(const QList<QStandardItem*> &items) |
1530 | |
1531 | Appends rows containing \a items. The column count will not change. |
1532 | |
1533 | \sa insertRow() |
1534 | */ |
1535 | |
1536 | /*! |
1537 | \fn void QStandardItem::appendColumn(const QList<QStandardItem*> &items) |
1538 | |
1539 | Appends a column containing \a items. If necessary, the row count is |
1540 | increased to the size of \a items. |
1541 | |
1542 | \sa insertColumn() |
1543 | */ |
1544 | |
1545 | /*! |
1546 | \fn bool QStandardItemModel::insertRow(int row, const QModelIndex &parent) |
1547 | |
1548 | Inserts a single row before the given \a row in the child items of the |
1549 | \a parent specified. Returns true if the row is inserted; otherwise |
1550 | returns false. |
1551 | |
1552 | \sa insertRows(), insertColumn(), removeRow() |
1553 | */ |
1554 | |
1555 | /*! |
1556 | \fn bool QStandardItemModel::insertColumn(int column, const QModelIndex &parent) |
1557 | |
1558 | Inserts a single column before the given \a column in the child items of |
1559 | the \a parent specified. Returns true if the column is inserted; otherwise |
1560 | returns false. |
1561 | |
1562 | \sa insertColumns(), insertRow(), removeColumn() |
1563 | */ |
1564 | |
1565 | /*! |
1566 | \fn QStandardItem::insertRow(int row, QStandardItem *item) |
1567 | \overload |
1568 | |
1569 | Inserts a row at \a row containing \a item. |
1570 | |
1571 | When building a list or a tree that has only one column, this function |
1572 | provides a convenient way to insert a single new item. |
1573 | */ |
1574 | |
1575 | /*! |
1576 | \fn QStandardItem::appendRow(QStandardItem *item) |
1577 | \overload |
1578 | |
1579 | Appends a row containing \a item. |
1580 | |
1581 | When building a list or a tree that has only one column, this function |
1582 | provides a convenient way to append a single new item. |
1583 | */ |
1584 | |
1585 | /*! |
1586 | Removes the given \a row. The items that were in the row are deleted. |
1587 | |
1588 | \sa takeRow(), removeRows(), removeColumn() |
1589 | */ |
1590 | void QStandardItem::removeRow(int row) |
1591 | { |
1592 | removeRows(row, 1); |
1593 | } |
1594 | |
1595 | /*! |
1596 | Removes the given \a column. The items that were in the |
1597 | column are deleted. |
1598 | |
1599 | \sa takeColumn(), removeColumns(), removeRow() |
1600 | */ |
1601 | void QStandardItem::removeColumn(int column) |
1602 | { |
1603 | removeColumns(column, 1); |
1604 | } |
1605 | |
1606 | /*! |
1607 | Removes \a count rows at row \a row. The items that were in those rows are |
1608 | deleted. |
1609 | |
1610 | \sa removeRow(), removeColumn() |
1611 | */ |
1612 | void QStandardItem::removeRows(int row, int count) |
1613 | { |
1614 | Q_D(QStandardItem); |
1615 | if ((count < 1) || (row < 0) || ((row + count) > rowCount())) |
1616 | return; |
1617 | if (d->model) |
1618 | d->model->d_func()->rowsAboutToBeRemoved(this, row, row + count - 1); |
1619 | int i = d->childIndex(row, 0); |
1620 | int n = count * d->columnCount(); |
1621 | for (int j = i; j < n+i; ++j) { |
1622 | QStandardItem *oldItem = d->children.at(j); |
1623 | if (oldItem) |
1624 | oldItem->d_func()->setModel(0); |
1625 | delete oldItem; |
1626 | } |
1627 | d->children.remove(qMax(i, 0), n); |
1628 | d->rows -= count; |
1629 | if (d->model) |
1630 | d->model->d_func()->rowsRemoved(this, row, count); |
1631 | } |
1632 | |
1633 | /*! |
1634 | Removes \a count columns at column \a column. The items that were in those |
1635 | columns are deleted. |
1636 | |
1637 | \sa removeColumn(), removeRows() |
1638 | */ |
1639 | void QStandardItem::removeColumns(int column, int count) |
1640 | { |
1641 | Q_D(QStandardItem); |
1642 | if ((count < 1) || (column < 0) || ((column + count) > columnCount())) |
1643 | return; |
1644 | if (d->model) |
1645 | d->model->d_func()->columnsAboutToBeRemoved(this, column, column + count - 1); |
1646 | for (int row = d->rowCount() - 1; row >= 0; --row) { |
1647 | int i = d->childIndex(row, column); |
1648 | for (int j=i; j<i+count; ++j) { |
1649 | QStandardItem *oldItem = d->children.at(j); |
1650 | if (oldItem) |
1651 | oldItem->d_func()->setModel(0); |
1652 | delete oldItem; |
1653 | } |
1654 | d->children.remove(i, count); |
1655 | } |
1656 | d->columns -= count; |
1657 | if (d->model) |
1658 | d->model->d_func()->columnsRemoved(this, column, count); |
1659 | } |
1660 | |
1661 | /*! |
1662 | Returns true if this item has any children; otherwise returns false. |
1663 | |
1664 | \sa rowCount(), columnCount(), child() |
1665 | */ |
1666 | bool QStandardItem::hasChildren() const |
1667 | { |
1668 | return (rowCount() > 0) && (columnCount() > 0); |
1669 | } |
1670 | |
1671 | /*! |
1672 | Sets the child item at (\a row, \a column) to \a item. This item (the parent |
1673 | item) takes ownership of \a item. If necessary, the row count and column |
1674 | count are increased to fit the item. |
1675 | |
1676 | \sa child() |
1677 | */ |
1678 | void QStandardItem::setChild(int row, int column, QStandardItem *item) |
1679 | { |
1680 | Q_D(QStandardItem); |
1681 | d->setChild(row, column, item, true); |
1682 | } |
1683 | |
1684 | /*! |
1685 | \fn QStandardItem::setChild(int row, QStandardItem *item) |
1686 | \overload |
1687 | |
1688 | Sets the child at \a row to \a item. |
1689 | */ |
1690 | |
1691 | /*! |
1692 | Returns the child item at (\a row, \a column) if one has been set; otherwise |
1693 | returns 0. |
1694 | |
1695 | \sa setChild(), takeChild(), parent() |
1696 | */ |
1697 | QStandardItem *QStandardItem::child(int row, int column) const |
1698 | { |
1699 | Q_D(const QStandardItem); |
1700 | int index = d->childIndex(row, column); |
1701 | if (index == -1) |
1702 | return 0; |
1703 | return d->children.at(index); |
1704 | } |
1705 | |
1706 | /*! |
1707 | Removes the child item at (\a row, \a column) without deleting it, and returns |
1708 | a pointer to the item. If there was no child at the given location, then |
1709 | this function returns 0. |
1710 | |
1711 | Note that this function, unlike takeRow() and takeColumn(), does not affect |
1712 | the dimensions of the child table. |
1713 | |
1714 | \sa child(), takeRow(), takeColumn() |
1715 | */ |
1716 | QStandardItem *QStandardItem::takeChild(int row, int column) |
1717 | { |
1718 | Q_D(QStandardItem); |
1719 | QStandardItem *item = 0; |
1720 | int index = d->childIndex(row, column); |
1721 | if (index != -1) { |
1722 | item = d->children.at(index); |
1723 | if (item) |
1724 | item->d_func()->setParentAndModel(0, 0); |
1725 | d->children.replace(index, 0); |
1726 | } |
1727 | return item; |
1728 | } |
1729 | |
1730 | /*! |
1731 | Removes \a row without deleting the row items, and returns a list of |
1732 | pointers to the removed items. For items in the row that have not been |
1733 | set, the corresponding pointers in the list will be 0. |
1734 | |
1735 | \sa removeRow(), insertRow(), takeColumn() |
1736 | */ |
1737 | QList<QStandardItem*> QStandardItem::takeRow(int row) |
1738 | { |
1739 | Q_D(QStandardItem); |
1740 | if ((row < 0) || (row >= rowCount())) |
1741 | return QList<QStandardItem*>(); |
1742 | if (d->model) |
1743 | d->model->d_func()->rowsAboutToBeRemoved(this, row, row); |
1744 | QList<QStandardItem*> items; |
1745 | int index = d->childIndex(row, 0); // Will return -1 if there are no columns |
1746 | if (index != -1) { |
1747 | int col_count = d->columnCount(); |
1748 | for (int column = 0; column < col_count; ++column) { |
1749 | QStandardItem *ch = d->children.at(index + column); |
1750 | if (ch) |
1751 | ch->d_func()->setParentAndModel(0, 0); |
1752 | items.append(ch); |
1753 | } |
1754 | d->children.remove(index, col_count); |
1755 | } |
1756 | d->rows--; |
1757 | if (d->model) |
1758 | d->model->d_func()->rowsRemoved(this, row, 1); |
1759 | return items; |
1760 | } |
1761 | |
1762 | /*! |
1763 | Removes \a column without deleting the column items, and returns a list of |
1764 | pointers to the removed items. For items in the column that have not been |
1765 | set, the corresponding pointers in the list will be 0. |
1766 | |
1767 | \sa removeColumn(), insertColumn(), takeRow() |
1768 | */ |
1769 | QList<QStandardItem*> QStandardItem::takeColumn(int column) |
1770 | { |
1771 | Q_D(QStandardItem); |
1772 | if ((column < 0) || (column >= columnCount())) |
1773 | return QList<QStandardItem*>(); |
1774 | if (d->model) |
1775 | d->model->d_func()->columnsAboutToBeRemoved(this, column, column); |
1776 | QList<QStandardItem*> items; |
1777 | |
1778 | for (int row = d->rowCount() - 1; row >= 0; --row) { |
1779 | int index = d->childIndex(row, column); |
1780 | QStandardItem *ch = d->children.at(index); |
1781 | if (ch) |
1782 | ch->d_func()->setParentAndModel(0, 0); |
1783 | d->children.remove(index); |
1784 | items.prepend(ch); |
1785 | } |
1786 | d->columns--; |
1787 | if (d->model) |
1788 | d->model->d_func()->columnsRemoved(this, column, 1); |
1789 | return items; |
1790 | } |
1791 | |
1792 | /*! |
1793 | Returns true if this item is less than \a other; otherwise returns false. |
1794 | |
1795 | The default implementation uses the data for the item's sort role (see |
1796 | QStandardItemModel::sortRole) to perform the comparison if the item |
1797 | belongs to a model; otherwise, the data for the item's Qt::DisplayRole |
1798 | (text()) is used to perform the comparison. |
1799 | |
1800 | sortChildren() and QStandardItemModel::sort() use this function when |
1801 | sorting items. If you want custom sorting, you can subclass QStandardItem |
1802 | and reimplement this function. |
1803 | */ |
1804 | bool QStandardItem::operator<(const QStandardItem &other) const |
1805 | { |
1806 | const int role = model() ? model()->sortRole() : Qt::DisplayRole; |
1807 | const QVariant l = data(role), r = other.data(role); |
1808 | // this code is copied from QSortFilterProxyModel::lessThan() |
1809 | switch (l.userType()) { |
1810 | case QVariant::Invalid: |
1811 | return (r.type() == QVariant::Invalid); |
1812 | case QVariant::Int: |
1813 | return l.toInt() < r.toInt(); |
1814 | case QVariant::UInt: |
1815 | return l.toUInt() < r.toUInt(); |
1816 | case QVariant::LongLong: |
1817 | return l.toLongLong() < r.toLongLong(); |
1818 | case QVariant::ULongLong: |
1819 | return l.toULongLong() < r.toULongLong(); |
1820 | case QMetaType::Float: |
1821 | return l.toFloat() < r.toFloat(); |
1822 | case QVariant::Double: |
1823 | return l.toDouble() < r.toDouble(); |
1824 | case QVariant::Char: |
1825 | return l.toChar() < r.toChar(); |
1826 | case QVariant::Date: |
1827 | return l.toDate() < r.toDate(); |
1828 | case QVariant::Time: |
1829 | return l.toTime() < r.toTime(); |
1830 | case QVariant::DateTime: |
1831 | return l.toDateTime() < r.toDateTime(); |
1832 | case QVariant::String: |
1833 | default: |
1834 | return l.toString().compare(r.toString()) < 0; |
1835 | } |
1836 | } |
1837 | |
1838 | /*! |
1839 | Sorts the children of the item using the given \a order, by the values in |
1840 | the given \a column. |
1841 | |
1842 | \note This function is recursive, therefore it sorts the children of the |
1843 | item, its grandchildren, etc. |
1844 | |
1845 | \sa {operator<()} |
1846 | */ |
1847 | void QStandardItem::sortChildren(int column, Qt::SortOrder order) |
1848 | { |
1849 | Q_D(QStandardItem); |
1850 | if ((column < 0) || (rowCount() == 0)) |
1851 | return; |
1852 | if (d->model) |
1853 | emit d->model->layoutAboutToBeChanged(); |
1854 | d->sortChildren(column, order); |
1855 | if (d->model) |
1856 | emit d->model->layoutChanged(); |
1857 | } |
1858 | |
1859 | /*! |
1860 | Returns a copy of this item. The item's children are not copied. |
1861 | |
1862 | When subclassing QStandardItem, you can reimplement this function |
1863 | to provide QStandardItemModel with a factory that it can use to |
1864 | create new items on demand. |
1865 | |
1866 | \sa QStandardItemModel::setItemPrototype(), operator=() |
1867 | */ |
1868 | QStandardItem *QStandardItem::clone() const |
1869 | { |
1870 | return new QStandardItem(*this); |
1871 | } |
1872 | |
1873 | /*! |
1874 | Returns the type of this item. The type is used to distinguish custom |
1875 | items from the base class. When subclassing QStandardItem, you should |
1876 | reimplement this function and return a new value greater than or equal |
1877 | to \l UserType. |
1878 | |
1879 | \sa QStandardItem::Type |
1880 | */ |
1881 | int QStandardItem::type() const |
1882 | { |
1883 | return Type; |
1884 | } |
1885 | |
1886 | #ifndef QT_NO_DATASTREAM |
1887 | |
1888 | /*! |
1889 | Reads the item from stream \a in. Only the data and flags of the item are |
1890 | read, not the child items. |
1891 | |
1892 | \sa write() |
1893 | */ |
1894 | void QStandardItem::read(QDataStream &in) |
1895 | { |
1896 | Q_D(QStandardItem); |
1897 | in >> d->values; |
1898 | qint32 flags; |
1899 | in >> flags; |
1900 | setFlags(Qt::ItemFlags(flags)); |
1901 | } |
1902 | |
1903 | /*! |
1904 | Writes the item to stream \a out. Only the data and flags of the item |
1905 | are written, not the child items. |
1906 | |
1907 | \sa read() |
1908 | */ |
1909 | void QStandardItem::write(QDataStream &out) const |
1910 | { |
1911 | Q_D(const QStandardItem); |
1912 | out << d->values; |
1913 | out << flags(); |
1914 | } |
1915 | |
1916 | /*! |
1917 | \relates QStandardItem |
1918 | \since 4.2 |
1919 | |
1920 | Reads a QStandardItem from stream \a in into \a item. |
1921 | |
1922 | This operator uses QStandardItem::read(). |
1923 | |
1924 | \sa {Serializing Qt Data Types} |
1925 | */ |
1926 | QDataStream &operator>>(QDataStream &in, QStandardItem &item) |
1927 | { |
1928 | item.read(in); |
1929 | return in; |
1930 | } |
1931 | |
1932 | /*! |
1933 | \relates QStandardItem |
1934 | \since 4.2 |
1935 | |
1936 | Writes the QStandardItem \a item to stream \a out. |
1937 | |
1938 | This operator uses QStandardItem::write(). |
1939 | |
1940 | \sa {Serializing Qt Data Types} |
1941 | */ |
1942 | QDataStream &operator<<(QDataStream &out, const QStandardItem &item) |
1943 | { |
1944 | item.write(out); |
1945 | return out; |
1946 | } |
1947 | |
1948 | #endif // QT_NO_DATASTREAM |
1949 | |
1950 | /*! |
1951 | \class QStandardItemModel |
1952 | \brief The QStandardItemModel class provides a generic model for storing custom data. |
1953 | \ingroup model-view |
1954 | |
1955 | QStandardItemModel can be used as a repository for standard Qt |
1956 | data types. It is one of the \l {Model/View Classes} and is part |
1957 | of Qt's \l {Model/View Programming}{model/view} framework. |
1958 | |
1959 | QStandardItemModel provides a classic item-based approach to working with |
1960 | the model. The items in a QStandardItemModel are provided by |
1961 | QStandardItem. |
1962 | |
1963 | QStandardItemModel implements the QAbstractItemModel interface, which |
1964 | means that the model can be used to provide data in any view that supports |
1965 | that interface (such as QListView, QTableView and QTreeView, and your own |
1966 | custom views). For performance and flexibility, you may want to subclass |
1967 | QAbstractItemModel to provide support for different kinds of data |
1968 | repositories. For example, the QDirModel provides a model interface to the |
1969 | underlying file system. |
1970 | |
1971 | When you want a list or tree, you typically create an empty |
1972 | QStandardItemModel and use appendRow() to add items to the model, and |
1973 | item() to access an item. If your model represents a table, you typically |
1974 | pass the dimensions of the table to the QStandardItemModel constructor and |
1975 | use setItem() to position items into the table. You can also use setRowCount() |
1976 | and setColumnCount() to alter the dimensions of the model. To insert items, |
1977 | use insertRow() or insertColumn(), and to remove items, use removeRow() or |
1978 | removeColumn(). |
1979 | |
1980 | You can set the header labels of your model with setHorizontalHeaderLabels() |
1981 | and setVerticalHeaderLabels(). |
1982 | |
1983 | You can search for items in the model with findItems(), and sort the model by |
1984 | calling sort(). |
1985 | |
1986 | Call clear() to remove all items from the model. |
1987 | |
1988 | An example usage of QStandardItemModel to create a table: |
1989 | |
1990 | \snippet doc/src/snippets/code/src_gui_itemviews_qstandarditemmodel.cpp 0 |
1991 | |
1992 | An example usage of QStandardItemModel to create a tree: |
1993 | |
1994 | \snippet doc/src/snippets/code/src_gui_itemviews_qstandarditemmodel.cpp 1 |
1995 | |
1996 | After setting the model on a view, you typically want to react to user |
1997 | actions, such as an item being clicked. Since a QAbstractItemView provides |
1998 | QModelIndex-based signals and functions, you need a way to obtain the |
1999 | QStandardItem that corresponds to a given QModelIndex, and vice |
2000 | versa. itemFromIndex() and indexFromItem() provide this mapping. Typical |
2001 | usage of itemFromIndex() includes obtaining the item at the current index |
2002 | in a view, and obtaining the item that corresponds to an index carried by |
2003 | a QAbstractItemView signal, such as QAbstractItemView::clicked(). First |
2004 | you connect the view's signal to a slot in your class: |
2005 | |
2006 | \snippet doc/src/snippets/code/src_gui_itemviews_qstandarditemmodel.cpp 2 |
2007 | |
2008 | When you receive the signal, you call itemFromIndex() on the given model |
2009 | index to get a pointer to the item: |
2010 | |
2011 | \snippet doc/src/snippets/code/src_gui_itemviews_qstandarditemmodel.cpp 3 |
2012 | |
2013 | Conversely, you must obtain the QModelIndex of an item when you want to |
2014 | invoke a model/view function that takes an index as argument. You can |
2015 | obtain the index either by using the model's indexFromItem() function, or, |
2016 | equivalently, by calling QStandardItem::index(): |
2017 | |
2018 | \snippet doc/src/snippets/code/src_gui_itemviews_qstandarditemmodel.cpp 4 |
2019 | |
2020 | You are, of course, not required to use the item-based approach; you could |
2021 | instead rely entirely on the QAbstractItemModel interface when working with |
2022 | the model, or use a combination of the two as appropriate. |
2023 | |
2024 | \sa QStandardItem, {Model/View Programming}, QAbstractItemModel, |
2025 | {itemviews/simpletreemodel}{Simple Tree Model example}, |
2026 | {Item View Convenience Classes} |
2027 | */ |
2028 | |
2029 | /*! |
2030 | \fn void QStandardItemModel::itemChanged(QStandardItem *item) |
2031 | \since 4.2 |
2032 | |
2033 | This signal is emitted whenever the data of \a item has changed. |
2034 | */ |
2035 | |
2036 | /*! |
2037 | Constructs a new item model with the given \a parent. |
2038 | */ |
2039 | QStandardItemModel::QStandardItemModel(QObject *parent) |
2040 | : QAbstractItemModel(*new QStandardItemModelPrivate, parent) |
2041 | { |
2042 | Q_D(QStandardItemModel); |
2043 | d->init(); |
2044 | d->root->d_func()->setModel(this); |
2045 | } |
2046 | |
2047 | /*! |
2048 | Constructs a new item model that initially has \a rows rows and \a columns |
2049 | columns, and that has the given \a parent. |
2050 | */ |
2051 | QStandardItemModel::QStandardItemModel(int rows, int columns, QObject *parent) |
2052 | : QAbstractItemModel(*new QStandardItemModelPrivate, parent) |
2053 | { |
2054 | Q_D(QStandardItemModel); |
2055 | d->init(); |
2056 | d->root->insertColumns(0, columns); |
2057 | d->columnHeaderItems.insert(0, columns, 0); |
2058 | d->root->insertRows(0, rows); |
2059 | d->rowHeaderItems.insert(0, rows, 0); |
2060 | d->root->d_func()->setModel(this); |
2061 | } |
2062 | |
2063 | /*! |
2064 | \internal |
2065 | */ |
2066 | QStandardItemModel::QStandardItemModel(QStandardItemModelPrivate &dd, QObject *parent) |
2067 | : QAbstractItemModel(dd, parent) |
2068 | { |
2069 | Q_D(QStandardItemModel); |
2070 | d->init(); |
2071 | } |
2072 | |
2073 | /*! |
2074 | Destructs the model. The model destroys all its items. |
2075 | */ |
2076 | QStandardItemModel::~QStandardItemModel() |
2077 | { |
2078 | } |
2079 | |
2080 | /*! |
2081 | Removes all items (including header items) from the model and sets the |
2082 | number of rows and columns to zero. |
2083 | |
2084 | \sa removeColumns(), removeRows() |
2085 | */ |
2086 | void QStandardItemModel::clear() |
2087 | { |
2088 | Q_D(QStandardItemModel); |
2089 | d->root.reset(new QStandardItem); |
2090 | d->root->d_func()->setModel(this); |
2091 | qDeleteAll(d->columnHeaderItems); |
2092 | d->columnHeaderItems.clear(); |
2093 | qDeleteAll(d->rowHeaderItems); |
2094 | d->rowHeaderItems.clear(); |
2095 | reset(); |
2096 | } |
2097 | |
2098 | /*! |
2099 | \since 4.2 |
2100 | |
2101 | Returns a pointer to the QStandardItem associated with the given \a index. |
2102 | |
2103 | Calling this function is typically the initial step when processing |
2104 | QModelIndex-based signals from a view, such as |
2105 | QAbstractItemView::activated(). In your slot, you call itemFromIndex(), |
2106 | with the QModelIndex carried by the signal as argument, to obtain a |
2107 | pointer to the corresponding QStandardItem. |
2108 | |
2109 | Note that this function will lazily create an item for the index (using |
2110 | itemPrototype()), and set it in the parent item's child table, if no item |
2111 | already exists at that index. |
2112 | |
2113 | If \a index is an invalid index, this function returns 0. |
2114 | |
2115 | \sa indexFromItem() |
2116 | */ |
2117 | QStandardItem *QStandardItemModel::itemFromIndex(const QModelIndex &index) const |
2118 | { |
2119 | Q_D(const QStandardItemModel); |
2120 | if ((index.row() < 0) || (index.column() < 0) || (index.model() != this)) |
2121 | return 0; |
2122 | QStandardItem *parent = static_cast<QStandardItem*>(index.internalPointer()); |
2123 | if (parent == 0) |
2124 | return 0; |
2125 | QStandardItem *item = parent->child(index.row(), index.column()); |
2126 | // lazy part |
2127 | if (item == 0) { |
2128 | item = d->createItem(); |
2129 | parent->d_func()->setChild(index.row(), index.column(), item); |
2130 | } |
2131 | return item; |
2132 | } |
2133 | |
2134 | /*! |
2135 | \since 4.2 |
2136 | |
2137 | Returns the QModelIndex associated with the given \a item. |
2138 | |
2139 | Use this function when you want to perform an operation that requires the |
2140 | QModelIndex of the item, such as |
2141 | QAbstractItemView::scrollTo(). QStandardItem::index() is provided as |
2142 | convenience; it is equivalent to calling this function. |
2143 | |
2144 | \sa itemFromIndex(), QStandardItem::index() |
2145 | */ |
2146 | QModelIndex QStandardItemModel::indexFromItem(const QStandardItem *item) const |
2147 | { |
2148 | if (item && item->d_func()->parent) { |
2149 | QPair<int, int> pos = item->d_func()->position(); |
2150 | return createIndex(pos.first, pos.second, item->d_func()->parent); |
2151 | } |
2152 | return QModelIndex(); |
2153 | } |
2154 | |
2155 | /*! |
2156 | \since 4.2 |
2157 | |
2158 | Sets the number of rows in this model to \a rows. If |
2159 | this is less than rowCount(), the data in the unwanted rows |
2160 | is discarded. |
2161 | |
2162 | \sa setColumnCount() |
2163 | */ |
2164 | void QStandardItemModel::setRowCount(int rows) |
2165 | { |
2166 | Q_D(QStandardItemModel); |
2167 | d->root->setRowCount(rows); |
2168 | } |
2169 | |
2170 | /*! |
2171 | \since 4.2 |
2172 | |
2173 | Sets the number of columns in this model to \a columns. If |
2174 | this is less than columnCount(), the data in the unwanted columns |
2175 | is discarded. |
2176 | |
2177 | \sa setRowCount() |
2178 | */ |
2179 | void QStandardItemModel::setColumnCount(int columns) |
2180 | { |
2181 | Q_D(QStandardItemModel); |
2182 | d->root->setColumnCount(columns); |
2183 | } |
2184 | |
2185 | /*! |
2186 | \since 4.2 |
2187 | |
2188 | Sets the item for the given \a row and \a column to \a item. The model |
2189 | takes ownership of the item. If necessary, the row count and column count |
2190 | are increased to fit the item. The previous item at the given location (if |
2191 | there was one) is deleted. |
2192 | |
2193 | \sa item() |
2194 | */ |
2195 | void QStandardItemModel::setItem(int row, int column, QStandardItem *item) |
2196 | { |
2197 | Q_D(QStandardItemModel); |
2198 | d->root->d_func()->setChild(row, column, item, true); |
2199 | } |
2200 | |
2201 | /*! |
2202 | \fn QStandardItemModel::setItem(int row, QStandardItem *item) |
2203 | \overload |
2204 | */ |
2205 | |
2206 | /*! |
2207 | \since 4.2 |
2208 | |
2209 | Returns the item for the given \a row and \a column if one has been set; |
2210 | otherwise returns 0. |
2211 | |
2212 | \sa setItem(), takeItem(), itemFromIndex() |
2213 | */ |
2214 | QStandardItem *QStandardItemModel::item(int row, int column) const |
2215 | { |
2216 | Q_D(const QStandardItemModel); |
2217 | return d->root->child(row, column); |
2218 | } |
2219 | |
2220 | /*! |
2221 | \since 4.2 |
2222 | |
2223 | Returns the model's invisible root item. |
2224 | |
2225 | The invisible root item provides access to the model's top-level items |
2226 | through the QStandardItem API, making it possible to write functions that |
2227 | can treat top-level items and their children in a uniform way; for |
2228 | example, recursive functions involving a tree model. |
2229 | |
2230 | \note Calling \l{QAbstractItemModel::index()}{index()} on the QStandardItem object |
2231 | retrieved from this function is not valid. |
2232 | */ |
2233 | QStandardItem *QStandardItemModel::invisibleRootItem() const |
2234 | { |
2235 | Q_D(const QStandardItemModel); |
2236 | return d->root.data(); |
2237 | } |
2238 | |
2239 | /*! |
2240 | \since 4.2 |
2241 | |
2242 | Sets the horizontal header item for \a column to \a item. The model takes |
2243 | ownership of the item. If necessary, the column count is increased to fit |
2244 | the item. The previous header item (if there was one) is deleted. |
2245 | |
2246 | \sa horizontalHeaderItem(), setHorizontalHeaderLabels(), |
2247 | setVerticalHeaderItem() |
2248 | */ |
2249 | void QStandardItemModel::setHorizontalHeaderItem(int column, QStandardItem *item) |
2250 | { |
2251 | Q_D(QStandardItemModel); |
2252 | if (column < 0) |
2253 | return; |
2254 | if (columnCount() <= column) |
2255 | setColumnCount(column + 1); |
2256 | |
2257 | QStandardItem *oldItem = d->columnHeaderItems.at(column); |
2258 | if (item == oldItem) |
2259 | return; |
2260 | |
2261 | if (item) { |
2262 | if (item->model() == 0) { |
2263 | item->d_func()->setModel(this); |
2264 | } else { |
2265 | qWarning("QStandardItem::setHorizontalHeaderItem: Ignoring duplicate insertion of item %p" , |
2266 | item); |
2267 | return; |
2268 | } |
2269 | } |
2270 | |
2271 | if (oldItem) |
2272 | oldItem->d_func()->setModel(0); |
2273 | delete oldItem; |
2274 | |
2275 | d->columnHeaderItems.replace(column, item); |
2276 | emit headerDataChanged(Qt::Horizontal, column, column); |
2277 | } |
2278 | |
2279 | /*! |
2280 | \since 4.2 |
2281 | |
2282 | Returns the horizontal header item for \a column if one has been set; |
2283 | otherwise returns 0. |
2284 | |
2285 | \sa setHorizontalHeaderItem(), verticalHeaderItem() |
2286 | */ |
2287 | QStandardItem *QStandardItemModel::horizontalHeaderItem(int column) const |
2288 | { |
2289 | Q_D(const QStandardItemModel); |
2290 | if ((column < 0) || (column >= columnCount())) |
2291 | return 0; |
2292 | return d->columnHeaderItems.at(column); |
2293 | } |
2294 | |
2295 | /*! |
2296 | \since 4.2 |
2297 | |
2298 | Sets the vertical header item for \a row to \a item. The model takes |
2299 | ownership of the item. If necessary, the row count is increased to fit the |
2300 | item. The previous header item (if there was one) is deleted. |
2301 | |
2302 | \sa verticalHeaderItem(), setVerticalHeaderLabels(), |
2303 | setHorizontalHeaderItem() |
2304 | */ |
2305 | void QStandardItemModel::setVerticalHeaderItem(int row, QStandardItem *item) |
2306 | { |
2307 | Q_D(QStandardItemModel); |
2308 | if (row < 0) |
2309 | return; |
2310 | if (rowCount() <= row) |
2311 | setRowCount(row + 1); |
2312 | |
2313 | QStandardItem *oldItem = d->rowHeaderItems.at(row); |
2314 | if (item == oldItem) |
2315 | return; |
2316 | |
2317 | if (item) { |
2318 | if (item->model() == 0) { |
2319 | item->d_func()->setModel(this); |
2320 | } else { |
2321 | qWarning("QStandardItem::setVerticalHeaderItem: Ignoring duplicate insertion of item %p" , |
2322 | item); |
2323 | return; |
2324 | } |
2325 | } |
2326 | |
2327 | if (oldItem) |
2328 | oldItem->d_func()->setModel(0); |
2329 | delete oldItem; |
2330 | |
2331 | d->rowHeaderItems.replace(row, item); |
2332 | emit headerDataChanged(Qt::Vertical, row, row); |
2333 | } |
2334 | |
2335 | /*! |
2336 | \since 4.2 |
2337 | |
2338 | Returns the vertical header item for row \a row if one has been set; |
2339 | otherwise returns 0. |
2340 | |
2341 | \sa setVerticalHeaderItem(), horizontalHeaderItem() |
2342 | */ |
2343 | QStandardItem *QStandardItemModel::verticalHeaderItem(int row) const |
2344 | { |
2345 | Q_D(const QStandardItemModel); |
2346 | if ((row < 0) || (row >= rowCount())) |
2347 | return 0; |
2348 | return d->rowHeaderItems.at(row); |
2349 | } |
2350 | |
2351 | /*! |
2352 | \since 4.2 |
2353 | |
2354 | Sets the horizontal header labels using \a labels. If necessary, the |
2355 | column count is increased to the size of \a labels. |
2356 | |
2357 | \sa setHorizontalHeaderItem() |
2358 | */ |
2359 | void QStandardItemModel::setHorizontalHeaderLabels(const QStringList &labels) |
2360 | { |
2361 | Q_D(QStandardItemModel); |
2362 | if (columnCount() < labels.count()) |
2363 | setColumnCount(labels.count()); |
2364 | for (int i = 0; i < labels.count(); ++i) { |
2365 | QStandardItem *item = horizontalHeaderItem(i); |
2366 | if (!item) { |
2367 | item = d->createItem(); |
2368 | setHorizontalHeaderItem(i, item); |
2369 | } |
2370 | item->setText(labels.at(i)); |
2371 | } |
2372 | } |
2373 | |
2374 | /*! |
2375 | \since 4.2 |
2376 | |
2377 | Sets the vertical header labels using \a labels. If necessary, the row |
2378 | count is increased to the size of \a labels. |
2379 | |
2380 | \sa setVerticalHeaderItem() |
2381 | */ |
2382 | void QStandardItemModel::setVerticalHeaderLabels(const QStringList &labels) |
2383 | { |
2384 | Q_D(QStandardItemModel); |
2385 | if (rowCount() < labels.count()) |
2386 | setRowCount(labels.count()); |
2387 | for (int i = 0; i < labels.count(); ++i) { |
2388 | QStandardItem *item = verticalHeaderItem(i); |
2389 | if (!item) { |
2390 | item = d->createItem(); |
2391 | setVerticalHeaderItem(i, item); |
2392 | } |
2393 | item->setText(labels.at(i)); |
2394 | } |
2395 | } |
2396 | |
2397 | /*! |
2398 | \since 4.2 |
2399 | |
2400 | Sets the item prototype for the model to the specified \a item. The model |
2401 | takes ownership of the prototype. |
2402 | |
2403 | The item prototype acts as a QStandardItem factory, by relying on the |
2404 | QStandardItem::clone() function. To provide your own prototype, subclass |
2405 | QStandardItem, reimplement QStandardItem::clone() and set the prototype to |
2406 | be an instance of your custom class. Whenever QStandardItemModel needs to |
2407 | create an item on demand (for instance, when a view or item delegate calls |
2408 | setData())), the new items will be instances of your custom class. |
2409 | |
2410 | \sa itemPrototype(), QStandardItem::clone() |
2411 | */ |
2412 | void QStandardItemModel::setItemPrototype(const QStandardItem *item) |
2413 | { |
2414 | Q_D(QStandardItemModel); |
2415 | if (d->itemPrototype != item) { |
2416 | delete d->itemPrototype; |
2417 | d->itemPrototype = item; |
2418 | } |
2419 | } |
2420 | |
2421 | /*! |
2422 | \since 4.2 |
2423 | |
2424 | Returns the item prototype used by the model. The model uses the item |
2425 | prototype as an item factory when it needs to construct new items on |
2426 | demand (for instance, when a view or item delegate calls setData()). |
2427 | |
2428 | \sa setItemPrototype() |
2429 | */ |
2430 | const QStandardItem *QStandardItemModel::itemPrototype() const |
2431 | { |
2432 | Q_D(const QStandardItemModel); |
2433 | return d->itemPrototype; |
2434 | } |
2435 | |
2436 | /*! |
2437 | \since 4.2 |
2438 | |
2439 | Returns a list of items that match the given \a text, using the given \a |
2440 | flags, in the given \a column. |
2441 | */ |
2442 | QList<QStandardItem*> QStandardItemModel::findItems(const QString &text, |
2443 | Qt::MatchFlags flags, int column) const |
2444 | { |
2445 | QModelIndexList indexes = match(index(0, column, QModelIndex()), |
2446 | Qt::DisplayRole, text, -1, flags); |
2447 | QList<QStandardItem*> items; |
2448 | for (int i = 0; i < indexes.size(); ++i) |
2449 | items.append(itemFromIndex(indexes.at(i))); |
2450 | return items; |
2451 | } |
2452 | |
2453 | /*! |
2454 | \since 4.2 |
2455 | |
2456 | Appends a row containing \a items. If necessary, the column count is |
2457 | increased to the size of \a items. |
2458 | |
2459 | \sa insertRow(), appendColumn() |
2460 | */ |
2461 | void QStandardItemModel::appendRow(const QList<QStandardItem*> &items) |
2462 | { |
2463 | invisibleRootItem()->appendRow(items); |
2464 | } |
2465 | |
2466 | /*! |
2467 | \since 4.2 |
2468 | |
2469 | Appends a column containing \a items. If necessary, the row count is |
2470 | increased to the size of \a items. |
2471 | |
2472 | \sa insertColumn(), appendRow() |
2473 | */ |
2474 | void QStandardItemModel::appendColumn(const QList<QStandardItem*> &items) |
2475 | { |
2476 | invisibleRootItem()->appendColumn(items); |
2477 | } |
2478 | |
2479 | /*! |
2480 | \since 4.2 |
2481 | \fn QStandardItemModel::appendRow(QStandardItem *item) |
2482 | \overload |
2483 | |
2484 | When building a list or a tree that has only one column, this function |
2485 | provides a convenient way to append a single new \a item. |
2486 | */ |
2487 | |
2488 | /*! |
2489 | \since 4.2 |
2490 | |
2491 | Inserts a row at \a row containing \a items. If necessary, the column |
2492 | count is increased to the size of \a items. |
2493 | |
2494 | \sa takeRow(), appendRow(), insertColumn() |
2495 | */ |
2496 | void QStandardItemModel::insertRow(int row, const QList<QStandardItem*> &items) |
2497 | { |
2498 | invisibleRootItem()->insertRow(row, items); |
2499 | } |
2500 | |
2501 | /*! |
2502 | \since 4.2 |
2503 | |
2504 | \fn void QStandardItemModel::insertRow(int row, QStandardItem *item) |
2505 | \overload |
2506 | |
2507 | Inserts a row at \a row containing \a item. |
2508 | |
2509 | When building a list or a tree that has only one column, this function |
2510 | provides a convenient way to append a single new item. |
2511 | */ |
2512 | |
2513 | /*! |
2514 | \since 4.2 |
2515 | |
2516 | Inserts a column at \a column containing \a items. If necessary, the row |
2517 | count is increased to the size of \a items. |
2518 | |
2519 | \sa takeColumn(), appendColumn(), insertRow() |
2520 | */ |
2521 | void QStandardItemModel::insertColumn(int column, const QList<QStandardItem*> &items) |
2522 | { |
2523 | invisibleRootItem()->insertColumn(column, items); |
2524 | } |
2525 | |
2526 | /*! |
2527 | \since 4.2 |
2528 | |
2529 | Removes the item at (\a row, \a column) without deleting it. The model |
2530 | releases ownership of the item. |
2531 | |
2532 | \sa item(), takeRow(), takeColumn() |
2533 | */ |
2534 | QStandardItem *QStandardItemModel::takeItem(int row, int column) |
2535 | { |
2536 | Q_D(QStandardItemModel); |
2537 | return d->root->takeChild(row, column); |
2538 | } |
2539 | |
2540 | /*! |
2541 | \since 4.2 |
2542 | |
2543 | Removes the given \a row without deleting the row items, and returns a |
2544 | list of pointers to the removed items. The model releases ownership of the |
2545 | items. For items in the row that have not been set, the corresponding |
2546 | pointers in the list will be 0. |
2547 | |
2548 | \sa takeColumn() |
2549 | */ |
2550 | QList<QStandardItem*> QStandardItemModel::takeRow(int row) |
2551 | { |
2552 | Q_D(QStandardItemModel); |
2553 | return d->root->takeRow(row); |
2554 | } |
2555 | |
2556 | /*! |
2557 | \since 4.2 |
2558 | |
2559 | Removes the given \a column without deleting the column items, and returns |
2560 | a list of pointers to the removed items. The model releases ownership of |
2561 | the items. For items in the column that have not been set, the |
2562 | corresponding pointers in the list will be 0. |
2563 | |
2564 | \sa takeRow() |
2565 | */ |
2566 | QList<QStandardItem*> QStandardItemModel::takeColumn(int column) |
2567 | { |
2568 | Q_D(QStandardItemModel); |
2569 | return d->root->takeColumn(column); |
2570 | } |
2571 | |
2572 | /*! |
2573 | \since 4.2 |
2574 | |
2575 | Removes the horizontal header item at \a column from the header without |
2576 | deleting it, and returns a pointer to the item. The model releases |
2577 | ownership of the item. |
2578 | |
2579 | \sa horizontalHeaderItem(), takeVerticalHeaderItem() |
2580 | */ |
2581 | QStandardItem *QStandardItemModel::takeHorizontalHeaderItem(int column) |
2582 | { |
2583 | Q_D(QStandardItemModel); |
2584 | if ((column < 0) || (column >= columnCount())) |
2585 | return 0; |
2586 | QStandardItem * = d->columnHeaderItems.at(column); |
2587 | if (headerItem) { |
2588 | headerItem->d_func()->setParentAndModel(0, 0); |
2589 | d->columnHeaderItems.replace(column, 0); |
2590 | } |
2591 | return headerItem; |
2592 | } |
2593 | |
2594 | /*! |
2595 | \since 4.2 |
2596 | |
2597 | Removes the vertical header item at \a row from the header without |
2598 | deleting it, and returns a pointer to the item. The model releases |
2599 | ownership of the item. |
2600 | |
2601 | \sa verticalHeaderItem(), takeHorizontalHeaderItem() |
2602 | */ |
2603 | QStandardItem *QStandardItemModel::takeVerticalHeaderItem(int row) |
2604 | { |
2605 | Q_D(QStandardItemModel); |
2606 | if ((row < 0) || (row >= rowCount())) |
2607 | return 0; |
2608 | QStandardItem * = d->rowHeaderItems.at(row); |
2609 | if (headerItem) { |
2610 | headerItem->d_func()->setParentAndModel(0, 0); |
2611 | d->rowHeaderItems.replace(row, 0); |
2612 | } |
2613 | return headerItem; |
2614 | } |
2615 | |
2616 | /*! |
2617 | \since 4.2 |
2618 | \property QStandardItemModel::sortRole |
2619 | \brief the item role that is used to query the model's data when sorting items |
2620 | |
2621 | The default value is Qt::DisplayRole. |
2622 | |
2623 | \sa sort(), QStandardItem::sortChildren() |
2624 | */ |
2625 | int QStandardItemModel::sortRole() const |
2626 | { |
2627 | Q_D(const QStandardItemModel); |
2628 | return d->sortRole; |
2629 | } |
2630 | |
2631 | void QStandardItemModel::setSortRole(int role) |
2632 | { |
2633 | Q_D(QStandardItemModel); |
2634 | d->sortRole = role; |
2635 | } |
2636 | |
2637 | /*! |
2638 | \reimp |
2639 | */ |
2640 | int QStandardItemModel::columnCount(const QModelIndex &parent) const |
2641 | { |
2642 | Q_D(const QStandardItemModel); |
2643 | QStandardItem *item = d->itemFromIndex(parent); |
2644 | return item ? item->columnCount() : 0; |
2645 | } |
2646 | |
2647 | /*! |
2648 | \reimp |
2649 | */ |
2650 | QVariant QStandardItemModel::data(const QModelIndex &index, int role) const |
2651 | { |
2652 | Q_D(const QStandardItemModel); |
2653 | QStandardItem *item = d->itemFromIndex(index); |
2654 | return item ? item->data(role) : QVariant(); |
2655 | } |
2656 | |
2657 | /*! |
2658 | \reimp |
2659 | */ |
2660 | Qt::ItemFlags QStandardItemModel::flags(const QModelIndex &index) const |
2661 | { |
2662 | Q_D(const QStandardItemModel); |
2663 | if (!d->indexValid(index)) |
2664 | return d->root->flags(); |
2665 | QStandardItem *item = d->itemFromIndex(index); |
2666 | if (item) |
2667 | return item->flags(); |
2668 | return Qt::ItemIsSelectable |
2669 | |Qt::ItemIsEnabled |
2670 | |Qt::ItemIsEditable |
2671 | |Qt::ItemIsDragEnabled |
2672 | |Qt::ItemIsDropEnabled; |
2673 | } |
2674 | |
2675 | /*! |
2676 | \reimp |
2677 | */ |
2678 | bool QStandardItemModel::hasChildren(const QModelIndex &parent) const |
2679 | { |
2680 | Q_D(const QStandardItemModel); |
2681 | QStandardItem *item = d->itemFromIndex(parent); |
2682 | return item ? item->hasChildren() : false; |
2683 | } |
2684 | |
2685 | /*! |
2686 | \reimp |
2687 | */ |
2688 | QVariant QStandardItemModel::headerData(int section, Qt::Orientation orientation, int role) const |
2689 | { |
2690 | Q_D(const QStandardItemModel); |
2691 | if ((section < 0) |
2692 | || ((orientation == Qt::Horizontal) && (section >= columnCount())) |
2693 | || ((orientation == Qt::Vertical) && (section >= rowCount()))) { |
2694 | return QVariant(); |
2695 | } |
2696 | QStandardItem * = 0; |
2697 | if (orientation == Qt::Horizontal) |
2698 | headerItem = d->columnHeaderItems.at(section); |
2699 | else if (orientation == Qt::Vertical) |
2700 | headerItem = d->rowHeaderItems.at(section); |
2701 | return headerItem ? headerItem->data(role) |
2702 | : QAbstractItemModel::headerData(section, orientation, role); |
2703 | } |
2704 | |
2705 | /*! |
2706 | \reimp |
2707 | |
2708 | QStandardItemModel supports both copy and move. |
2709 | */ |
2710 | Qt::DropActions QStandardItemModel::supportedDropActions () const |
2711 | { |
2712 | return Qt::CopyAction | Qt::MoveAction; |
2713 | } |
2714 | |
2715 | /*! |
2716 | \reimp |
2717 | */ |
2718 | QModelIndex QStandardItemModel::index(int row, int column, const QModelIndex &parent) const |
2719 | { |
2720 | Q_D(const QStandardItemModel); |
2721 | QStandardItem *parentItem = d->itemFromIndex(parent); |
2722 | if ((parentItem == 0) |
2723 | || (row < 0) |
2724 | || (column < 0) |
2725 | || (row >= parentItem->rowCount()) |
2726 | || (column >= parentItem->columnCount())) { |
2727 | return QModelIndex(); |
2728 | } |
2729 | return createIndex(row, column, parentItem); |
2730 | } |
2731 | |
2732 | /*! |
2733 | \reimp |
2734 | */ |
2735 | bool QStandardItemModel::insertColumns(int column, int count, const QModelIndex &parent) |
2736 | { |
2737 | Q_D(QStandardItemModel); |
2738 | QStandardItem *item = parent.isValid() ? itemFromIndex(parent) : d->root.data(); |
2739 | if (item == 0) |
2740 | return false; |
2741 | return item->d_func()->insertColumns(column, count, QList<QStandardItem*>()); |
2742 | } |
2743 | |
2744 | /*! |
2745 | \reimp |
2746 | */ |
2747 | bool QStandardItemModel::insertRows(int row, int count, const QModelIndex &parent) |
2748 | { |
2749 | Q_D(QStandardItemModel); |
2750 | QStandardItem *item = parent.isValid() ? itemFromIndex(parent) : d->root.data(); |
2751 | if (item == 0) |
2752 | return false; |
2753 | return item->d_func()->insertRows(row, count, QList<QStandardItem*>()); |
2754 | } |
2755 | |
2756 | /*! |
2757 | \reimp |
2758 | */ |
2759 | QMap<int, QVariant> QStandardItemModel::itemData(const QModelIndex &index) const |
2760 | { |
2761 | Q_D(const QStandardItemModel); |
2762 | QStandardItem *item = d->itemFromIndex(index); |
2763 | return item ? item->d_func()->itemData() : QMap<int, QVariant>(); |
2764 | } |
2765 | |
2766 | /*! |
2767 | \reimp |
2768 | */ |
2769 | QModelIndex QStandardItemModel::parent(const QModelIndex &child) const |
2770 | { |
2771 | Q_D(const QStandardItemModel); |
2772 | if (!d->indexValid(child)) |
2773 | return QModelIndex(); |
2774 | QStandardItem *parentItem = static_cast<QStandardItem*>(child.internalPointer()); |
2775 | return indexFromItem(parentItem); |
2776 | } |
2777 | |
2778 | /*! |
2779 | \reimp |
2780 | */ |
2781 | bool QStandardItemModel::removeColumns(int column, int count, const QModelIndex &parent) |
2782 | { |
2783 | Q_D(QStandardItemModel); |
2784 | QStandardItem *item = d->itemFromIndex(parent); |
2785 | if ((item == 0) || (count < 1) || (column < 0) || ((column + count) > item->columnCount())) |
2786 | return false; |
2787 | item->removeColumns(column, count); |
2788 | return true; |
2789 | } |
2790 | |
2791 | /*! |
2792 | \reimp |
2793 | */ |
2794 | bool QStandardItemModel::removeRows(int row, int count, const QModelIndex &parent) |
2795 | { |
2796 | Q_D(QStandardItemModel); |
2797 | QStandardItem *item = d->itemFromIndex(parent); |
2798 | if ((item == 0) || (count < 1) || (row < 0) || ((row + count) > item->rowCount())) |
2799 | return false; |
2800 | item->removeRows(row, count); |
2801 | return true; |
2802 | } |
2803 | |
2804 | /*! |
2805 | \reimp |
2806 | */ |
2807 | int QStandardItemModel::rowCount(const QModelIndex &parent) const |
2808 | { |
2809 | Q_D(const QStandardItemModel); |
2810 | QStandardItem *item = d->itemFromIndex(parent); |
2811 | return item ? item->rowCount() : 0; |
2812 | } |
2813 | |
2814 | /*! |
2815 | \reimp |
2816 | */ |
2817 | bool QStandardItemModel::setData(const QModelIndex &index, const QVariant &value, int role) |
2818 | { |
2819 | if (!index.isValid()) |
2820 | return false; |
2821 | QStandardItem *item = itemFromIndex(index); |
2822 | if (item == 0) |
2823 | return false; |
2824 | item->setData(value, role); |
2825 | return true; |
2826 | } |
2827 | |
2828 | /*! |
2829 | \reimp |
2830 | */ |
2831 | bool QStandardItemModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) |
2832 | { |
2833 | Q_D(QStandardItemModel); |
2834 | if ((section < 0) |
2835 | || ((orientation == Qt::Horizontal) && (section >= columnCount())) |
2836 | || ((orientation == Qt::Vertical) && (section >= rowCount()))) { |
2837 | return false; |
2838 | } |
2839 | QStandardItem * = 0; |
2840 | if (orientation == Qt::Horizontal) { |
2841 | headerItem = d->columnHeaderItems.at(section); |
2842 | if (headerItem == 0) { |
2843 | headerItem = d->createItem(); |
2844 | headerItem->d_func()->setModel(this); |
2845 | d->columnHeaderItems.replace(section, headerItem); |
2846 | } |
2847 | } else if (orientation == Qt::Vertical) { |
2848 | headerItem = d->rowHeaderItems.at(section); |
2849 | if (headerItem == 0) { |
2850 | headerItem = d->createItem(); |
2851 | headerItem->d_func()->setModel(this); |
2852 | d->rowHeaderItems.replace(section, headerItem); |
2853 | } |
2854 | } |
2855 | if (headerItem) { |
2856 | headerItem->setData(value, role); |
2857 | return true; |
2858 | } |
2859 | return false; |
2860 | } |
2861 | |
2862 | /*! |
2863 | \reimp |
2864 | */ |
2865 | bool QStandardItemModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles) |
2866 | { |
2867 | QStandardItem *item = itemFromIndex(index); |
2868 | if (item == 0) |
2869 | return false; |
2870 | item->d_func()->setItemData(roles); |
2871 | return true; |
2872 | } |
2873 | |
2874 | /*! |
2875 | \reimp |
2876 | */ |
2877 | void QStandardItemModel::sort(int column, Qt::SortOrder order) |
2878 | { |
2879 | Q_D(QStandardItemModel); |
2880 | d->root->sortChildren(column, order); |
2881 | } |
2882 | |
2883 | /*! |
2884 | \fn QObject *QStandardItemModel::parent() const |
2885 | \internal |
2886 | */ |
2887 | |
2888 | |
2889 | /*! |
2890 | \reimp |
2891 | */ |
2892 | QStringList QStandardItemModel::mimeTypes() const |
2893 | { |
2894 | return QAbstractItemModel::mimeTypes() << QLatin1String("application/x-qstandarditemmodeldatalist" ); |
2895 | } |
2896 | |
2897 | /*! |
2898 | \reimp |
2899 | */ |
2900 | QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const |
2901 | { |
2902 | QMimeData *data = QAbstractItemModel::mimeData(indexes); |
2903 | if(!data) |
2904 | return 0; |
2905 | |
2906 | QString format = QLatin1String("application/x-qstandarditemmodeldatalist" ); |
2907 | if (!mimeTypes().contains(format)) |
2908 | return data; |
2909 | QByteArray encoded; |
2910 | QDataStream stream(&encoded, QIODevice::WriteOnly); |
2911 | |
2912 | QSet<QStandardItem*> itemsSet; |
2913 | QStack<QStandardItem*> stack; |
2914 | itemsSet.reserve(indexes.count()); |
2915 | stack.reserve(indexes.count()); |
2916 | for (int i = 0; i < indexes.count(); ++i) { |
2917 | QStandardItem *item = itemFromIndex(indexes.at(i)); |
2918 | itemsSet << item; |
2919 | stack.push(item); |
2920 | } |
2921 | |
2922 | //remove duplicates childrens |
2923 | { |
2924 | QSet<QStandardItem *> seen; |
2925 | while (!stack.isEmpty()) { |
2926 | QStandardItem *itm = stack.pop(); |
2927 | if (seen.contains(itm)) |
2928 | continue; |
2929 | seen.insert(itm); |
2930 | |
2931 | const QVector<QStandardItem*> &childList = itm->d_func()->children; |
2932 | for (int i = 0; i < childList.count(); ++i) { |
2933 | QStandardItem *chi = childList.at(i); |
2934 | if (chi) { |
2935 | QSet<QStandardItem *>::iterator it = itemsSet.find(chi); |
2936 | if (it != itemsSet.end()) { |
2937 | itemsSet.erase(it); |
2938 | } |
2939 | stack.push(chi); |
2940 | } |
2941 | } |
2942 | } |
2943 | } |
2944 | |
2945 | stack.reserve(itemsSet.count()); |
2946 | foreach (QStandardItem *item, itemsSet) { |
2947 | stack.push(item); |
2948 | } |
2949 | |
2950 | //stream everything recursively |
2951 | while (!stack.isEmpty()) { |
2952 | QStandardItem *item = stack.pop(); |
2953 | if(itemsSet.contains(item)) { //if the item is selection 'top-level', strem its position |
2954 | stream << item->row() << item->column(); |
2955 | } |
2956 | if(item) { |
2957 | stream << *item << item->columnCount() << item->d_ptr->children.count(); |
2958 | stack += item->d_ptr->children; |
2959 | } else { |
2960 | QStandardItem dummy; |
2961 | stream << dummy << 0 << 0; |
2962 | } |
2963 | } |
2964 | |
2965 | data->setData(format, encoded); |
2966 | return data; |
2967 | } |
2968 | |
2969 | |
2970 | /* \internal |
2971 | Used by QStandardItemModel::dropMimeData |
2972 | stream out an item and his children |
2973 | */ |
2974 | void QStandardItemModelPrivate::decodeDataRecursive(QDataStream &stream, QStandardItem *item) |
2975 | { |
2976 | int colCount, childCount; |
2977 | stream >> *item; |
2978 | stream >> colCount >> childCount; |
2979 | item->setColumnCount(colCount); |
2980 | |
2981 | int childPos = childCount; |
2982 | |
2983 | while(childPos > 0) { |
2984 | childPos--; |
2985 | QStandardItem *child = createItem(); |
2986 | decodeDataRecursive(stream, child); |
2987 | item->setChild( childPos / colCount, childPos % colCount, child); |
2988 | } |
2989 | } |
2990 | |
2991 | |
2992 | /*! |
2993 | \reimp |
2994 | */ |
2995 | bool QStandardItemModel::dropMimeData(const QMimeData *data, Qt::DropAction action, |
2996 | int row, int column, const QModelIndex &parent) |
2997 | { |
2998 | Q_D(QStandardItemModel); |
2999 | // check if the action is supported |
3000 | if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction)) |
3001 | return false; |
3002 | // check if the format is supported |
3003 | QString format = QLatin1String("application/x-qstandarditemmodeldatalist" ); |
3004 | if (!data->hasFormat(format)) |
3005 | return QAbstractItemModel::dropMimeData(data, action, row, column, parent); |
3006 | |
3007 | if (row > rowCount(parent)) |
3008 | row = rowCount(parent); |
3009 | if (row == -1) |
3010 | row = rowCount(parent); |
3011 | if (column == -1) |
3012 | column = 0; |
3013 | |
3014 | // decode and insert |
3015 | QByteArray encoded = data->data(format); |
3016 | QDataStream stream(&encoded, QIODevice::ReadOnly); |
3017 | |
3018 | |
3019 | //code based on QAbstractItemModel::decodeData |
3020 | // adapted to work with QStandardItem |
3021 | int top = INT_MAX; |
3022 | int left = INT_MAX; |
3023 | int bottom = 0; |
3024 | int right = 0; |
3025 | QVector<int> rows, columns; |
3026 | QVector<QStandardItem *> items; |
3027 | |
3028 | while (!stream.atEnd()) { |
3029 | int r, c; |
3030 | QStandardItem *item = d->createItem(); |
3031 | stream >> r >> c; |
3032 | d->decodeDataRecursive(stream, item); |
3033 | |
3034 | rows.append(r); |
3035 | columns.append(c); |
3036 | items.append(item); |
3037 | top = qMin(r, top); |
3038 | left = qMin(c, left); |
3039 | bottom = qMax(r, bottom); |
3040 | right = qMax(c, right); |
3041 | } |
3042 | |
3043 | // insert the dragged items into the table, use a bit array to avoid overwriting items, |
3044 | // since items from different tables can have the same row and column |
3045 | int dragRowCount = 0; |
3046 | int dragColumnCount = right - left + 1; |
3047 | |
3048 | // Compute the number of continuous rows upon insertion and modify the rows to match |
3049 | QVector<int> rowsToInsert(bottom + 1); |
3050 | for (int i = 0; i < rows.count(); ++i) |
3051 | rowsToInsert[rows.at(i)] = 1; |
3052 | for (int i = 0; i < rowsToInsert.count(); ++i) { |
3053 | if (rowsToInsert[i] == 1){ |
3054 | rowsToInsert[i] = dragRowCount; |
3055 | ++dragRowCount; |
3056 | } |
3057 | } |
3058 | for (int i = 0; i < rows.count(); ++i) |
3059 | rows[i] = top + rowsToInsert[rows[i]]; |
3060 | |
3061 | QBitArray isWrittenTo(dragRowCount * dragColumnCount); |
3062 | |
3063 | // make space in the table for the dropped data |
3064 | int colCount = columnCount(parent); |
3065 | if (colCount < dragColumnCount + column) { |
3066 | insertColumns(colCount, dragColumnCount + column - colCount, parent); |
3067 | colCount = columnCount(parent); |
3068 | } |
3069 | insertRows(row, dragRowCount, parent); |
3070 | |
3071 | row = qMax(0, row); |
3072 | column = qMax(0, column); |
3073 | |
3074 | QStandardItem *parentItem = itemFromIndex (parent); |
3075 | if (!parentItem) |
3076 | parentItem = invisibleRootItem(); |
3077 | |
3078 | QVector<QPersistentModelIndex> newIndexes(items.size()); |
3079 | // set the data in the table |
3080 | for (int j = 0; j < items.size(); ++j) { |
3081 | int relativeRow = rows.at(j) - top; |
3082 | int relativeColumn = columns.at(j) - left; |
3083 | int destinationRow = relativeRow + row; |
3084 | int destinationColumn = relativeColumn + column; |
3085 | int flat = (relativeRow * dragColumnCount) + relativeColumn; |
3086 | // if the item was already written to, or we just can't fit it in the table, create a new row |
3087 | if (destinationColumn >= colCount || isWrittenTo.testBit(flat)) { |
3088 | destinationColumn = qBound(column, destinationColumn, colCount - 1); |
3089 | destinationRow = row + dragRowCount; |
3090 | insertRows(row + dragRowCount, 1, parent); |
3091 | flat = (dragRowCount * dragColumnCount) + relativeColumn; |
3092 | isWrittenTo.resize(++dragRowCount * dragColumnCount); |
3093 | } |
3094 | if (!isWrittenTo.testBit(flat)) { |
3095 | newIndexes[j] = index(destinationRow, destinationColumn, parentItem->index()); |
3096 | isWrittenTo.setBit(flat); |
3097 | } |
3098 | } |
3099 | |
3100 | for(int k = 0; k < newIndexes.size(); k++) { |
3101 | if (newIndexes.at(k).isValid()) { |
3102 | parentItem->setChild(newIndexes.at(k).row(), newIndexes.at(k).column(), items.at(k)); |
3103 | } else { |
3104 | delete items.at(k); |
3105 | } |
3106 | } |
3107 | |
3108 | return true; |
3109 | } |
3110 | |
3111 | QT_END_NAMESPACE |
3112 | |
3113 | #include "moc_qstandarditemmodel.cpp" |
3114 | |
3115 | #endif // QT_NO_STANDARDITEMMODEL |
3116 | |