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