Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qtreewidget.cpp
Go to the documentation of this file.
1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qtreewidget.h"
5
6#include <qheaderview.h>
7#include <qpainter.h>
8#include <qstack.h>
9#include <qdebug.h>
10#include <private/qtreewidget_p.h>
11#include <private/qwidgetitemdata_p.h>
12#include <private/qtreewidgetitemiterator_p.h>
13
14#include <QtCore/private/qduplicatetracker_p.h>
15
16#include <algorithm>
17
19
21{
22public:
23 inline bool operator()(QTreeWidgetItem *i1, QTreeWidgetItem *i2) const
24 { return *i1 < *i2; }
25};
26
28{
29public:
30 inline bool operator()(QTreeWidgetItem *i1, QTreeWidgetItem *i2) const
31 { return *i2 < *i1; }
32};
33
34/*
35 \class QTreeModel
36 \brief The QTreeModel class manages the items stored in a tree view.
37
38 \ingroup model-view
39 \inmodule QtWidgets
40
41*/
42
80 headerItem(new QTreeWidgetItem)
81{
82 rootItem->view = parent;
83 rootItem->itemFlags = Qt::ItemIsDropEnabled;
84 headerItem->view = parent;
85 setColumnCount(columns);
86}
87
94 : QAbstractItemModel(dd, parent), rootItem(new QTreeWidgetItem), headerItem(new QTreeWidgetItem)
95{
96 rootItem->view = parent;
97 rootItem->itemFlags = Qt::ItemIsDropEnabled;
98 headerItem->view = parent;
99}
100
108{
109 clear();
110 headerItem->view = nullptr;
111 delete headerItem;
112 rootItem->view = nullptr;
113 delete rootItem;
114}
115
123{
124 SkipSorting skipSorting(this);
126 for (int i = 0; i < rootItem->childCount(); ++i) {
127 QTreeWidgetItem *item = rootItem->children.at(i);
128 item->par = nullptr;
129 item->view = nullptr;
130 delete item;
131 }
132 rootItem->children.clear();
133 sortPendingTimer.stop();
135}
136
144{
145 SkipSorting skipSorting(this);
146 if (columns < 0)
147 return;
148 if (!headerItem) {
149 headerItem = new QTreeWidgetItem();
150 headerItem->view = view();
151 }
152 int count = columnCount();
153 if (count == columns)
154 return;
155
156 if (columns < count) {
157 beginRemoveColumns(QModelIndex(), columns, count - 1);
158 headerItem->values.resize(columns);
160 } else {
161 beginInsertColumns(QModelIndex(), count, columns - 1);
162 headerItem->values.resize(columns);
163 for (int i = count; i < columns; ++i) {// insert data without emitting the dataChanged signal
164 headerItem->values[i].append(QWidgetItemData(Qt::DisplayRole, QString::number(i + 1)));
165 headerItem->d->display.append(QString::number(i + 1));
166 }
168 }
169}
170
180{
181 if (!index.isValid())
182 return nullptr;
183 return static_cast<QTreeWidgetItem*>(index.internalPointer());
184}
185
194{
195 executePendingSort();
196
197 if (!item || (item == rootItem))
198 return QModelIndex();
199 const QTreeWidgetItem *par = item->parent();
200 QTreeWidgetItem *itm = const_cast<QTreeWidgetItem*>(item);
201 if (!par)
202 par = rootItem;
203 int row;
204 int guess = item->d->rowGuess;
205 if (guess >= 0
206 && par->children.size() > guess
207 && par->children.at(guess) == itm) {
208 row = guess;
209 } else {
210 row = par->children.lastIndexOf(itm);
211 itm->d->rowGuess = row;
212 }
213 return createIndex(row, column, itm);
214}
215
224QModelIndex QTreeModel::index(int row, int column, const QModelIndex &parent) const
225{
226 executePendingSort();
227
228 int c = columnCount(parent);
229 if (row < 0 || column < 0 || column >= c)
230 return QModelIndex();
231
232 QTreeWidgetItem *parentItem = parent.isValid() ? item(parent) : rootItem;
233 if (parentItem && row < parentItem->childCount()) {
234 QTreeWidgetItem *itm = parentItem->child(row);
235 if (itm)
236 return createIndex(row, column, itm);
237 return QModelIndex();
238 }
239
240 return QModelIndex();
241}
242
252{
253 SkipSorting skipSorting(this); //The reason we don't sort here is that this might be called from a valid QPersistentModelIndex
254 //We don't want it to become suddenly invalid
255
256 if (!child.isValid())
257 return QModelIndex();
258 QTreeWidgetItem *itm = static_cast<QTreeWidgetItem *>(child.internalPointer());
259 if (!itm || itm == rootItem)
260 return QModelIndex();
261 QTreeWidgetItem *parent = itm->parent();
262 return index(parent, 0);
263}
264
272int QTreeModel::rowCount(const QModelIndex &parent) const
273{
274 if (!parent.isValid())
275 return rootItem->childCount();
276
277 QTreeWidgetItem *parentItem = item(parent);
278 if (parentItem)
279 return parentItem->childCount();
280 return 0;
281}
282
292{
294 if (!headerItem)
295 return 0;
296 return headerItem->columnCount();
297}
298
299bool QTreeModel::hasChildren(const QModelIndex &parent) const
300{
301 if (!parent.isValid())
302 return (rootItem->childCount() > 0);
303
305 if (!itm)
306 return false;
307 switch (itm->d->policy) {
309 return true;
311 return false;
313 return (itm->childCount() > 0);
314 }
315 return false;
316}
317
327{
328 if (!index.isValid())
329 return QVariant();
330 QTreeWidgetItem *itm = item(index);
331 if (itm)
332 return itm->data(index.column(), role);
333 return QVariant();
334}
335
346bool QTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
347{
348 if (!index.isValid())
349 return false;
350 QTreeWidgetItem *itm = item(index);
351 if (itm) {
352 itm->setData(index.column(), role, value);
353 return true;
354 }
355 return false;
356}
357
359{
361 return false;
362 QTreeWidgetItem *itm = item(index);
363 if (!itm)
364 return false;
365 const auto beginIter = itm->values.at(index.column()).cbegin();
366 const auto endIter = itm->values.at(index.column()).cend();
367 if (std::all_of(beginIter, endIter, [](const QWidgetItemData& data) -> bool { return !data.value.isValid(); })
368 && !itm->d->display.at(index.column()).isValid()) {
369 return true; //it's already cleared
370 }
371 itm->d->display[index.column()] = QVariant();
372 itm->values[index.column()].clear();
373 emit dataChanged(index, index, QList<int> {});
374 return true;
375}
376
377QMap<int, QVariant> QTreeModel::itemData(const QModelIndex &index) const
378{
379 QMap<int, QVariant> roles;
380 QTreeWidgetItem *itm = item(index);
381 if (itm) {
382 int column = index.column();
383 if (column < itm->values.size()) {
384 for (int i = 0; i < itm->values.at(column).size(); ++i) {
385 roles.insert(itm->values.at(column).at(i).role,
386 itm->values.at(column).at(i).value);
387 }
388 }
389
390 // the two special cases
391 QVariant displayValue = itm->data(column, Qt::DisplayRole);
392 if (displayValue.isValid())
393 roles.insert(Qt::DisplayRole, displayValue);
394
395 QVariant checkValue = itm->data(column, Qt::CheckStateRole);
396 if (checkValue.isValid())
397 roles.insert(Qt::CheckStateRole, checkValue);
398 }
399 return roles;
400}
401
406bool QTreeModel::insertRows(int row, int count, const QModelIndex &parent)
407{
408 SkipSorting skipSorting(this);
409 if (count < 1 || row < 0 || row > rowCount(parent) || parent.column() > 0)
410 return false;
411
414 while (count > 0) {
416 item->view = view();
417 item->par = par;
418 if (par)
419 par->children.insert(row++, item);
420 else
421 rootItem->children.insert(row++, item);
422 --count;
423 }
425 return true;
426}
427
433{
434 SkipSorting skipSorting(this);
435 if (count < 1 || column < 0 || column > columnCount(parent) || parent.column() > 0 || !headerItem)
436 return false;
437
439
440 int oldCount = columnCount(parent);
441 column = qBound(0, column, oldCount);
442 headerItem->values.resize(oldCount + count);
443 for (int i = oldCount; i < oldCount + count; ++i) {
444 headerItem->values[i].append(QWidgetItemData(Qt::DisplayRole, QString::number(i + 1)));
445 headerItem->d->display.append(QString::number(i + 1));
446 }
447
448 QStack<QTreeWidgetItem*> itemstack;
449 itemstack.push(0);
450 while (!itemstack.isEmpty()) {
451 QTreeWidgetItem *par = itemstack.pop();
452 QList<QTreeWidgetItem*> children = par ? par->children : rootItem->children;
453 for (int row = 0; row < children.size(); ++row) {
455 if (child->children.size())
456 itemstack.push(child);
457 child->values.insert(column, count, QList<QWidgetItemData>());
458 }
459 }
460
462 return true;
463}
464
469bool QTreeModel::removeRows(int row, int count, const QModelIndex &parent) {
470 if (count < 1 || row < 0 || (row + count) > rowCount(parent))
471 return false;
472 QTreeWidgetItem *parentItem = item(parent);
473 // if parentItem is valid, begin/end RemoveRows is handled by takeChild below
474 if (!parentItem)
476 for (int i = row + count - 1; i >= row; --i) {
477 QTreeWidgetItem *child = parentItem ? parentItem->takeChild(i) : rootItem->children.takeAt(i);
479 child->view = nullptr;
480 delete child;
481 }
482 if (!parentItem)
484 return true;
485}
486
495QVariant QTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
496{
497 if (orientation != Qt::Horizontal)
498 return QVariant();
499
500 if (headerItem)
501 return headerItem->data(section, role);
502 if (role == Qt::DisplayRole)
503 return QString::number(section + 1);
504 return QVariant();
505}
506
517bool QTreeModel::setHeaderData(int section, Qt::Orientation orientation,
518 const QVariant &value, int role)
519{
520 if (section < 0 || orientation != Qt::Horizontal || !headerItem || section >= columnCount())
521 return false;
522
523 headerItem->setData(section, role, value);
524 return true;
525}
526
534Qt::ItemFlags QTreeModel::flags(const QModelIndex &index) const
535{
536 if (!index.isValid())
537 return rootItem->flags();
538 QTreeWidgetItem *itm = item(index);
539 Q_ASSERT(itm);
540 return itm->flags();
541}
542
551{
552 SkipSorting skipSorting(this);
553 sortPendingTimer.stop();
554
555 if (column < 0 || column >= columnCount())
556 return;
557
558 //layoutAboutToBeChanged and layoutChanged will be called by sortChildren
559 rootItem->sortChildren(column, order, true);
560}
561
566 int start, int end, const QModelIndex &parent)
567{
568 if (isChanging())
569 return;
570
571 sortPendingTimer.stop();
572
573 if (column < 0 || column >= columnCount())
574 return;
575
576 SkipSorting skipSorting(this);
577
579 if (!itm)
580 itm = rootItem;
581 QList<QTreeWidgetItem*> lst = itm->children;
582
583 int count = end - start + 1;
584 QList<QPair<QTreeWidgetItem *, int>> sorting(count);
585 for (int i = 0; i < count; ++i) {
586 sorting[i].first = lst.at(start + i);
587 sorting[i].second = start + i;
588 }
589
591 std::stable_sort(sorting.begin(), sorting.end(), compare);
592
593 QModelIndexList oldPersistentIndexes;
594 QModelIndexList newPersistentIndexes;
595 QList<QTreeWidgetItem*>::iterator lit = lst.begin();
596 bool changed = false;
597
598 for (int i = 0; i < count; ++i) {
599 int oldRow = sorting.at(i).second;
600
601 int tmpitepos = lit - lst.begin();
602 QTreeWidgetItem *item = lst.takeAt(oldRow);
603 if (tmpitepos > lst.size())
604 --tmpitepos;
605 lit = lst.begin() + tmpitepos;
606
607 lit = sortedInsertionIterator(lit, lst.end(), order, item);
608 int newRow = qMax<qsizetype>(lit - lst.begin(), 0);
609
610 if ((newRow < oldRow) && !(*item < *lst.at(oldRow - 1)) && !(*lst.at(oldRow - 1) < *item ))
611 newRow = oldRow;
612
613 lit = lst.insert(lit, item);
614 if (newRow != oldRow) {
615 // we are going to change the persistent indexes, so we need to prepare
616 if (!changed) { // this will only happen once
617 changed = true;
618 emit layoutAboutToBeChanged({parent}, QAbstractItemModel::VerticalSortHint); // the selection model needs to know
619 oldPersistentIndexes = persistentIndexList();
620 newPersistentIndexes = oldPersistentIndexes;
621 }
622 for (int j = i + 1; j < count; ++j) {
623 int otherRow = sorting.at(j).second;
624 if (oldRow < otherRow && newRow >= otherRow)
625 --sorting[j].second;
626 else if (oldRow > otherRow && newRow <= otherRow)
627 ++sorting[j].second;
628 }
629 for (int k = 0; k < newPersistentIndexes.size(); ++k) {
630 QModelIndex pi = newPersistentIndexes.at(k);
631 if (pi.parent() != parent)
632 continue;
633 int oldPersistentRow = pi.row();
634 int newPersistentRow = oldPersistentRow;
635 if (oldPersistentRow == oldRow)
636 newPersistentRow = newRow;
637 else if (oldRow < oldPersistentRow && newRow >= oldPersistentRow)
638 newPersistentRow = oldPersistentRow - 1;
639 else if (oldRow > oldPersistentRow && newRow <= oldPersistentRow)
640 newPersistentRow = oldPersistentRow + 1;
641 if (newPersistentRow != oldPersistentRow)
642 newPersistentIndexes[k] = createIndex(newPersistentRow,
643 pi.column(), pi.internalPointer());
644 }
645 }
646 }
647
648 if (changed) {
649 itm->children = lst;
650 changePersistentIndexList(oldPersistentIndexes, newPersistentIndexes);
652 }
653}
654
664bool QTreeModel::itemLessThan(const QPair<QTreeWidgetItem*,int> &left,
665 const QPair<QTreeWidgetItem*,int> &right)
666{
667 return *(left.first) < *(right.first);
668}
669
679bool QTreeModel::itemGreaterThan(const QPair<QTreeWidgetItem*,int> &left,
680 const QPair<QTreeWidgetItem*,int> &right)
681{
682 return *(right.first) < *(left.first);
683}
684
697
699{
700 auto v = view();
701 if (v)
702 return v->mimeTypes();
703 return {};
704}
705
707{
708 return QAbstractItemModel::mimeData(cachedIndexes);
709}
710
712{
713 QList<QTreeWidgetItem *> items;
714 std::transform(indexes.begin(), indexes.end(), std::back_inserter(items),
715 [this](const QModelIndex &idx) -> QTreeWidgetItem * { return item(idx); });
716
717 // Ensure we only have one item as an item may have more than
718 // one index selected if there is more than one column
719 std::sort(items.begin(), items.end());
720 items.erase(std::unique(items.begin(), items.end()), items.end());
721
722 // cachedIndexes is a little hack to avoid copying from QModelIndexList to
723 // QList<QTreeWidgetItem*> and back again in the view
724 cachedIndexes = indexes;
726 cachedIndexes.clear();
727 return mimeData;
728}
729
731 int row, int column, const QModelIndex &parent)
732{
733 if (row == -1 && column == -1)
734 row = rowCount(parent); // append
735 return view()->dropMimeData(item(parent), row, data, action);
736}
737
738Qt::DropActions QTreeModel::supportedDropActions() const
739{
740 return view()->supportedDropActions();
741}
742
744{
745 SkipSorting skipSorting(this); //this is kind of wrong, but not doing this would kill performance
747 QModelIndex right = index(item, item->columnCount() - 1);
749}
750
751bool QTreeModel::isChanging() const
752{
753 Q_D(const QTreeModel);
754 return !d->changes.isEmpty();
755}
756
763void QTreeModel::emitDataChanged(QTreeWidgetItem *item, int column, const QList<int> &roles)
764{
765 if (signalsBlocked())
766 return;
767
768 if (headerItem == item && column < item->columnCount()) {
769 if (column == -1)
771 else
773 return;
774 }
775
776 SkipSorting skipSorting(this); //This is a little bit wrong, but not doing it would kill performance
777
778 QModelIndex bottomRight, topLeft;
779 if (column == -1) {
780 topLeft = index(item, 0);
781 bottomRight = createIndex(topLeft.row(), columnCount() - 1, item);
782 } else {
783 topLeft = index(item, column);
784 bottomRight = topLeft;
785 }
786 emit dataChanged(topLeft, bottomRight, roles);
787}
788
790{
791 QModelIndex par = index(parent, 0);
792 beginInsertRows(par, row, row + count - 1);
793}
794
799
801{
802 Q_ASSERT(row >= 0);
803 Q_ASSERT(count > 0);
805 if (!parent)
806 parent = rootItem;
807 // now update the iterators
808 for (int i = 0; i < iterators.size(); ++i) {
809 for (int j = 0; j < count; j++) {
810 QTreeWidgetItem *c = parent->child(row + j);
811 iterators[i]->d_func()->ensureValidIterator(c);
812 }
813 }
814}
815
820
821void QTreeModel::sortItems(QList<QTreeWidgetItem*> *items, int column, Qt::SortOrder order)
822{
823 // see QTreeViewItem::operator<
825 if (isChanging())
826 return;
827
828 // store the original order of indexes
829 QList<QPair<QTreeWidgetItem *, int>> sorting(items->size());
830 for (int i = 0; i < sorting.size(); ++i) {
831 sorting[i].first = items->at(i);
832 sorting[i].second = i;
833 }
834
835 // do the sorting
837 std::stable_sort(sorting.begin(), sorting.end(), compare);
838
839 QModelIndexList fromList;
841 int colCount = columnCount();
842 for (int r = 0; r < sorting.size(); ++r) {
843 int oldRow = sorting.at(r).second;
844 if (oldRow == r)
845 continue;
846 QTreeWidgetItem *item = sorting.at(r).first;
847 items->replace(r, item);
848 for (int c = 0; c < colCount; ++c) {
849 QModelIndex from = createIndex(oldRow, c, item);
850 if (static_cast<QAbstractItemModelPrivate *>(d_ptr.data())->persistent.indexes.contains(from)) {
852 fromList << from;
853 toList << to;
854 }
855 }
856 }
858}
859
861{
862 if (ev->timerId() == sortPendingTimer.timerId()) {
863 executePendingSort();
864 } else {
866 }
867}
868
979{
980 const QTreeModel *model = treeModel();
981 if (!model || !view->selectionModel())
982 return;
983 const QModelIndex index = model->index(this, 0);
987 d->selected = select;
988}
989
999{
1000 return d->selected;
1001}
1002
1016{
1017 const QTreeModel *model = treeModel();
1018 if (!model)
1019 return;
1020 if (this == model->headerItem) {
1021 view->header()->setHidden(hide);
1022 } else {
1023 const QModelIndex index = view->d_func()->index(this);
1024 view->setRowHidden(index.row(), index.parent(), hide);
1025 }
1026 d->hidden = hide;
1027}
1028
1039{
1040 const QTreeModel *model = treeModel();
1041 if (!model)
1042 return false;
1043 if (this == model->headerItem)
1044 return view->header()->isHidden();
1045 if (view->d_func()->hiddenIndexes.isEmpty())
1046 return false;
1047 QTreeModel::SkipSorting skipSorting(model);
1048 return view->d_func()->isRowHidden(view->d_func()->index(this));
1049}
1050
1061{
1062 const QTreeModel *model = treeModel();
1063 if (!model)
1064 return;
1065 QTreeModel::SkipSorting skipSorting(model);
1066 view->setExpanded(view->d_func()->index(this), expand);
1067}
1068
1078{
1079 const QTreeModel *model = treeModel();
1080 if (!model)
1081 return false;
1082 QTreeModel::SkipSorting skipSorting(model);
1083 return view->isExpanded(view->d_func()->index(this));
1084}
1085
1096{
1097 const QTreeModel *model = treeModel();
1098 if (!model || this == model->headerItem)
1099 return; // We can't set the header items to spanning
1100 const QModelIndex index = model->index(this, 0);
1101 view->setFirstColumnSpanned(index.row(), index.parent(), span);
1102}
1103
1113{
1114 const QTreeModel *model = treeModel();
1115 if (!model || this == model->headerItem)
1116 return false;
1117 const QModelIndex index = model->index(this, 0);
1118 return view->isFirstColumnSpanned(index.row(), index.parent());
1119}
1120
1386
1396 : rtti(type), d(new QTreeWidgetItemPrivate(this))
1397{
1398 for (int i = 0; i < strings.size(); ++i)
1399 setText(i, strings.at(i));
1400}
1401
1412 : rtti(type), d(new QTreeWidgetItemPrivate(this))
1413{
1414 // do not set this->view here otherwise insertChild() will fail
1415 if (QTreeModel *model = treeModel(treeview)) {
1416 model->rootItem->addChild(this);
1417 values.reserve(model->headerItem->columnCount());
1418 }
1419}
1420
1432 : rtti(type), d(new QTreeWidgetItemPrivate(this))
1433{
1434 for (int i = 0; i < strings.size(); ++i)
1435 setText(i, strings.at(i));
1436 // do not set this->view here otherwise insertChild() will fail
1437 if (QTreeModel *model = treeModel(treeview)) {
1438 model->rootItem->addChild(this);
1439 values.reserve(model->headerItem->columnCount());
1440 }
1441}
1442
1452 : rtti(type), d(new QTreeWidgetItemPrivate(this))
1453{
1454 // do not set this->view here otherwise insertChild() will fail
1455 if (QTreeModel *model = treeModel(treeview)) {
1456 int i = model->rootItem->children.indexOf(after) + 1;
1457 model->rootItem->insertChild(i, this);
1458 values.reserve(model->headerItem->columnCount());
1459 }
1460}
1461
1468 : rtti(type), d(new QTreeWidgetItemPrivate(this))
1469{
1470 if (parent)
1471 parent->addChild(this);
1472}
1473
1481 : rtti(type), d(new QTreeWidgetItemPrivate(this))
1482{
1483 for (int i = 0; i < strings.size(); ++i)
1484 setText(i, strings.at(i));
1485 if (parent)
1486 parent->addChild(this);
1487}
1488
1498 : rtti(type), d(new QTreeWidgetItemPrivate(this))
1499{
1500 if (parent) {
1501 int i = parent->children.indexOf(after) + 1;
1502 parent->insertChild(i, this);
1503 }
1504}
1505
1515{
1516 QTreeModel *model = treeModel();
1517 QTreeModel::SkipSorting skipSorting(model);
1518
1519 if (par) {
1520 int i = par->children.indexOf(this);
1521 if (i >= 0) {
1522 if (model) model->beginRemoveItems(par, i, 1);
1523 // users _could_ do changes when connected to rowsAboutToBeRemoved,
1524 // so we check again to make sure 'i' is valid
1525 if (!par->children.isEmpty() && par->children.at(i) == this)
1526 par->children.takeAt(i);
1527 if (model) model->endRemoveItems();
1528 }
1529 } else if (model) {
1530 if (this == model->headerItem) {
1531 model->headerItem = nullptr;
1532 } else {
1533 int i = model->rootItem->children.indexOf(this);
1534 if (i >= 0) {
1535 model->beginRemoveItems(nullptr, i, 1);
1536 // users _could_ do changes when connected to rowsAboutToBeRemoved,
1537 // so we check again to make sure 'i' is valid
1538 if (!model->rootItem->children.isEmpty() && model->rootItem->children.at(i) == this)
1539 model->rootItem->children.takeAt(i);
1540 model->endRemoveItems();
1541 }
1542 }
1543 }
1544 // at this point the persistent indexes for the children should also be invalidated
1545 // since we invalidated the parent
1546 for (int i = 0; i < children.size(); ++i) {
1547 QTreeWidgetItem *child = children.at(i);
1548 // make sure the child does not try to remove itself from our children list
1549 child->par = nullptr;
1550 // make sure the child does not try to remove itself from the top level list
1551 child->view = nullptr;
1552 delete child;
1553 }
1554
1555 children.clear();
1556 delete d;
1557}
1558
1563{
1564 QTreeWidgetItem *copy = nullptr;
1565
1566 QStack<const QTreeWidgetItem*> stack;
1567 QStack<QTreeWidgetItem*> parentStack;
1568 stack.push(this);
1569 parentStack.push(0);
1570
1571 QTreeWidgetItem *root = nullptr;
1572 const QTreeWidgetItem *item = nullptr;
1573 QTreeWidgetItem *parent = nullptr;
1574 while (!stack.isEmpty()) {
1575 // get current item, and copied parent
1576 item = stack.pop();
1577 parent = parentStack.pop();
1578
1579 // copy item
1580 copy = new QTreeWidgetItem(*item);
1581 if (!root)
1582 root = copy;
1583
1584 // set parent and add to parents children list
1585 if (parent) {
1586 copy->par = parent;
1587 parent->children.insert(0, copy);
1588 }
1589
1590 for (int i = 0; i < item->childCount(); ++i) {
1591 stack.push(item->child(i));
1592 parentStack.push(copy);
1593 }
1594 }
1595 return root;
1596}
1597
1606{
1607 if (d->policy == policy)
1608 return;
1609 d->policy = policy;
1610
1611 if (!view)
1612 return;
1613
1615}
1616
1627
1637{
1638 const bool enable = (flags & Qt::ItemIsEnabled);
1639 const bool changedState = bool(itemFlags & Qt::ItemIsEnabled) != enable;
1640 const bool changedExplicit = d->disabled != !enable;
1641
1642 d->disabled = !enable;
1643
1644 if (enable && par && !(par->itemFlags & Qt::ItemIsEnabled)) // inherit from parent
1645 itemFlags = flags & ~Qt::ItemIsEnabled;
1646 else // this item is explicitly disabled or has no parent
1647 itemFlags = flags;
1648
1649 if (changedState && changedExplicit) { // if the propagate the change to the children
1650 QStack<QTreeWidgetItem*> parents;
1651 parents.push(this);
1652 while (!parents.isEmpty()) {
1653 QTreeWidgetItem *parent = parents.pop();
1654 for (int i = 0; i < parent->children.size(); ++i) {
1655 QTreeWidgetItem *child = parent->children.at(i);
1656 if (!child->d->disabled) { // if not explicitly disabled
1657 parents.push(child);
1658 if (enable)
1659 child->itemFlags = child->itemFlags | Qt::ItemIsEnabled;
1660 else
1661 child->itemFlags = child->itemFlags & ~Qt::ItemIsEnabled;
1662 child->itemChanged(); // ### we may want to optimize this
1663 }
1664 }
1665 }
1666 }
1667 itemChanged();
1668}
1669
1671{
1672 QTreeModel *model = item->treeModel();
1673 if (!model)
1674 return;
1675 QStack<QTreeWidgetItem *> parents;
1676 parents.push(item);
1677 while (!parents.isEmpty()) {
1678 QTreeWidgetItem *parent = parents.pop();
1679 if (parent->d->hidden) {
1680 const QModelIndex index = model->index(parent, 0);
1681 item->view->setRowHidden(index.row(), index.parent(), inserting);
1682 }
1683 for (int i = 0; i < parent->children.size(); ++i) {
1684 QTreeWidgetItem *child = parent->children.at(i);
1685 parents.push(child);
1686 }
1687 }
1688}
1689
1691{
1692 Q_ASSERT(item);
1693 const bool enable = item->par ? (item->par->itemFlags.testFlag(Qt::ItemIsEnabled)) : true;
1694
1695 QStack<QTreeWidgetItem*> parents;
1696 parents.push(item);
1697 while (!parents.isEmpty()) {
1698 QTreeWidgetItem *parent = parents.pop();
1699 if (!parent->d->disabled) { // if not explicitly disabled
1700 Qt::ItemFlags oldFlags = parent->itemFlags;
1701 if (enable)
1702 parent->itemFlags = parent->itemFlags | Qt::ItemIsEnabled;
1703 else
1704 parent->itemFlags = parent->itemFlags & ~Qt::ItemIsEnabled;
1705 if (parent->itemFlags != oldFlags)
1706 parent->itemChanged();
1707 }
1708
1709 for (int i = 0; i < parent->children.size(); ++i) {
1710 QTreeWidgetItem *child = parent->children.at(i);
1711 parents.push(child);
1712 }
1713 }
1714}
1727Qt::ItemFlags QTreeWidgetItem::flags() const
1728{
1729 return itemFlags;
1730}
1731
1743{
1744 if (column < 0)
1745 return;
1746
1747 QTreeModel *model = treeModel();
1748 switch (role) {
1749 case Qt::EditRole:
1750 case Qt::DisplayRole: {
1751 if (values.size() <= column) {
1752 if (model && this == model->headerItem)
1753 model->setColumnCount(column + 1);
1754 else
1755 values.resize(column + 1);
1756 }
1757 if (d->display.size() <= column) {
1758 for (int i = d->display.size() - 1; i < column - 1; ++i)
1759 d->display.append(QVariant());
1760 d->display.append(value);
1761 } else if (d->display[column] != value) {
1762 d->display[column] = value;
1763 } else {
1764 return; // value is unchanged
1765 }
1766 } break;
1767 case Qt::CheckStateRole:
1768 if ((itemFlags & Qt::ItemIsAutoTristate) && value != Qt::PartiallyChecked) {
1769 for (int i = 0; i < children.size(); ++i) {
1770 QTreeWidgetItem *child = children.at(i);
1771 if (child->data(column, role).isValid()) {// has a CheckState
1772 Qt::ItemFlags f = itemFlags; // a little hack to avoid multiple dataChanged signals
1773 itemFlags &= ~Qt::ItemIsAutoTristate;
1774 child->setData(column, role, value);
1775 itemFlags = f;
1776 }
1777 }
1778 }
1779 Q_FALLTHROUGH();
1780 default:
1781 if (column < values.size()) {
1782 bool found = false;
1783 const QList<QWidgetItemData> column_values = values.at(column);
1784 for (int i = 0; i < column_values.size(); ++i) {
1785 if (column_values.at(i).role == role) {
1786 if (column_values.at(i).value == value)
1787 return; // value is unchanged
1788 values[column][i].value = value;
1789 found = true;
1790 break;
1791 }
1792 }
1793 if (!found)
1794 values[column].append(QWidgetItemData(role, value));
1795 } else {
1796 if (model && this == model->headerItem)
1797 model->setColumnCount(column + 1);
1798 else
1799 values.resize(column + 1);
1800 values[column].append(QWidgetItemData(role, value));
1801 }
1802 }
1803
1804 if (model) {
1805 const QList<int> roles((role == Qt::DisplayRole || role == Qt::EditRole)
1806 ? QList<int>({ Qt::DisplayRole, Qt::EditRole })
1807 : QList<int>({ role }));
1808 model->emitDataChanged(this, column, roles);
1809 if (role == Qt::CheckStateRole) {
1811 for (p = par; p && (p->itemFlags & Qt::ItemIsAutoTristate); p = p->par)
1812 model->emitDataChanged(p, column, roles);
1813 }
1814 }
1815}
1816
1821{
1822 switch (role) {
1823 case Qt::EditRole:
1824 case Qt::DisplayRole:
1825 if (column >= 0 && column < d->display.size())
1826 return d->display.at(column);
1827 break;
1828 case Qt::CheckStateRole:
1829 // special case for check state in tristate
1830 if (children.size() && (itemFlags & Qt::ItemIsAutoTristate))
1831 return childrenCheckState(column);
1832 Q_FALLTHROUGH();
1833 default:
1834 if (column >= 0 && column < values.size()) {
1835 const QList<QWidgetItemData> &column_values = values.at(column);
1836 for (const auto &column_value : column_values) {
1837 if (column_value.role == role)
1838 return column_value.value;
1839 }
1840 }
1841 }
1842 return QVariant();
1843}
1844
1851{
1852 int column = view ? view->sortColumn() : 0;
1854 const QVariant v2 = other.data(column, Qt::DisplayRole);
1856}
1857
1858#ifndef QT_NO_DATASTREAM
1859
1866{
1867 // convert from streams written before we introduced display (4.2.0)
1868 if (in.version() < QDataStream::Qt_4_2) {
1869 d->display.clear();
1870 in >> values;
1871 // move the display value over to the display string list
1872 for (int column = 0; column < values.size(); ++column) {
1873 d->display << QVariant();
1874 for (int i = 0; i < values.at(column).size(); ++i) {
1875 if (values.at(column).at(i).role == Qt::DisplayRole) {
1876 d->display[column] = values.at(column).at(i).value;
1877 values[column].remove(i--);
1878 }
1879 }
1880 }
1881 } else {
1882 in >> values >> d->display;
1883 }
1884}
1885
1892{
1893 out << values << d->display;
1894}
1895#endif // QT_NO_DATASTREAM
1896
1908 : rtti(Type),
1911 itemFlags(other.itemFlags)
1912{
1913 d->display = other.d->display;
1914}
1915
1925{
1926 values = other.values;
1927 d->display = other.d->display;
1928 d->policy = other.d->policy;
1929 itemFlags = other.itemFlags;
1930 return *this;
1931}
1932
1939{
1940 if (child) {
1941 insertChild(children.size(), child);
1942 child->d->rowGuess = children.size() - 1;
1943 }
1944}
1945
1952{
1953 if (index < 0 || index > children.size() || child == nullptr || child->view != nullptr || child->par != nullptr)
1954 return;
1955
1956 if (QTreeModel *model = treeModel()) {
1957 QTreeModel::SkipSorting skipSorting(model);
1958 if (model->rootItem == this)
1959 child->par = nullptr;
1960 else
1961 child->par = this;
1962 if (view->isSortingEnabled()) {
1963 // do a delayed sort instead
1964 if (!model->sortPendingTimer.isActive())
1965 model->sortPendingTimer.start(0, model);
1966 }
1967 model->beginInsertItems(this, index, 1);
1968 int cols = model->columnCount();
1969 QStack<QTreeWidgetItem*> stack;
1970 stack.push(child);
1971 while (!stack.isEmpty()) {
1972 QTreeWidgetItem *i = stack.pop();
1973 i->view = view;
1974 i->values.reserve(cols);
1975 for (int c = 0; c < i->children.size(); ++c)
1976 stack.push(i->children.at(c));
1977 }
1978 children.insert(index, child);
1979 d->updateHiddenStatus(child, true);
1980 model->endInsertItems();
1981 } else {
1982 child->par = this;
1983 children.insert(index, child);
1984 }
1985 if (child->par)
1987}
1988
1997
2002{
2003 // we move this outside the check of the index to allow executing
2004 // pending sorts from inline functions, using this function (hack)
2005 QTreeModel *model = treeModel();
2006 if (model) {
2007 // This will trigger a layoutChanged signal, thus we might want to optimize
2008 // this function by not emitting the rowsRemoved signal etc to the view.
2009 // On the other hand we also need to make sure that the selectionmodel
2010 // is updated in case we take an item that is selected.
2011 model->skipPendingSort = false;
2012 model->executePendingSort();
2013 }
2014 if (index >= 0 && index < children.size()) {
2015 if (model) model->beginRemoveItems(this, index, 1);
2016 d->updateHiddenStatus(children.at(index), false);
2017 QTreeWidgetItem *item = children.takeAt(index);
2018 item->par = nullptr;
2019 QStack<QTreeWidgetItem*> stack;
2020 stack.push(item);
2021 while (!stack.isEmpty()) {
2022 QTreeWidgetItem *i = stack.pop();
2023 i->view = nullptr;
2024 for (int c = 0; c < i->children.size(); ++c)
2025 stack.push(i->children.at(c));
2026 }
2028 if (model) model->endRemoveRows();
2029 return item;
2030 }
2031 return nullptr;
2032}
2033
2041void QTreeWidgetItem::addChildren(const QList<QTreeWidgetItem*> &children)
2042{
2043 insertChildren(this->children.size(), children);
2044}
2045
2053void QTreeWidgetItem::insertChildren(int index, const QList<QTreeWidgetItem*> &children)
2054{
2055 if (index < 0 || index > this->children.size() || children.isEmpty())
2056 return;
2057
2058 if (view && view->isSortingEnabled()) {
2059 for (int n = 0; n < children.size(); ++n)
2060 insertChild(index, children.at(n));
2061 return;
2062 }
2063 QTreeModel *model = treeModel();
2064 QStack<QTreeWidgetItem*> stack;
2065 QList<QTreeWidgetItem*> itemsToInsert;
2066 for (int n = 0; n < children.size(); ++n) {
2067 QTreeWidgetItem *child = children.at(n);
2068 if (child->view || child->par)
2069 continue;
2070 itemsToInsert.append(child);
2071 if (view && model) {
2072 if (child->childCount() == 0)
2073 child->view = view;
2074 else
2075 stack.push(child);
2076 }
2077 if (model && (model->rootItem == this))
2078 child->par = nullptr;
2079 else
2080 child->par = this;
2081 }
2082 if (!itemsToInsert.isEmpty()) {
2083 while (!stack.isEmpty()) {
2084 QTreeWidgetItem *i = stack.pop();
2085 i->view = view;
2086 for (int c = 0; c < i->children.size(); ++c)
2087 stack.push(i->children.at(c));
2088 }
2089 if (model) model->beginInsertItems(this, index, itemsToInsert.size());
2090 for (int n = 0; n < itemsToInsert.size(); ++n) {
2091 QTreeWidgetItem *child = itemsToInsert.at(n);
2092 this->children.insert(index + n, child);
2093 if (child->par)
2095 d->updateHiddenStatus(child, true);
2096 }
2097 if (model) model->endInsertItems();
2098 }
2099}
2100
2106QList<QTreeWidgetItem*> QTreeWidgetItem::takeChildren()
2107{
2108 QList<QTreeWidgetItem*> removed;
2109 if (children.size() > 0) {
2110 QTreeModel *model = treeModel();
2111 if (model) {
2112 // This will trigger a layoutChanged signal, thus we might want to optimize
2113 // this function by not emitting the rowsRemoved signal etc to the view.
2114 // On the other hand we also need to make sure that the selectionmodel
2115 // is updated in case we take an item that is selected.
2116 model->executePendingSort();
2117 }
2118 if (model) model->beginRemoveItems(this, 0, children.size());
2119 for (int n = 0; n < children.size(); ++n) {
2120 QTreeWidgetItem *item = children.at(n);
2121 item->par = nullptr;
2122 QStack<QTreeWidgetItem*> stack;
2123 stack.push(item);
2124 while (!stack.isEmpty()) {
2125 QTreeWidgetItem *i = stack.pop();
2126 i->view = nullptr;
2127 for (int c = 0; c < i->children.size(); ++c)
2128 stack.push(i->children.at(c));
2129 }
2131 }
2132 removed = children;
2133 children.clear(); // detach
2134 if (model) model->endRemoveItems();
2135 }
2136 return removed;
2137}
2138
2139
2141{
2142 QTreeModel *model = q->treeModel();
2143 if (!model)
2144 return;
2145 model->sortItems(&q->children, column, order);
2146 if (climb) {
2148 for (; it != q->children.end(); ++it) {
2149 //here we call the private object's method to avoid emitting
2150 //the layoutAboutToBeChanged and layoutChanged signals
2151 (*it)->d->sortChildren(column, order, climb);
2152 }
2153 }
2154}
2155
2164{
2165 QTreeModel *model = treeModel();
2166 if (!model)
2167 return;
2168 if (model->isChanging())
2169 return;
2170 QTreeModel::SkipSorting skipSorting(model);
2171 int oldSortColumn = view->d_func()->explicitSortColumn;
2172 view->d_func()->explicitSortColumn = column;
2174 d->sortChildren(column, order, climb);
2176 view->d_func()->explicitSortColumn = oldSortColumn;
2177}
2178
2187QVariant QTreeWidgetItem::childrenCheckState(int column) const
2188{
2189 if (column < 0)
2190 return QVariant();
2191 bool checkedChildren = false;
2192 bool uncheckedChildren = false;
2193 for (const auto *child : children) {
2195 if (!value.isValid())
2196 return QVariant();
2197
2198 switch (static_cast<Qt::CheckState>(value.toInt()))
2199 {
2200 case Qt::Unchecked:
2201 uncheckedChildren = true;
2202 break;
2203 case Qt::Checked:
2204 checkedChildren = true;
2205 break;
2207 default:
2208 return Qt::PartiallyChecked;
2209 }
2210
2211 if (uncheckedChildren && checkedChildren)
2212 return Qt::PartiallyChecked;
2213 }
2214
2215 if (uncheckedChildren)
2216 return Qt::Unchecked;
2217 else if (checkedChildren)
2218 return Qt::Checked;
2219 else
2220 return QVariant(); // value was not defined
2221}
2222
2236{
2237 itemChanged();
2238}
2239
2243void QTreeWidgetItem::itemChanged()
2244{
2245 if (QTreeModel *model = treeModel())
2246 model->itemChanged(this);
2247}
2248
2252void QTreeWidgetItem::executePendingSort() const
2253{
2254 if (QTreeModel *model = treeModel())
2255 model->executePendingSort();
2256}
2257
2262QTreeModel *QTreeWidgetItem::treeModel(QTreeWidget *v) const
2263{
2264 if (!v)
2265 v = view;
2266 return (v ? qobject_cast<QTreeModel*>(v->model()) : nullptr);
2267}
2268
2269
2270#ifndef QT_NO_DATASTREAM
2281{
2282 item.write(out);
2283 return out;
2284}
2285
2296{
2297 item.read(in);
2298 return in;
2299}
2300#endif // QT_NO_DATASTREAM
2301
2302
2308
2310{
2311 Q_Q(QTreeWidget);
2312 emit q->itemPressed(item(index), index.column());
2313}
2314
2316{
2317 Q_Q(QTreeWidget);
2318 emit q->itemClicked(item(index), index.column());
2319}
2320
2322{
2323 Q_Q(QTreeWidget);
2324 emit q->itemDoubleClicked(item(index), index.column());
2325}
2326
2328{
2329 Q_Q(QTreeWidget);
2330 emit q->itemActivated(item(index), index.column());
2331}
2332
2334{
2335 Q_Q(QTreeWidget);
2336 emit q->itemEntered(item(index), index.column());
2337}
2338
2340{
2341 Q_Q(QTreeWidget);
2342 QTreeWidgetItem *indexItem = item(index);
2343 if (indexItem)
2344 emit q->itemChanged(indexItem, index.column());
2345}
2346
2348{
2349 Q_Q(QTreeWidget);
2350 emit q->itemExpanded(item(index));
2351}
2352
2354{
2355 Q_Q(QTreeWidget);
2356 emit q->itemCollapsed(item(index));
2357}
2358
2360 const QModelIndex &previous)
2361{
2362 Q_Q(QTreeWidget);
2363 QTreeWidgetItem *currentItem = item(current);
2364 QTreeWidgetItem *previousItem = item(previous);
2365 emit q->currentItemChanged(currentItem, previousItem);
2366}
2367
2376
2378{
2379 Q_Q(QTreeWidget);
2380 QModelIndexList indices = selected.indexes();
2381 int i;
2382 QTreeModel *m = treeModel();
2383 for (i = 0; i < indices.size(); ++i) {
2384 QTreeWidgetItem *item = m->item(indices.at(i));
2385 item->d->selected = true;
2386 }
2387
2388 indices = deselected.indexes();
2389 for (i = 0; i < indices.size(); ++i) {
2390 QTreeWidgetItem *item = m->item(indices.at(i));
2391 item->d->selected = false;
2392 }
2393
2394 emit q->itemSelectionChanged();
2395}
2396
2398 const QModelIndex &bottomRight)
2399{
2400 if (sortingEnabled && topLeft.isValid() && bottomRight.isValid()
2401 && !treeModel()->sortPendingTimer.isActive()) {
2403 if (column >= topLeft.column() && column <= bottomRight.column()) {
2405 treeModel()->ensureSorted(column, order, topLeft.row(),
2406 bottomRight.row(), topLeft.parent());
2407 }
2408 }
2409}
2410
2576 : QTreeView(*new QTreeWidgetPrivate(), parent)
2577{
2578 Q_D(QTreeWidget);
2579 QTreeView::setModel(new QTreeModel(1, this));
2580 d->connections = {
2605 };
2606 header()->setSectionsClickable(false);
2607}
2608
2614{
2615 Q_D(QTreeWidget);
2616 d->clearConnections();
2617}
2618
2619/*
2620 Returns the number of header columns in the view.
2621
2622 \sa sortColumn(), currentColumn(), topLevelItemCount()
2623*/
2624
2626{
2627 Q_D(const QTreeWidget);
2628 return d->model->columnCount();
2629}
2630
2631/*
2632 Sets the number of header \a columns in the tree widget.
2633*/
2634
2636{
2637 Q_D(QTreeWidget);
2638 if (columns < 0)
2639 return;
2640 d->treeModel()->setColumnCount(columns);
2641}
2642
2655{
2656 Q_D(const QTreeWidget);
2657 return d->treeModel()->rootItem;
2658}
2659
2668{
2669 Q_D(const QTreeWidget);
2670 return d->treeModel()->rootItem->child(index);
2671}
2672
2683{
2684 Q_D(const QTreeWidget);
2685 return d->treeModel()->rootItem->childCount();
2686}
2687
2697{
2698 Q_D(QTreeWidget);
2699 d->treeModel()->rootItem->insertChild(index, item);
2700}
2701
2713
2722{
2723 Q_D(QTreeWidget);
2724 return d->treeModel()->rootItem->takeChild(index);
2725}
2726
2734{
2735 Q_D(const QTreeWidget);
2736 d->treeModel()->executePendingSort();
2737 return d->treeModel()->rootItem->children.indexOf(item);
2738}
2739
2749void QTreeWidget::insertTopLevelItems(int index, const QList<QTreeWidgetItem*> &items)
2750{
2751 Q_D(QTreeWidget);
2752 d->treeModel()->rootItem->insertChildren(index, items);
2753}
2754
2760void QTreeWidget::addTopLevelItems(const QList<QTreeWidgetItem*> &items)
2761{
2763}
2764
2772{
2773 Q_D(const QTreeWidget);
2774 return d->treeModel()->headerItem;
2775}
2776
2787{
2788 Q_D(QTreeWidget);
2789 if (!item)
2790 return;
2791 item->view = this;
2792
2793 int oldCount = columnCount();
2794 if (oldCount < item->columnCount())
2795 d->treeModel()->beginInsertColumns(QModelIndex(), oldCount, item->columnCount() - 1);
2796 else if (oldCount > item->columnCount())
2797 d->treeModel()->beginRemoveColumns(QModelIndex(), item->columnCount(), oldCount - 1);
2798 delete d->treeModel()->headerItem;
2799 d->treeModel()->headerItem = item;
2800 if (oldCount < item->columnCount())
2801 d->treeModel()->endInsertColumns();
2802 else if (oldCount > item->columnCount())
2803 d->treeModel()->endRemoveColumns();
2804 d->treeModel()->headerDataChanged(Qt::Horizontal, 0, oldCount);
2805}
2806
2807
2817{
2818 Q_D(QTreeWidget);
2819 if (columnCount() < labels.size())
2820 setColumnCount(labels.size());
2821 QTreeWidgetItem *item = d->treeModel()->headerItem;
2822 for (int i = 0; i < labels.size(); ++i)
2823 item->setText(i, labels.at(i));
2824}
2825
2839{
2840 Q_D(const QTreeWidget);
2841 return d->item(currentIndex());
2842}
2843
2851{
2852 return currentIndex().column();
2853}
2854
2867
2879
2888 QItemSelectionModel::SelectionFlags command)
2889{
2890 Q_D(QTreeWidget);
2891 d->selectionModel->setCurrentIndex(d->index(item, column), command);
2892}
2893
2894
2902{
2903 Q_D(const QTreeWidget);
2904 return d->item(indexAt(p));
2905}
2906
2921{
2922 Q_D(const QTreeWidget);
2923 //the visual rect for an item is across all columns. So we need to determine
2924 //what is the first and last column and get their visual index rects
2925 const QModelIndex base = d->index(item);
2926 const int firstVisiblesection = header()->logicalIndexAt(- header()->offset());
2927 const int lastVisibleSection = header()->logicalIndexAt(header()->length() - header()->offset() - 1);
2928 const QModelIndex first = base.sibling(base.row(), firstVisiblesection);
2929 const QModelIndex last = base.sibling(base.row(), lastVisibleSection);
2930 return visualRect(first) | visualRect(last);
2931}
2932
2941{
2942 Q_D(const QTreeWidget);
2943 return (d->explicitSortColumn != -1
2944 ? d->explicitSortColumn
2946}
2947
2956{
2957 Q_D(QTreeWidget);
2959 d->model->sort(column, order);
2960}
2961
2967{
2968 Q_D(QTreeWidget);
2969 edit(d->index(item, column));
2970}
2971
2983
2998
3013
3021{
3022 Q_D(const QTreeWidget);
3024}
3025
3054
3060QList<QTreeWidgetItem*> QTreeWidget::selectedItems() const
3061{
3062 Q_D(const QTreeWidget);
3063 const QModelIndexList indexes = selectionModel()->selectedIndexes();
3064 QList<QTreeWidgetItem*> items;
3065 items.reserve(indexes.size());
3066 QDuplicateTracker<QTreeWidgetItem *> seen(indexes.size());
3067 for (const auto &index : indexes) {
3068 QTreeWidgetItem *item = d->item(index);
3069 if (item->isHidden() || seen.hasSeen(item))
3070 continue;
3071 items.append(item);
3072 }
3073 return items;
3074}
3075
3079QList<QTreeWidgetItem*> QTreeWidget::findItems(const QString &text, Qt::MatchFlags flags, int column) const
3080{
3081 Q_D(const QTreeWidget);
3082 QModelIndexList indexes = d->model->match(model()->index(0, column, QModelIndex()),
3083 Qt::DisplayRole, text, -1, flags);
3084 QList<QTreeWidgetItem*> items;
3085 const int indexesSize = indexes.size();
3086 items.reserve(indexesSize);
3087 for (int i = 0; i < indexesSize; ++i)
3088 items.append(d->item(indexes.at(i)));
3089 return items;
3090}
3091
3092
3099{
3100 Q_D(const QTreeWidget);
3101 if (item == d->treeModel()->headerItem)
3102 return nullptr;
3103 const QModelIndex index = d->index(item);
3104 const QModelIndex above = indexAbove(index);
3105 return d->item(above);
3106}
3107
3114{
3115 Q_D(const QTreeWidget);
3116 if (item == d->treeModel()->headerItem)
3117 return nullptr;
3118 const QModelIndex index = d->index(item);
3119 const QModelIndex below = indexBelow(index);
3120 return d->item(below);
3121}
3122
3127{
3128 Q_D(QTreeWidget);
3130 QItemSelection newSelection = selectionModel->selection();
3131 if (!newSelection.isEmpty())
3132 d->selectionChanged(newSelection, QItemSelection());
3133}
3134
3146
3154{
3155 Q_D(QTreeWidget);
3156 QTreeModel::SkipSorting skipSorting(d->treeModel());
3157 expand(d->index(item));
3158}
3159
3167{
3168 Q_D(QTreeWidget);
3169 QTreeModel::SkipSorting skipSorting(d->treeModel());
3170 collapse(d->index(item));
3171}
3172
3183{
3184 Q_D(QTreeWidget);
3185 selectionModel()->clear();
3186 d->treeModel()->clear();
3187}
3188
3196{
3197 return model()->QAbstractItemModel::mimeTypes();
3198}
3199
3208QMimeData *QTreeWidget::mimeData(const QList<QTreeWidgetItem *> &items) const
3209{
3210 Q_D(const QTreeWidget);
3211 if (d->treeModel()->cachedIndexes.isEmpty()) {
3212 QList<QModelIndex> indexes;
3213 for (const auto *item : items) {
3214 if (Q_UNLIKELY(!item)) {
3215 qWarning("QTreeWidget::mimeData: Null-item passed");
3216 return nullptr;
3217 }
3218
3219 for (int c = 0; c < item->values.size(); ++c) {
3221 if (Q_UNLIKELY(!index.isValid())) {
3222 qWarning() << "QTreeWidget::mimeData: No index associated with item :" << item;
3223 return nullptr;
3224 }
3225 indexes << index;
3226 }
3227 }
3228 return d->model->QAbstractItemModel::mimeData(indexes);
3229 }
3230 return d->treeModel()->internalMimeData();
3231}
3232
3244 const QMimeData *data, Qt::DropAction action)
3245{
3246 QModelIndex idx;
3247 if (parent) idx = indexFromItem(parent);
3248 return model()->QAbstractItemModel::dropMimeData(data, action , index, 0, idx);
3249}
3250
3257{
3258 return model()->QAbstractItemModel::supportedDropActions() | Qt::MoveAction;
3259}
3260
3269{
3270 Q_D(const QTreeWidget);
3271 return d->index(item, column);
3272}
3273
3280{
3281 Q_D(const QTreeWidget);
3282 return d->item(index);
3283}
3284
3285#if QT_CONFIG(draganddrop)
3287void QTreeWidget::dropEvent(QDropEvent *event) {
3288 Q_D(QTreeWidget);
3289 if (event->source() == this && (event->dropAction() == Qt::MoveAction ||
3290 dragDropMode() == QAbstractItemView::InternalMove)) {
3291 QModelIndex topIndex;
3292 int col = -1;
3293 int row = -1;
3294 // check whether a subclass has already accepted the event, ie. moved the data
3295 if (!event->isAccepted() && d->dropOn(event, &row, &col, &topIndex)) {
3296 const QList<QModelIndex> idxs = selectedIndexes();
3297 QList<QPersistentModelIndex> indexes;
3298 const int indexesCount = idxs.size();
3299 indexes.reserve(indexesCount);
3300 for (const auto &idx : idxs)
3301 indexes.append(idx);
3302
3303 if (indexes.contains(topIndex))
3304 return;
3305
3306 // When removing items the drop location could shift
3307 QPersistentModelIndex dropRow = model()->index(row, col, topIndex);
3308
3309 // Remove the items
3310 QList<QTreeWidgetItem *> taken;
3311 for (const auto &index : indexes) {
3313 if (!parent || !parent->parent()) {
3314 taken.append(takeTopLevelItem(index.row()));
3315 } else {
3316 taken.append(parent->parent()->takeChild(index.row()));
3317 }
3318 }
3319
3320 // insert them back in at their new positions
3321 for (int i = 0; i < indexes.size(); ++i) {
3322 // Either at a specific point or appended
3323 if (row == -1) {
3324 if (topIndex.isValid()) {
3325 QTreeWidgetItem *parent = itemFromIndex(topIndex);
3326 parent->insertChild(parent->childCount(), taken.takeFirst());
3327 } else {
3328 insertTopLevelItem(topLevelItemCount(), taken.takeFirst());
3329 }
3330 } else {
3331 int r = dropRow.row() >= 0 ? dropRow.row() : row;
3332 if (topIndex.isValid()) {
3333 QTreeWidgetItem *parent = itemFromIndex(topIndex);
3334 parent->insertChild(qMin(r, parent->childCount()), taken.takeFirst());
3335 } else {
3336 insertTopLevelItem(qMin(r, topLevelItemCount()), taken.takeFirst());
3337 }
3338 }
3339 }
3340
3341 event->accept();
3342 }
3343 // either we or a subclass accepted the move event, so assume that the data was
3344 // moved and that QAbstractItemView shouldn't remove the source when QDrag::exec returns
3345 if (event->isAccepted())
3346 d->dropEventMoved = true;
3347 }
3348
3349 QTreeView::dropEvent(event);
3350}
3351#endif
3352
3358{
3359 Q_ASSERT(!"QTreeWidget::setModel() - Changing the model of the QTreeWidget is not allowed.");
3360}
3361
3366{
3367 Q_D(QTreeWidget);
3368 if (e->type() == QEvent::Polish)
3369 d->treeModel()->executePendingSort();
3370 return QTreeView::event(e);
3371}
3372
3377{
3378 q_func()->executePendingSort();
3379}
3380
3382
3383#include "moc_qtreewidget.cpp"
3384#include "moc_qtreewidget_p.cpp"
static bool variantLessThan(const QVariant &v1, const QVariant &v2)
struct QAbstractItemModelPrivate::Persistent persistent
Q_INVOKABLE int const QModelIndex & parent
Returns the parent of the model item with the given index.
void endResetModel()
Completes a model reset operation.
void columnsRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted after columns have been removed from the model.
void endRemoveRows()
Ends a row removal operation.
QModelIndexList persistentIndexList() const
void beginRemoveColumns(const QModelIndex &parent, int first, int last)
Begins a column removal operation.
void changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to)
void layoutAboutToBeChanged(const QList< QPersistentModelIndex > &parents=QList< QPersistentModelIndex >(), QAbstractItemModel::LayoutChangeHint hint=QAbstractItemModel::NoLayoutChangeHint)
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles=QList< int >())
This signal is emitted whenever the data in an existing item changes.
virtual QMimeData * mimeData(const QModelIndexList &indexes) const
Returns an object that contains serialized items of data corresponding to the list of indexes specifi...
void layoutChanged(const QList< QPersistentModelIndex > &parents=QList< QPersistentModelIndex >(), QAbstractItemModel::LayoutChangeHint hint=QAbstractItemModel::NoLayoutChangeHint)
bool checkIndex(const QModelIndex &index, CheckIndexOptions options=CheckIndexOption::NoOption) const
void headerDataChanged(Qt::Orientation orientation, int first, int last)
This signal is emitted whenever a header is changed.
void beginInsertColumns(const QModelIndex &parent, int first, int last)
Begins a column insertion operation.
void endInsertRows()
Ends a row insertion operation.
void beginResetModel()
Begins a model reset operation.
void endRemoveColumns()
Ends a column removal operation.
QModelIndex createIndex(int row, int column, const void *data=nullptr) const
Creates a model index for the given row and column with the internal pointer ptr.
void endInsertColumns()
Ends a column insertion operation.
void beginRemoveRows(const QModelIndex &parent, int first, int last)
Begins a row removal operation.
virtual Q_INVOKABLE QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const =0
Returns the index of the item in the model specified by the given row, column and parent index.
void beginInsertRows(const QModelIndex &parent, int first, int last)
Begins a row insertion operation.
QWidget * indexWidget(const QModelIndex &index) const
void activated(const QModelIndex &index)
This signal is emitted when the item specified by index is activated by the user.
QAbstractItemModel * model() const
Returns the model that this view is presenting.
void setCurrentIndex(const QModelIndex &index)
Sets the current item to be the item at index.
void doubleClicked(const QModelIndex &index)
This signal is emitted when a mouse button is double-clicked.
bool event(QEvent *event) override
\reimp
void entered(const QModelIndex &index)
This signal is emitted when the mouse cursor enters the item specified by index.
QModelIndex currentIndex() const
Returns the model index of the current item.
bool isPersistentEditorOpen(const QModelIndex &index) const
void setIndexWidget(const QModelIndex &index, QWidget *widget)
void scheduleDelayedItemsLayout()
Schedules a layout of the items in the view to be executed when the event processing starts.
void openPersistentEditor(const QModelIndex &index)
Opens a persistent editor on the item at the given index.
void pressed(const QModelIndex &index)
This signal is emitted when a mouse button is pressed.
ScrollHint
\value EnsureVisible Scroll to ensure that the item is visible.
void clicked(const QModelIndex &index)
This signal is emitted when a mouse button is left-clicked.
QItemSelectionModel * selectionModel() const
Returns the current selection model.
void closePersistentEditor(const QModelIndex &index)
Closes the persistent editor for the item at the given index.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Returns the index of the data in row and column with parent.
int timerId() const noexcept
Returns the timer's ID.
Definition qbasictimer.h:35
void stop()
Stops the timer.
\inmodule QtCore\reentrant
Definition qdatastream.h:46
\inmodule QtCore
Definition qcoreevent.h:45
Type type() const
Returns the event type.
Definition qcoreevent.h:304
void setSectionsClickable(bool clickable)
Set \l sectionsClickable to clickable.
void setSortIndicator(int logicalIndex, Qt::SortOrder order)
Sets the sort indicator for the section specified by the given logicalIndex in the direction specifie...
Qt::SortOrder sortIndicatorOrder() const
Returns the order for the sort indicator.
int logicalIndexAt(int position) const
Returns the section that covers the given position in the viewport.
int sortIndicatorSection() const
Returns the logical index of the section that has a sort indicator.
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
This signal is emitted whenever the selection changes.
void currentChanged(const QModelIndex &current, const QModelIndex &previous)
This signal is emitted whenever the current item changes.
QModelIndexList selectedIndexes
virtual void select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
Selects the model item index using the specified command, and emits selectionChanged().
virtual void clear()
Clears the selection model.
\inmodule QtCore
Q_CORE_EXPORT QModelIndexList indexes() const
Returns a list of model indexes that correspond to the selected items.
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
iterator erase(const_iterator begin, const_iterator end)
Definition qlist.h:889
iterator insert(qsizetype i, parameter_type t)
Definition qlist.h:488
iterator end()
Definition qlist.h:626
T takeAt(qsizetype i)
Definition qlist.h:609
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
iterator begin()
Definition qlist.h:625
void reserve(qsizetype size)
Definition qlist.h:753
void replace(qsizetype i, parameter_type t)
Definition qlist.h:543
void resize(qsizetype size)
Definition qlist.h:403
const_iterator cend() const noexcept
Definition qlist.h:631
void append(parameter_type t)
Definition qlist.h:458
const_iterator cbegin() const noexcept
Definition qlist.h:630
void clear()
Definition qlist.h:434
\inmodule QtCore Represents a handle to a signal-slot (or signal-functor) connection.
\inmodule QtCore
Definition qmimedata.h:16
\inmodule QtCore
constexpr int row() const noexcept
Returns the row this model index refers to.
QModelIndex parent() const
Returns the parent of the model index, or QModelIndex() if it has no parent.
constexpr int column() const noexcept
Returns the column this model index refers to.
constexpr bool isValid() const noexcept
Returns {true} if this model index is valid; otherwise returns {false}.
static QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot, Qt::ConnectionType type=Qt::AutoConnection)
Definition qobject_p.h:299
const QObjectList & children() const
Returns a list of child objects.
Definition qobject.h:201
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
virtual void timerEvent(QTimerEvent *event)
This event handler can be reimplemented in a subclass to receive timer events for the object.
Definition qobject.cpp:1470
bool signalsBlocked() const noexcept
Returns true if signals are blocked; otherwise returns false.
Definition qobject.h:135
QScopedPointer< QObjectData > d_ptr
Definition qobject.h:373
\inmodule QtCore\reentrant
Definition qpoint.h:25
\inmodule QtCore\reentrant
Definition qrect.h:30
T * data() const noexcept
Returns the value of the pointer referenced by this object.
iterator begin()
Definition qset.h:136
iterator end()
Definition qset.h:140
int columnCount(const QModelIndex &parent=QModelIndex()) const override
\reimp
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:8084
\inmodule QtCore
Definition qcoreevent.h:366
bool operator()(QTreeWidgetItem *i1, QTreeWidgetItem *i2) const
bool operator()(QTreeWidgetItem *i1, QTreeWidgetItem *i2) const
void executePendingOperations() const override
see QTBUG-94546
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) override
void ensureSorted(int column, Qt::SortOrder order, int start, int end, const QModelIndex &parent)
int rowCount(const QModelIndex &parent) const override
bool setData(const QModelIndex &index, const QVariant &value, int role) override
bool insertColumns(int column, int count, const QModelIndex &) override
QTreeWidget * view() const
void emitDataChanged(QTreeWidgetItem *item, int column, const QList< int > &roles)
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
void endInsertItems()
void itemChanged(QTreeWidgetItem *item)
void setColumnCount(int columns)
friend class QTreeWidgetItem
bool insertRows(int row, int count, const QModelIndex &) override
void sortItems(QList< QTreeWidgetItem * > *items, int column, Qt::SortOrder order)
QMimeData * internalMimeData() const
QTreeWidgetItem * item(const QModelIndex &index) const
Qt::DropActions supportedDropActions() const override
QMimeData * mimeData(const QModelIndexList &indexes) const override
Returns an object that contains serialized items of data corresponding to the list of indexes specifi...
QTreeModel(int columns=0, QTreeWidget *parent=nullptr)
int columnCount(const QModelIndex &parent=QModelIndex()) const override
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
void sort(int column, Qt::SortOrder order) override
static bool itemLessThan(const QPair< QTreeWidgetItem *, int > &left, const QPair< QTreeWidgetItem *, int > &right)
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
Qt::ItemFlags flags(const QModelIndex &index) const override
\reimp
bool clearItemData(const QModelIndex &index) override
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
Handles the data supplied by a drag and drop operation that ended with the given action.
static QList< QTreeWidgetItem * >::iterator sortedInsertionIterator(const QList< QTreeWidgetItem * >::iterator &begin, const QList< QTreeWidgetItem * >::iterator &end, Qt::SortOrder order, QTreeWidgetItem *item)
QStringList mimeTypes() const override
Returns the list of allowed MIME types.
QMap< int, QVariant > itemData(const QModelIndex &index) const override
Returns a map with values for all predefined roles in the model for the item at the given index.
QModelIndex index(const QTreeWidgetItem *item, int column) const
bool hasChildren(const QModelIndex &parent) const override
Returns {true} if parent has any children; otherwise returns {false}.
void timerEvent(QTimerEvent *) override
This event handler can be reimplemented in a subclass to receive timer events for the object.
void beginRemoveItems(QTreeWidgetItem *parent, int row, int count)
void beginInsertItems(QTreeWidgetItem *parent, int row, int count)
void endRemoveItems()
static bool itemGreaterThan(const QPair< QTreeWidgetItem *, int > &left, const QPair< QTreeWidgetItem *, int > &right)
QHeaderView * header
The QTreeView class provides a default model/view implementation of a tree view.
Definition qtreeview.h:20
bool isSortingEnabled() const
void expand(const QModelIndex &index)
Expands the model item specified by the index.
void setSelectionModel(QItemSelectionModel *selectionModel) override
\reimp
void collapse(const QModelIndex &index)
Collapses the model item specified by the index.
void setModel(QAbstractItemModel *model) override
\reimp
QModelIndex indexBelow(const QModelIndex &index) const
Returns the model index of the item below index.
bool isExpanded(const QModelIndex &index) const
Returns true if the model item index is expanded; otherwise returns false.
QHeaderView * header() const
Returns the header for the tree view.
void setExpanded(const QModelIndex &index, bool expand)
Sets the item referred to by index to either collapse or expanded, depending on the value of expanded...
QModelIndex indexAt(const QPoint &p) const override
\reimp
QModelIndex indexAbove(const QModelIndex &index) const
Returns the model index of the item above index.
void setFirstColumnSpanned(int row, const QModelIndex &parent, bool span)
QModelIndexList selectedIndexes() const override
\reimp
void collapsed(const QModelIndex &index)
This signal is emitted when the item specified by index is collapsed.
void scrollTo(const QModelIndex &index, ScrollHint hint=EnsureVisible) override
Scroll the contents of the tree view until the given model item index is visible.
void setRowHidden(int row, const QModelIndex &parent, bool hide)
If hide is true the row with the given parent is hidden, otherwise the row is shown.
bool isRowHidden(int row, const QModelIndex &parent) const
Returns true if the item in the given row of the parent is hidden; otherwise returns false.
QRect visualRect(const QModelIndex &index) const override
Returns the rectangle on the viewport occupied by the item at index.
bool isFirstColumnSpanned(int row, const QModelIndex &parent) const
void expanded(const QModelIndex &index)
This signal is emitted when the item specified by index is expanded.
void sortChildren(int column, Qt::SortOrder order, bool climb)
void updateHiddenStatus(QTreeWidgetItem *item, bool inserting)
QTreeWidgetItem::ChildIndicatorPolicy policy
void propagateDisabled(QTreeWidgetItem *item)
The QTreeWidgetItem class provides an item for use with the QTreeWidget convenience class.
Definition qtreewidget.h:23
void setChildIndicatorPolicy(QTreeWidgetItem::ChildIndicatorPolicy policy)
Sets the item indicator policy.
void insertChildren(int index, const QList< QTreeWidgetItem * > &children)
void setExpanded(bool expand)
void setHidden(bool hide)
void setText(int column, const QString &text)
Sets the text to be displayed in the given column to the given text.
QTreeWidgetItem & operator=(const QTreeWidgetItem &other)
Assigns other's data and flags to this item.
QTreeWidgetItem * child(int index) const
Returns the item at the given index in the list of the item's children.
bool isFirstColumnSpanned() const
bool isSelected() const
QTreeWidgetItem * takeChild(int index)
Removes the item at index and returns it, otherwise return 0.
virtual bool operator<(const QTreeWidgetItem &other) const
Returns true if the text in the item is less than the text in the other item, otherwise returns false...
virtual void setData(int column, int role, const QVariant &value)
Sets the value for the item's column and role to the given value.
void setFirstColumnSpanned(bool span)
QTreeWidgetItem(int type=Type)
Constructs a tree widget item of the specified type.
virtual void read(QDataStream &in)
Reads the item from stream in.
QTreeWidgetItem * parent() const
Returns the item's parent.
void insertChild(int index, QTreeWidgetItem *child)
Inserts the child item at index in the list of children.
void addChildren(const QList< QTreeWidgetItem * > &children)
void setFlags(Qt::ItemFlags flags)
Sets the flags for the item to the given flags.
QDataStream & operator<<(QDataStream &out, const QTreeWidgetItem &item)
Writes the tree widget item item to stream out.
bool isHidden() const
void sortChildren(int column, Qt::SortOrder order)
@ DontShowIndicatorWhenChildless
Definition qtreewidget.h:61
QDataStream & operator>>(QDataStream &in, QTreeWidgetItem &item)
Reads a tree widget item from stream in into item.
int childCount() const
Returns the number of child items.
virtual ~QTreeWidgetItem()
Destroys this tree widget item.
void setSelected(bool select)
Qt::ItemFlags flags() const
Returns the flags used to describe the item.
void removeChild(QTreeWidgetItem *child)
Removes the given item indicated by child.
QTreeWidgetItem::ChildIndicatorPolicy childIndicatorPolicy() const
Returns the item indicator policy.
bool isExpanded() const
int columnCount() const
Returns the number of columns in the item.
void addChild(QTreeWidgetItem *child)
Appends the child item to the list of children.
virtual QVariant data(int column, int role) const
Returns the value for the item's column and role.
virtual void write(QDataStream &out) const
Writes the item to stream out.
virtual QTreeWidgetItem * clone() const
Creates a deep copy of the item and of its children.
QList< QTreeWidgetItem * > takeChildren()
void emitItemPressed(const QModelIndex &index)
QTreeModel * treeModel() const
void emitItemChanged(const QModelIndex &index)
std::array< QMetaObject::Connection, 12 > connections
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
void emitCurrentItemChanged(const QModelIndex &previous, const QModelIndex &index)
void emitItemEntered(const QModelIndex &index)
void emitItemExpanded(const QModelIndex &index)
void emitItemActivated(const QModelIndex &index)
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
void emitItemClicked(const QModelIndex &index)
void emitItemCollapsed(const QModelIndex &index)
void emitItemDoubleClicked(const QModelIndex &index)
The QTreeWidget class provides a tree view that uses a predefined tree model.
void expandItem(const QTreeWidgetItem *item)
Expands the item.
void addTopLevelItems(const QList< QTreeWidgetItem * > &items)
Appends the list of items as a top-level items in the widget.
QTreeWidgetItem * topLevelItem(int index) const
Returns the top level item at the given index, or \nullptr if the item does not exist.
~QTreeWidget()
Destroys the tree widget and all its items.
QModelIndex indexFromItem(const QTreeWidgetItem *item, int column=0) const
Returns the QModelIndex associated with the given item in the given column.
void sortItems(int column, Qt::SortOrder order)
Sorts the items in the widget in the specified order by the values in the given column.
void closePersistentEditor(QTreeWidgetItem *item, int column=0)
Closes the persistent editor for the item in the given column.
QTreeWidgetItem * invisibleRootItem() const
QList< QTreeWidgetItem * > findItems(const QString &text, Qt::MatchFlags flags, int column=0) const
Returns a list of items that match the given text, using the given flags, in the given column.
QRect visualItemRect(const QTreeWidgetItem *item) const
Returns the rectangle on the viewport occupied by the item at item.
virtual bool dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action)
Handles the data supplied by a drag and drop operation that ended with the given action in the index ...
void addTopLevelItem(QTreeWidgetItem *item)
bool event(QEvent *e) override
\reimp
QWidget * itemWidget(QTreeWidgetItem *item, int column) const
void collapseItem(const QTreeWidgetItem *item)
Closes the item.
QTreeWidgetItem * takeTopLevelItem(int index)
Removes the top-level item at the given index in the tree and returns it, otherwise returns \nullptr;...
virtual QMimeData * mimeData(const QList< QTreeWidgetItem * > &items) const
Returns an object that contains a serialized description of the specified items.
friend class QTreeModel
void clear()
Clears the tree widget by removing all of its items and selections.
void openPersistentEditor(QTreeWidgetItem *item, int column=0)
Opens a persistent editor for the item in the given column.
QTreeWidget(QWidget *parent=nullptr)
Constructs a tree widget with the given parent.
virtual QStringList mimeTypes() const
Returns a list of MIME types that can be used to describe a list of treewidget items.
QTreeWidgetItem * itemAbove(const QTreeWidgetItem *item) const
void insertTopLevelItems(int index, const QList< QTreeWidgetItem * > &items)
void setSelectionModel(QItemSelectionModel *selectionModel) override
\reimp
void setItemWidget(QTreeWidgetItem *item, int column, QWidget *widget)
QList< QTreeWidgetItem * > selectedItems() const
Returns a list of all selected non-hidden items.
void editItem(QTreeWidgetItem *item, int column=0)
Starts editing the item in the given column if it is editable.
QTreeWidgetItem * itemAt(const QPoint &p) const
Returns a pointer to the item at the coordinates p.
int columnCount
the number of columns displayed in the tree widget
void setCurrentItem(QTreeWidgetItem *item)
Sets the current item in the tree widget.
void insertTopLevelItem(int index, QTreeWidgetItem *item)
Inserts the item at index in the top level in the view.
QTreeWidgetItem * headerItem() const
Returns the item used for the tree widget's header.
void setModel(QAbstractItemModel *model) override
\reimp
void setHeaderItem(QTreeWidgetItem *item)
Sets the header item for the tree widget.
int sortColumn() const
int indexOfTopLevelItem(QTreeWidgetItem *item) const
Returns the index of the given top-level item, or -1 if the item cannot be found.
QTreeWidgetItem * itemFromIndex(const QModelIndex &index) const
Returns a pointer to the QTreeWidgetItem associated with the given index.
QTreeWidgetItem * itemBelow(const QTreeWidgetItem *item) const
QTreeWidgetItem * currentItem() const
Returns the current item in the tree widget.
virtual Qt::DropActions supportedDropActions() const
Returns the drop actions supported by this view.
void scrollToItem(const QTreeWidgetItem *item, QAbstractItemView::ScrollHint hint=EnsureVisible)
Ensures that the item is visible, scrolling the view if necessary using the specified hint.
int topLevelItemCount
the number of top-level items
bool isPersistentEditorOpen(QTreeWidgetItem *item, int column=0) const
void setColumnCount(int columns)
void setHeaderLabels(const QStringList &labels)
Adds a column in the header for each item in the labels list, and sets the label for each column.
int currentColumn() const
\inmodule QtCore
Definition qvariant.h:65
T value() const &
Definition qvariant.h:516
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:714
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
#define this
Definition dialogs.cpp:9
QOpenGLWidget * widget
[1]
QString text
list append(new Employee("Blackpool", "Stephen"))
QSet< QString >::iterator it
struct wl_display * display
Definition linuxdmabuf.h:41
Combined button and popup list for selecting options.
Definition qcompare.h:63
CheckState
@ Unchecked
@ Checked
@ PartiallyChecked
Orientation
Definition qnamespace.h:98
@ Horizontal
Definition qnamespace.h:99
@ EditRole
@ CheckStateRole
@ DisplayRole
SortOrder
Definition qnamespace.h:121
@ AscendingOrder
Definition qnamespace.h:122
DropAction
@ MoveAction
@ ItemIsEnabled
@ ItemIsDropEnabled
@ ItemIsAutoTristate
static jboolean copy(JNIEnv *, jobject)
#define Q_FALLTHROUGH()
#define Q_UNLIKELY(x)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection * connection
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qWarning
Definition qlogging.h:166
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
GLint GLfloat GLfloat GLfloat v2
GLenum GLsizei GLsizei GLint * values
[15]
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLboolean r
[2]
GLuint GLuint end
GLsizei const GLchar ** strings
[1]
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLdouble GLdouble right
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat f
GLint left
GLenum type
GLbitfield flags
GLint GLfloat GLfloat v1
GLboolean enable
GLuint start
GLenum GLuint GLintptr offset
GLint first
GLfloat n
GLsizei GLenum const void * indices
GLenum GLenum GLsizei void GLsizei void * column
struct _cl_event * event
const GLubyte * c
GLuint in
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLenum GLenum GLsizei void * row
GLenum GLenum GLsizei void GLsizei void void * span
GLfloat GLfloat p
[1]
GLfixed GLfixed GLint GLint order
const QQuickItem * rootItem(const I &item)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
static QList< QVariant > toList(char **buf, int count)
static QT_BEGIN_NAMESPACE QVariant hint(QPlatformIntegration::StyleHint h)
#define emit
#define Q_UNUSED(x)
static int compare(quint64 a, quint64 b)
static const uint base
Definition qurlidna.cpp:20
QSqlQueryModel * model
[16]
QTextStream out(stdout)
[7]
QMimeData * mimeData
QObject::connect nullptr
QSharedPointer< T > other(t)
[5]
QGraphicsItem * item
edit hide()
selection select(topLeft, bottomRight)
QList< QTreeWidgetItem * > items
QLayoutItem * child
[0]
QSizePolicy policy
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
Definition qlist.h:962
qsizetype lastIndexOf(const AT &t, qsizetype from=-1) const noexcept
Definition qlist.h:969
Definition moc.h:23