1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qtreewidget.h"
5
6#include <qheaderview.h>
7#include <qpainter.h>
8#include <qstack.h>
9#include <qdebug.h>
10#include <private/qtreewidget_p.h>
11#include <private/qwidgetitemdata_p.h>
12#include <private/qtreewidgetitemiterator_p.h>
13
14#include <QtCore/private/qduplicatetracker_p.h>
15
16#include <algorithm>
17
18QT_BEGIN_NAMESPACE
19
20class QTreeModelLessThan
21{
22public:
23 inline bool operator()(QTreeWidgetItem *i1, QTreeWidgetItem *i2) const
24 { return *i1 < *i2; }
25};
26
27class QTreeModelGreaterThan
28{
29public:
30 inline bool operator()(QTreeWidgetItem *i1, QTreeWidgetItem *i2) const
31 { return *i2 < *i1; }
32};
33
34/*
35 \class QTreeModel
36 \brief The QTreeModel class manages the items stored in a tree view.
37
38 \ingroup model-view
39 \inmodule QtWidgets
40
41*/
42
43/*!
44 \enum QTreeWidgetItem::ChildIndicatorPolicy
45
46 \value ShowIndicator The controls for expanding and collapsing will be shown for this item even if there are no children.
47 \value DontShowIndicator The controls for expanding and collapsing will never be shown even if there are children. If the node is forced open the user will not be able to expand or collapse the item.
48 \value DontShowIndicatorWhenChildless The controls for expanding and collapsing will be shown if the item contains children.
49*/
50
51/*!
52 \fn void QTreeWidgetItem::setDisabled(bool disabled)
53
54 Disables the item if \a disabled is true; otherwise enables the item.
55
56 \sa setFlags()
57*/
58
59/*!
60 \fn bool QTreeWidgetItem::isDisabled() const
61
62 Returns \c true if the item is disabled; otherwise returns \c false.
63
64 \sa setFlags()
65*/
66
67/*!
68 \internal
69
70 Constructs a tree model with a \a parent object and the given
71 number of \a columns.
72*/
73
74QTreeModel::QTreeModel(int columns, QTreeWidget *parent)
75 : QAbstractItemModel(*new QTreeModelPrivate, parent),
76 rootItem(new QTreeWidgetItem),
77 headerItem(new QTreeWidgetItem)
78{
79 rootItem->view = parent;
80 rootItem->itemFlags = Qt::ItemIsDropEnabled;
81 headerItem->view = parent;
82 setColumnCount(columns);
83}
84
85/*!
86 \internal
87
88*/
89
90QTreeModel::QTreeModel(QTreeModelPrivate &dd, QTreeWidget *parent)
91 : QAbstractItemModel(dd, parent), rootItem(new QTreeWidgetItem), headerItem(new QTreeWidgetItem)
92{
93 rootItem->view = parent;
94 rootItem->itemFlags = Qt::ItemIsDropEnabled;
95 headerItem->view = parent;
96}
97
98/*!
99 \internal
100
101 Destroys this tree model.
102*/
103
104QTreeModel::~QTreeModel()
105{
106 clear();
107 headerItem->view = nullptr;
108 delete headerItem;
109 rootItem->view = nullptr;
110 delete rootItem;
111}
112
113/*!
114 \internal
115
116 Removes all items in the model.
117*/
118
119void QTreeModel::clear()
120{
121 SkipSorting skipSorting(this);
122 beginResetModel();
123 for (int i = 0; i < rootItem->childCount(); ++i) {
124 QTreeWidgetItem *item = rootItem->children.at(i);
125 item->par = nullptr;
126 item->view = nullptr;
127 delete item;
128 }
129 rootItem->children.clear();
130 sortPendingTimer.stop();
131 endResetModel();
132}
133
134/*!
135 \internal
136
137 Sets the number of \a columns in the tree model.
138*/
139
140void QTreeModel::setColumnCount(int columns)
141{
142 SkipSorting skipSorting(this);
143 if (columns < 0)
144 return;
145 if (!headerItem) {
146 headerItem = new QTreeWidgetItem();
147 headerItem->view = view();
148 }
149 int count = columnCount();
150 if (count == columns)
151 return;
152
153 if (columns < count) {
154 beginRemoveColumns(parent: QModelIndex(), first: columns, last: count - 1);
155 headerItem->values.resize(size: columns);
156 endRemoveColumns();
157 } else {
158 beginInsertColumns(parent: QModelIndex(), first: count, last: columns - 1);
159 headerItem->values.resize(size: columns);
160 for (int i = count; i < columns; ++i) {// insert data without emitting the dataChanged signal
161 headerItem->values[i].append(t: QWidgetItemData(Qt::DisplayRole, QString::number(i + 1)));
162 headerItem->d->display.append(t: QString::number(i + 1));
163 }
164 endInsertColumns();
165 }
166}
167
168/*!
169 \internal
170
171 Returns the tree view item corresponding to the \a index given.
172
173 \sa QModelIndex
174*/
175
176QTreeWidgetItem *QTreeModel::item(const QModelIndex &index) const
177{
178 if (!index.isValid())
179 return nullptr;
180 return static_cast<QTreeWidgetItem*>(index.internalPointer());
181}
182
183/*!
184 \internal
185
186 Returns the model index that refers to the
187 tree view \a item and \a column.
188*/
189
190QModelIndex QTreeModel::index(const QTreeWidgetItem *item, int column) const
191{
192 executePendingSort();
193
194 if (!item || (item == rootItem))
195 return QModelIndex();
196 const QTreeWidgetItem *par = item->parent();
197 QTreeWidgetItem *itm = const_cast<QTreeWidgetItem*>(item);
198 if (!par)
199 par = rootItem;
200 int row;
201 int guess = item->d->rowGuess;
202 if (guess >= 0
203 && par->children.size() > guess
204 && par->children.at(i: guess) == itm) {
205 row = guess;
206 } else {
207 row = par->children.lastIndexOf(t: itm);
208 itm->d->rowGuess = row;
209 }
210 return createIndex(arow: row, acolumn: column, adata: itm);
211}
212
213/*!
214 \internal
215 \reimp
216
217 Returns the model index with the given \a row,
218 \a column and \a parent.
219*/
220
221QModelIndex QTreeModel::index(int row, int column, const QModelIndex &parent) const
222{
223 executePendingSort();
224
225 int c = columnCount(parent);
226 if (row < 0 || column < 0 || column >= c)
227 return QModelIndex();
228
229 QTreeWidgetItem *parentItem = parent.isValid() ? item(index: parent) : rootItem;
230 if (parentItem && row < parentItem->childCount()) {
231 QTreeWidgetItem *itm = parentItem->child(index: row);
232 if (itm)
233 return createIndex(arow: row, acolumn: column, adata: itm);
234 return QModelIndex();
235 }
236
237 return QModelIndex();
238}
239
240/*!
241 \internal
242 \reimp
243
244 Returns the parent model index of the index given as
245 the \a child.
246*/
247
248QModelIndex QTreeModel::parent(const QModelIndex &child) const
249{
250 SkipSorting skipSorting(this); //The reason we don't sort here is that this might be called from a valid QPersistentModelIndex
251 //We don't want it to become suddenly invalid
252
253 if (!child.isValid())
254 return QModelIndex();
255 QTreeWidgetItem *itm = static_cast<QTreeWidgetItem *>(child.internalPointer());
256 if (!itm || itm == rootItem)
257 return QModelIndex();
258 QTreeWidgetItem *parent = itm->parent();
259 return index(item: parent, column: 0);
260}
261
262/*!
263 \internal
264 \reimp
265
266 Returns the number of rows in the \a parent model index.
267*/
268
269int QTreeModel::rowCount(const QModelIndex &parent) const
270{
271 if (!parent.isValid())
272 return rootItem->childCount();
273
274 QTreeWidgetItem *parentItem = item(index: parent);
275 if (parentItem)
276 return parentItem->childCount();
277 return 0;
278}
279
280/*!
281 \internal
282 \reimp
283
284 Returns the number of columns in the item referred to by
285 the given \a index.
286*/
287
288int QTreeModel::columnCount(const QModelIndex &index) const
289{
290 Q_UNUSED(index);
291 if (!headerItem)
292 return 0;
293 return headerItem->columnCount();
294}
295
296bool QTreeModel::hasChildren(const QModelIndex &parent) const
297{
298 if (!parent.isValid())
299 return (rootItem->childCount() > 0);
300
301 QTreeWidgetItem *itm = item(index: parent);
302 if (!itm)
303 return false;
304 switch (itm->d->policy) {
305 case QTreeWidgetItem::ShowIndicator:
306 return true;
307 case QTreeWidgetItem::DontShowIndicator:
308 return false;
309 case QTreeWidgetItem::DontShowIndicatorWhenChildless:
310 return (itm->childCount() > 0);
311 }
312 return false;
313}
314
315/*!
316 \internal
317 \reimp
318
319 Returns the data corresponding to the given model \a index
320 and \a role.
321*/
322
323QVariant QTreeModel::data(const QModelIndex &index, int role) const
324{
325 if (!index.isValid())
326 return QVariant();
327 QTreeWidgetItem *itm = item(index);
328 if (itm)
329 return itm->data(column: index.column(), role);
330 return QVariant();
331}
332
333/*!
334 \internal
335 \reimp
336
337 Sets the data for the item specified by the \a index and \a role
338 to that referred to by the \a value.
339
340 Returns \c true if successful; otherwise returns \c false.
341*/
342
343bool QTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
344{
345 if (!index.isValid())
346 return false;
347 QTreeWidgetItem *itm = item(index);
348 if (itm) {
349 itm->setData(column: index.column(), role, value);
350 return true;
351 }
352 return false;
353}
354
355bool QTreeModel::clearItemData(const QModelIndex &index)
356{
357 if (!checkIndex(index, options: CheckIndexOption::IndexIsValid))
358 return false;
359 QTreeWidgetItem *itm = item(index);
360 if (!itm)
361 return false;
362 const auto beginIter = itm->values.at(i: index.column()).cbegin();
363 const auto endIter = itm->values.at(i: index.column()).cend();
364 if (std::all_of(first: beginIter, last: endIter, pred: [](const QWidgetItemData& data) -> bool { return !data.value.isValid(); })
365 && !itm->d->display.at(i: index.column()).isValid()) {
366 return true; //it's already cleared
367 }
368 itm->d->display[index.column()] = QVariant();
369 itm->values[index.column()].clear();
370 emit dataChanged(topLeft: index, bottomRight: index, roles: QList<int> {});
371 return true;
372}
373
374QMap<int, QVariant> QTreeModel::itemData(const QModelIndex &index) const
375{
376 QMap<int, QVariant> roles;
377 QTreeWidgetItem *itm = item(index);
378 if (itm) {
379 int column = index.column();
380 if (column < itm->values.size()) {
381 for (int i = 0; i < itm->values.at(i: column).size(); ++i) {
382 roles.insert(key: itm->values.at(i: column).at(i).role,
383 value: itm->values.at(i: column).at(i).value);
384 }
385 }
386
387 // the two special cases
388 QVariant displayValue = itm->data(column, role: Qt::DisplayRole);
389 if (displayValue.isValid())
390 roles.insert(key: Qt::DisplayRole, value: displayValue);
391
392 QVariant checkValue = itm->data(column, role: Qt::CheckStateRole);
393 if (checkValue.isValid())
394 roles.insert(key: Qt::CheckStateRole, value: checkValue);
395 }
396 return roles;
397}
398
399/*!
400 \internal
401 \reimp
402*/
403bool QTreeModel::insertRows(int row, int count, const QModelIndex &parent)
404{
405 SkipSorting skipSorting(this);
406 if (count < 1 || row < 0 || row > rowCount(parent) || parent.column() > 0)
407 return false;
408
409 beginInsertRows(parent, first: row, last: row + count - 1);
410 QTreeWidgetItem *par = item(index: parent);
411 while (count > 0) {
412 QTreeWidgetItem *item = new QTreeWidgetItem();
413 item->view = view();
414 item->par = par;
415 if (par)
416 par->children.insert(i: row++, t: item);
417 else
418 rootItem->children.insert(i: row++, t: item);
419 --count;
420 }
421 endInsertRows();
422 return true;
423}
424
425/*!
426 \internal
427 \reimp
428*/
429bool QTreeModel::insertColumns(int column, int count, const QModelIndex &parent)
430{
431 SkipSorting skipSorting(this);
432 if (count < 1 || column < 0 || column > columnCount(index: parent) || parent.column() > 0 || !headerItem)
433 return false;
434
435 beginInsertColumns(parent, first: column, last: column + count - 1);
436
437 int oldCount = columnCount(index: parent);
438 column = qBound(min: 0, val: column, max: oldCount);
439 headerItem->values.resize(size: oldCount + count);
440 for (int i = oldCount; i < oldCount + count; ++i) {
441 headerItem->values[i].append(t: QWidgetItemData(Qt::DisplayRole, QString::number(i + 1)));
442 headerItem->d->display.append(t: QString::number(i + 1));
443 }
444
445 QStack<QTreeWidgetItem*> itemstack;
446 itemstack.push(t: 0);
447 while (!itemstack.isEmpty()) {
448 QTreeWidgetItem *par = itemstack.pop();
449 QList<QTreeWidgetItem*> children = par ? par->children : rootItem->children;
450 for (int row = 0; row < children.size(); ++row) {
451 QTreeWidgetItem *child = children.at(i: row);
452 if (child->children.size())
453 itemstack.push(t: child);
454 child->values.insert(i: column, n: count, t: QList<QWidgetItemData>());
455 }
456 }
457
458 endInsertColumns();
459 return true;
460}
461
462/*!
463 \internal
464 \reimp
465*/
466bool QTreeModel::removeRows(int row, int count, const QModelIndex &parent) {
467 if (count < 1 || row < 0 || (row + count) > rowCount(parent))
468 return false;
469 QTreeWidgetItem *parentItem = item(index: parent);
470 // if parentItem is valid, begin/end RemoveRows is handled by takeChild below
471 if (!parentItem)
472 beginRemoveRows(parent, first: row, last: row + count - 1);
473 for (int i = row + count - 1; i >= row; --i) {
474 QTreeWidgetItem *child = parentItem ? parentItem->takeChild(index: i) : rootItem->children.takeAt(i);
475 Q_ASSERT(child);
476 child->view = nullptr;
477 delete child;
478 }
479 if (!parentItem)
480 endRemoveRows();
481 return true;
482}
483
484/*!
485 \internal
486 \reimp
487
488 Returns the header data corresponding to the given header \a section,
489 \a orientation and data \a role.
490*/
491
492QVariant QTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
493{
494 if (orientation != Qt::Horizontal)
495 return QVariant();
496
497 if (headerItem)
498 return headerItem->data(column: section, role);
499 if (role == Qt::DisplayRole)
500 return QString::number(section + 1);
501 return QVariant();
502}
503
504/*!
505 \internal
506 \reimp
507
508 Sets the header data for the item specified by the header \a section,
509 \a orientation and data \a role to the given \a value.
510
511 Returns \c true if successful; otherwise returns \c false.
512*/
513
514bool QTreeModel::setHeaderData(int section, Qt::Orientation orientation,
515 const QVariant &value, int role)
516{
517 if (section < 0 || orientation != Qt::Horizontal || !headerItem || section >= columnCount())
518 return false;
519
520 headerItem->setData(column: section, role, value);
521 return true;
522}
523
524/*!
525 \reimp
526
527 Returns the flags for the item referred to the given \a index.
528
529*/
530
531Qt::ItemFlags QTreeModel::flags(const QModelIndex &index) const
532{
533 if (!index.isValid())
534 return rootItem->flags();
535 QTreeWidgetItem *itm = item(index);
536 Q_ASSERT(itm);
537 return itm->flags();
538}
539
540/*!
541 \internal
542
543 Sorts the entire tree in the model in the given \a order,
544 by the values in the given \a column.
545*/
546
547void QTreeModel::sort(int column, Qt::SortOrder order)
548{
549 SkipSorting skipSorting(this);
550 sortPendingTimer.stop();
551
552 if (column < 0 || column >= columnCount())
553 return;
554
555 //layoutAboutToBeChanged and layoutChanged will be called by sortChildren
556 rootItem->sortChildren(column, order, climb: true);
557}
558
559/*!
560 \internal
561*/
562void QTreeModel::ensureSorted(int column, Qt::SortOrder order,
563 int start, int end, const QModelIndex &parent)
564{
565 if (isChanging())
566 return;
567
568 sortPendingTimer.stop();
569
570 if (column < 0 || column >= columnCount())
571 return;
572
573 SkipSorting skipSorting(this);
574
575 QTreeWidgetItem *itm = item(index: parent);
576 if (!itm)
577 itm = rootItem;
578 QList<QTreeWidgetItem*> lst = itm->children;
579
580 int count = end - start + 1;
581 QList<std::pair<QTreeWidgetItem *, int>> sorting(count);
582 for (int i = 0; i < count; ++i) {
583 sorting[i].first = lst.at(i: start + i);
584 sorting[i].second = start + i;
585 }
586
587 const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
588 std::stable_sort(first: sorting.begin(), last: sorting.end(), comp: compare);
589
590 QModelIndexList oldPersistentIndexes;
591 QModelIndexList newPersistentIndexes;
592 QList<QTreeWidgetItem*>::iterator lit = lst.begin();
593 bool changed = false;
594
595 for (int i = 0; i < count; ++i) {
596 int oldRow = sorting.at(i).second;
597
598 int tmpitepos = lit - lst.begin();
599 QTreeWidgetItem *item = lst.takeAt(i: oldRow);
600 if (tmpitepos > lst.size())
601 --tmpitepos;
602 lit = lst.begin() + tmpitepos;
603
604 lit = sortedInsertionIterator(begin: lit, end: lst.end(), order, item);
605 int newRow = qMax<qsizetype>(a: lit - lst.begin(), b: 0);
606
607 if ((newRow < oldRow) && !(*item < *lst.at(i: oldRow - 1)) && !(*lst.at(i: oldRow - 1) < *item ))
608 newRow = oldRow;
609
610 lit = lst.insert(before: lit, t: item);
611 if (newRow != oldRow) {
612 // we are going to change the persistent indexes, so we need to prepare
613 if (!changed) { // this will only happen once
614 changed = true;
615 emit layoutAboutToBeChanged(parents: {parent}, hint: QAbstractItemModel::VerticalSortHint); // the selection model needs to know
616 oldPersistentIndexes = persistentIndexList();
617 newPersistentIndexes = oldPersistentIndexes;
618 }
619 for (int j = i + 1; j < count; ++j) {
620 int otherRow = sorting.at(i: j).second;
621 if (oldRow < otherRow && newRow >= otherRow)
622 --sorting[j].second;
623 else if (oldRow > otherRow && newRow <= otherRow)
624 ++sorting[j].second;
625 }
626 for (int k = 0; k < newPersistentIndexes.size(); ++k) {
627 QModelIndex pi = newPersistentIndexes.at(i: k);
628 if (pi.parent() != parent)
629 continue;
630 int oldPersistentRow = pi.row();
631 int newPersistentRow = oldPersistentRow;
632 if (oldPersistentRow == oldRow)
633 newPersistentRow = newRow;
634 else if (oldRow < oldPersistentRow && newRow >= oldPersistentRow)
635 newPersistentRow = oldPersistentRow - 1;
636 else if (oldRow > oldPersistentRow && newRow <= oldPersistentRow)
637 newPersistentRow = oldPersistentRow + 1;
638 if (newPersistentRow != oldPersistentRow)
639 newPersistentIndexes[k] = createIndex(arow: newPersistentRow,
640 acolumn: pi.column(), adata: pi.internalPointer());
641 }
642 }
643 }
644
645 if (changed) {
646 itm->children = lst;
647 changePersistentIndexList(from: oldPersistentIndexes, to: newPersistentIndexes);
648 emit layoutChanged(parents: {parent}, hint: QAbstractItemModel::VerticalSortHint);
649 }
650}
651
652/*!
653 \internal
654
655 Returns \c true if the value of the \a left item is
656 less than the value of the \a right item.
657
658 Used by the sorting functions.
659*/
660
661bool QTreeModel::itemLessThan(const std::pair<QTreeWidgetItem*,int> &left,
662 const std::pair<QTreeWidgetItem*,int> &right)
663{
664 return *(left.first) < *(right.first);
665}
666
667/*!
668 \internal
669
670 Returns \c true if the value of the \a left item is
671 greater than the value of the \a right item.
672
673 Used by the sorting functions.
674*/
675
676bool QTreeModel::itemGreaterThan(const std::pair<QTreeWidgetItem*,int> &left,
677 const std::pair<QTreeWidgetItem*,int> &right)
678{
679 return *(right.first) < *(left.first);
680}
681
682/*!
683 \internal
684*/
685QList<QTreeWidgetItem*>::iterator QTreeModel::sortedInsertionIterator(
686 const QList<QTreeWidgetItem*>::iterator &begin,
687 const QList<QTreeWidgetItem*>::iterator &end,
688 Qt::SortOrder order, QTreeWidgetItem *item)
689{
690 if (order == Qt::AscendingOrder)
691 return std::lower_bound(first: begin, last: end, val: item, comp: QTreeModelLessThan());
692 return std::lower_bound(first: begin, last: end, val: item, comp: QTreeModelGreaterThan());
693}
694
695QStringList QTreeModel::mimeTypes() const
696{
697 auto v = view();
698 if (v)
699 return v->mimeTypes();
700 return {};
701}
702
703QMimeData *QTreeModel::internalMimeData() const
704{
705 return QAbstractItemModel::mimeData(indexes: cachedIndexes);
706}
707
708QMimeData *QTreeModel::mimeData(const QModelIndexList &indexes) const
709{
710 QList<QTreeWidgetItem *> items;
711 std::transform(first: indexes.begin(), last: indexes.end(), result: std::back_inserter(x&: items),
712 unary_op: [this](const QModelIndex &idx) -> QTreeWidgetItem * { return item(index: idx); });
713
714 // Ensure we only have one item as an item may have more than
715 // one index selected if there is more than one column
716 std::sort(first: items.begin(), last: items.end());
717 items.erase(abegin: std::unique(first: items.begin(), last: items.end()), aend: items.end());
718
719 // cachedIndexes is a little hack to avoid copying from QModelIndexList to
720 // QList<QTreeWidgetItem*> and back again in the view
721 cachedIndexes = indexes;
722 QMimeData *mimeData = view()->mimeData(items);
723 cachedIndexes.clear();
724 return mimeData;
725}
726
727bool QTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
728 int row, int column, const QModelIndex &parent)
729{
730 if (row == -1 && column == -1)
731 row = rowCount(parent); // append
732 return view()->dropMimeData(parent: item(index: parent), index: row, data, action);
733}
734
735Qt::DropActions QTreeModel::supportedDropActions() const
736{
737 return view()->supportedDropActions();
738}
739
740Qt::DropActions QTreeModel::supportedDragActions() const
741{
742#if QT_CONFIG(draganddrop)
743 return view()->supportedDragActions();
744#else
745 return Qt::DropActions(Qt::IgnoreAction);
746#endif
747}
748
749void QTreeModel::itemChanged(QTreeWidgetItem *item)
750{
751 if (item->columnCount() <= 0)
752 return;
753 SkipSorting skipSorting(this); //this is kind of wrong, but not doing this would kill performance
754 QModelIndex left = index(item, column: 0);
755 QModelIndex right = index(item, column: item->columnCount() - 1);
756 emit dataChanged(topLeft: left, bottomRight: right);
757}
758
759bool QTreeModel::isChanging() const
760{
761 Q_D(const QTreeModel);
762 return !d->changes.isEmpty();
763}
764
765/*!
766 \internal
767 Emits the dataChanged() signal for the given \a item.
768 if column is -1 then all columns have changed
769*/
770
771void QTreeModel::emitDataChanged(QTreeWidgetItem *item, int column, const QList<int> &roles)
772{
773 if (signalsBlocked())
774 return;
775
776 if (headerItem == item && column < item->columnCount()) {
777 if (column == -1)
778 emit headerDataChanged(orientation: Qt::Horizontal, first: 0, last: columnCount() - 1);
779 else
780 emit headerDataChanged(orientation: Qt::Horizontal, first: column, last: column);
781 return;
782 }
783
784 SkipSorting skipSorting(this); //This is a little bit wrong, but not doing it would kill performance
785
786 QModelIndex bottomRight, topLeft;
787 if (column == -1) {
788 topLeft = index(item, column: 0);
789 bottomRight = createIndex(arow: topLeft.row(), acolumn: columnCount() - 1, adata: item);
790 } else {
791 topLeft = index(item, column);
792 bottomRight = topLeft;
793 }
794 emit dataChanged(topLeft, bottomRight, roles);
795}
796
797void QTreeModel::beginInsertItems(QTreeWidgetItem *parent, int row, int count)
798{
799 QModelIndex par = index(item: parent, column: 0);
800 beginInsertRows(parent: par, first: row, last: row + count - 1);
801}
802
803void QTreeModel::endInsertItems()
804{
805 endInsertRows();
806}
807
808void QTreeModel::beginRemoveItems(QTreeWidgetItem *parent, int row, int count)
809{
810 Q_ASSERT(row >= 0);
811 Q_ASSERT(count > 0);
812 beginRemoveRows(parent: index(item: parent, column: 0), first: row, last: row + count - 1);
813 if (!parent)
814 parent = rootItem;
815 // now update the iterators
816 for (int i = 0; i < iterators.size(); ++i) {
817 for (int j = 0; j < count; j++) {
818 QTreeWidgetItem *c = parent->child(index: row + j);
819 iterators[i]->d_func()->ensureValidIterator(itemToBeRemoved: c);
820 }
821 }
822}
823
824void QTreeModel::endRemoveItems()
825{
826 endRemoveRows();
827}
828
829void QTreeModel::sortItems(QList<QTreeWidgetItem*> *items, int column, Qt::SortOrder order)
830{
831 // see QTreeViewItem::operator<
832 Q_UNUSED(column);
833 if (isChanging())
834 return;
835
836 // store the original order of indexes
837 QList<std::pair<QTreeWidgetItem *, int>> sorting(items->size());
838 for (int i = 0; i < sorting.size(); ++i) {
839 sorting[i].first = items->at(i);
840 sorting[i].second = i;
841 }
842
843 // do the sorting
844 const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
845 std::stable_sort(first: sorting.begin(), last: sorting.end(), comp: compare);
846
847 QModelIndexList fromList;
848 QModelIndexList toList;
849 int colCount = columnCount();
850 for (int r = 0; r < sorting.size(); ++r) {
851 int oldRow = sorting.at(i: r).second;
852 if (oldRow == r)
853 continue;
854 QTreeWidgetItem *item = sorting.at(i: r).first;
855 items->replace(i: r, t: item);
856 for (int c = 0; c < colCount; ++c) {
857 QModelIndex from = createIndex(arow: oldRow, acolumn: c, adata: item);
858 if (static_cast<QAbstractItemModelPrivate *>(d_ptr.data())->persistent.indexes.contains(key: from)) {
859 QModelIndex to = createIndex(arow: r, acolumn: c, adata: item);
860 fromList << from;
861 toList << to;
862 }
863 }
864 }
865 changePersistentIndexList(from: fromList, to: toList);
866}
867
868void QTreeModel::timerEvent(QTimerEvent *ev)
869{
870 if (ev->timerId() == sortPendingTimer.timerId()) {
871 executePendingSort();
872 } else {
873 QAbstractItemModel::timerEvent(event: ev);
874 }
875}
876
877/*!
878 \class QTreeWidgetItem
879
880 \brief The QTreeWidgetItem class provides an item for use with the
881 QTreeWidget convenience class.
882
883 \ingroup model-view
884 \inmodule QtWidgets
885
886 Tree widget items are used to hold rows of information for tree widgets.
887 Rows usually contain several columns of data, each of which can contain
888 a text label and an icon.
889
890 The QTreeWidgetItem class is a convenience class that replaces the
891 QListViewItem class in Qt 3. It provides an item for use with
892 the QTreeWidget class.
893
894 Items are usually constructed with a parent that is either a QTreeWidget
895 (for top-level items) or a QTreeWidgetItem (for items on lower levels of
896 the tree). For example, the following code constructs a top-level item
897 to represent cities of the world, and adds a entry for Oslo as a child
898 item:
899
900 \snippet qtreewidget-using/mainwindow.cpp 3
901
902 Items can be added in a particular order by specifying the item they
903 follow when they are constructed:
904
905 \snippet qtreewidget-using/mainwindow.cpp 5
906
907 Each column in an item can have its own background brush which is set with
908 the setBackground() function. The current background brush can be
909 found with background().
910 The text label for each column can be rendered with its own font and brush.
911 These are specified with the setFont() and setForeground() functions,
912 and read with font() and foreground().
913
914 The main difference between top-level items and those in lower levels of
915 the tree is that a top-level item has no parent(). This information
916 can be used to tell the difference between items, and is useful to know
917 when inserting and removing items from the tree.
918 Children of an item can be removed with takeChild() and inserted at a
919 given index in the list of children with the insertChild() function.
920
921 By default, items are enabled, selectable, checkable, and can be the source
922 of a drag and drop operation.
923 Each item's flags can be changed by calling setFlags() with the appropriate
924 value (see \l{Qt::ItemFlags}). Checkable items can be checked and unchecked
925 with the setCheckState() function. The corresponding checkState() function
926 indicates whether the item is currently checked.
927
928 \section1 Subclassing
929
930 When subclassing QTreeWidgetItem to provide custom items, it is possible to
931 define new types for them so that they can be distinguished from standard
932 items. The constructors for subclasses that require this feature need to
933 call the base class constructor with a new type value equal to or greater
934 than \l UserType.
935
936 \sa QTreeWidget, QTreeWidgetItemIterator, {Model/View Programming},
937 QListWidgetItem, QTableWidgetItem
938*/
939
940/*!
941 \enum QTreeWidgetItem::ItemType
942
943 This enum describes the types that are used to describe tree widget items.
944
945 \value Type The default type for tree widget items.
946 \value UserType The minimum value for custom types. Values below UserType are
947 reserved by Qt.
948
949 You can define new user types in QTreeWidgetItem subclasses to ensure that
950 custom items are treated specially; for example, when items are sorted.
951
952 \sa type()
953*/
954
955/*!
956 \fn int QTreeWidgetItem::type() const
957
958 Returns the type passed to the QTreeWidgetItem constructor.
959*/
960
961/*!
962 \fn void QTreeWidgetItem::sortChildren(int column, Qt::SortOrder order)
963
964 Sorts the children of the item using the given \a order,
965 by the values in the given \a column.
966
967 \note This function does nothing if the item is not associated with a
968 QTreeWidget.
969*/
970
971/*!
972 \fn QTreeWidget *QTreeWidgetItem::treeWidget() const
973
974 Returns the tree widget that contains the item.
975*/
976
977/*!
978 \fn void QTreeWidgetItem::setSelected(bool select)
979
980 Sets the selected state of the item to \a select.
981
982 \sa isSelected()
983*/
984void QTreeWidgetItem::setSelected(bool select)
985{
986 const QTreeModel *model = treeModel();
987 if (!model || !view->selectionModel())
988 return;
989 const QModelIndex index = model->index(item: this, column: 0);
990 view->selectionModel()->select(index, command: (select ? QItemSelectionModel::Select
991 : QItemSelectionModel::Deselect)
992 | QItemSelectionModel::Rows);
993 d->selected = select;
994}
995
996/*!
997 \fn bool QTreeWidgetItem::isSelected() const
998
999 Returns \c true if the item is selected, otherwise returns \c false.
1000
1001 \sa setSelected()
1002*/
1003bool QTreeWidgetItem::isSelected() const
1004{
1005 return d->selected;
1006}
1007
1008/*!
1009 \fn void QTreeWidgetItem::setHidden(bool hide)
1010
1011 Hides the item if \a hide is true, otherwise shows the item.
1012 \note A call to this function has no effect if the item is not currently in a view. In particular,
1013 calling \c setHidden(true) on an item and only then adding it to a view will result in
1014 a visible item.
1015
1016 \sa isHidden()
1017*/
1018
1019void QTreeWidgetItem::setHidden(bool hide)
1020{
1021 const QTreeModel *model = treeModel();
1022 if (!model)
1023 return;
1024 if (this == model->headerItem) {
1025 view->header()->setHidden(hide);
1026 } else {
1027 const QModelIndex index = view->d_func()->index(item: this);
1028 view->setRowHidden(row: index.row(), parent: index.parent(), hide);
1029 }
1030 d->hidden = hide;
1031}
1032
1033/*!
1034 \fn bool QTreeWidgetItem::isHidden() const
1035
1036 Returns \c true if the item is hidden, otherwise returns \c false.
1037
1038 \sa setHidden()
1039*/
1040
1041bool QTreeWidgetItem::isHidden() const
1042{
1043 const QTreeModel *model = treeModel();
1044 if (!model)
1045 return false;
1046 if (this == model->headerItem)
1047 return view->header()->isHidden();
1048 if (view->d_func()->hiddenIndexes.isEmpty())
1049 return false;
1050 QTreeModel::SkipSorting skipSorting(model);
1051 return view->d_func()->isRowHidden(idx: view->d_func()->index(item: this));
1052}
1053
1054/*!
1055 \fn void QTreeWidgetItem::setExpanded(bool expand)
1056
1057 Expands the item if \a expand is true, otherwise collapses the item.
1058 \warning The QTreeWidgetItem must be added to the QTreeWidget before calling this function.
1059
1060 \sa isExpanded()
1061*/
1062void QTreeWidgetItem::setExpanded(bool expand)
1063{
1064 const QTreeModel *model = treeModel();
1065 if (!model)
1066 return;
1067 QTreeModel::SkipSorting skipSorting(model);
1068 view->setExpanded(index: view->d_func()->index(item: this), expand);
1069}
1070
1071/*!
1072 \fn bool QTreeWidgetItem::isExpanded() const
1073
1074 Returns \c true if the item is expanded, otherwise returns \c false.
1075
1076 \sa setExpanded()
1077*/
1078bool QTreeWidgetItem::isExpanded() const
1079{
1080 const QTreeModel *model = treeModel();
1081 if (!model)
1082 return false;
1083 QTreeModel::SkipSorting skipSorting(model);
1084 return view->isExpanded(index: view->d_func()->index(item: this));
1085}
1086
1087/*!
1088 \fn void QTreeWidgetItem::setFirstColumnSpanned(bool span)
1089
1090 Sets the first section to span all columns if \a span is true;
1091 otherwise all item sections are shown.
1092
1093 \sa isFirstColumnSpanned()
1094*/
1095void QTreeWidgetItem::setFirstColumnSpanned(bool span)
1096{
1097 const QTreeModel *model = treeModel();
1098 if (!model || this == model->headerItem)
1099 return; // We can't set the header items to spanning
1100 const QModelIndex index = model->index(item: this, column: 0);
1101 view->setFirstColumnSpanned(row: index.row(), parent: index.parent(), span);
1102}
1103
1104/*!
1105 \fn bool QTreeWidgetItem::isFirstColumnSpanned() const
1106
1107 Returns \c true if the item is spanning all the columns in a row; otherwise returns \c false.
1108
1109 \sa setFirstColumnSpanned()
1110*/
1111bool QTreeWidgetItem::isFirstColumnSpanned() const
1112{
1113 const QTreeModel *model = treeModel();
1114 if (!model || this == model->headerItem)
1115 return false;
1116 const QModelIndex index = model->index(item: this, column: 0);
1117 return view->isFirstColumnSpanned(row: index.row(), parent: index.parent());
1118}
1119
1120/*!
1121 \fn QString QTreeWidgetItem::text(int column) const
1122
1123 Returns the text in the specified \a column.
1124
1125 \sa setText()
1126*/
1127
1128/*!
1129 \fn void QTreeWidgetItem::setText(int column, const QString &text)
1130
1131 Sets the text to be displayed in the given \a column to the given \a text.
1132
1133 \sa text(), setFont(), setForeground()
1134*/
1135
1136/*!
1137 \fn QIcon QTreeWidgetItem::icon(int column) const
1138
1139 Returns the icon that is displayed in the specified \a column.
1140
1141 \sa setIcon(), {QAbstractItemView::iconSize}{iconSize}
1142*/
1143
1144/*!
1145 \fn void QTreeWidgetItem::setIcon(int column, const QIcon &icon)
1146
1147 Sets the icon to be displayed in the given \a column to \a icon.
1148
1149 \sa icon(), setText(), {QAbstractItemView::iconSize}{iconSize}
1150*/
1151
1152/*!
1153 \fn QString QTreeWidgetItem::statusTip(int column) const
1154
1155 Returns the status tip for the contents of the given \a column.
1156
1157 \sa setStatusTip()
1158*/
1159
1160/*!
1161 \fn void QTreeWidgetItem::setStatusTip(int column, const QString &statusTip)
1162
1163 Sets the status tip for the given \a column to the given \a statusTip.
1164 QTreeWidget mouse tracking needs to be enabled for this feature to work.
1165
1166 \sa statusTip(), setToolTip(), setWhatsThis()
1167*/
1168
1169/*!
1170 \fn QString QTreeWidgetItem::toolTip(int column) const
1171
1172 Returns the tool tip for the given \a column.
1173
1174 \sa setToolTip()
1175*/
1176
1177/*!
1178 \fn void QTreeWidgetItem::setToolTip(int column, const QString &toolTip)
1179
1180 Sets the tooltip for the given \a column to \a toolTip.
1181
1182 \sa toolTip(), setStatusTip(), setWhatsThis()
1183*/
1184
1185/*!
1186 \fn QString QTreeWidgetItem::whatsThis(int column) const
1187
1188 Returns the "What's This?" help for the contents of the given \a column.
1189
1190 \sa setWhatsThis()
1191*/
1192
1193/*!
1194 \fn void QTreeWidgetItem::setWhatsThis(int column, const QString &whatsThis)
1195
1196 Sets the "What's This?" help for the given \a column to \a whatsThis.
1197
1198 \sa whatsThis(), setStatusTip(), setToolTip()
1199*/
1200
1201/*!
1202 \fn QFont QTreeWidgetItem::font(int column) const
1203
1204 Returns the font used to render the text in the specified \a column.
1205
1206 \sa setFont()
1207*/
1208
1209/*!
1210 \fn void QTreeWidgetItem::setFont(int column, const QFont &font)
1211
1212 Sets the font used to display the text in the given \a column to the given
1213 \a font.
1214
1215 \sa font(), setText(), setForeground()
1216*/
1217
1218/*!
1219 \fn QBrush QTreeWidgetItem::background(int column) const
1220
1221 Returns the brush used to render the background of the specified \a column.
1222
1223 \sa foreground()
1224*/
1225
1226/*!
1227 \fn void QTreeWidgetItem::setBackground(int column, const QBrush &brush)
1228
1229 Sets the background brush of the label in the given \a column to the
1230 specified \a brush.
1231 Setting a default-constructed brush will let the view use the
1232 default color from the style.
1233
1234 \note If \l{Qt Style Sheets} are used on the same widget as setBackground(),
1235 style sheets will take precedence if the settings conflict.
1236
1237 \sa setForeground()
1238*/
1239
1240
1241/*!
1242 \fn QBrush QTreeWidgetItem::foreground(int column) const
1243
1244 Returns the brush used to render the foreground (e.g. text) of the
1245 specified \a column.
1246 Setting a default-constructed brush will let the view use the
1247 default color from the style.
1248
1249 \sa background()
1250*/
1251
1252/*!
1253 \fn void QTreeWidgetItem::setForeground(int column, const QBrush &brush)
1254
1255 Sets the foreground brush of the label in the given \a column to the
1256 specified \a brush.
1257
1258 \sa setBackground()
1259*/
1260
1261/*!
1262 \fn Qt::CheckState QTreeWidgetItem::checkState(int column) const
1263
1264 Returns the check state of the label in the given \a column.
1265
1266 \sa Qt::CheckState
1267*/
1268
1269/*!
1270 \fn void QTreeWidgetItem::setCheckState(int column, Qt::CheckState state)
1271
1272 Sets the item in the given \a column check state to be \a state.
1273
1274 \sa checkState()
1275*/
1276
1277/*!
1278 \fn QSize QTreeWidgetItem::sizeHint(int column) const
1279
1280 Returns the size hint set for the tree item in the given
1281 \a column (see \l{QSize}).
1282*/
1283
1284/*!
1285 \fn void QTreeWidgetItem::setSizeHint(int column, const QSize &size)
1286
1287 Sets the size hint for the tree item in the given \a column to be \a size.
1288 If no size hint is set or \a size is invalid, the item
1289 delegate will compute the size hint based on the item data.
1290*/
1291
1292/*!
1293 \fn QTreeWidgetItem *QTreeWidgetItem::parent() const
1294
1295 Returns the item's parent.
1296
1297 \sa child()
1298*/
1299
1300/*!
1301 \fn QTreeWidgetItem *QTreeWidgetItem::child(int index) const
1302
1303 Returns the item at the given \a index in the list of the item's children.
1304
1305 \sa parent()
1306*/
1307
1308/*!
1309 \fn int QTreeWidgetItem::childCount() const
1310
1311 Returns the number of child items.
1312*/
1313
1314/*!
1315 \fn int QTreeWidgetItem::columnCount() const
1316
1317 Returns the number of columns in the item.
1318*/
1319
1320/*!
1321 \if defined(qt7)
1322
1323 \fn Qt::Alignment QTreeWidgetItem::textAlignment(int column) const
1324
1325 Returns the text alignment for the label in the given \a column.
1326
1327 \else
1328
1329 \fn int QTreeWidgetItem::textAlignment(int column) const
1330
1331 Returns the text alignment for the label in the given \a column.
1332
1333 \note This function returns an int for historical reasons. It will
1334 be corrected to return Qt::Alignment in Qt 7.
1335
1336 \sa Qt::Alignment
1337
1338 \endif
1339*/
1340
1341/*!
1342 \obsolete [6.4] Use the overload that takes a Qt::Alignment argument.
1343
1344 \fn void QTreeWidgetItem::setTextAlignment(int column, int alignment)
1345
1346 Sets the text alignment for the label in the given \a column to
1347 the \a alignment specified.
1348
1349 \sa Qt::Alignment
1350*/
1351
1352/*!
1353 \since 6.4
1354
1355 \fn void QTreeWidgetItem::setTextAlignment(int column, Qt::Alignment alignment)
1356
1357 Sets the text alignment for the label in the given \a column to
1358 the \a alignment specified.
1359*/
1360
1361/*!
1362 \fn void QTreeWidgetItem::setTextAlignment(int column, Qt::AlignmentFlag alignment)
1363 \internal
1364*/
1365
1366/*!
1367 \fn int QTreeWidgetItem::indexOfChild(QTreeWidgetItem *child) const
1368
1369 Returns the index of the given \a child in the item's list of children.
1370*/
1371
1372/*!
1373 Constructs a tree widget item of the specified \a type. The item
1374 must be inserted into a tree widget.
1375
1376 \sa type()
1377*/
1378QTreeWidgetItem::QTreeWidgetItem(int type) : rtti(type), d(new QTreeWidgetItemPrivate(this)) { }
1379
1380/*!
1381 Constructs a tree widget item of the specified \a type. The item
1382 must be inserted into a tree widget.
1383 The given list of \a strings will be set as the item text for each
1384 column in the item.
1385
1386 \sa type()
1387*/
1388QTreeWidgetItem::QTreeWidgetItem(const QStringList &strings, int type)
1389 : rtti(type), d(new QTreeWidgetItemPrivate(this))
1390{
1391 for (int i = 0; i < strings.size(); ++i)
1392 setText(column: i, atext: strings.at(i));
1393}
1394
1395/*!
1396 \fn QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *parent, int type)
1397
1398 Constructs a tree widget item of the specified \a type and appends it
1399 to the items in the given \a parent.
1400
1401 \sa type()
1402*/
1403
1404QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *treeview, int type)
1405 : rtti(type), d(new QTreeWidgetItemPrivate(this))
1406{
1407 // do not set this->view here otherwise insertChild() will fail
1408 if (QTreeModel *model = treeModel(v: treeview)) {
1409 model->rootItem->addChild(child: this);
1410 values.reserve(asize: model->headerItem->columnCount());
1411 }
1412}
1413
1414/*!
1415 \fn QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *parent, const QStringList &strings, int type)
1416
1417 Constructs a tree widget item of the specified \a type and appends it
1418 to the items in the given \a parent. The given list of \a strings will be set as
1419 the item text for each column in the item.
1420
1421 \sa type()
1422*/
1423
1424QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *treeview, const QStringList &strings, int type)
1425 : rtti(type), d(new QTreeWidgetItemPrivate(this))
1426{
1427 for (int i = 0; i < strings.size(); ++i)
1428 setText(column: i, atext: strings.at(i));
1429 // do not set this->view here otherwise insertChild() will fail
1430 if (QTreeModel *model = treeModel(v: treeview)) {
1431 model->rootItem->addChild(child: this);
1432 values.reserve(asize: model->headerItem->columnCount());
1433 }
1434}
1435
1436/*!
1437 \fn QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *parent, QTreeWidgetItem *preceding, int type)
1438
1439 Constructs a tree widget item of the specified \a type and inserts it into
1440 the given \a parent after the \a preceding item.
1441
1442 \sa type()
1443*/
1444QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *treeview, QTreeWidgetItem *after, int type)
1445 : rtti(type), d(new QTreeWidgetItemPrivate(this))
1446{
1447 // do not set this->view here otherwise insertChild() will fail
1448 if (QTreeModel *model = treeModel(v: treeview)) {
1449 int i = model->rootItem->children.indexOf(t: after) + 1;
1450 model->rootItem->insertChild(index: i, child: this);
1451 values.reserve(asize: model->headerItem->columnCount());
1452 }
1453}
1454
1455/*!
1456 Constructs a tree widget item and append it to the given \a parent.
1457
1458 \sa type()
1459*/
1460QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, int type)
1461 : rtti(type), d(new QTreeWidgetItemPrivate(this))
1462{
1463 if (parent)
1464 parent->addChild(child: this);
1465}
1466
1467/*!
1468 Constructs a tree widget item and append it to the given \a parent.
1469 The given list of \a strings will be set as the item text for each column in the item.
1470
1471 \sa type()
1472*/
1473QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, const QStringList &strings, int type)
1474 : rtti(type), d(new QTreeWidgetItemPrivate(this))
1475{
1476 for (int i = 0; i < strings.size(); ++i)
1477 setText(column: i, atext: strings.at(i));
1478 if (parent)
1479 parent->addChild(child: this);
1480}
1481
1482/*!
1483 \fn QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, QTreeWidgetItem *preceding, int type)
1484
1485 Constructs a tree widget item of the specified \a type that is inserted
1486 into the \a parent after the \a preceding child item.
1487
1488 \sa type()
1489*/
1490QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, QTreeWidgetItem *after, int type)
1491 : rtti(type), d(new QTreeWidgetItemPrivate(this))
1492{
1493 if (parent) {
1494 int i = parent->children.indexOf(t: after) + 1;
1495 parent->insertChild(index: i, child: this);
1496 }
1497}
1498
1499/*!
1500 Destroys this tree widget item.
1501
1502 The item will be removed from \l{QTreeWidget}s to which it has
1503 been added. This makes it safe to delete an item at any time.
1504
1505*/
1506
1507QTreeWidgetItem::~QTreeWidgetItem()
1508{
1509 QTreeModel *model = treeModel();
1510 QTreeModel::SkipSorting skipSorting(model);
1511
1512 if (par) {
1513 int i = par->children.indexOf(t: this);
1514 if (i >= 0) {
1515 if (model) model->beginRemoveItems(parent: par, row: i, count: 1);
1516 // users _could_ do changes when connected to rowsAboutToBeRemoved,
1517 // so we check again to make sure 'i' is valid
1518 if (!par->children.isEmpty() && par->children.at(i) == this)
1519 par->children.takeAt(i);
1520 if (model) model->endRemoveItems();
1521 }
1522 } else if (model) {
1523 if (this == model->headerItem) {
1524 model->headerItem = nullptr;
1525 } else {
1526 int i = model->rootItem->children.indexOf(t: this);
1527 if (i >= 0) {
1528 model->beginRemoveItems(parent: nullptr, row: i, count: 1);
1529 // users _could_ do changes when connected to rowsAboutToBeRemoved,
1530 // so we check again to make sure 'i' is valid
1531 if (!model->rootItem->children.isEmpty() && model->rootItem->children.at(i) == this)
1532 model->rootItem->children.takeAt(i);
1533 model->endRemoveItems();
1534 }
1535 }
1536 }
1537 // at this point the persistent indexes for the children should also be invalidated
1538 // since we invalidated the parent
1539 for (int i = 0; i < children.size(); ++i) {
1540 QTreeWidgetItem *child = children.at(i);
1541 // make sure the child does not try to remove itself from our children list
1542 child->par = nullptr;
1543 // make sure the child does not try to remove itself from the top level list
1544 child->view = nullptr;
1545 delete child;
1546 }
1547
1548 children.clear();
1549 delete d;
1550}
1551
1552/*!
1553 Creates a deep copy of the item and of its children.
1554*/
1555QTreeWidgetItem *QTreeWidgetItem::clone() const
1556{
1557 QTreeWidgetItem *copy = nullptr;
1558
1559 QStack<const QTreeWidgetItem*> stack;
1560 QStack<QTreeWidgetItem*> parentStack;
1561 stack.push(t: this);
1562 parentStack.push(t: 0);
1563
1564 QTreeWidgetItem *root = nullptr;
1565 const QTreeWidgetItem *item = nullptr;
1566 QTreeWidgetItem *parent = nullptr;
1567 while (!stack.isEmpty()) {
1568 // get current item, and copied parent
1569 item = stack.pop();
1570 parent = parentStack.pop();
1571
1572 // copy item
1573 copy = new QTreeWidgetItem(*item);
1574 if (!root)
1575 root = copy;
1576
1577 // set parent and add to parents children list
1578 if (parent) {
1579 copy->par = parent;
1580 parent->children.insert(i: 0, t: copy);
1581 }
1582
1583 for (int i = 0; i < item->childCount(); ++i) {
1584 stack.push(t: item->child(index: i));
1585 parentStack.push(t: copy);
1586 }
1587 }
1588 return root;
1589}
1590
1591/*!
1592 Sets the item indicator \a policy. This policy decides when the
1593 tree branch expand/collapse indicator is shown.
1594 The default value is DontShowIndicatorWhenChildless.
1595
1596 \sa childIndicatorPolicy()
1597*/
1598void QTreeWidgetItem::setChildIndicatorPolicy(QTreeWidgetItem::ChildIndicatorPolicy policy)
1599{
1600 if (d->policy == policy)
1601 return;
1602 d->policy = policy;
1603
1604 if (!view)
1605 return;
1606
1607 view->scheduleDelayedItemsLayout();
1608}
1609
1610/*!
1611 Returns the item indicator policy. This policy decides when the
1612 tree branch expand/collapse indicator is shown.
1613
1614 \sa setChildIndicatorPolicy()
1615*/
1616QTreeWidgetItem::ChildIndicatorPolicy QTreeWidgetItem::childIndicatorPolicy() const
1617{
1618 return d->policy;
1619}
1620
1621/*!
1622 \fn void QTreeWidgetItem::setFlags(Qt::ItemFlags flags)
1623
1624 Sets the flags for the item to the given \a flags. These determine whether
1625 the item can be selected or modified. This is often used to disable an item.
1626
1627 \sa flags()
1628*/
1629void QTreeWidgetItem::setFlags(Qt::ItemFlags flags)
1630{
1631 const bool enable = (flags & Qt::ItemIsEnabled);
1632 const bool changedState = bool(itemFlags & Qt::ItemIsEnabled) != enable;
1633 const bool changedExplicit = d->disabled != !enable;
1634
1635 d->disabled = !enable;
1636
1637 if (enable && par && !(par->itemFlags & Qt::ItemIsEnabled)) // inherit from parent
1638 itemFlags = flags & ~Qt::ItemIsEnabled;
1639 else // this item is explicitly disabled or has no parent
1640 itemFlags = flags;
1641
1642 if (changedState && changedExplicit) { // if the propagate the change to the children
1643 QStack<QTreeWidgetItem*> parents;
1644 parents.push(t: this);
1645 while (!parents.isEmpty()) {
1646 QTreeWidgetItem *parent = parents.pop();
1647 for (int i = 0; i < parent->children.size(); ++i) {
1648 QTreeWidgetItem *child = parent->children.at(i);
1649 if (!child->d->disabled) { // if not explicitly disabled
1650 parents.push(t: child);
1651 if (enable)
1652 child->itemFlags = child->itemFlags | Qt::ItemIsEnabled;
1653 else
1654 child->itemFlags = child->itemFlags & ~Qt::ItemIsEnabled;
1655 child->itemChanged(); // ### we may want to optimize this
1656 }
1657 }
1658 }
1659 }
1660 itemChanged();
1661}
1662
1663void QTreeWidgetItemPrivate::updateHiddenStatus(QTreeWidgetItem *item, bool inserting)
1664{
1665 QTreeModel *model = item->treeModel();
1666 if (!model)
1667 return;
1668 QStack<QTreeWidgetItem *> parents;
1669 parents.push(t: item);
1670 while (!parents.isEmpty()) {
1671 QTreeWidgetItem *parent = parents.pop();
1672 if (parent->d->hidden) {
1673 const QModelIndex index = model->index(item: parent, column: 0);
1674 item->view->setRowHidden(row: index.row(), parent: index.parent(), hide: inserting);
1675 }
1676 for (int i = 0; i < parent->children.size(); ++i) {
1677 QTreeWidgetItem *child = parent->children.at(i);
1678 parents.push(t: child);
1679 }
1680 }
1681}
1682
1683void QTreeWidgetItemPrivate::propagateDisabled(QTreeWidgetItem *item)
1684{
1685 Q_ASSERT(item);
1686 const bool enable = item->par ? (item->par->itemFlags.testFlag(flag: Qt::ItemIsEnabled)) : true;
1687
1688 QStack<QTreeWidgetItem*> parents;
1689 parents.push(t: item);
1690 while (!parents.isEmpty()) {
1691 QTreeWidgetItem *parent = parents.pop();
1692 if (!parent->d->disabled) { // if not explicitly disabled
1693 Qt::ItemFlags oldFlags = parent->itemFlags;
1694 if (enable)
1695 parent->itemFlags = parent->itemFlags | Qt::ItemIsEnabled;
1696 else
1697 parent->itemFlags = parent->itemFlags & ~Qt::ItemIsEnabled;
1698 if (parent->itemFlags != oldFlags)
1699 parent->itemChanged();
1700 }
1701
1702 for (int i = 0; i < parent->children.size(); ++i) {
1703 QTreeWidgetItem *child = parent->children.at(i);
1704 parents.push(t: child);
1705 }
1706 }
1707}
1708/*!
1709 \fn Qt::ItemFlags QTreeWidgetItem::flags() const
1710
1711 Returns the flags used to describe the item. These determine whether
1712 the item can be checked, edited, and selected.
1713
1714 The default value for flags is
1715 Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled |
1716 Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled.
1717
1718 \sa setFlags()
1719*/
1720Qt::ItemFlags QTreeWidgetItem::flags() const
1721{
1722 return itemFlags;
1723}
1724
1725/*!
1726 Sets the value for the item's \a column and \a role to the given
1727 \a value.
1728
1729 The \a role describes the type of data specified by \a value, and is defined by
1730 the Qt::ItemDataRole enum.
1731
1732 \note The default implementation treats Qt::EditRole and Qt::DisplayRole as
1733 referring to the same data.
1734*/
1735void QTreeWidgetItem::setData(int column, int role, const QVariant &value)
1736{
1737 if (column < 0)
1738 return;
1739
1740 QTreeModel *model = treeModel();
1741 switch (role) {
1742 case Qt::EditRole:
1743 case Qt::DisplayRole: {
1744 if (values.size() <= column) {
1745 if (model && this == model->headerItem)
1746 model->setColumnCount(column + 1);
1747 else
1748 values.resize(size: column + 1);
1749 }
1750 if (d->display.size() <= column) {
1751 for (int i = d->display.size() - 1; i < column - 1; ++i)
1752 d->display.append(t: QVariant());
1753 d->display.append(t: value);
1754 } else if (d->display[column] != value) {
1755 d->display[column] = value;
1756 } else {
1757 return; // value is unchanged
1758 }
1759 } break;
1760 case Qt::CheckStateRole:
1761 if ((itemFlags & Qt::ItemIsAutoTristate) && value != Qt::PartiallyChecked) {
1762 for (int i = 0; i < children.size(); ++i) {
1763 QTreeWidgetItem *child = children.at(i);
1764 if (child->data(column, role).isValid()) {// has a CheckState
1765 Qt::ItemFlags f = itemFlags; // a little hack to avoid multiple dataChanged signals
1766 itemFlags &= ~Qt::ItemIsAutoTristate;
1767 child->setData(column, role, value);
1768 itemFlags = f;
1769 }
1770 }
1771 }
1772 Q_FALLTHROUGH();
1773 default:
1774 if (column < values.size()) {
1775 bool found = false;
1776 const QList<QWidgetItemData> column_values = values.at(i: column);
1777 for (int i = 0; i < column_values.size(); ++i) {
1778 if (column_values.at(i).role == role) {
1779 if (column_values.at(i).value == value)
1780 return; // value is unchanged
1781 values[column][i].value = value;
1782 found = true;
1783 break;
1784 }
1785 }
1786 if (!found)
1787 values[column].append(t: QWidgetItemData(role, value));
1788 } else {
1789 if (model && this == model->headerItem)
1790 model->setColumnCount(column + 1);
1791 else
1792 values.resize(size: column + 1);
1793 values[column].append(t: QWidgetItemData(role, value));
1794 }
1795 }
1796
1797 if (model) {
1798 const QList<int> roles((role == Qt::DisplayRole || role == Qt::EditRole)
1799 ? QList<int>({ Qt::DisplayRole, Qt::EditRole })
1800 : QList<int>({ role }));
1801 model->emitDataChanged(item: this, column, roles);
1802 if (role == Qt::CheckStateRole) {
1803 QTreeWidgetItem *p;
1804 for (p = par; p && (p->itemFlags & Qt::ItemIsAutoTristate); p = p->par)
1805 model->emitDataChanged(item: p, column, roles);
1806 }
1807 }
1808}
1809
1810/*!
1811 Returns the value for the item's \a column and \a role.
1812*/
1813QVariant QTreeWidgetItem::data(int column, int role) const
1814{
1815 switch (role) {
1816 case Qt::EditRole:
1817 case Qt::DisplayRole:
1818 if (column >= 0 && column < d->display.size())
1819 return d->display.at(i: column);
1820 break;
1821 case Qt::CheckStateRole:
1822 // special case for check state in tristate
1823 if (children.size() && (itemFlags & Qt::ItemIsAutoTristate))
1824 return childrenCheckState(column);
1825 Q_FALLTHROUGH();
1826 default:
1827 if (column >= 0 && column < values.size()) {
1828 const QList<QWidgetItemData> &column_values = values.at(i: column);
1829 for (const auto &column_value : column_values) {
1830 if (column_value.role == role)
1831 return column_value.value;
1832 }
1833 }
1834 }
1835 return QVariant();
1836}
1837
1838/*!
1839 Returns \c true if the text in the item is less than the text in the
1840 \a other item, otherwise returns \c false.
1841*/
1842
1843bool QTreeWidgetItem::operator<(const QTreeWidgetItem &other) const
1844{
1845 int column = view ? view->sortColumn() : 0;
1846 const QVariant v1 = data(column, role: Qt::DisplayRole);
1847 const QVariant v2 = other.data(column, role: Qt::DisplayRole);
1848 return QAbstractItemModelPrivate::variantLessThan(v1, v2);
1849}
1850
1851#ifndef QT_NO_DATASTREAM
1852
1853/*!
1854 Reads the item from stream \a in. This only reads data into a single item.
1855
1856 \sa write()
1857*/
1858void QTreeWidgetItem::read(QDataStream &in)
1859{
1860 // convert from streams written before we introduced display (4.2.0)
1861 if (in.version() < QDataStream::Qt_4_2) {
1862 d->display.clear();
1863 in >> values;
1864 // move the display value over to the display string list
1865 for (int column = 0; column < values.size(); ++column) {
1866 d->display << QVariant();
1867 for (int i = 0; i < values.at(i: column).size(); ++i) {
1868 if (values.at(i: column).at(i).role == Qt::DisplayRole) {
1869 d->display[column] = values.at(i: column).at(i).value;
1870 values[column].remove(i: i--);
1871 }
1872 }
1873 }
1874 } else {
1875 in >> values >> d->display;
1876 }
1877}
1878
1879/*!
1880 Writes the item to stream \a out. This only writes data from one single item.
1881
1882 \sa read()
1883*/
1884void QTreeWidgetItem::write(QDataStream &out) const
1885{
1886 out << values << d->display;
1887}
1888#endif // QT_NO_DATASTREAM
1889
1890/*!
1891 Constructs a copy of \a other. Note that type() and treeWidget()
1892 are not copied.
1893
1894 This function is useful when reimplementing clone().
1895
1896 \sa data(), flags()
1897*/
1898QTreeWidgetItem::QTreeWidgetItem(const QTreeWidgetItem &other)
1899 : rtti(Type),
1900 values(other.values),
1901 d(new QTreeWidgetItemPrivate(this)),
1902 itemFlags(other.itemFlags)
1903{
1904 d->display = other.d->display;
1905}
1906
1907/*!
1908 Assigns \a other's data and flags to this item. Note that type()
1909 and treeWidget() are not copied.
1910
1911 This function is useful when reimplementing clone().
1912
1913 \sa data(), flags()
1914*/
1915QTreeWidgetItem &QTreeWidgetItem::operator=(const QTreeWidgetItem &other)
1916{
1917 values = other.values;
1918 d->display = other.d->display;
1919 d->policy = other.d->policy;
1920 itemFlags = other.itemFlags;
1921 return *this;
1922}
1923
1924/*!
1925 Appends the \a child item to the list of children.
1926
1927 \sa insertChild(), takeChild()
1928*/
1929void QTreeWidgetItem::addChild(QTreeWidgetItem *child)
1930{
1931 if (child) {
1932 insertChild(index: children.size(), child);
1933 child->d->rowGuess = children.size() - 1;
1934 }
1935}
1936
1937/*!
1938 Inserts the \a child item at \a index in the list of children.
1939
1940 If the child has already been inserted somewhere else it won't be inserted again.
1941*/
1942void QTreeWidgetItem::insertChild(int index, QTreeWidgetItem *child)
1943{
1944 if (index < 0 || index > children.size() || child == nullptr || child->view != nullptr || child->par != nullptr)
1945 return;
1946
1947 if (QTreeModel *model = treeModel()) {
1948 QTreeModel::SkipSorting skipSorting(model);
1949 if (model->rootItem == this)
1950 child->par = nullptr;
1951 else
1952 child->par = this;
1953 if (view->isSortingEnabled()) {
1954 // do a delayed sort instead
1955 if (!model->sortPendingTimer.isActive())
1956 model->sortPendingTimer.start(msec: 0, obj: model);
1957 }
1958 model->beginInsertItems(parent: this, row: index, count: 1);
1959 int cols = model->columnCount();
1960 QStack<QTreeWidgetItem*> stack;
1961 stack.push(t: child);
1962 while (!stack.isEmpty()) {
1963 QTreeWidgetItem *i = stack.pop();
1964 i->view = view;
1965 i->values.reserve(asize: cols);
1966 for (int c = 0; c < i->children.size(); ++c)
1967 stack.push(t: i->children.at(i: c));
1968 }
1969 children.insert(i: index, t: child);
1970 d->updateHiddenStatus(item: child, inserting: true);
1971 model->endInsertItems();
1972 } else {
1973 child->par = this;
1974 children.insert(i: index, t: child);
1975 }
1976 if (child->par)
1977 d->propagateDisabled(item: child);
1978}
1979
1980/*!
1981 Removes the given item indicated by \a child.
1982 The removed item will not be deleted.
1983*/
1984void QTreeWidgetItem::removeChild(QTreeWidgetItem *child)
1985{
1986 (void)takeChild(index: children.indexOf(t: child));
1987}
1988
1989/*!
1990 Removes the item at \a index and returns it, otherwise return 0.
1991*/
1992QTreeWidgetItem *QTreeWidgetItem::takeChild(int index)
1993{
1994 // we move this outside the check of the index to allow executing
1995 // pending sorts from inline functions, using this function (hack)
1996 QTreeModel *model = treeModel();
1997 if (model) {
1998 // This will trigger a layoutChanged signal, thus we might want to optimize
1999 // this function by not emitting the rowsRemoved signal etc to the view.
2000 // On the other hand we also need to make sure that the selectionmodel
2001 // is updated in case we take an item that is selected.
2002 model->skipPendingSort = false;
2003 model->executePendingSort();
2004 }
2005 if (index >= 0 && index < children.size()) {
2006 if (model) model->beginRemoveItems(parent: this, row: index, count: 1);
2007 d->updateHiddenStatus(item: children.at(i: index), inserting: false);
2008 QTreeWidgetItem *item = children.takeAt(i: index);
2009 item->par = nullptr;
2010 QStack<QTreeWidgetItem*> stack;
2011 stack.push(t: item);
2012 while (!stack.isEmpty()) {
2013 QTreeWidgetItem *i = stack.pop();
2014 i->view = nullptr;
2015 for (int c = 0; c < i->children.size(); ++c)
2016 stack.push(t: i->children.at(i: c));
2017 }
2018 d->propagateDisabled(item);
2019 if (model) model->endRemoveRows();
2020 return item;
2021 }
2022 return nullptr;
2023}
2024
2025/*!
2026 Appends the given list of \a children to the item.
2027
2028 \sa insertChildren(), takeChildren()
2029*/
2030void QTreeWidgetItem::addChildren(const QList<QTreeWidgetItem*> &children)
2031{
2032 insertChildren(index: this->children.size(), children);
2033}
2034
2035/*!
2036 Inserts the given list of \a children into the list of the item children at \a index .
2037
2038 Children that have already been inserted somewhere else won't be inserted.
2039*/
2040void QTreeWidgetItem::insertChildren(int index, const QList<QTreeWidgetItem*> &children)
2041{
2042 if (index < 0 || index > this->children.size() || children.isEmpty())
2043 return;
2044
2045 if (view && view->isSortingEnabled()) {
2046 for (int n = 0; n < children.size(); ++n)
2047 insertChild(index, child: children.at(i: n));
2048 return;
2049 }
2050 QTreeModel *model = treeModel();
2051 QStack<QTreeWidgetItem*> stack;
2052 QList<QTreeWidgetItem*> itemsToInsert;
2053 for (int n = 0; n < children.size(); ++n) {
2054 QTreeWidgetItem *child = children.at(i: n);
2055 if (child->view || child->par)
2056 continue;
2057 itemsToInsert.append(t: child);
2058 if (view && model) {
2059 if (child->childCount() == 0)
2060 child->view = view;
2061 else
2062 stack.push(t: child);
2063 }
2064 if (model && (model->rootItem == this))
2065 child->par = nullptr;
2066 else
2067 child->par = this;
2068 }
2069 if (!itemsToInsert.isEmpty()) {
2070 while (!stack.isEmpty()) {
2071 QTreeWidgetItem *i = stack.pop();
2072 i->view = view;
2073 for (int c = 0; c < i->children.size(); ++c)
2074 stack.push(t: i->children.at(i: c));
2075 }
2076 if (model) model->beginInsertItems(parent: this, row: index, count: itemsToInsert.size());
2077 for (int n = 0; n < itemsToInsert.size(); ++n) {
2078 QTreeWidgetItem *child = itemsToInsert.at(i: n);
2079 this->children.insert(i: index + n, t: child);
2080 if (child->par)
2081 d->propagateDisabled(item: child);
2082 d->updateHiddenStatus(item: child, inserting: true);
2083 }
2084 if (model) model->endInsertItems();
2085 }
2086}
2087
2088/*!
2089 Removes the list of children and returns it, otherwise returns an empty list.
2090*/
2091QList<QTreeWidgetItem*> QTreeWidgetItem::takeChildren()
2092{
2093 QList<QTreeWidgetItem*> removed;
2094 if (children.size() > 0) {
2095 QTreeModel *model = treeModel();
2096 if (model) {
2097 // This will trigger a layoutChanged signal, thus we might want to optimize
2098 // this function by not emitting the rowsRemoved signal etc to the view.
2099 // On the other hand we also need to make sure that the selectionmodel
2100 // is updated in case we take an item that is selected.
2101 model->executePendingSort();
2102 }
2103 if (model) model->beginRemoveItems(parent: this, row: 0, count: children.size());
2104 for (int n = 0; n < children.size(); ++n) {
2105 QTreeWidgetItem *item = children.at(i: n);
2106 item->par = nullptr;
2107 QStack<QTreeWidgetItem*> stack;
2108 stack.push(t: item);
2109 while (!stack.isEmpty()) {
2110 QTreeWidgetItem *i = stack.pop();
2111 i->view = nullptr;
2112 for (int c = 0; c < i->children.size(); ++c)
2113 stack.push(t: i->children.at(i: c));
2114 }
2115 d->propagateDisabled(item);
2116 }
2117 removed = children;
2118 children.clear(); // detach
2119 if (model) model->endRemoveItems();
2120 }
2121 return removed;
2122}
2123
2124
2125void QTreeWidgetItemPrivate::sortChildren(int column, Qt::SortOrder order, bool climb)
2126{
2127 QTreeModel *model = q->treeModel();
2128 if (!model)
2129 return;
2130 model->sortItems(items: &q->children, column, order);
2131 if (climb) {
2132 QList<QTreeWidgetItem*>::iterator it = q->children.begin();
2133 for (; it != q->children.end(); ++it) {
2134 //here we call the private object's method to avoid emitting
2135 //the layoutAboutToBeChanged and layoutChanged signals
2136 (*it)->d->sortChildren(column, order, climb);
2137 }
2138 }
2139}
2140
2141/*!
2142 \internal
2143
2144 Sorts the children by the value in the given \a column, in the \a order
2145 specified. If \a climb is true, the items below each of the children will
2146 also be sorted.
2147*/
2148void QTreeWidgetItem::sortChildren(int column, Qt::SortOrder order, bool climb)
2149{
2150 QTreeModel *model = treeModel();
2151 if (!model)
2152 return;
2153 if (model->isChanging())
2154 return;
2155 QTreeModel::SkipSorting skipSorting(model);
2156 int oldSortColumn = view->d_func()->explicitSortColumn;
2157 view->d_func()->explicitSortColumn = column;
2158 emit model->layoutAboutToBeChanged(parents: {}, hint: QAbstractItemModel::VerticalSortHint);
2159 d->sortChildren(column, order, climb);
2160 emit model->layoutChanged(parents: {}, hint: QAbstractItemModel::VerticalSortHint);
2161 view->d_func()->explicitSortColumn = oldSortColumn;
2162}
2163
2164/*!
2165 \internal
2166
2167 Calculates the checked state of the item based on the checked state
2168 of its children. E.g. if all children checked => this item is also
2169 checked; if some children checked => this item is partially checked;
2170 if no children checked => this item is unchecked.
2171*/
2172QVariant QTreeWidgetItem::childrenCheckState(int column) const
2173{
2174 if (column < 0)
2175 return QVariant();
2176 bool checkedChildren = false;
2177 bool uncheckedChildren = false;
2178 for (const auto *child : children) {
2179 QVariant value = child->data(column, role: Qt::CheckStateRole);
2180 if (!value.isValid())
2181 return QVariant();
2182
2183 switch (static_cast<Qt::CheckState>(value.toInt()))
2184 {
2185 case Qt::Unchecked:
2186 uncheckedChildren = true;
2187 break;
2188 case Qt::Checked:
2189 checkedChildren = true;
2190 break;
2191 case Qt::PartiallyChecked:
2192 default:
2193 return Qt::PartiallyChecked;
2194 }
2195
2196 if (uncheckedChildren && checkedChildren)
2197 return Qt::PartiallyChecked;
2198 }
2199
2200 if (uncheckedChildren)
2201 return Qt::Unchecked;
2202 else if (checkedChildren)
2203 return Qt::Checked;
2204 else
2205 return QVariant(); // value was not defined
2206}
2207
2208/*!
2209 Causes the model associated with this item to emit a
2210 \l{QAbstractItemModel::dataChanged()}{dataChanged}() signal for this
2211 item.
2212
2213 You normally only need to call this function if you have subclassed
2214 QTreeWidgetItem and reimplemented data() and/or setData().
2215
2216 \sa setData()
2217*/
2218void QTreeWidgetItem::emitDataChanged()
2219{
2220 itemChanged();
2221}
2222
2223/*!
2224 \internal
2225*/
2226void QTreeWidgetItem::itemChanged()
2227{
2228 if (QTreeModel *model = treeModel())
2229 model->itemChanged(item: this);
2230}
2231
2232/*!
2233 \internal
2234*/
2235void QTreeWidgetItem::executePendingSort() const
2236{
2237 if (QTreeModel *model = treeModel())
2238 model->executePendingSort();
2239}
2240
2241/*!
2242 \internal
2243 returns the QTreeModel if a view is set
2244*/
2245QTreeModel *QTreeWidgetItem::treeModel(QTreeWidget *v) const
2246{
2247 if (!v)
2248 v = view;
2249 return (v ? qobject_cast<QTreeModel*>(object: v->model()) : nullptr);
2250}
2251
2252
2253#ifndef QT_NO_DATASTREAM
2254/*!
2255 \relates QTreeWidgetItem
2256
2257 Writes the tree widget item \a item to stream \a out.
2258
2259 This operator uses QTreeWidgetItem::write().
2260
2261 \sa {Serializing Qt Data Types}
2262*/
2263QDataStream &operator<<(QDataStream &out, const QTreeWidgetItem &item)
2264{
2265 item.write(out);
2266 return out;
2267}
2268
2269/*!
2270 \relates QTreeWidgetItem
2271
2272 Reads a tree widget item from stream \a in into \a item.
2273
2274 This operator uses QTreeWidgetItem::read().
2275
2276 \sa {Serializing Qt Data Types}
2277*/
2278QDataStream &operator>>(QDataStream &in, QTreeWidgetItem &item)
2279{
2280 item.read(in);
2281 return in;
2282}
2283#endif // QT_NO_DATASTREAM
2284
2285
2286void QTreeWidgetPrivate::clearConnections()
2287{
2288 for (const QMetaObject::Connection &connection : connections)
2289 QObject::disconnect(connection);
2290}
2291
2292void QTreeWidgetPrivate::emitItemPressed(const QModelIndex &index)
2293{
2294 Q_Q(QTreeWidget);
2295 emit q->itemPressed(item: item(index), column: index.column());
2296}
2297
2298void QTreeWidgetPrivate::emitItemClicked(const QModelIndex &index)
2299{
2300 Q_Q(QTreeWidget);
2301 emit q->itemClicked(item: item(index), column: index.column());
2302}
2303
2304void QTreeWidgetPrivate::emitItemDoubleClicked(const QModelIndex &index)
2305{
2306 Q_Q(QTreeWidget);
2307 emit q->itemDoubleClicked(item: item(index), column: index.column());
2308}
2309
2310void QTreeWidgetPrivate::emitItemActivated(const QModelIndex &index)
2311{
2312 Q_Q(QTreeWidget);
2313 emit q->itemActivated(item: item(index), column: index.column());
2314}
2315
2316void QTreeWidgetPrivate::emitItemEntered(const QModelIndex &index)
2317{
2318 Q_Q(QTreeWidget);
2319 emit q->itemEntered(item: item(index), column: index.column());
2320}
2321
2322void QTreeWidgetPrivate::emitItemChanged(const QModelIndex &index)
2323{
2324 Q_Q(QTreeWidget);
2325 QTreeWidgetItem *indexItem = item(index);
2326 if (indexItem)
2327 emit q->itemChanged(item: indexItem, column: index.column());
2328}
2329
2330void QTreeWidgetPrivate::emitItemExpanded(const QModelIndex &index)
2331{
2332 Q_Q(QTreeWidget);
2333 emit q->itemExpanded(item: item(index));
2334}
2335
2336void QTreeWidgetPrivate::emitItemCollapsed(const QModelIndex &index)
2337{
2338 Q_Q(QTreeWidget);
2339 emit q->itemCollapsed(item: item(index));
2340}
2341
2342void QTreeWidgetPrivate::emitCurrentItemChanged(const QModelIndex &current,
2343 const QModelIndex &previous)
2344{
2345 Q_Q(QTreeWidget);
2346 QTreeWidgetItem *currentItem = item(index: current);
2347 QTreeWidgetItem *previousItem = item(index: previous);
2348 emit q->currentItemChanged(current: currentItem, previous: previousItem);
2349}
2350
2351void QTreeWidgetPrivate::sort()
2352{
2353 if (sortingEnabled) {
2354 int column = header->sortIndicatorSection();
2355 Qt::SortOrder order = header->sortIndicatorOrder();
2356 treeModel()->sort(column, order);
2357 }
2358}
2359
2360void QTreeWidgetPrivate::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
2361{
2362 Q_Q(QTreeWidget);
2363 QModelIndexList indices = selected.indexes();
2364 int i;
2365 QTreeModel *m = treeModel();
2366 for (i = 0; i < indices.size(); ++i) {
2367 QTreeWidgetItem *item = m->item(index: indices.at(i));
2368 item->d->selected = true;
2369 }
2370
2371 indices = deselected.indexes();
2372 for (i = 0; i < indices.size(); ++i) {
2373 QTreeWidgetItem *item = m->item(index: indices.at(i));
2374 item->d->selected = false;
2375 }
2376
2377 emit q->itemSelectionChanged();
2378}
2379
2380void QTreeWidgetPrivate::dataChanged(const QModelIndex &topLeft,
2381 const QModelIndex &bottomRight)
2382{
2383 if (sortingEnabled && topLeft.isValid() && bottomRight.isValid()
2384 && !treeModel()->sortPendingTimer.isActive()) {
2385 int column = header->sortIndicatorSection();
2386 if (column >= topLeft.column() && column <= bottomRight.column()) {
2387 Qt::SortOrder order = header->sortIndicatorOrder();
2388 treeModel()->ensureSorted(column, order, start: topLeft.row(),
2389 end: bottomRight.row(), parent: topLeft.parent());
2390 }
2391 }
2392}
2393
2394/*!
2395 \class QTreeWidget
2396
2397 \brief The QTreeWidget class provides a tree view that uses a predefined
2398 tree model.
2399
2400 \ingroup model-view
2401 \inmodule QtWidgets
2402
2403 \image fusion-treeview.png
2404
2405 The QTreeWidget class is a convenience class that provides a standard
2406 tree widget with a classic item-based interface similar to that used by
2407 the QListView class in Qt 3.
2408 This class is based on Qt's Model/View architecture and uses a default
2409 model to hold items, each of which is a QTreeWidgetItem.
2410
2411 Developers who do not need the flexibility of the Model/View framework
2412 can use this class to create simple hierarchical lists very easily. A more
2413 flexible approach involves combining a QTreeView with a standard item model.
2414 This allows the storage of data to be separated from its representation.
2415
2416 In its simplest form, a tree widget can be constructed in the following way:
2417
2418 \snippet code/src_gui_itemviews_qtreewidget.cpp 0
2419
2420 Before items can be added to the tree widget, the number of columns must
2421 be set with setColumnCount(). This allows each item to have one or more
2422 labels or other decorations. The number of columns in use can be found
2423 with the columnCount() function.
2424
2425 The tree can have a header that contains a section for each column in
2426 the widget. It is easiest to set up the labels for each section by
2427 supplying a list of strings with setHeaderLabels(), but a custom header
2428 can be constructed with a QTreeWidgetItem and inserted into the tree
2429 with the setHeaderItem() function.
2430
2431 The items in the tree can be sorted by column according to a predefined
2432 sort order. If sorting is enabled, the user can sort the items by clicking
2433 on a column header. Sorting can be enabled or disabled by calling
2434 \l{QTreeView::setSortingEnabled()}{setSortingEnabled()}. The
2435 \l{QTreeView::isSortingEnabled()}{isSortingEnabled()} function indicates
2436 whether sorting is enabled.
2437
2438 \sa QTreeWidgetItem, QTreeWidgetItemIterator, QTreeView,
2439 {Model/View Programming}
2440*/
2441
2442/*!
2443 \property QTreeWidget::columnCount
2444 \brief the number of columns displayed in the tree widget
2445
2446 By default, this property has a value of 1.
2447*/
2448
2449/*!
2450 \fn void QTreeWidget::itemActivated(QTreeWidgetItem *item, int column)
2451
2452 This signal is emitted when the user activates an item by single-
2453 or double-clicking (depending on the platform, i.e. on the
2454 QStyle::SH_ItemView_ActivateItemOnSingleClick style hint) or
2455 pressing a special key (e.g., \uicontrol Enter).
2456
2457 The specified \a item is the item that was clicked, or \nullptr if
2458 no item was clicked. The \a column is the item's column that was
2459 clicked, or -1 if no item was clicked.
2460*/
2461
2462/*!
2463 \fn void QTreeWidget::itemPressed(QTreeWidgetItem *item, int column)
2464
2465 This signal is emitted when the user presses a mouse button inside
2466 the widget.
2467
2468 The specified \a item is the item that was clicked, or \nullptr if
2469 no item was clicked. The \a column is the item's column that was
2470 clicked, or -1 if no item was clicked.
2471*/
2472
2473/*!
2474 \fn void QTreeWidget::itemClicked(QTreeWidgetItem *item, int column)
2475
2476 This signal is emitted when the user clicks inside the widget.
2477
2478 The specified \a item is the item that was clicked. The \a column is the
2479 item's column that was clicked. If no item was clicked, no signal will be
2480 emitted.
2481*/
2482
2483/*!
2484 \fn void QTreeWidget::itemDoubleClicked(QTreeWidgetItem *item, int column)
2485
2486 This signal is emitted when the user double clicks inside the
2487 widget.
2488
2489 The specified \a item is the item that was clicked, or \nullptr if
2490 no item was clicked. The \a column is the item's column that was
2491 clicked. If no item was double clicked, no signal will be emitted.
2492*/
2493
2494/*!
2495 \fn void QTreeWidget::itemExpanded(QTreeWidgetItem *item)
2496
2497 This signal is emitted when the specified \a item is expanded so that
2498 all of its children are displayed.
2499
2500 \sa QTreeWidgetItem::isExpanded(), itemCollapsed(), expandItem()
2501*/
2502
2503/*!
2504 \fn void QTreeWidget::itemCollapsed(QTreeWidgetItem *item)
2505
2506 This signal is emitted when the specified \a item is collapsed so that
2507 none of its children are displayed.
2508
2509 \note This signal will not be emitted if an item changes its state when
2510 collapseAll() is invoked.
2511
2512 \sa QTreeWidgetItem::isExpanded(), itemExpanded(), collapseItem()
2513*/
2514
2515/*!
2516 \fn void QTreeWidget::currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
2517
2518 This signal is emitted when the current item changes. The current
2519 item is specified by \a current, and this replaces the \a previous
2520 current item.
2521
2522 \sa setCurrentItem()
2523*/
2524
2525/*!
2526 \fn void QTreeWidget::itemSelectionChanged()
2527
2528 This signal is emitted when the selection changes in the tree widget.
2529 The current selection can be found with selectedItems().
2530*/
2531
2532/*!
2533 \fn void QTreeWidget::itemEntered(QTreeWidgetItem *item, int column)
2534
2535 This signal is emitted when the mouse cursor enters an \a item over the
2536 specified \a column.
2537 QTreeWidget mouse tracking needs to be enabled for this feature to work.
2538*/
2539
2540/*!
2541 \fn void QTreeWidget::itemChanged(QTreeWidgetItem *item, int column)
2542
2543 This signal is emitted when the contents of the \a column in the specified
2544 \a item changes.
2545*/
2546
2547/*!
2548 \fn void QTreeWidget::removeItemWidget(QTreeWidgetItem *item, int column)
2549
2550 Removes the widget set in the given \a item in the given \a column.
2551
2552 \sa itemWidget(), setItemWidget()
2553*/
2554
2555/*!
2556 Constructs a tree widget with the given \a parent.
2557*/
2558QTreeWidget::QTreeWidget(QWidget *parent)
2559 : QTreeView(*new QTreeWidgetPrivate(), parent)
2560{
2561 Q_D(QTreeWidget);
2562 QTreeView::setModel(new QTreeModel(1, this));
2563 d->connections = {
2564 QObjectPrivate::connect(sender: this, signal: &QTreeWidget::pressed,
2565 receiverPrivate: d, slot: &QTreeWidgetPrivate::emitItemPressed),
2566 QObjectPrivate::connect(sender: this, signal: &QTreeWidget::clicked,
2567 receiverPrivate: d, slot: &QTreeWidgetPrivate::emitItemClicked),
2568 QObjectPrivate::connect(sender: this, signal: &QTreeWidget::doubleClicked,
2569 receiverPrivate: d, slot: &QTreeWidgetPrivate::emitItemDoubleClicked),
2570 QObjectPrivate::connect(sender: this, signal: &QTreeWidget::activated,
2571 receiverPrivate: d, slot: &QTreeWidgetPrivate::emitItemActivated),
2572 QObjectPrivate::connect(sender: this, signal: &QTreeWidget::entered,
2573 receiverPrivate: d, slot: &QTreeWidgetPrivate::emitItemEntered),
2574 QObjectPrivate::connect(sender: this, signal: &QTreeWidget::expanded,
2575 receiverPrivate: d, slot: &QTreeWidgetPrivate::emitItemExpanded),
2576 QObjectPrivate::connect(sender: this, signal: &QTreeWidget::collapsed,
2577 receiverPrivate: d, slot: &QTreeWidgetPrivate::emitItemCollapsed),
2578 QObjectPrivate::connect(sender: model(), signal: &QAbstractItemModel::dataChanged,
2579 receiverPrivate: d, slot: &QTreeWidgetPrivate::emitItemChanged),
2580 QObjectPrivate::connect(sender: model(), signal: &QAbstractItemModel::dataChanged,
2581 receiverPrivate: d, slot: &QTreeWidgetPrivate::dataChanged),
2582 QObjectPrivate::connect(sender: model(), signal: &QAbstractItemModel::columnsRemoved,
2583 receiverPrivate: d, slot: &QTreeWidgetPrivate::sort),
2584 QObjectPrivate::connect(sender: selectionModel(), signal: &QItemSelectionModel::currentChanged,
2585 receiverPrivate: d, slot: &QTreeWidgetPrivate::emitCurrentItemChanged),
2586 QObjectPrivate::connect(sender: selectionModel(), signal: &QItemSelectionModel::selectionChanged,
2587 receiverPrivate: d, slot: &QTreeWidgetPrivate::selectionChanged)
2588 };
2589 header()->setSectionsClickable(false);
2590}
2591
2592/*!
2593 Destroys the tree widget and all its items.
2594*/
2595
2596QTreeWidget::~QTreeWidget()
2597{
2598 Q_D(QTreeWidget);
2599 d->clearConnections();
2600}
2601
2602/*
2603 Returns the number of header columns in the view.
2604
2605 \sa sortColumn(), currentColumn(), topLevelItemCount()
2606*/
2607
2608int QTreeWidget::columnCount() const
2609{
2610 Q_D(const QTreeWidget);
2611 return d->model->columnCount();
2612}
2613
2614/*
2615 Sets the number of header \a columns in the tree widget.
2616*/
2617
2618void QTreeWidget::setColumnCount(int columns)
2619{
2620 Q_D(QTreeWidget);
2621 if (columns < 0)
2622 return;
2623 d->treeModel()->setColumnCount(columns);
2624}
2625
2626/*!
2627 Returns the tree widget's invisible root item.
2628
2629 The invisible root item provides access to the tree widget's top-level items
2630 through the QTreeWidgetItem API, making it possible to write functions that
2631 can treat top-level items and their children in a uniform way; for example,
2632 recursive functions.
2633*/
2634
2635QTreeWidgetItem *QTreeWidget::invisibleRootItem() const
2636{
2637 Q_D(const QTreeWidget);
2638 return d->treeModel()->rootItem;
2639}
2640
2641/*!
2642 Returns the top level item at the given \a index, or \nullptr if the
2643 item does not exist.
2644
2645 \sa topLevelItemCount(), insertTopLevelItem()
2646*/
2647
2648QTreeWidgetItem *QTreeWidget::topLevelItem(int index) const
2649{
2650 Q_D(const QTreeWidget);
2651 return d->treeModel()->rootItem->child(index);
2652}
2653
2654/*!
2655 \property QTreeWidget::topLevelItemCount
2656 \brief the number of top-level items
2657
2658 By default, this property has a value of 0.
2659
2660 \sa columnCount(), currentItem()
2661*/
2662
2663int QTreeWidget::topLevelItemCount() const
2664{
2665 Q_D(const QTreeWidget);
2666 return d->treeModel()->rootItem->childCount();
2667}
2668
2669/*!
2670 Inserts the \a item at \a index in the top level in the view.
2671
2672 If the item has already been inserted somewhere else it won't be inserted.
2673
2674 \sa addTopLevelItem(), columnCount()
2675*/
2676
2677void QTreeWidget::insertTopLevelItem(int index, QTreeWidgetItem *item)
2678{
2679 Q_D(QTreeWidget);
2680 d->treeModel()->rootItem->insertChild(index, child: item);
2681}
2682
2683/*!
2684 Appends the \a item as a top-level item in the widget.
2685
2686 \sa insertTopLevelItem()
2687*/
2688void QTreeWidget::addTopLevelItem(QTreeWidgetItem *item)
2689{
2690 insertTopLevelItem(index: topLevelItemCount(), item);
2691}
2692
2693/*!
2694 Removes the top-level item at the given \a index in the tree and
2695 returns it, otherwise returns \nullptr;
2696
2697 \sa insertTopLevelItem(), topLevelItem(), topLevelItemCount()
2698*/
2699
2700QTreeWidgetItem *QTreeWidget::takeTopLevelItem(int index)
2701{
2702 Q_D(QTreeWidget);
2703 return d->treeModel()->rootItem->takeChild(index);
2704}
2705
2706/*!
2707 Returns the index of the given top-level \a item, or -1 if the item
2708 cannot be found.
2709
2710 \sa sortItems(), topLevelItemCount()
2711 */
2712int QTreeWidget::indexOfTopLevelItem(QTreeWidgetItem *item) const
2713{
2714 Q_D(const QTreeWidget);
2715 d->treeModel()->executePendingSort();
2716 return d->treeModel()->rootItem->children.indexOf(t: item);
2717}
2718
2719/*!
2720 Inserts the list of \a items at \a index in the top level in the view.
2721
2722 Items that have already been inserted somewhere else won't be inserted.
2723
2724 \sa addTopLevelItems()
2725*/
2726void QTreeWidget::insertTopLevelItems(int index, const QList<QTreeWidgetItem*> &items)
2727{
2728 Q_D(QTreeWidget);
2729 d->treeModel()->rootItem->insertChildren(index, children: items);
2730}
2731
2732/*!
2733 Appends the list of \a items as a top-level items in the widget.
2734
2735 \sa insertTopLevelItems()
2736*/
2737void QTreeWidget::addTopLevelItems(const QList<QTreeWidgetItem*> &items)
2738{
2739 insertTopLevelItems(index: topLevelItemCount(), items);
2740}
2741
2742/*!
2743 Returns the item used for the tree widget's header.
2744
2745 \sa setHeaderItem()
2746*/
2747
2748QTreeWidgetItem *QTreeWidget::headerItem() const
2749{
2750 Q_D(const QTreeWidget);
2751 return d->treeModel()->headerItem;
2752}
2753
2754/*!
2755 Sets the header \a item for the tree widget. The label for each column in
2756 the header is supplied by the corresponding label in the item.
2757
2758 The tree widget takes ownership of the item.
2759
2760 \sa headerItem(), setHeaderLabels()
2761*/
2762
2763void QTreeWidget::setHeaderItem(QTreeWidgetItem *item)
2764{
2765 Q_D(QTreeWidget);
2766 if (!item)
2767 return;
2768 item->view = this;
2769
2770 int oldCount = columnCount();
2771 if (oldCount < item->columnCount())
2772 d->treeModel()->beginInsertColumns(parent: QModelIndex(), first: oldCount, last: item->columnCount() - 1);
2773 else if (oldCount > item->columnCount())
2774 d->treeModel()->beginRemoveColumns(parent: QModelIndex(), first: item->columnCount(), last: oldCount - 1);
2775 delete d->treeModel()->headerItem;
2776 d->treeModel()->headerItem = item;
2777 if (oldCount < item->columnCount())
2778 d->treeModel()->endInsertColumns();
2779 else if (oldCount > item->columnCount())
2780 d->treeModel()->endRemoveColumns();
2781 d->treeModel()->headerDataChanged(orientation: Qt::Horizontal, first: 0, last: oldCount);
2782}
2783
2784
2785/*!
2786 Adds a column in the header for each item in the \a labels list, and sets
2787 the label for each column.
2788
2789 Note that setHeaderLabels() won't remove existing columns.
2790
2791 \sa setHeaderItem(), setHeaderLabel()
2792*/
2793void QTreeWidget::setHeaderLabels(const QStringList &labels)
2794{
2795 Q_D(QTreeWidget);
2796 if (columnCount() < labels.size())
2797 setColumnCount(labels.size());
2798 QTreeWidgetItem *item = d->treeModel()->headerItem;
2799 for (int i = 0; i < labels.size(); ++i)
2800 item->setText(column: i, atext: labels.at(i));
2801}
2802
2803/*!
2804 \fn void QTreeWidget::setHeaderLabel(const QString &label)
2805
2806 Same as setHeaderLabels(QStringList(\a label)).
2807*/
2808
2809/*!
2810 Returns the current item in the tree widget.
2811
2812 \sa setCurrentItem(), currentItemChanged()
2813*/
2814QTreeWidgetItem *QTreeWidget::currentItem() const
2815{
2816 Q_D(const QTreeWidget);
2817 return d->item(index: currentIndex());
2818}
2819
2820/*!
2821 Returns the current column in the tree widget.
2822
2823 \sa setCurrentItem(), columnCount()
2824*/
2825int QTreeWidget::currentColumn() const
2826{
2827 return currentIndex().column();
2828}
2829
2830/*!
2831 Sets the current \a item in the tree widget.
2832
2833 Unless the selection mode is \l{QAbstractItemView::}{NoSelection},
2834 the item is also selected.
2835
2836 \sa currentItem(), currentItemChanged()
2837*/
2838void QTreeWidget::setCurrentItem(QTreeWidgetItem *item)
2839{
2840 setCurrentItem(item, column: 0);
2841}
2842
2843/*!
2844 Sets the current \a item in the tree widget and the current column to \a column.
2845
2846 \sa currentItem()
2847*/
2848void QTreeWidget::setCurrentItem(QTreeWidgetItem *item, int column)
2849{
2850 Q_D(QTreeWidget);
2851 setCurrentIndex(d->index(item, column));
2852}
2853
2854/*!
2855 Sets the current \a item in the tree widget and the current column to \a column,
2856 using the given \a command.
2857
2858 \sa currentItem()
2859*/
2860void QTreeWidget::setCurrentItem(QTreeWidgetItem *item, int column,
2861 QItemSelectionModel::SelectionFlags command)
2862{
2863 Q_D(QTreeWidget);
2864 d->selectionModel->setCurrentIndex(index: d->index(item, column), command);
2865}
2866
2867
2868/*!
2869 Returns a pointer to the item at the coordinates \a p. The coordinates
2870 are relative to the tree widget's \l{QAbstractScrollArea::}{viewport()}.
2871
2872 \sa visualItemRect()
2873*/
2874QTreeWidgetItem *QTreeWidget::itemAt(const QPoint &p) const
2875{
2876 Q_D(const QTreeWidget);
2877 return d->item(index: indexAt(p));
2878}
2879
2880/*!
2881 \fn QTreeWidgetItem *QTreeWidget::itemAt(int x, int y) const
2882 \overload
2883
2884 Returns a pointer to the item at the coordinates (\a x, \a y). The coordinates
2885 are relative to the tree widget's \l{QAbstractScrollArea::}{viewport()}.
2886*/
2887
2888/*!
2889 Returns the rectangle on the viewport occupied by the item at \a item.
2890
2891 \sa itemAt()
2892*/
2893QRect QTreeWidget::visualItemRect(const QTreeWidgetItem *item) const
2894{
2895 Q_D(const QTreeWidget);
2896 //the visual rect for an item is across all columns. So we need to determine
2897 //what is the first and last column and get their visual index rects
2898 const QModelIndex base = d->index(item);
2899 const int firstVisiblesection = header()->logicalIndexAt(position: - header()->offset());
2900 const int lastVisibleSection = header()->logicalIndexAt(position: header()->length() - header()->offset() - 1);
2901 const QModelIndex first = base.sibling(arow: base.row(), acolumn: firstVisiblesection);
2902 const QModelIndex last = base.sibling(arow: base.row(), acolumn: lastVisibleSection);
2903 return visualRect(index: first) | visualRect(index: last);
2904}
2905
2906/*!
2907 Returns the column used to sort the contents of the widget.
2908
2909 \sa sortItems()
2910*/
2911int QTreeWidget::sortColumn() const
2912{
2913 Q_D(const QTreeWidget);
2914 return (d->explicitSortColumn != -1
2915 ? d->explicitSortColumn
2916 : header()->sortIndicatorSection());
2917}
2918
2919/*!
2920 Sorts the items in the widget in the specified \a order by the values in
2921 the given \a column.
2922
2923 \sa sortColumn()
2924*/
2925
2926void QTreeWidget::sortItems(int column, Qt::SortOrder order)
2927{
2928 Q_D(QTreeWidget);
2929 header()->setSortIndicator(logicalIndex: column, order);
2930 d->model->sort(column, order);
2931}
2932
2933/*!
2934 Starts editing the \a item in the given \a column if it is editable.
2935*/
2936
2937void QTreeWidget::editItem(QTreeWidgetItem *item, int column)
2938{
2939 Q_D(QTreeWidget);
2940 edit(index: d->index(item, column));
2941}
2942
2943/*!
2944 Opens a persistent editor for the \a item in the given \a column.
2945
2946 \sa closePersistentEditor(), isPersistentEditorOpen()
2947*/
2948
2949void QTreeWidget::openPersistentEditor(QTreeWidgetItem *item, int column)
2950{
2951 Q_D(QTreeWidget);
2952 QAbstractItemView::openPersistentEditor(index: d->index(item, column));
2953}
2954
2955/*!
2956 Closes the persistent editor for the \a item in the given \a column.
2957
2958 This function has no effect if no persistent editor is open for this
2959 combination of item and column.
2960
2961 \sa openPersistentEditor(), isPersistentEditorOpen()
2962*/
2963
2964void QTreeWidget::closePersistentEditor(QTreeWidgetItem *item, int column)
2965{
2966 Q_D(QTreeWidget);
2967 QAbstractItemView::closePersistentEditor(index: d->index(item, column));
2968}
2969
2970/*!
2971 \since 5.10
2972
2973 Returns whether a persistent editor is open for item \a item in
2974 column \a column.
2975
2976 \sa openPersistentEditor(), closePersistentEditor()
2977*/
2978
2979bool QTreeWidget::isPersistentEditorOpen(QTreeWidgetItem *item, int column) const
2980{
2981 Q_D(const QTreeWidget);
2982 return QAbstractItemView::isPersistentEditorOpen(index: d->index(item, column));
2983}
2984
2985/*!
2986 Returns the widget displayed in the cell specified by \a item and the given \a column.
2987
2988 \sa setItemWidget(), removeItemWidget()
2989*/
2990QWidget *QTreeWidget::itemWidget(QTreeWidgetItem *item, int column) const
2991{
2992 Q_D(const QTreeWidget);
2993 return QAbstractItemView::indexWidget(index: d->index(item, column));
2994}
2995
2996/*!
2997 Sets the given \a widget to be displayed in the cell specified by the given
2998 \a item and \a column.
2999
3000 The given \a widget's \l {QWidget::}{autoFillBackground} property must be
3001 set to true, otherwise the widget's background will be transparent, showing
3002 both the model data and the tree widget item.
3003
3004 This function should only be used to display static content in the place of
3005 a tree widget item. If you want to display custom dynamic content or
3006 implement a custom editor widget, use QTreeView and subclass QStyledItemDelegate
3007 instead.
3008
3009 This function cannot be called before the item hierarchy has been set up,
3010 i.e., the QTreeWidgetItem that will hold \a widget must have been added to
3011 the view before \a widget is set.
3012
3013 \note The tree takes ownership of \a widget.
3014
3015 \sa itemWidget(), removeItemWidget(), {Delegate Classes}
3016*/
3017void QTreeWidget::setItemWidget(QTreeWidgetItem *item, int column, QWidget *widget)
3018{
3019 Q_D(QTreeWidget);
3020 QAbstractItemView::setIndexWidget(index: d->index(item, column), widget);
3021}
3022
3023/*!
3024 Returns a list of all selected non-hidden items.
3025
3026 \sa itemSelectionChanged()
3027*/
3028QList<QTreeWidgetItem*> QTreeWidget::selectedItems() const
3029{
3030 Q_D(const QTreeWidget);
3031 const QModelIndexList indexes = selectionModel()->selectedIndexes();
3032 QList<QTreeWidgetItem*> items;
3033 items.reserve(asize: indexes.size());
3034 QDuplicateTracker<QTreeWidgetItem *> seen(indexes.size());
3035 for (const auto &index : indexes) {
3036 QTreeWidgetItem *item = d->item(index);
3037 if (item->isHidden() || seen.hasSeen(s: item))
3038 continue;
3039 items.append(t: item);
3040 }
3041 return items;
3042}
3043
3044/*!
3045 Returns a list of items that match the given \a text, using the given \a flags, in the given \a column.
3046*/
3047QList<QTreeWidgetItem*> QTreeWidget::findItems(const QString &text, Qt::MatchFlags flags, int column) const
3048{
3049 Q_D(const QTreeWidget);
3050 QModelIndexList indexes = d->model->match(start: model()->index(row: 0, column, parent: QModelIndex()),
3051 role: Qt::DisplayRole, value: text, hits: -1, flags);
3052 QList<QTreeWidgetItem*> items;
3053 const int indexesSize = indexes.size();
3054 items.reserve(asize: indexesSize);
3055 for (int i = 0; i < indexesSize; ++i)
3056 items.append(t: d->item(index: indexes.at(i)));
3057 return items;
3058}
3059
3060
3061/*!
3062 Returns the item above the given \a item.
3063*/
3064QTreeWidgetItem *QTreeWidget::itemAbove(const QTreeWidgetItem *item) const
3065{
3066 Q_D(const QTreeWidget);
3067 if (item == d->treeModel()->headerItem)
3068 return nullptr;
3069 const QModelIndex index = d->index(item);
3070 const QModelIndex above = indexAbove(index);
3071 return d->item(index: above);
3072}
3073
3074/*!
3075 Returns the item visually below the given \a item.
3076*/
3077QTreeWidgetItem *QTreeWidget::itemBelow(const QTreeWidgetItem *item) const
3078{
3079 Q_D(const QTreeWidget);
3080 if (item == d->treeModel()->headerItem)
3081 return nullptr;
3082 const QModelIndex index = d->index(item);
3083 const QModelIndex below = indexBelow(index);
3084 return d->item(index: below);
3085}
3086
3087/*!
3088 \reimp
3089 */
3090void QTreeWidget::setSelectionModel(QItemSelectionModel *selectionModel)
3091{
3092 Q_D(QTreeWidget);
3093 QTreeView::setSelectionModel(selectionModel);
3094 QItemSelection newSelection = selectionModel->selection();
3095 if (!newSelection.isEmpty())
3096 d->selectionChanged(selected: newSelection, deselected: QItemSelection());
3097}
3098
3099/*!
3100 Ensures that the \a item is visible, scrolling the view if necessary using
3101 the specified \a hint.
3102
3103 \sa currentItem(), itemAt(), topLevelItem()
3104*/
3105void QTreeWidget::scrollToItem(const QTreeWidgetItem *item, QAbstractItemView::ScrollHint hint)
3106{
3107 Q_D(QTreeWidget);
3108 QTreeView::scrollTo(index: d->index(item), hint);
3109}
3110
3111/*!
3112 Expands the \a item. This causes the tree containing the item's children
3113 to be expanded.
3114
3115 \sa collapseItem(), currentItem(), itemAt(), topLevelItem(), itemExpanded()
3116*/
3117void QTreeWidget::expandItem(const QTreeWidgetItem *item)
3118{
3119 Q_D(QTreeWidget);
3120 QTreeModel::SkipSorting skipSorting(d->treeModel());
3121 expand(index: d->index(item));
3122}
3123
3124/*!
3125 Closes the \a item. This causes the tree containing the item's children
3126 to be collapsed.
3127
3128 \sa expandItem(), currentItem(), itemAt(), topLevelItem()
3129*/
3130void QTreeWidget::collapseItem(const QTreeWidgetItem *item)
3131{
3132 Q_D(QTreeWidget);
3133 QTreeModel::SkipSorting skipSorting(d->treeModel());
3134 collapse(index: d->index(item));
3135}
3136
3137/*!
3138 Clears the tree widget by removing all of its items and selections.
3139
3140 \b{Note:} Since each item is removed from the tree widget before being
3141 deleted, the return value of QTreeWidgetItem::treeWidget() will be invalid
3142 when called from an item's destructor.
3143
3144 \sa takeTopLevelItem(), topLevelItemCount(), columnCount()
3145*/
3146void QTreeWidget::clear()
3147{
3148 Q_D(QTreeWidget);
3149 selectionModel()->clear();
3150 d->treeModel()->clear();
3151}
3152
3153/*!
3154 Returns a list of MIME types that can be used to describe a list of
3155 treewidget items.
3156
3157 \sa mimeData()
3158*/
3159QStringList QTreeWidget::mimeTypes() const
3160{
3161 return model()->QAbstractItemModel::mimeTypes();
3162}
3163
3164/*!
3165 Returns an object that contains a serialized description of the specified
3166 \a items. The format used to describe the items is obtained from the
3167 mimeTypes() function.
3168
3169 If the list of items is empty, \nullptr is returned rather than a
3170 serialized empty list.
3171*/
3172QMimeData *QTreeWidget::mimeData(const QList<QTreeWidgetItem *> &items) const
3173{
3174 Q_D(const QTreeWidget);
3175 if (d->treeModel()->cachedIndexes.isEmpty()) {
3176 QList<QModelIndex> indexes;
3177 for (const auto *item : items) {
3178 if (Q_UNLIKELY(!item)) {
3179 qWarning(msg: "QTreeWidget::mimeData: Null-item passed");
3180 return nullptr;
3181 }
3182
3183 for (int c = 0; c < item->values.size(); ++c) {
3184 const QModelIndex index = indexFromItem(item, column: c);
3185 if (Q_UNLIKELY(!index.isValid())) {
3186 qWarning() << "QTreeWidget::mimeData: No index associated with item :" << item;
3187 return nullptr;
3188 }
3189 indexes << index;
3190 }
3191 }
3192 return d->model->QAbstractItemModel::mimeData(indexes);
3193 }
3194 return d->treeModel()->internalMimeData();
3195}
3196
3197/*!
3198 Handles the \a data supplied by a drag and drop operation that ended with
3199 the given \a action in the \a index in the given \a parent item.
3200
3201 The default implementation returns \c true if the drop was
3202 successfully handled by decoding the mime data and inserting it
3203 into the model; otherwise it returns \c false.
3204
3205 \sa supportedDropActions(), supportedDragActions
3206*/
3207bool QTreeWidget::dropMimeData(QTreeWidgetItem *parent, int index,
3208 const QMimeData *data, Qt::DropAction action)
3209{
3210 QModelIndex idx;
3211 if (parent) idx = indexFromItem(item: parent);
3212 return model()->QAbstractItemModel::dropMimeData(data, action , row: index, column: 0, parent: idx);
3213}
3214
3215/*!
3216 Returns the drop actions supported by this view.
3217
3218 \sa Qt::DropActions, supportedDragActions, dropMimeData()
3219*/
3220Qt::DropActions QTreeWidget::supportedDropActions() const
3221{
3222 return model()->QAbstractItemModel::supportedDropActions() | Qt::MoveAction;
3223}
3224
3225#if QT_CONFIG(draganddrop)
3226/*!
3227 \property QTreeWidget::supportedDragActions
3228 \brief the drag actions supported by this view
3229
3230 \since 6.10
3231 \sa Qt::DropActions, supportedDropActions()
3232*/
3233Qt::DropActions QTreeWidget::supportedDragActions() const
3234{
3235 Q_D(const QTreeWidget);
3236 return d->supportedDragActions.value_or(u: supportedDropActions());
3237}
3238
3239void QTreeWidget::setSupportedDragActions(Qt::DropActions actions)
3240{
3241 Q_D(QTreeWidget);
3242 d->supportedDragActions = actions;
3243}
3244#endif // QT_CONFIG(draganddrop)
3245
3246/*!
3247 Returns the QModelIndex associated with the given \a item in the given \a column.
3248
3249 \note In Qt versions prior to 5.7, this function took a non-\c{const} \a item.
3250
3251 \sa itemFromIndex(), topLevelItem()
3252*/
3253QModelIndex QTreeWidget::indexFromItem(const QTreeWidgetItem *item, int column) const
3254{
3255 Q_D(const QTreeWidget);
3256 return d->index(item, column);
3257}
3258
3259/*!
3260 Returns a pointer to the QTreeWidgetItem associated with the given \a index.
3261
3262 \sa indexFromItem()
3263*/
3264QTreeWidgetItem *QTreeWidget::itemFromIndex(const QModelIndex &index) const
3265{
3266 Q_D(const QTreeWidget);
3267 return d->item(index);
3268}
3269
3270#if QT_CONFIG(draganddrop)
3271/*! \reimp */
3272void QTreeWidget::dropEvent(QDropEvent *event) {
3273 Q_D(QTreeWidget);
3274 if (event->source() == this && (event->dropAction() == Qt::MoveAction ||
3275 dragDropMode() == QAbstractItemView::InternalMove)) {
3276 QModelIndex topIndex;
3277 int col = -1;
3278 int row = -1;
3279 // check whether a subclass has already accepted the event, ie. moved the data
3280 if (!event->isAccepted() && d->dropOn(event, row: &row, col: &col, index: &topIndex)) {
3281 const QList<QModelIndex> idxs = selectedIndexes();
3282 QList<QPersistentModelIndex> indexes;
3283 const int indexesCount = idxs.size();
3284 indexes.reserve(asize: indexesCount);
3285 for (const auto &idx : idxs)
3286 indexes.append(t: idx);
3287
3288 if (indexes.contains(t: topIndex))
3289 return;
3290
3291 // When removing items the drop location could shift
3292 QPersistentModelIndex dropRow = model()->index(row, column: col, parent: topIndex);
3293
3294 // Remove the items
3295 QList<QTreeWidgetItem *> taken;
3296 for (const auto &index : indexes) {
3297 QTreeWidgetItem *parent = itemFromIndex(index);
3298 if (!parent || !parent->parent()) {
3299 taken.append(t: takeTopLevelItem(index: index.row()));
3300 } else {
3301 taken.append(t: parent->parent()->takeChild(index: index.row()));
3302 }
3303 }
3304
3305 // insert them back in at their new positions
3306 for (int i = 0; i < indexes.size(); ++i) {
3307 // Either at a specific point or appended
3308 if (row == -1) {
3309 if (topIndex.isValid()) {
3310 QTreeWidgetItem *parent = itemFromIndex(index: topIndex);
3311 parent->insertChild(index: parent->childCount(), child: taken.takeFirst());
3312 } else {
3313 insertTopLevelItem(index: topLevelItemCount(), item: taken.takeFirst());
3314 }
3315 } else {
3316 int r = dropRow.row() >= 0 ? dropRow.row() : row;
3317 if (topIndex.isValid()) {
3318 QTreeWidgetItem *parent = itemFromIndex(index: topIndex);
3319 parent->insertChild(index: qMin(a: r, b: parent->childCount()), child: taken.takeFirst());
3320 } else {
3321 insertTopLevelItem(index: qMin(a: r, b: topLevelItemCount()), item: taken.takeFirst());
3322 }
3323 }
3324 }
3325
3326 event->accept();
3327 }
3328 // either we or a subclass accepted the move event, so assume that the data was
3329 // moved and that QAbstractItemView shouldn't remove the source when QDrag::exec returns
3330 if (event->isAccepted())
3331 d->dropEventMoved = true;
3332 }
3333
3334 QTreeView::dropEvent(event);
3335}
3336#endif
3337
3338/*!
3339 \reimp
3340*/
3341
3342void QTreeWidget::setModel(QAbstractItemModel * /*model*/)
3343{
3344 Q_ASSERT(!"QTreeWidget::setModel() - Changing the model of the QTreeWidget is not allowed.");
3345}
3346
3347/*!
3348 \reimp
3349*/
3350bool QTreeWidget::event(QEvent *e)
3351{
3352 Q_D(QTreeWidget);
3353 if (e->type() == QEvent::Polish)
3354 d->treeModel()->executePendingSort();
3355 return QTreeView::event(event: e);
3356}
3357
3358/*!
3359 see QTBUG-94546
3360*/
3361void QTreeModelPrivate::executePendingOperations() const
3362{
3363 q_func()->executePendingSort();
3364}
3365
3366QT_END_NAMESPACE
3367
3368#include "moc_qtreewidget.cpp"
3369#include "moc_qtreewidget_p.cpp"
3370

source code of qtbase/src/widgets/itemviews/qtreewidget.cpp