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