7#include <qheaderview.h>
11#include <private/qtreewidget_p.h>
12#include <private/qwidgetitemdata_p.h>
13#include <private/qtreewidgetitemiterator_p.h>
15#include <QtCore/private/qduplicatetracker_p.h>
21class QTreeModelLessThan
24 inline bool operator()(QTreeWidgetItem *i1, QTreeWidgetItem *i2)
const
31 inline bool operator()(QTreeWidgetItem *i1, QTreeWidgetItem *i2)
const
36
37
38
39
40
41
42
45
46
47
48
49
50
53
54
55
56
57
58
61
62
63
64
65
66
69
70
71
72
73
75QTreeModel::QTreeModel(
int columns, QTreeWidget *parent)
76 : QAbstractItemModel(*
new QTreeModelPrivate, parent),
77 rootItem(
new QTreeWidgetItem),
78 headerItem(
new QTreeWidgetItem)
80 rootItem->view = parent;
81 rootItem->itemFlags = Qt::ItemIsDropEnabled;
82 headerItem->view = parent;
83 setColumnCount(columns);
87
88
89
91QTreeModel::QTreeModel(QTreeModelPrivate &dd, QTreeWidget *parent)
92 : QAbstractItemModel(dd, parent), rootItem(
new QTreeWidgetItem), headerItem(
new QTreeWidgetItem)
94 rootItem->view = parent;
95 rootItem->itemFlags = Qt::ItemIsDropEnabled;
96 headerItem->view = parent;
100
101
102
103
105QTreeModel::~QTreeModel()
108 headerItem->view =
nullptr;
110 rootItem->view =
nullptr;
115
116
117
118
120void QTreeModel::clear()
122 SkipSorting skipSorting(
this);
124 for (
int i = 0; i < rootItem->childCount(); ++i) {
125 QTreeWidgetItem *item = rootItem->children.at(i);
127 item->view =
nullptr;
130 rootItem->children.clear();
131 sortPendingTimer.stop();
136
137
138
139
141void QTreeModel::setColumnCount(
int columns)
143 SkipSorting skipSorting(
this);
147 headerItem =
new QTreeWidgetItem();
148 headerItem->view = view();
150 int count = columnCount();
151 if (count == columns)
154 if (columns < count) {
155 beginRemoveColumns(QModelIndex(), columns, count - 1);
156 headerItem->values.resize(columns);
159 beginInsertColumns(QModelIndex(), count, columns - 1);
160 headerItem->values.resize(columns);
161 for (
int i = count; i < columns; ++i) {
162 headerItem->values[i].append(QWidgetItemData(Qt::DisplayRole, QString::number(i + 1)));
163 headerItem->d->display.append(QString::number(i + 1));
170
171
172
173
174
175
177QTreeWidgetItem *QTreeModel::item(
const QModelIndex &index)
const
179 if (!index.isValid())
181 return static_cast<QTreeWidgetItem*>(index.internalPointer());
185
186
187
188
189
191QModelIndex QTreeModel::index(
const QTreeWidgetItem *item,
int column)
const
193 executePendingSort();
195 if (!item || (item == rootItem))
196 return QModelIndex();
197 const QTreeWidgetItem *par = item->parent();
198 QTreeWidgetItem *itm =
const_cast<QTreeWidgetItem*>(item);
202 int guess = item->d->rowGuess;
204 && par->children.size() > guess
205 && par->children.at(guess) == itm) {
208 row = par->children.lastIndexOf(itm);
209 itm->d->rowGuess = row;
211 return createIndex(row, column, itm);
215
216
217
218
219
220
222QModelIndex QTreeModel::index(
int row,
int column,
const QModelIndex &parent)
const
224 executePendingSort();
226 int c = columnCount(parent);
227 if (row < 0 || column < 0 || column >= c)
228 return QModelIndex();
230 QTreeWidgetItem *parentItem = parent.isValid() ? item(parent) : rootItem;
231 if (parentItem && row < parentItem->childCount()) {
232 QTreeWidgetItem *itm = parentItem->child(row);
234 return createIndex(row, column, itm);
235 return QModelIndex();
238 return QModelIndex();
242
243
244
245
246
247
249QModelIndex QTreeModel::parent(
const QModelIndex &child)
const
251 SkipSorting skipSorting(
this);
254 if (!child.isValid())
255 return QModelIndex();
256 QTreeWidgetItem *itm =
static_cast<QTreeWidgetItem *>(child.internalPointer());
257 if (!itm || itm == rootItem)
258 return QModelIndex();
259 QTreeWidgetItem *parent = itm->parent();
260 return index(parent, 0);
264
265
266
267
268
270int QTreeModel::rowCount(
const QModelIndex &parent)
const
272 if (!parent.isValid())
273 return rootItem->childCount();
275 QTreeWidgetItem *parentItem = item(parent);
277 return parentItem->childCount();
282
283
284
285
286
287
289int QTreeModel::columnCount(
const QModelIndex &index)
const
294 return headerItem->columnCount();
297bool QTreeModel::hasChildren(
const QModelIndex &parent)
const
299 if (!parent.isValid())
300 return (rootItem->childCount() > 0);
302 QTreeWidgetItem *itm = item(parent);
305 switch (itm->d->policy) {
306 case QTreeWidgetItem::ShowIndicator:
308 case QTreeWidgetItem::DontShowIndicator:
310 case QTreeWidgetItem::DontShowIndicatorWhenChildless:
311 return (itm->childCount() > 0);
317
318
319
320
321
322
324QVariant QTreeModel::data(
const QModelIndex &index,
int role)
const
326 if (!index.isValid())
328 QTreeWidgetItem *itm = item(index);
330 return itm->data(index.column(), role);
335
336
337
338
339
340
341
342
344bool QTreeModel::setData(
const QModelIndex &index,
const QVariant &value,
int role)
346 if (!index.isValid())
348 QTreeWidgetItem *itm = item(index);
350 itm->setData(index.column(), role, value);
356bool QTreeModel::clearItemData(
const QModelIndex &index)
358 if (!checkIndex(index, CheckIndexOption::IndexIsValid))
360 QTreeWidgetItem *itm = item(index);
363 const auto beginIter = itm->values.at(index.column()).cbegin();
364 const auto endIter = itm->values.at(index.column()).cend();
365 if (std::all_of(beginIter, endIter, [](
const QWidgetItemData& data) ->
bool {
return !data.value.isValid(); })
366 && !itm->d->display.at(index.column()).isValid()) {
369 itm->d->display[index.column()] = QVariant();
370 itm->values[index.column()].clear();
371 emit dataChanged(index, index, QList<
int> {});
375QMap<
int, QVariant> QTreeModel::itemData(
const QModelIndex &index)
const
377 QMap<
int, QVariant> roles;
378 QTreeWidgetItem *itm = item(index);
380 int column = index.column();
381 if (column < itm->values.size()) {
382 for (
int i = 0; i < itm->values.at(column).size(); ++i) {
383 roles.insert(itm->values.at(column).at(i).role,
384 itm->values.at(column).at(i).value);
389 QVariant displayValue = itm->data(column, Qt::DisplayRole);
390 if (displayValue.isValid())
391 roles.insert(Qt::DisplayRole, displayValue);
393 QVariant checkValue = itm->data(column, Qt::CheckStateRole);
394 if (checkValue.isValid())
395 roles.insert(Qt::CheckStateRole, checkValue);
401
402
403
404bool QTreeModel::insertRows(
int row,
int count,
const QModelIndex &parent)
406 SkipSorting skipSorting(
this);
407 if (count < 1 || row < 0 || row > rowCount(parent) || parent.column() > 0)
410 beginInsertRows(parent, row, row + count - 1);
411 QTreeWidgetItem *par = item(parent);
413 QTreeWidgetItem *item =
new QTreeWidgetItem();
417 par->children.insert(row++, item);
419 rootItem->children.insert(row++, item);
427
428
429
430bool QTreeModel::insertColumns(
int column,
int count,
const QModelIndex &parent)
432 SkipSorting skipSorting(
this);
433 if (count < 1 || column < 0 || column > columnCount(parent) || parent.column() > 0 || !headerItem)
436 beginInsertColumns(parent, column, column + count - 1);
438 int oldCount = columnCount(parent);
439 column = qBound(0, column, oldCount);
440 headerItem->values.resize(oldCount + count);
441 for (
int i = oldCount; i < oldCount + count; ++i) {
442 headerItem->values[i].append(QWidgetItemData(Qt::DisplayRole, QString::number(i + 1)));
443 headerItem->d->display.append(QString::number(i + 1));
446 QStack<QTreeWidgetItem*> itemstack;
448 while (!itemstack.isEmpty()) {
449 QTreeWidgetItem *par = itemstack.pop();
450 QList<QTreeWidgetItem*> children = par ? par->children : rootItem->children;
451 for (
int row = 0; row < children.size(); ++row) {
452 QTreeWidgetItem *child = children.at(row);
453 if (child->children.size())
454 itemstack.push(child);
455 child->values.insert(column, count, QList<QWidgetItemData>());
464
465
466
467bool QTreeModel::removeRows(
int row,
int count,
const QModelIndex &parent) {
468 if (count < 1 || row < 0 || (row + count) > rowCount(parent))
470 QTreeWidgetItem *parentItem = item(parent);
473 beginRemoveRows(parent, row, row + count - 1);
474 for (
int i = row + count - 1; i >= row; --i) {
475 QTreeWidgetItem *child = parentItem ? parentItem->takeChild(i) : rootItem->children.takeAt(i);
477 child->view =
nullptr;
486
487
488
489
490
491
493QVariant QTreeModel::headerData(
int section, Qt::Orientation orientation,
int role)
const
495 if (orientation != Qt::Horizontal)
499 return headerItem->data(section, role);
500 if (role == Qt::DisplayRole)
501 return QString::number(section + 1);
506
507
508
509
510
511
512
513
515bool QTreeModel::setHeaderData(
int section, Qt::Orientation orientation,
516 const QVariant &value,
int role)
518 if (section < 0 || orientation != Qt::Horizontal || !headerItem || section >= columnCount())
521 headerItem->setData(section, role, value);
526
527
528
529
530
532Qt::ItemFlags QTreeModel::flags(
const QModelIndex &index)
const
534 if (!index.isValid())
535 return rootItem->flags();
536 QTreeWidgetItem *itm = item(index);
542
543
544
545
546
548void QTreeModel::sort(
int column, Qt::SortOrder order)
550 SkipSorting skipSorting(
this);
551 sortPendingTimer.stop();
553 if (column < 0 || column >= columnCount())
557 rootItem->sortChildren(column, order,
true);
561
562
563void QTreeModel::ensureSorted(
int column, Qt::SortOrder order,
564 int start,
int end,
const QModelIndex &parent)
569 sortPendingTimer.stop();
571 if (column < 0 || column >= columnCount())
574 SkipSorting skipSorting(
this);
576 QTreeWidgetItem *itm = item(parent);
579 QList<QTreeWidgetItem*> lst = itm->children;
581 int count = end - start + 1;
582 QList<std::pair<QTreeWidgetItem *,
int>> sorting(count);
583 for (
int i = 0; i < count; ++i) {
584 sorting[i].first = lst.at(start + i);
585 sorting[i].second = start + i;
588 const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
589 std::stable_sort(sorting.begin(), sorting.end(), compare);
591 QModelIndexList oldPersistentIndexes;
592 QModelIndexList newPersistentIndexes;
593 QList<QTreeWidgetItem*>::iterator lit = lst.begin();
594 bool changed =
false;
596 for (
int i = 0; i < count; ++i) {
597 int oldRow = sorting.at(i).second;
599 int tmpitepos = lit - lst.begin();
600 QTreeWidgetItem *item = lst.takeAt(oldRow);
601 if (tmpitepos > lst.size())
603 lit = lst.begin() + tmpitepos;
605 lit = sortedInsertionIterator(lit, lst.end(), order, item);
606 int newRow = qMax<qsizetype>(lit - lst.begin(), 0);
608 if ((newRow < oldRow) && !(*item < *lst.at(oldRow - 1)) && !(*lst.at(oldRow - 1) < *item ))
611 lit = lst.insert(lit, item);
612 if (newRow != oldRow) {
616 emit layoutAboutToBeChanged({parent}, QAbstractItemModel::VerticalSortHint);
617 oldPersistentIndexes = persistentIndexList();
618 newPersistentIndexes = oldPersistentIndexes;
620 for (
int j = i + 1; j < count; ++j) {
621 int otherRow = sorting.at(j).second;
622 if (oldRow < otherRow && newRow >= otherRow)
624 else if (oldRow > otherRow && newRow <= otherRow)
627 for (
int k = 0; k < newPersistentIndexes.size(); ++k) {
628 QModelIndex pi = newPersistentIndexes.at(k);
629 if (pi.parent() != parent)
631 int oldPersistentRow = pi.row();
632 int newPersistentRow = oldPersistentRow;
633 if (oldPersistentRow == oldRow)
634 newPersistentRow = newRow;
635 else if (oldRow < oldPersistentRow && newRow >= oldPersistentRow)
636 newPersistentRow = oldPersistentRow - 1;
637 else if (oldRow > oldPersistentRow && newRow <= oldPersistentRow)
638 newPersistentRow = oldPersistentRow + 1;
639 if (newPersistentRow != oldPersistentRow)
640 newPersistentIndexes[k] = createIndex(newPersistentRow,
641 pi.column(), pi.internalPointer());
648 changePersistentIndexList(oldPersistentIndexes, newPersistentIndexes);
649 emit layoutChanged({parent}, QAbstractItemModel::VerticalSortHint);
654
655
656
657
658
659
660
662bool QTreeModel::itemLessThan(
const std::pair<QTreeWidgetItem*,
int> &left,
663 const std::pair<QTreeWidgetItem*,
int> &right)
665 return *(left.first) < *(right.first);
669
670
671
672
673
674
675
677bool QTreeModel::itemGreaterThan(
const std::pair<QTreeWidgetItem*,
int> &left,
678 const std::pair<QTreeWidgetItem*,
int> &right)
680 return *(right.first) < *(left.first);
684
685
686QList<QTreeWidgetItem*>::iterator QTreeModel::sortedInsertionIterator(
687 const QList<QTreeWidgetItem*>::iterator &begin,
688 const QList<QTreeWidgetItem*>::iterator &end,
689 Qt::SortOrder order, QTreeWidgetItem *item)
691 if (order == Qt::AscendingOrder)
692 return std::lower_bound(begin, end, item, QTreeModelLessThan());
693 return std::lower_bound(begin, end, item, QTreeModelGreaterThan());
696QStringList QTreeModel::mimeTypes()
const
700 return v->mimeTypes();
704QMimeData *QTreeModel::internalMimeData()
const
706 return QAbstractItemModel::mimeData(cachedIndexes);
709QMimeData *QTreeModel::mimeData(
const QModelIndexList &indexes)
const
711 QList<QTreeWidgetItem *> items;
712 std::transform(indexes.begin(), indexes.end(), std::back_inserter(items),
713 [
this](
const QModelIndex &idx) -> QTreeWidgetItem * {
return item(idx); });
717 std::sort(items.begin(), items.end());
718 items.erase(std::unique(items.begin(), items.end()), items.end());
722 cachedIndexes = indexes;
723 QMimeData *mimeData = view()->mimeData(items);
724 cachedIndexes.clear();
728bool QTreeModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
729 int row,
int column,
const QModelIndex &parent)
731 if (row == -1 && column == -1)
732 row = rowCount(parent);
733 return view()->dropMimeData(item(parent), row, data, action);
736Qt::DropActions QTreeModel::supportedDropActions()
const
738 return view()->supportedDropActions();
741Qt::DropActions QTreeModel::supportedDragActions()
const
743#if QT_CONFIG(draganddrop)
744 return view()->supportedDragActions();
746 return Qt::DropActions(Qt::IgnoreAction);
750void QTreeModel::itemChanged(QTreeWidgetItem *item)
752 if (item->columnCount() <= 0)
754 SkipSorting skipSorting(
this);
755 QModelIndex left = index(item, 0);
756 QModelIndex right = index(item, item->columnCount() - 1);
757 emit dataChanged(left, right);
760bool QTreeModel::isChanging()
const
762 Q_D(
const QTreeModel);
763 return !d->changes.isEmpty();
767
768
769
770
772void QTreeModel::emitDataChanged(QTreeWidgetItem *item,
int column,
const QList<
int> &roles)
774 if (signalsBlocked())
777 if (headerItem == item && column < item->columnCount()) {
779 emit headerDataChanged(Qt::Horizontal, 0, columnCount() - 1);
781 emit headerDataChanged(Qt::Horizontal, column, column);
785 SkipSorting skipSorting(
this);
787 QModelIndex bottomRight, topLeft;
789 topLeft = index(item, 0);
790 bottomRight = createIndex(topLeft.row(), columnCount() - 1, item);
792 topLeft = index(item, column);
793 bottomRight = topLeft;
795 emit dataChanged(topLeft, bottomRight, roles);
798void QTreeModel::beginInsertItems(QTreeWidgetItem *parent,
int row,
int count)
800 QModelIndex par = index(parent, 0);
801 beginInsertRows(par, row, row + count - 1);
804void QTreeModel::endInsertItems()
809void QTreeModel::beginRemoveItems(QTreeWidgetItem *parent,
int row,
int count)
813 beginRemoveRows(index(parent, 0), row, row + count - 1);
817 for (
int i = 0; i < iterators.size(); ++i) {
818 for (
int j = 0; j < count; j++) {
819 QTreeWidgetItem *c = parent->child(row + j);
820 iterators[i]->d_func()->ensureValidIterator(c);
825void QTreeModel::endRemoveItems()
830void QTreeModel::sortItems(QList<QTreeWidgetItem*> *items,
int column, Qt::SortOrder order)
838 QList<std::pair<QTreeWidgetItem *,
int>> sorting(items->size());
839 for (
int i = 0; i < sorting.size(); ++i) {
840 sorting[i].first = items->at(i);
841 sorting[i].second = i;
845 const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
846 std::stable_sort(sorting.begin(), sorting.end(), compare);
848 QModelIndexList fromList;
849 QModelIndexList toList;
850 int colCount = columnCount();
851 for (
int r = 0; r < sorting.size(); ++r) {
852 int oldRow = sorting.at(r).second;
855 QTreeWidgetItem *item = sorting.at(r).first;
856 items->replace(r, item);
857 for (
int c = 0; c < colCount; ++c) {
858 QModelIndex from = createIndex(oldRow, c, item);
859 if (
static_cast<QAbstractItemModelPrivate *>(d_ptr.data())->persistent.indexes.contains(from)) {
860 QModelIndex to = createIndex(r, c, item);
866 changePersistentIndexList(fromList, toList);
869void QTreeModel::timerEvent(QTimerEvent *ev)
871 if (ev->timerId() == sortPendingTimer.timerId()) {
872 executePendingSort();
874 QAbstractItemModel::timerEvent(ev);
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
942
943
944
945
946
947
948
949
950
951
952
953
954
957
958
959
960
963
964
965
966
967
968
969
970
973
974
975
976
979
980
981
982
983
984
985void QTreeWidgetItem::setSelected(
bool select)
987 const QTreeModel *model = treeModel();
988 if (!model || !view->selectionModel())
990 const QModelIndex index = model->index(
this, 0);
991 view->selectionModel()->select(index, (select ? QItemSelectionModel::Select
992 : QItemSelectionModel::Deselect)
993 | QItemSelectionModel::Rows);
994 d->selected = select;
998
999
1000
1001
1002
1003
1004bool QTreeWidgetItem::isSelected()
const
1010
1011
1012
1013
1014
1015
1016
1017
1018
1020void QTreeWidgetItem::setHidden(
bool hide)
1022 const QTreeModel *model = treeModel();
1025 if (
this == model->headerItem) {
1026 view->header()->setHidden(hide);
1028 const QModelIndex index = view->d_func()->index(
this);
1029 view->setRowHidden(index.row(), index.parent(), hide);
1035
1036
1037
1038
1039
1040
1042bool QTreeWidgetItem::isHidden()
const
1044 const QTreeModel *model = treeModel();
1047 if (
this == model->headerItem)
1048 return view->header()->isHidden();
1049 if (view->d_func()->hiddenIndexes.isEmpty())
1051 QTreeModel::SkipSorting skipSorting(model);
1052 return view->d_func()->isRowHidden(view->d_func()->index(
this));
1056
1057
1058
1059
1060
1061
1062
1063void QTreeWidgetItem::setExpanded(
bool expand)
1065 const QTreeModel *model = treeModel();
1068 QTreeModel::SkipSorting skipSorting(model);
1069 view->setExpanded(view->d_func()->index(
this), expand);
1073
1074
1075
1076
1077
1078
1079bool QTreeWidgetItem::isExpanded()
const
1081 const QTreeModel *model = treeModel();
1084 QTreeModel::SkipSorting skipSorting(model);
1085 return view->isExpanded(view->d_func()->index(
this));
1089
1090
1091
1092
1093
1094
1095
1096void QTreeWidgetItem::setFirstColumnSpanned(
bool span)
1098 const QTreeModel *model = treeModel();
1099 if (!model ||
this == model->headerItem)
1101 const QModelIndex index = model->index(
this, 0);
1102 view->setFirstColumnSpanned(index.row(), index.parent(), span);
1106
1107
1108
1109
1110
1111
1112bool QTreeWidgetItem::isFirstColumnSpanned()
const
1114 const QTreeModel *model = treeModel();
1115 if (!model ||
this == model->headerItem)
1117 const QModelIndex index = model->index(
this, 0);
1118 return view->isFirstColumnSpanned(index.row(), index.parent());
1122
1123
1124
1125
1126
1127
1130
1131
1132
1133
1134
1135
1138
1139
1140
1141
1142
1143
1146
1147
1148
1149
1150
1151
1154
1155
1156
1157
1158
1159
1162
1163
1164
1165
1166
1167
1168
1171
1172
1173
1174
1175
1176
1179
1180
1181
1182
1183
1184
1187
1188
1189
1190
1191
1192
1195
1196
1197
1198
1199
1200
1203
1204
1205
1206
1207
1208
1211
1212
1213
1214
1215
1216
1217
1220
1221
1222
1223
1224
1225
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1243
1244
1245
1246
1247
1248
1249
1250
1251
1254
1255
1256
1257
1258
1259
1260
1263
1264
1265
1266
1267
1268
1271
1272
1273
1274
1275
1276
1279
1280
1281
1282
1283
1286
1287
1288
1289
1290
1291
1294
1295
1296
1297
1298
1299
1302
1303
1304
1305
1306
1307
1310
1311
1312
1313
1316
1317
1318
1319
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1343
1344
1345
1346
1347
1348
1349
1350
1351
1354
1355
1356
1357
1358
1359
1360
1363
1364
1365
1368
1369
1370
1371
1374
1375
1376
1377
1378
1379QTreeWidgetItem::QTreeWidgetItem(
int type) : rtti(type), d(
new QTreeWidgetItemPrivate(
this)) { }
1382
1383
1384
1385
1386
1387
1388
1389QTreeWidgetItem::QTreeWidgetItem(
const QStringList &strings,
int type)
1390 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1392 for (
int i = 0; i < strings.size(); ++i)
1393 setText(i, strings.at(i));
1397
1398
1399
1400
1401
1402
1403
1405QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *treeview,
int type)
1406 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1409 if (QTreeModel *model = treeModel(treeview)) {
1410 model->rootItem->addChild(
this);
1411 values.reserve(model->headerItem->columnCount());
1416
1417
1418
1419
1420
1421
1422
1423
1425QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *treeview,
const QStringList &strings,
int type)
1426 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1428 for (
int i = 0; i < strings.size(); ++i)
1429 setText(i, strings.at(i));
1431 if (QTreeModel *model = treeModel(treeview)) {
1432 model->rootItem->addChild(
this);
1433 values.reserve(model->headerItem->columnCount());
1438
1439
1440
1441
1442
1443
1444
1445QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *treeview, QTreeWidgetItem *after,
int type)
1446 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1449 if (QTreeModel *model = treeModel(treeview)) {
1450 int i = model->rootItem->children.indexOf(after) + 1;
1451 model->rootItem->insertChild(i,
this);
1452 values.reserve(model->headerItem->columnCount());
1457
1458
1459
1460
1461QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent,
int type)
1462 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1465 parent->addChild(
this);
1469
1470
1471
1472
1473
1474QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent,
const QStringList &strings,
int type)
1475 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1477 for (
int i = 0; i < strings.size(); ++i)
1478 setText(i, strings.at(i));
1480 parent->addChild(
this);
1484
1485
1486
1487
1488
1489
1490
1491QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, QTreeWidgetItem *after,
int type)
1492 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1495 int i = parent->children.indexOf(after) + 1;
1496 parent->insertChild(i,
this);
1501
1502
1503
1504
1505
1506
1508QTreeWidgetItem::~QTreeWidgetItem()
1510 QTreeModel *model = treeModel();
1511 QTreeModel::SkipSorting skipSorting(model);
1514 int i = par->children.indexOf(
this);
1516 if (model) model->beginRemoveItems(par, i, 1);
1519 if (!par->children.isEmpty() && par->children.at(i) ==
this)
1520 par->children.takeAt(i);
1521 if (model) model->endRemoveItems();
1524 if (
this == model->headerItem) {
1525 model->headerItem =
nullptr;
1527 int i = model->rootItem->children.indexOf(
this);
1529 model->beginRemoveItems(
nullptr, i, 1);
1532 if (!model->rootItem->children.isEmpty() && model->rootItem->children.at(i) ==
this)
1533 model->rootItem->children.takeAt(i);
1534 model->endRemoveItems();
1540 for (
int i = 0; i < children.size(); ++i) {
1541 QTreeWidgetItem *child = children.at(i);
1543 child->par =
nullptr;
1545 child->view =
nullptr;
1554
1555
1556QTreeWidgetItem *QTreeWidgetItem::clone()
const
1558 QTreeWidgetItem *copy =
nullptr;
1560 QStack<
const QTreeWidgetItem*> stack;
1561 QStack<QTreeWidgetItem*> parentStack;
1563 parentStack.push(0);
1565 QTreeWidgetItem *root =
nullptr;
1566 const QTreeWidgetItem *item =
nullptr;
1567 QTreeWidgetItem *parent =
nullptr;
1568 while (!stack.isEmpty()) {
1571 parent = parentStack.pop();
1574 copy =
new QTreeWidgetItem(*item);
1581 parent->children.insert(0, copy);
1584 for (
int i = 0; i < item->childCount(); ++i) {
1585 stack.push(item->child(i));
1586 parentStack.push(copy);
1593
1594
1595
1596
1597
1598
1599void QTreeWidgetItem::setChildIndicatorPolicy(QTreeWidgetItem::ChildIndicatorPolicy policy)
1601 if (d->policy == policy)
1608 view->scheduleDelayedItemsLayout();
1612
1613
1614
1615
1616
1617QTreeWidgetItem::ChildIndicatorPolicy QTreeWidgetItem::childIndicatorPolicy()
const
1623
1624
1625
1626
1627
1628
1629
1630void QTreeWidgetItem::setFlags(Qt::ItemFlags flags)
1632 const bool enable = (flags & Qt::ItemIsEnabled);
1633 const bool changedState =
bool(itemFlags & Qt::ItemIsEnabled) != enable;
1634 const bool changedExplicit = d->disabled != !enable;
1636 d->disabled = !enable;
1638 if (enable && par && !(par->itemFlags & Qt::ItemIsEnabled))
1639 itemFlags = flags & ~Qt::ItemIsEnabled;
1643 if (changedState && changedExplicit) {
1644 QStack<QTreeWidgetItem*> parents;
1646 while (!parents.isEmpty()) {
1647 QTreeWidgetItem *parent = parents.pop();
1648 for (
int i = 0; i < parent->children.size(); ++i) {
1649 QTreeWidgetItem *child = parent->children.at(i);
1650 if (!child->d->disabled) {
1651 parents.push(child);
1653 child->itemFlags = child->itemFlags | Qt::ItemIsEnabled;
1655 child->itemFlags = child->itemFlags & ~Qt::ItemIsEnabled;
1656 child->itemChanged();
1664void QTreeWidgetItemPrivate::updateHiddenStatus(QTreeWidgetItem *item,
bool inserting)
1666 QTreeModel *model = item->treeModel();
1669 QStack<QTreeWidgetItem *> parents;
1671 while (!parents.isEmpty()) {
1672 QTreeWidgetItem *parent = parents.pop();
1673 if (parent->d->hidden) {
1674 const QModelIndex index = model->index(parent, 0);
1675 item->view->setRowHidden(index.row(), index.parent(), inserting);
1677 for (
int i = 0; i < parent->children.size(); ++i) {
1678 QTreeWidgetItem *child = parent->children.at(i);
1679 parents.push(child);
1684void QTreeWidgetItemPrivate::propagateDisabled(QTreeWidgetItem *item)
1687 const bool enable = item->par ? (item->par->itemFlags.testFlag(Qt::ItemIsEnabled)) :
true;
1689 QStack<QTreeWidgetItem*> parents;
1691 while (!parents.isEmpty()) {
1692 QTreeWidgetItem *parent = parents.pop();
1693 if (!parent->d->disabled) {
1694 Qt::ItemFlags oldFlags = parent->itemFlags;
1696 parent->itemFlags = parent->itemFlags | Qt::ItemIsEnabled;
1698 parent->itemFlags = parent->itemFlags & ~Qt::ItemIsEnabled;
1699 if (parent->itemFlags != oldFlags)
1700 parent->itemChanged();
1703 for (
int i = 0; i < parent->children.size(); ++i) {
1704 QTreeWidgetItem *child = parent->children.at(i);
1705 parents.push(child);
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721Qt::ItemFlags QTreeWidgetItem::flags()
const
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736void QTreeWidgetItem::setData(
int column,
int role,
const QVariant &value)
1741 QTreeModel *model = treeModel();
1744 case Qt::DisplayRole: {
1745 if (values.size() <= column) {
1746 if (model &&
this == model->headerItem)
1747 model->setColumnCount(column + 1);
1749 values.resize(column + 1);
1751 if (d->display.size() <= column) {
1752 for (
int i = d->display.size() - 1; i < column - 1; ++i)
1753 d->display.append(QVariant());
1754 d->display.append(value);
1755 }
else if (d->display[column] != value) {
1756 d->display[column] = value;
1761 case Qt::CheckStateRole:
1762 if ((itemFlags & Qt::ItemIsAutoTristate) && value != Qt::PartiallyChecked) {
1763 for (
int i = 0; i < children.size(); ++i) {
1764 QTreeWidgetItem *child = children.at(i);
1765 if (child->data(column, role).isValid()) {
1766 Qt::ItemFlags f = itemFlags;
1767 itemFlags &= ~Qt::ItemIsAutoTristate;
1768 child->setData(column, role, value);
1775 if (column < values.size()) {
1777 const QList<QWidgetItemData> column_values = values.at(column);
1778 for (
int i = 0; i < column_values.size(); ++i) {
1779 if (column_values.at(i).role == role) {
1780 if (column_values.at(i).value == value)
1782 values[column][i].value = value;
1788 values[column].append(QWidgetItemData(role, value));
1790 if (model &&
this == model->headerItem)
1791 model->setColumnCount(column + 1);
1793 values.resize(column + 1);
1794 values[column].append(QWidgetItemData(role, value));
1799 const QList<
int> roles((role == Qt::DisplayRole || role == Qt::EditRole)
1800 ? QList<
int>({ Qt::DisplayRole, Qt::EditRole })
1801 : QList<
int>({ role }));
1802 model->emitDataChanged(
this, column, roles);
1803 if (role == Qt::CheckStateRole) {
1805 for (p = par; p && (p->itemFlags & Qt::ItemIsAutoTristate); p = p->par)
1806 model->emitDataChanged(p, column, roles);
1812
1813
1814QVariant QTreeWidgetItem::data(
int column,
int role)
const
1818 case Qt::DisplayRole:
1819 if (column >= 0 && column < d->display.size())
1820 return d->display.at(column);
1822 case Qt::CheckStateRole:
1824 if (children.size() && (itemFlags & Qt::ItemIsAutoTristate))
1825 return childrenCheckState(column);
1828 if (column >= 0 && column < values.size()) {
1829 const QList<QWidgetItemData> &column_values = values.at(column);
1830 for (
const auto &column_value : column_values) {
1831 if (column_value.role == role)
1832 return column_value.value;
1840
1841
1842
1844bool QTreeWidgetItem::operator<(
const QTreeWidgetItem &other)
const
1846 int column = view ? view->sortColumn() : 0;
1847 const QVariant v1 = data(column, Qt::DisplayRole);
1848 const QVariant v2 = other.data(column, Qt::DisplayRole);
1849 return QAbstractItemModelPrivate::variantLessThan(v1, v2);
1852#ifndef QT_NO_DATASTREAM
1855
1856
1857
1858
1859void QTreeWidgetItem::read(QDataStream &in)
1862 if (in.version() < QDataStream::Qt_4_2) {
1866 for (
int column = 0; column < values.size(); ++column) {
1867 d->display << QVariant();
1868 for (
int i = 0; i < values.at(column).size(); ++i) {
1869 if (values.at(column).at(i).role == Qt::DisplayRole) {
1870 d->display[column] = values.at(column).at(i).value;
1871 values[column].remove(i--);
1876 in >> values >> d->display;
1881
1882
1883
1884
1885void QTreeWidgetItem::write(QDataStream &out)
const
1887 out << values << d->display;
1892
1893
1894
1895
1896
1897
1898
1899QTreeWidgetItem::QTreeWidgetItem(
const QTreeWidgetItem &other)
1901 values(other.values),
1902 d(
new QTreeWidgetItemPrivate(
this)),
1903 itemFlags(other.itemFlags)
1905 d->display = other.d->display;
1909
1910
1911
1912
1913
1914
1915
1916QTreeWidgetItem &QTreeWidgetItem::operator=(
const QTreeWidgetItem &other)
1918 values = other.values;
1919 d->display = other.d->display;
1920 d->policy = other.d->policy;
1921 itemFlags = other.itemFlags;
1926
1927
1928
1929
1930void QTreeWidgetItem::addChild(QTreeWidgetItem *child)
1933 insertChild(children.size(), child);
1934 child->d->rowGuess = children.size() - 1;
1939
1940
1941
1942
1943void QTreeWidgetItem::insertChild(
int index, QTreeWidgetItem *child)
1945 if (index < 0 || index > children.size() || child ==
nullptr || child->view !=
nullptr || child->par !=
nullptr)
1948 if (QTreeModel *model = treeModel()) {
1949 QTreeModel::SkipSorting skipSorting(model);
1950 if (model->rootItem ==
this)
1951 child->par =
nullptr;
1954 if (view->isSortingEnabled()) {
1956 if (!model->sortPendingTimer.isActive())
1957 model->sortPendingTimer.start(0, model);
1959 model->beginInsertItems(
this, index, 1);
1960 int cols = model->columnCount();
1961 QStack<QTreeWidgetItem*> stack;
1963 while (!stack.isEmpty()) {
1964 QTreeWidgetItem *i = stack.pop();
1966 i->values.reserve(cols);
1967 for (
int c = 0; c < i->children.size(); ++c)
1968 stack.push(i->children.at(c));
1970 children.insert(index, child);
1971 d->updateHiddenStatus(child,
true);
1972 model->endInsertItems();
1975 children.insert(index, child);
1978 d->propagateDisabled(child);
1982
1983
1984
1985void QTreeWidgetItem::removeChild(QTreeWidgetItem *child)
1987 (
void)takeChild(children.indexOf(child));
1991
1992
1993QTreeWidgetItem *QTreeWidgetItem::takeChild(
int index)
1997 QTreeModel *model = treeModel();
2003 model->skipPendingSort =
false;
2004 model->executePendingSort();
2006 if (index >= 0 && index < children.size()) {
2007 if (model) model->beginRemoveItems(
this, index, 1);
2008 d->updateHiddenStatus(children.at(index),
false);
2009 QTreeWidgetItem *item = children.takeAt(index);
2010 item->par =
nullptr;
2011 QStack<QTreeWidgetItem*> stack;
2013 while (!stack.isEmpty()) {
2014 QTreeWidgetItem *i = stack.pop();
2016 for (
int c = 0; c < i->children.size(); ++c)
2017 stack.push(i->children.at(c));
2019 d->propagateDisabled(item);
2020 if (model) model->endRemoveRows();
2027
2028
2029
2030
2031void QTreeWidgetItem::addChildren(
const QList<QTreeWidgetItem*> &children)
2033 insertChildren(
this->children.size(), children);
2037
2038
2039
2040
2041void QTreeWidgetItem::insertChildren(
int index,
const QList<QTreeWidgetItem*> &children)
2043 if (index < 0 || index >
this->children.size() || children.isEmpty())
2046 if (view && view->isSortingEnabled()) {
2047 for (
int n = 0; n < children.size(); ++n)
2048 insertChild(index, children.at(n));
2051 QTreeModel *model = treeModel();
2052 QStack<QTreeWidgetItem*> stack;
2053 QList<QTreeWidgetItem*> itemsToInsert;
2054 for (
int n = 0; n < children.size(); ++n) {
2055 QTreeWidgetItem *child = children.at(n);
2056 if (child->view || child->par)
2058 itemsToInsert.append(child);
2059 if (view && model) {
2060 if (child->childCount() == 0)
2065 if (model && (model->rootItem ==
this))
2066 child->par =
nullptr;
2070 if (!itemsToInsert.isEmpty()) {
2071 while (!stack.isEmpty()) {
2072 QTreeWidgetItem *i = stack.pop();
2074 for (
int c = 0; c < i->children.size(); ++c)
2075 stack.push(i->children.at(c));
2077 if (model) model->beginInsertItems(
this, index, itemsToInsert.size());
2078 for (
int n = 0; n < itemsToInsert.size(); ++n) {
2079 QTreeWidgetItem *child = itemsToInsert.at(n);
2080 this->children.insert(index + n, child);
2082 d->propagateDisabled(child);
2083 d->updateHiddenStatus(child,
true);
2085 if (model) model->endInsertItems();
2090
2091
2092QList<QTreeWidgetItem*> QTreeWidgetItem::takeChildren()
2094 QList<QTreeWidgetItem*> removed;
2095 if (children.size() > 0) {
2096 QTreeModel *model = treeModel();
2102 model->executePendingSort();
2104 if (model) model->beginRemoveItems(
this, 0, children.size());
2105 for (
int n = 0; n < children.size(); ++n) {
2106 QTreeWidgetItem *item = children.at(n);
2107 item->par =
nullptr;
2108 QStack<QTreeWidgetItem*> stack;
2110 while (!stack.isEmpty()) {
2111 QTreeWidgetItem *i = stack.pop();
2113 for (
int c = 0; c < i->children.size(); ++c)
2114 stack.push(i->children.at(c));
2116 d->propagateDisabled(item);
2120 if (model) model->endRemoveItems();
2126void QTreeWidgetItemPrivate::sortChildren(
int column, Qt::SortOrder order,
bool climb)
2128 QTreeModel *model = q->treeModel();
2131 model->sortItems(&q->children, column, order);
2133 QList<QTreeWidgetItem*>::iterator it = q->children.begin();
2134 for (; it != q->children.end(); ++it) {
2137 (*it)->d->sortChildren(column, order, climb);
2143
2144
2145
2146
2147
2148
2149void QTreeWidgetItem::sortChildren(
int column, Qt::SortOrder order,
bool climb)
2151 QTreeModel *model = treeModel();
2154 if (model->isChanging())
2156 QTreeModel::SkipSorting skipSorting(model);
2157 int oldSortColumn = view->d_func()->explicitSortColumn;
2158 view->d_func()->explicitSortColumn = column;
2159 emit model->layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint);
2160 d->sortChildren(column, order, climb);
2161 emit model->layoutChanged({}, QAbstractItemModel::VerticalSortHint);
2162 view->d_func()->explicitSortColumn = oldSortColumn;
2166
2167
2168
2169
2170
2171
2172
2173QVariant QTreeWidgetItem::childrenCheckState(
int column)
const
2177 bool checkedChildren =
false;
2178 bool uncheckedChildren =
false;
2179 for (
const auto *child : children) {
2180 QVariant value = child->data(column, Qt::CheckStateRole);
2181 if (!value.isValid())
2184 switch (
static_cast<Qt::CheckState>(value.toInt()))
2187 uncheckedChildren =
true;
2190 checkedChildren =
true;
2192 case Qt::PartiallyChecked:
2194 return Qt::PartiallyChecked;
2197 if (uncheckedChildren && checkedChildren)
2198 return Qt::PartiallyChecked;
2201 if (uncheckedChildren)
2202 return Qt::Unchecked;
2203 else if (checkedChildren)
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219void QTreeWidgetItem::emitDataChanged()
2225
2226
2227void QTreeWidgetItem::itemChanged()
2229 if (QTreeModel *model = treeModel())
2230 model->itemChanged(
this);
2234
2235
2236void QTreeWidgetItem::executePendingSort()
const
2238 if (QTreeModel *model = treeModel())
2239 model->executePendingSort();
2243
2244
2245
2246QTreeModel *QTreeWidgetItem::treeModel(QTreeWidget *v)
const
2250 return (v ? qobject_cast<QTreeModel*>(v->model()) :
nullptr);
2254#ifndef QT_NO_DATASTREAM
2256
2257
2258
2259
2260
2261
2262
2263
2271
2272
2273
2274
2275
2276
2277
2278
2287void QTreeWidgetPrivate::clearConnections()
2289 for (
const QMetaObject::Connection &connection : connections)
2290 QObject::disconnect(connection);
2293void QTreeWidgetPrivate::emitItemPressed(
const QModelIndex &index)
2296 emit q->itemPressed(item(index), index.column());
2299void QTreeWidgetPrivate::emitItemClicked(
const QModelIndex &index)
2302 emit q->itemClicked(item(index), index.column());
2305void QTreeWidgetPrivate::emitItemDoubleClicked(
const QModelIndex &index)
2308 emit q->itemDoubleClicked(item(index), index.column());
2311void QTreeWidgetPrivate::emitItemActivated(
const QModelIndex &index)
2314 emit q->itemActivated(item(index), index.column());
2317void QTreeWidgetPrivate::emitItemEntered(
const QModelIndex &index)
2320 emit q->itemEntered(item(index), index.column());
2323void QTreeWidgetPrivate::emitItemChanged(
const QModelIndex &index)
2326 QTreeWidgetItem *indexItem = item(index);
2328 emit q->itemChanged(indexItem, index.column());
2331void QTreeWidgetPrivate::emitItemExpanded(
const QModelIndex &index)
2334 emit q->itemExpanded(item(index));
2337void QTreeWidgetPrivate::emitItemCollapsed(
const QModelIndex &index)
2340 emit q->itemCollapsed(item(index));
2343void QTreeWidgetPrivate::emitCurrentItemChanged(
const QModelIndex ¤t,
2344 const QModelIndex &previous)
2347 QTreeWidgetItem *currentItem = item(current);
2348 QTreeWidgetItem *previousItem = item(previous);
2349 emit q->currentItemChanged(currentItem, previousItem);
2352void QTreeWidgetPrivate::sort()
2354 if (sortingEnabled) {
2355 int column = header->sortIndicatorSection();
2356 Qt::SortOrder order = header->sortIndicatorOrder();
2357 treeModel()->sort(column, order);
2361void QTreeWidgetPrivate::selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected)
2364 QModelIndexList indices = selected.indexes();
2366 QTreeModel *m = treeModel();
2367 for (i = 0; i < indices.size(); ++i) {
2368 QTreeWidgetItem *item = m->item(indices.at(i));
2369 item->d->selected =
true;
2372 indices = deselected.indexes();
2373 for (i = 0; i < indices.size(); ++i) {
2374 QTreeWidgetItem *item = m->item(indices.at(i));
2375 item->d->selected =
false;
2378 emit q->itemSelectionChanged();
2381void QTreeWidgetPrivate::dataChanged(
const QModelIndex &topLeft,
2382 const QModelIndex &bottomRight)
2384 if (sortingEnabled && topLeft.isValid() && bottomRight.isValid()
2385 && !treeModel()->sortPendingTimer.isActive()) {
2386 int column = header->sortIndicatorSection();
2387 if (column >= topLeft.column() && column <= bottomRight.column()) {
2388 Qt::SortOrder order = header->sortIndicatorOrder();
2389 treeModel()->ensureSorted(column, order, topLeft.row(),
2390 bottomRight.row(), topLeft.parent());
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2444
2445
2446
2447
2448
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2464
2465
2466
2467
2468
2469
2470
2471
2472
2475
2476
2477
2478
2479
2480
2481
2482
2485
2486
2487
2488
2489
2490
2491
2492
2493
2496
2497
2498
2499
2500
2501
2502
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2517
2518
2519
2520
2521
2522
2523
2524
2527
2528
2529
2530
2531
2534
2535
2536
2537
2538
2539
2542
2543
2544
2545
2546
2549
2550
2551
2552
2553
2554
2557
2558
2559QTreeWidget::QTreeWidget(QWidget *parent)
2560 : QTreeView(*
new QTreeWidgetPrivate(), parent)
2563 QTreeView::setModel(
new QTreeModel(1,
this));
2565 QObjectPrivate::connect(
this, &QTreeWidget::pressed,
2566 d, &QTreeWidgetPrivate::emitItemPressed),
2567 QObjectPrivate::connect(
this, &QTreeWidget::clicked,
2568 d, &QTreeWidgetPrivate::emitItemClicked),
2569 QObjectPrivate::connect(
this, &QTreeWidget::doubleClicked,
2570 d, &QTreeWidgetPrivate::emitItemDoubleClicked),
2571 QObjectPrivate::connect(
this, &QTreeWidget::activated,
2572 d, &QTreeWidgetPrivate::emitItemActivated),
2573 QObjectPrivate::connect(
this, &QTreeWidget::entered,
2574 d, &QTreeWidgetPrivate::emitItemEntered),
2575 QObjectPrivate::connect(
this, &QTreeWidget::expanded,
2576 d, &QTreeWidgetPrivate::emitItemExpanded),
2577 QObjectPrivate::connect(
this, &QTreeWidget::collapsed,
2578 d, &QTreeWidgetPrivate::emitItemCollapsed),
2579 QObjectPrivate::connect(model(), &QAbstractItemModel::dataChanged,
2580 d, &QTreeWidgetPrivate::emitItemChanged),
2581 QObjectPrivate::connect(model(), &QAbstractItemModel::dataChanged,
2582 d, &QTreeWidgetPrivate::dataChanged),
2583 QObjectPrivate::connect(model(), &QAbstractItemModel::columnsRemoved,
2584 d, &QTreeWidgetPrivate::sort),
2585 QObjectPrivate::connect(selectionModel(), &QItemSelectionModel::currentChanged,
2586 d, &QTreeWidgetPrivate::emitCurrentItemChanged),
2587 QObjectPrivate::connect(selectionModel(), &QItemSelectionModel::selectionChanged,
2588 d, &QTreeWidgetPrivate::selectionChanged)
2590 header()->setSectionsClickable(
false);
2594
2595
2597QTreeWidget::~QTreeWidget()
2600 d->clearConnections();
2604
2605
2606
2607
2609int QTreeWidget::columnCount()
const
2611 Q_D(
const QTreeWidget);
2612 return d->model->columnCount();
2616
2617
2619void QTreeWidget::setColumnCount(
int columns)
2624 d->treeModel()->setColumnCount(columns);
2628
2629
2630
2631
2632
2633
2634
2636QTreeWidgetItem *QTreeWidget::invisibleRootItem()
const
2638 Q_D(
const QTreeWidget);
2639 return d->treeModel()->rootItem;
2643
2644
2645
2646
2647
2649QTreeWidgetItem *QTreeWidget::topLevelItem(
int index)
const
2651 Q_D(
const QTreeWidget);
2652 return d->treeModel()->rootItem->child(index);
2656
2657
2658
2659
2660
2661
2662
2664int QTreeWidget::topLevelItemCount()
const
2666 Q_D(
const QTreeWidget);
2667 return d->treeModel()->rootItem->childCount();
2671
2672
2673
2674
2675
2676
2678void QTreeWidget::insertTopLevelItem(
int index, QTreeWidgetItem *item)
2681 d->treeModel()->rootItem->insertChild(index, item);
2685
2686
2687
2688
2689void QTreeWidget::addTopLevelItem(QTreeWidgetItem *item)
2691 insertTopLevelItem(topLevelItemCount(), item);
2695
2696
2697
2698
2699
2701QTreeWidgetItem *QTreeWidget::takeTopLevelItem(
int index)
2704 return d->treeModel()->rootItem->takeChild(index);
2708
2709
2710
2711
2712
2713int QTreeWidget::indexOfTopLevelItem(QTreeWidgetItem *item)
const
2715 Q_D(
const QTreeWidget);
2716 d->treeModel()->executePendingSort();
2717 return d->treeModel()->rootItem->children.indexOf(item);
2721
2722
2723
2724
2725
2726
2727void QTreeWidget::insertTopLevelItems(
int index,
const QList<QTreeWidgetItem*> &items)
2730 d->treeModel()->rootItem->insertChildren(index, items);
2734
2735
2736
2737
2738void QTreeWidget::addTopLevelItems(
const QList<QTreeWidgetItem*> &items)
2740 insertTopLevelItems(topLevelItemCount(), items);
2744
2745
2746
2747
2749QTreeWidgetItem *QTreeWidget::headerItem()
const
2751 Q_D(
const QTreeWidget);
2752 return d->treeModel()->headerItem;
2756
2757
2758
2759
2760
2761
2762
2764void QTreeWidget::setHeaderItem(QTreeWidgetItem *item)
2771 int oldCount = columnCount();
2772 if (oldCount < item->columnCount())
2773 d->treeModel()->beginInsertColumns(QModelIndex(), oldCount, item->columnCount() - 1);
2774 else if (oldCount > item->columnCount())
2775 d->treeModel()->beginRemoveColumns(QModelIndex(), item->columnCount(), oldCount - 1);
2776 delete d->treeModel()->headerItem;
2777 d->treeModel()->headerItem = item;
2778 if (oldCount < item->columnCount())
2779 d->treeModel()->endInsertColumns();
2780 else if (oldCount > item->columnCount())
2781 d->treeModel()->endRemoveColumns();
2782 d->treeModel()->headerDataChanged(Qt::Horizontal, 0, oldCount);
2787
2788
2789
2790
2791
2792
2793
2794void QTreeWidget::setHeaderLabels(
const QStringList &labels)
2797 if (columnCount() < labels.size())
2798 setColumnCount(labels.size());
2799 QTreeWidgetItem *item = d->treeModel()->headerItem;
2800 for (
int i = 0; i < labels.size(); ++i)
2801 item->setText(i, labels.at(i));
2805
2806
2807
2808
2811
2812
2813
2814
2815QTreeWidgetItem *QTreeWidget::currentItem()
const
2817 Q_D(
const QTreeWidget);
2818 return d->item(currentIndex());
2822
2823
2824
2825
2826int QTreeWidget::currentColumn()
const
2828 return currentIndex().column();
2832
2833
2834
2835
2836
2837
2838
2839void QTreeWidget::setCurrentItem(QTreeWidgetItem *item)
2841 setCurrentItem(item, 0);
2845
2846
2847
2848
2849void QTreeWidget::setCurrentItem(QTreeWidgetItem *item,
int column)
2852 setCurrentIndex(d->index(item, column));
2856
2857
2858
2859
2860
2861void QTreeWidget::setCurrentItem(QTreeWidgetItem *item,
int column,
2862 QItemSelectionModel::SelectionFlags command)
2865 d->selectionModel->setCurrentIndex(d->index(item, column), command);
2870
2871
2872
2873
2874
2875QTreeWidgetItem *QTreeWidget::itemAt(
const QPoint &p)
const
2877 Q_D(
const QTreeWidget);
2878 return d->item(indexAt(p));
2882
2883
2884
2885
2886
2887
2890
2891
2892
2893
2894QRect QTreeWidget::visualItemRect(
const QTreeWidgetItem *item)
const
2896 Q_D(
const QTreeWidget);
2899 const QModelIndex base = d->index(item);
2900 const int firstVisiblesection = header()->logicalIndexAt(- header()->offset());
2901 const int lastVisibleSection = header()->logicalIndexAt(header()->length() - header()->offset() - 1);
2902 const QModelIndex first = base.sibling(base.row(), firstVisiblesection);
2903 const QModelIndex last = base.sibling(base.row(), lastVisibleSection);
2904 return visualRect(first) | visualRect(last);
2908
2909
2910
2911
2912int QTreeWidget::sortColumn()
const
2914 Q_D(
const QTreeWidget);
2915 return (d->explicitSortColumn != -1
2916 ? d->explicitSortColumn
2917 : header()->sortIndicatorSection());
2921
2922
2923
2924
2925
2927void QTreeWidget::sortItems(
int column, Qt::SortOrder order)
2930 header()->setSortIndicator(column, order);
2931 d->model->sort(column, order);
2935
2936
2938void QTreeWidget::editItem(QTreeWidgetItem *item,
int column)
2941 edit(d->index(item, column));
2945
2946
2947
2948
2950void QTreeWidget::openPersistentEditor(QTreeWidgetItem *item,
int column)
2953 QAbstractItemView::openPersistentEditor(d->index(item, column));
2957
2958
2959
2960
2961
2962
2963
2965void QTreeWidget::closePersistentEditor(QTreeWidgetItem *item,
int column)
2968 QAbstractItemView::closePersistentEditor(d->index(item, column));
2972
2973
2974
2975
2976
2977
2978
2980bool QTreeWidget::isPersistentEditorOpen(QTreeWidgetItem *item,
int column)
const
2982 Q_D(
const QTreeWidget);
2983 return QAbstractItemView::isPersistentEditorOpen(d->index(item, column));
2987
2988
2989
2990
2991QWidget *QTreeWidget::itemWidget(QTreeWidgetItem *item,
int column)
const
2993 Q_D(
const QTreeWidget);
2994 return QAbstractItemView::indexWidget(d->index(item, column));
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018void QTreeWidget::setItemWidget(QTreeWidgetItem *item,
int column, QWidget *widget)
3021 QAbstractItemView::setIndexWidget(d->index(item, column), widget);
3025
3026
3027
3028
3029QList<QTreeWidgetItem*> QTreeWidget::selectedItems()
const
3031 Q_D(
const QTreeWidget);
3032 const QModelIndexList indexes = selectionModel()->selectedIndexes();
3033 QList<QTreeWidgetItem*> items;
3034 items.reserve(indexes.size());
3035 QDuplicateTracker<QTreeWidgetItem *> seen(indexes.size());
3036 for (
const auto &index : indexes) {
3037 QTreeWidgetItem *item = d->item(index);
3038 if (item->isHidden() || seen.hasSeen(item))
3046
3047
3048QList<QTreeWidgetItem*> QTreeWidget::findItems(
const QString &text, Qt::MatchFlags flags,
int column)
const
3050 Q_D(
const QTreeWidget);
3051 QModelIndexList indexes = d->model->match(model()->index(0, column, QModelIndex()),
3052 Qt::DisplayRole, text, -1, flags);
3053 QList<QTreeWidgetItem*> items;
3054 const int indexesSize = indexes.size();
3055 items.reserve(indexesSize);
3056 for (
int i = 0; i < indexesSize; ++i)
3057 items.append(d->item(indexes.at(i)));
3063
3064
3065QTreeWidgetItem *QTreeWidget::itemAbove(
const QTreeWidgetItem *item)
const
3067 Q_D(
const QTreeWidget);
3068 if (item == d->treeModel()->headerItem)
3070 const QModelIndex index = d->index(item);
3071 const QModelIndex above = indexAbove(index);
3072 return d->item(above);
3076
3077
3078QTreeWidgetItem *QTreeWidget::itemBelow(
const QTreeWidgetItem *item)
const
3080 Q_D(
const QTreeWidget);
3081 if (item == d->treeModel()->headerItem)
3083 const QModelIndex index = d->index(item);
3084 const QModelIndex below = indexBelow(index);
3085 return d->item(below);
3089
3090
3091void QTreeWidget::setSelectionModel(QItemSelectionModel *selectionModel)
3094 QTreeView::setSelectionModel(selectionModel);
3095 QItemSelection newSelection = selectionModel->selection();
3096 if (!newSelection.isEmpty())
3097 d->selectionChanged(newSelection, QItemSelection());
3101
3102
3103
3104
3105
3106void QTreeWidget::scrollToItem(
const QTreeWidgetItem *item, QAbstractItemView::ScrollHint hint)
3109 QTreeView::scrollTo(d->index(item), hint);
3113
3114
3115
3116
3117
3118void QTreeWidget::expandItem(
const QTreeWidgetItem *item)
3121 QTreeModel::SkipSorting skipSorting(d->treeModel());
3122 expand(d->index(item));
3126
3127
3128
3129
3130
3131void QTreeWidget::collapseItem(
const QTreeWidgetItem *item)
3134 QTreeModel::SkipSorting skipSorting(d->treeModel());
3135 collapse(d->index(item));
3139
3140
3141
3142
3143
3144
3145
3146
3147void QTreeWidget::clear()
3150 selectionModel()->clear();
3151 d->treeModel()->clear();
3155
3156
3157
3158
3159
3160QStringList QTreeWidget::mimeTypes()
const
3162 return model()->QAbstractItemModel::mimeTypes();
3166
3167
3168
3169
3170
3171
3172
3173QMimeData *QTreeWidget::mimeData(
const QList<QTreeWidgetItem *> &items)
const
3175 Q_D(
const QTreeWidget);
3176 if (d->treeModel()->cachedIndexes.isEmpty()) {
3177 QList<QModelIndex> indexes;
3178 for (
const auto *item : items) {
3179 if (Q_UNLIKELY(!item)) {
3180 qWarning(
"QTreeWidget::mimeData: Null-item passed");
3184 for (
int c = 0; c < item->values.size(); ++c) {
3185 const QModelIndex index = indexFromItem(item, c);
3186 if (Q_UNLIKELY(!index.isValid())) {
3187 qWarning() <<
"QTreeWidget::mimeData: No index associated with item :" << item;
3193 return d->model->QAbstractItemModel::mimeData(indexes);
3195 return d->treeModel()->internalMimeData();
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208bool QTreeWidget::dropMimeData(QTreeWidgetItem *parent,
int index,
3209 const QMimeData *data, Qt::DropAction action)
3212 if (parent) idx = indexFromItem(parent);
3213 return model()->QAbstractItemModel::dropMimeData(data, action , index, 0, idx);
3217
3218
3219
3220
3221Qt::DropActions QTreeWidget::supportedDropActions()
const
3223 return model()->QAbstractItemModel::supportedDropActions() | Qt::MoveAction;
3226#if QT_CONFIG(draganddrop)
3228
3229
3230
3231
3232
3233
3234Qt::DropActions QTreeWidget::supportedDragActions()
const
3236 Q_D(
const QTreeWidget);
3237 return d->supportedDragActions.value_or(supportedDropActions());
3240void QTreeWidget::setSupportedDragActions(Qt::DropActions actions)
3243 d->supportedDragActions = actions;
3248
3249
3250
3251
3252
3253
3254QModelIndex QTreeWidget::indexFromItem(
const QTreeWidgetItem *item,
int column)
const
3256 Q_D(
const QTreeWidget);
3257 return d->index(item, column);
3261
3262
3263
3264
3265QTreeWidgetItem *QTreeWidget::itemFromIndex(
const QModelIndex &index)
const
3267 Q_D(
const QTreeWidget);
3268 return d->item(index);
3271#if QT_CONFIG(draganddrop)
3273void QTreeWidget::dropEvent(QDropEvent *event) {
3275 if (event->source() ==
this && (event->dropAction() == Qt::MoveAction ||
3276 dragDropMode() == QAbstractItemView::InternalMove)) {
3277 QModelIndex topIndex;
3281 if (!event->isAccepted() && d->dropOn(event, &row, &col, &topIndex)) {
3282 const QList<QModelIndex> idxs = selectedIndexes();
3283 QList<QPersistentModelIndex> indexes;
3284 const int indexesCount = idxs.size();
3285 indexes.reserve(indexesCount);
3286 for (
const auto &idx : idxs)
3287 indexes.append(idx);
3289 if (indexes.contains(topIndex))
3293 QPersistentModelIndex dropRow = model()->index(row, col, topIndex);
3296 QList<QTreeWidgetItem *> taken;
3297 for (
const auto &index : indexes) {
3298 QTreeWidgetItem *parent = itemFromIndex(index);
3299 if (!parent || !parent->parent()) {
3300 taken.append(takeTopLevelItem(index.row()));
3302 taken.append(parent->parent()->takeChild(index.row()));
3307 for (
int i = 0; i < indexes.size(); ++i) {
3310 if (topIndex.isValid()) {
3311 QTreeWidgetItem *parent = itemFromIndex(topIndex);
3312 parent->insertChild(parent->childCount(), taken.takeFirst());
3314 insertTopLevelItem(topLevelItemCount(), taken.takeFirst());
3317 int r = dropRow.row() >= 0 ? dropRow.row() : row;
3318 if (topIndex.isValid()) {
3319 QTreeWidgetItem *parent = itemFromIndex(topIndex);
3320 parent->insertChild(qMin(r, parent->childCount()), taken.takeFirst());
3322 insertTopLevelItem(qMin(r, topLevelItemCount()), taken.takeFirst());
3331 if (event->isAccepted())
3332 d->dropEventMoved =
true;
3335 QTreeView::dropEvent(event);
3340
3341
3343void QTreeWidget::setModel(QAbstractItemModel * )
3345 Q_ASSERT(!
"QTreeWidget::setModel() - Changing the model of the QTreeWidget is not allowed.");
3349
3350
3351bool QTreeWidget::event(QEvent *e)
3354 if (e->type() == QEvent::Polish)
3355 d->treeModel()->executePendingSort();
3356 return QTreeView::event(e);
3360
3361
3362void QTreeModelPrivate::executePendingOperations()
const
3364 q_func()->executePendingSort();
3369#include "moc_qtreewidget.cpp"
3370#include "moc_qtreewidget_p.cpp"
bool operator()(QTreeWidgetItem *i1, QTreeWidgetItem *i2) const
QDataStream & operator<<(QDataStream &stream, const QImage &image)
[0]
QDataStream & operator>>(QDataStream &stream, QImage &image)