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