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