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

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