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