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

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