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

source code of qtbase/src/gui/itemmodels/qstandarditemmodel.cpp