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