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