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

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