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

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