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
532
533
534
535
536
538Qt::ItemFlags QTreeModel::flags(
const QModelIndex &index)
const
540 if (!index.isValid())
541 return rootItem->flags();
542 QTreeWidgetItem *itm = item(index);
548
549
550
551
552
554void QTreeModel::sort(
int column, Qt::SortOrder order)
556 SkipSorting skipSorting(
this);
557 sortPendingTimer.stop();
559 if (column < 0 || column >= columnCount())
563 rootItem->sortChildren(column, order,
true);
567
568
569void QTreeModel::ensureSorted(
int column, Qt::SortOrder order,
570 int start,
int end,
const QModelIndex &parent)
575 sortPendingTimer.stop();
577 if (column < 0 || column >= columnCount())
580 SkipSorting skipSorting(
this);
582 QTreeWidgetItem *itm = item(parent);
585 QList<QTreeWidgetItem*> lst = itm->children;
587 int count = end - start + 1;
588 QList<std::pair<QTreeWidgetItem *,
int>> sorting(count);
589 for (
int i = 0; i < count; ++i) {
590 sorting[i].first = lst.at(start + i);
591 sorting[i].second = start + i;
594 const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
595 std::stable_sort(sorting.begin(), sorting.end(), compare);
597 QModelIndexList oldPersistentIndexes;
598 QModelIndexList newPersistentIndexes;
599 QList<QTreeWidgetItem*>::iterator lit = lst.begin();
600 bool changed =
false;
602 for (
int i = 0; i < count; ++i) {
603 int oldRow = sorting.at(i).second;
605 int tmpitepos = lit - lst.begin();
606 QTreeWidgetItem *item = lst.takeAt(oldRow);
607 if (tmpitepos > lst.size())
609 lit = lst.begin() + tmpitepos;
611 lit = sortedInsertionIterator(lit, lst.end(), order, item);
612 int newRow = qMax<qsizetype>(lit - lst.begin(), 0);
614 if ((newRow < oldRow) && !(*item < *lst.at(oldRow - 1)) && !(*lst.at(oldRow - 1) < *item ))
617 lit = lst.insert(lit, item);
618 if (newRow != oldRow) {
622 emit layoutAboutToBeChanged({parent}, QAbstractItemModel::VerticalSortHint);
623 oldPersistentIndexes = persistentIndexList();
624 newPersistentIndexes = oldPersistentIndexes;
626 for (
int j = i + 1; j < count; ++j) {
627 int otherRow = sorting.at(j).second;
628 if (oldRow < otherRow && newRow >= otherRow)
630 else if (oldRow > otherRow && newRow <= otherRow)
633 for (
int k = 0; k < newPersistentIndexes.size(); ++k) {
634 QModelIndex pi = newPersistentIndexes.at(k);
635 if (pi.parent() != parent)
637 int oldPersistentRow = pi.row();
638 int newPersistentRow = oldPersistentRow;
639 if (oldPersistentRow == oldRow)
640 newPersistentRow = newRow;
641 else if (oldRow < oldPersistentRow && newRow >= oldPersistentRow)
642 newPersistentRow = oldPersistentRow - 1;
643 else if (oldRow > oldPersistentRow && newRow <= oldPersistentRow)
644 newPersistentRow = oldPersistentRow + 1;
645 if (newPersistentRow != oldPersistentRow)
646 newPersistentIndexes[k] = createIndex(newPersistentRow,
647 pi.column(), pi.internalPointer());
654 changePersistentIndexList(oldPersistentIndexes, newPersistentIndexes);
655 emit layoutChanged({parent}, QAbstractItemModel::VerticalSortHint);
660
661
662
663
664
665
666
668bool QTreeModel::itemLessThan(
const std::pair<QTreeWidgetItem*,
int> &left,
669 const std::pair<QTreeWidgetItem*,
int> &right)
671 return *(left.first) < *(right.first);
675
676
677
678
679
680
681
683bool QTreeModel::itemGreaterThan(
const std::pair<QTreeWidgetItem*,
int> &left,
684 const std::pair<QTreeWidgetItem*,
int> &right)
686 return *(right.first) < *(left.first);
690
691
692QList<QTreeWidgetItem*>::iterator QTreeModel::sortedInsertionIterator(
693 const QList<QTreeWidgetItem*>::iterator &begin,
694 const QList<QTreeWidgetItem*>::iterator &end,
695 Qt::SortOrder order, QTreeWidgetItem *item)
697 if (order == Qt::AscendingOrder)
698 return std::lower_bound(begin, end, item, QTreeModelLessThan());
699 return std::lower_bound(begin, end, item, QTreeModelGreaterThan());
702QStringList QTreeModel::mimeTypes()
const
706 return v->mimeTypes();
710QMimeData *QTreeModel::internalMimeData()
const
712 return QAbstractItemModel::mimeData(cachedIndexes);
715QMimeData *QTreeModel::mimeData(
const QModelIndexList &indexes)
const
717 QList<QTreeWidgetItem *> items;
718 std::transform(indexes.begin(), indexes.end(), std::back_inserter(items),
719 [
this](
const QModelIndex &idx) -> QTreeWidgetItem * {
return item(idx); });
723 std::sort(items.begin(), items.end());
724 items.erase(std::unique(items.begin(), items.end()), items.end());
728 cachedIndexes = indexes;
729 QMimeData *mimeData = view()->mimeData(items);
730 cachedIndexes.clear();
734bool QTreeModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
735 int row,
int column,
const QModelIndex &parent)
737 if (row == -1 && column == -1)
738 row = rowCount(parent);
739 return view()->dropMimeData(item(parent), row, data, action);
742Qt::DropActions QTreeModel::supportedDropActions()
const
744 return view()->supportedDropActions();
747Qt::DropActions QTreeModel::supportedDragActions()
const
749#if QT_CONFIG(draganddrop)
750 return view()->supportedDragActions();
752 return Qt::DropActions(Qt::IgnoreAction);
756void QTreeModel::itemChanged(QTreeWidgetItem *item)
758 if (item->columnCount() <= 0)
760 SkipSorting skipSorting(
this);
761 QModelIndex left = index(item, 0);
762 QModelIndex right = index(item, item->columnCount() - 1);
763 emit dataChanged(left, right);
766bool QTreeModel::isChanging()
const
768 Q_D(
const QTreeModel);
769 return !d->changes.isEmpty();
773
774
775
777void QTreeModel::emitDataChanged(QTreeWidgetItem *item,
int column,
const QList<
int> &roles)
779 if (signalsBlocked())
782 if (headerItem == item && column < item->columnCount()) {
783 emit headerDataChanged(Qt::Horizontal, column, column);
787 SkipSorting skipSorting(
this);
789 const QModelIndex idx = index(item, column);
790 emit dataChanged(idx, idx, roles);
793void QTreeModel::beginInsertItems(QTreeWidgetItem *parent,
int row,
int count)
795 QModelIndex par = index(parent, 0);
796 beginInsertRows(par, row, row + count - 1);
799void QTreeModel::endInsertItems()
804void QTreeModel::beginRemoveItems(QTreeWidgetItem *parent,
int row,
int count)
808 beginRemoveRows(index(parent, 0), row, row + count - 1);
812 for (
int i = 0; i < iterators.size(); ++i) {
813 for (
int j = 0; j < count; j++) {
814 QTreeWidgetItem *c = parent->child(row + j);
815 iterators[i]->d_func()->ensureValidIterator(c);
820void QTreeModel::endRemoveItems()
825void QTreeModel::sortItems(QList<QTreeWidgetItem*> *items,
int column, Qt::SortOrder order)
833 QList<std::pair<QTreeWidgetItem *,
int>> sorting(items->size());
834 for (
int i = 0; i < sorting.size(); ++i) {
835 sorting[i].first = items->at(i);
836 sorting[i].second = i;
840 const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
841 std::stable_sort(sorting.begin(), sorting.end(), compare);
843 QModelIndexList fromList;
844 QModelIndexList toList;
845 int colCount = columnCount();
846 for (
int r = 0; r < sorting.size(); ++r) {
847 int oldRow = sorting.at(r).second;
850 QTreeWidgetItem *item = sorting.at(r).first;
851 items->replace(r, item);
852 for (
int c = 0; c < colCount; ++c) {
853 QModelIndex from = createIndex(oldRow, c, item);
854 if (
static_cast<QAbstractItemModelPrivate *>(d_ptr.data())->persistent.indexes.contains(from)) {
855 QModelIndex to = createIndex(r, c, item);
861 changePersistentIndexList(fromList, toList);
864void QTreeModel::timerEvent(QTimerEvent *ev)
866 if (ev->timerId() == sortPendingTimer.timerId()) {
867 executePendingSort();
869 QAbstractItemModel::timerEvent(ev);
874
875
876
877
878
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
937
938
939
940
941
942
943
944
945
946
947
948
949
952
953
954
955
958
959
960
961
962
963
964
965
968
969
970
971
974
975
976
977
978
979
980void QTreeWidgetItem::setSelected(
bool select)
982 const QTreeModel *model = treeModel();
983 if (!model || !view->selectionModel())
985 const QModelIndex index = model->index(
this, 0);
986 view->selectionModel()->select(index, (select ? QItemSelectionModel::Select
987 : QItemSelectionModel::Deselect)
988 | QItemSelectionModel::Rows);
989 d->selected = select;
993
994
995
996
997
998
999bool QTreeWidgetItem::isSelected()
const
1005
1006
1007
1008
1009
1010
1011
1012
1013
1015void QTreeWidgetItem::setHidden(
bool hide)
1017 const QTreeModel *model = treeModel();
1020 if (
this == model->headerItem) {
1021 view->header()->setHidden(hide);
1023 const QModelIndex index = view->d_func()->index(
this);
1024 view->setRowHidden(index.row(), index.parent(), hide);
1030
1031
1032
1033
1034
1035
1037bool QTreeWidgetItem::isHidden()
const
1039 const QTreeModel *model = treeModel();
1042 if (
this == model->headerItem)
1043 return view->header()->isHidden();
1044 if (view->d_func()->hiddenIndexes.isEmpty())
1046 QTreeModel::SkipSorting skipSorting(model);
1047 return view->d_func()->isRowHidden(view->d_func()->index(
this));
1051
1052
1053
1054
1055
1056
1057
1058void QTreeWidgetItem::setExpanded(
bool expand)
1060 const QTreeModel *model = treeModel();
1063 QTreeModel::SkipSorting skipSorting(model);
1064 view->setExpanded(view->d_func()->index(
this), expand);
1068
1069
1070
1071
1072
1073
1074bool QTreeWidgetItem::isExpanded()
const
1076 const QTreeModel *model = treeModel();
1079 QTreeModel::SkipSorting skipSorting(model);
1080 return view->isExpanded(view->d_func()->index(
this));
1084
1085
1086
1087
1088
1089
1090
1091void QTreeWidgetItem::setFirstColumnSpanned(
bool span)
1093 const QTreeModel *model = treeModel();
1094 if (!model ||
this == model->headerItem)
1096 const QModelIndex index = model->index(
this, 0);
1097 view->setFirstColumnSpanned(index.row(), index.parent(), span);
1101
1102
1103
1104
1105
1106
1107bool QTreeWidgetItem::isFirstColumnSpanned()
const
1109 const QTreeModel *model = treeModel();
1110 if (!model ||
this == model->headerItem)
1112 const QModelIndex index = model->index(
this, 0);
1113 return view->isFirstColumnSpanned(index.row(), index.parent());
1117
1118
1119
1120
1121
1122
1125
1126
1127
1128
1129
1130
1133
1134
1135
1136
1137
1138
1141
1142
1143
1144
1145
1146
1149
1150
1151
1152
1153
1154
1157
1158
1159
1160
1161
1162
1163
1166
1167
1168
1169
1170
1171
1174
1175
1176
1177
1178
1179
1182
1183
1184
1185
1186
1187
1190
1191
1192
1193
1194
1195
1198
1199
1200
1201
1202
1203
1206
1207
1208
1209
1210
1211
1212
1215
1216
1217
1218
1219
1220
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1238
1239
1240
1241
1242
1243
1244
1245
1246
1249
1250
1251
1252
1253
1254
1255
1258
1259
1260
1261
1262
1263
1266
1267
1268
1269
1270
1271
1274
1275
1276
1277
1278
1281
1282
1283
1284
1285
1286
1289
1290
1291
1292
1293
1294
1297
1298
1299
1300
1301
1302
1305
1306
1307
1308
1311
1312
1313
1314
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1338
1339
1340
1341
1342
1343
1344
1345
1346
1349
1350
1351
1352
1353
1354
1355
1358
1359
1360
1363
1364
1365
1366
1369
1370
1371
1372
1373
1374QTreeWidgetItem::QTreeWidgetItem(
int type) : rtti(type), d(
new QTreeWidgetItemPrivate(
this)) { }
1377
1378
1379
1380
1381
1382
1383
1384QTreeWidgetItem::QTreeWidgetItem(
const QStringList &strings,
int type)
1385 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1387 for (
int i = 0; i < strings.size(); ++i)
1388 setText(i, strings.at(i));
1392
1393
1394
1395
1396
1397
1398
1400QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *treeview,
int type)
1401 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1404 if (QTreeModel *model = treeModel(treeview)) {
1405 model->rootItem->addChild(
this);
1406 values.reserve(model->headerItem->columnCount());
1411
1412
1413
1414
1415
1416
1417
1418
1420QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *treeview,
const QStringList &strings,
int type)
1421 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1423 for (
int i = 0; i < strings.size(); ++i)
1424 setText(i, strings.at(i));
1426 if (QTreeModel *model = treeModel(treeview)) {
1427 model->rootItem->addChild(
this);
1428 values.reserve(model->headerItem->columnCount());
1433
1434
1435
1436
1437
1438
1439
1440QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *treeview, QTreeWidgetItem *after,
int type)
1441 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1444 if (QTreeModel *model = treeModel(treeview)) {
1445 int i = model->rootItem->children.indexOf(after) + 1;
1446 model->rootItem->insertChild(i,
this);
1447 values.reserve(model->headerItem->columnCount());
1452
1453
1454
1455
1456QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent,
int type)
1457 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1460 parent->addChild(
this);
1464
1465
1466
1467
1468
1469QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent,
const QStringList &strings,
int type)
1470 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1472 for (
int i = 0; i < strings.size(); ++i)
1473 setText(i, strings.at(i));
1475 parent->addChild(
this);
1479
1480
1481
1482
1483
1484
1485
1486QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, QTreeWidgetItem *after,
int type)
1487 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1490 int i = parent->children.indexOf(after) + 1;
1491 parent->insertChild(i,
this);
1496
1497
1498
1499
1500
1501
1503QTreeWidgetItem::~QTreeWidgetItem()
1505 QTreeModel *model = treeModel();
1506 QTreeModel::SkipSorting skipSorting(model);
1509 int i = par->children.indexOf(
this);
1511 if (model) model->beginRemoveItems(par, i, 1);
1514 if (!par->children.isEmpty() && par->children.at(i) ==
this)
1515 par->children.takeAt(i);
1516 if (model) model->endRemoveItems();
1519 if (
this == model->headerItem) {
1520 model->headerItem =
nullptr;
1522 int i = model->rootItem->children.indexOf(
this);
1524 model->beginRemoveItems(
nullptr, i, 1);
1527 if (!model->rootItem->children.isEmpty() && model->rootItem->children.at(i) ==
this)
1528 model->rootItem->children.takeAt(i);
1529 model->endRemoveItems();
1535 for (
int i = 0; i < children.size(); ++i) {
1536 QTreeWidgetItem *child = children.at(i);
1538 child->par =
nullptr;
1540 child->view =
nullptr;
1549
1550
1551QTreeWidgetItem *QTreeWidgetItem::clone()
const
1553 QTreeWidgetItem *copy =
nullptr;
1555 QStack<
const QTreeWidgetItem*> stack;
1556 QStack<QTreeWidgetItem*> parentStack;
1558 parentStack.push(0);
1560 QTreeWidgetItem *root =
nullptr;
1561 const QTreeWidgetItem *item =
nullptr;
1562 QTreeWidgetItem *parent =
nullptr;
1563 while (!stack.isEmpty()) {
1566 parent = parentStack.pop();
1569 copy =
new QTreeWidgetItem(*item);
1576 parent->children.insert(0, copy);
1579 for (
int i = 0; i < item->childCount(); ++i) {
1580 stack.push(item->child(i));
1581 parentStack.push(copy);
1588
1589
1590
1591
1592
1593
1594void QTreeWidgetItem::setChildIndicatorPolicy(QTreeWidgetItem::ChildIndicatorPolicy policy)
1596 if (d->policy == policy)
1603 view->scheduleDelayedItemsLayout();
1607
1608
1609
1610
1611
1612QTreeWidgetItem::ChildIndicatorPolicy QTreeWidgetItem::childIndicatorPolicy()
const
1618
1619
1620
1621
1622
1623
1624
1625void QTreeWidgetItem::setFlags(Qt::ItemFlags flags)
1627 const bool enable = (flags & Qt::ItemIsEnabled);
1628 const bool changedState =
bool(itemFlags & Qt::ItemIsEnabled) != enable;
1629 const bool changedExplicit = d->disabled != !enable;
1631 d->disabled = !enable;
1633 if (enable && par && !(par->itemFlags & Qt::ItemIsEnabled))
1634 itemFlags = flags & ~Qt::ItemIsEnabled;
1638 if (changedState && changedExplicit) {
1639 QStack<QTreeWidgetItem*> parents;
1641 while (!parents.isEmpty()) {
1642 QTreeWidgetItem *parent = parents.pop();
1643 for (
int i = 0; i < parent->children.size(); ++i) {
1644 QTreeWidgetItem *child = parent->children.at(i);
1645 if (!child->d->disabled) {
1646 parents.push(child);
1648 child->itemFlags = child->itemFlags | Qt::ItemIsEnabled;
1650 child->itemFlags = child->itemFlags & ~Qt::ItemIsEnabled;
1651 child->itemChanged();
1659void QTreeWidgetItemPrivate::updateHiddenStatus(QTreeWidgetItem *item,
bool inserting)
1661 QTreeModel *model = item->treeModel();
1664 QStack<QTreeWidgetItem *> parents;
1666 while (!parents.isEmpty()) {
1667 QTreeWidgetItem *parent = parents.pop();
1668 if (parent->d->hidden) {
1669 const QModelIndex index = model->index(parent, 0);
1670 item->view->setRowHidden(index.row(), index.parent(), inserting);
1672 for (
int i = 0; i < parent->children.size(); ++i) {
1673 QTreeWidgetItem *child = parent->children.at(i);
1674 parents.push(child);
1679void QTreeWidgetItemPrivate::propagateDisabled(QTreeWidgetItem *item)
1682 const bool enable = item->par ? (item->par->itemFlags.testFlag(Qt::ItemIsEnabled)) :
true;
1684 QStack<QTreeWidgetItem*> parents;
1686 while (!parents.isEmpty()) {
1687 QTreeWidgetItem *parent = parents.pop();
1688 if (!parent->d->disabled) {
1689 Qt::ItemFlags oldFlags = parent->itemFlags;
1691 parent->itemFlags = parent->itemFlags | Qt::ItemIsEnabled;
1693 parent->itemFlags = parent->itemFlags & ~Qt::ItemIsEnabled;
1694 if (parent->itemFlags != oldFlags)
1695 parent->itemChanged();
1698 for (
int i = 0; i < parent->children.size(); ++i) {
1699 QTreeWidgetItem *child = parent->children.at(i);
1700 parents.push(child);
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716Qt::ItemFlags QTreeWidgetItem::flags()
const
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731void QTreeWidgetItem::setData(
int column,
int role,
const QVariant &value)
1736 QTreeModel *model = treeModel();
1739 case Qt::DisplayRole: {
1740 if (values.size() <= column) {
1741 if (model &&
this == model->headerItem)
1742 model->setColumnCount(column + 1);
1744 values.resize(column + 1);
1746 if (d->display.size() <= column) {
1747 for (
int i = d->display.size() - 1; i < column - 1; ++i)
1748 d->display.append(QVariant());
1749 d->display.append(value);
1750 }
else if (d->display[column] != value) {
1751 d->display[column] = value;
1756 case Qt::CheckStateRole:
1757 if ((itemFlags & Qt::ItemIsAutoTristate) && value != Qt::PartiallyChecked) {
1758 for (
int i = 0; i < children.size(); ++i) {
1759 QTreeWidgetItem *child = children.at(i);
1760 if (child->data(column, role).isValid()) {
1761 Qt::ItemFlags f = itemFlags;
1762 itemFlags &= ~Qt::ItemIsAutoTristate;
1763 child->setData(column, role, value);
1770 if (column < values.size()) {
1772 const QList<QWidgetItemData> column_values = values.at(column);
1773 for (
int i = 0; i < column_values.size(); ++i) {
1774 if (column_values.at(i).role == role) {
1775 if (column_values.at(i).value == value)
1777 values[column][i].value = value;
1783 values[column].append(QWidgetItemData(role, value));
1785 if (model &&
this == model->headerItem)
1786 model->setColumnCount(column + 1);
1788 values.resize(column + 1);
1789 values[column].append(QWidgetItemData(role, value));
1794 const QList<
int> roles((role == Qt::DisplayRole || role == Qt::EditRole)
1795 ? QList<
int>({ Qt::DisplayRole, Qt::EditRole })
1796 : QList<
int>({ role }));
1797 model->emitDataChanged(
this, column, roles);
1798 if (role == Qt::CheckStateRole) {
1800 for (p = par; p && (p->itemFlags & Qt::ItemIsAutoTristate); p = p->par)
1801 model->emitDataChanged(p, column, roles);
1807
1808
1809QVariant QTreeWidgetItem::data(
int column,
int role)
const
1813 case Qt::DisplayRole:
1814 if (column >= 0 && column < d->display.size())
1815 return d->display.at(column);
1817 case Qt::CheckStateRole:
1819 if (children.size() && (itemFlags & Qt::ItemIsAutoTristate))
1820 return childrenCheckState(column);
1823 if (column >= 0 && column < values.size()) {
1824 const QList<QWidgetItemData> &column_values = values.at(column);
1825 for (
const auto &column_value : column_values) {
1826 if (column_value.role == role)
1827 return column_value.value;
1835
1836
1837
1839bool QTreeWidgetItem::operator<(
const QTreeWidgetItem &other)
const
1841 int column = view ? view->sortColumn() : 0;
1842 const QVariant v1 = data(column, Qt::DisplayRole);
1843 const QVariant v2 = other.data(column, Qt::DisplayRole);
1844 return QAbstractItemModelPrivate::variantLessThan(v1, v2);
1847#ifndef QT_NO_DATASTREAM
1850
1851
1852
1853
1854void QTreeWidgetItem::read(QDataStream &in)
1857 if (in.version() < QDataStream::Qt_4_2) {
1861 for (
int column = 0; column < values.size(); ++column) {
1862 d->display << QVariant();
1863 for (
int i = 0; i < values.at(column).size(); ++i) {
1864 if (values.at(column).at(i).role == Qt::DisplayRole) {
1865 d->display[column] = values.at(column).at(i).value;
1866 values[column].remove(i--);
1871 in >> values >> d->display;
1876
1877
1878
1879
1880void QTreeWidgetItem::write(QDataStream &out)
const
1882 out << values << d->display;
1887
1888
1889
1890
1891
1892
1893
1894QTreeWidgetItem::QTreeWidgetItem(
const QTreeWidgetItem &other)
1896 values(other.values),
1897 d(
new QTreeWidgetItemPrivate(
this)),
1898 itemFlags(other.itemFlags)
1900 d->display = other.d->display;
1904
1905
1906
1907
1908
1909
1910
1911QTreeWidgetItem &QTreeWidgetItem::operator=(
const QTreeWidgetItem &other)
1913 values = other.values;
1914 d->display = other.d->display;
1915 d->policy = other.d->policy;
1916 itemFlags = other.itemFlags;
1921
1922
1923
1924
1925void QTreeWidgetItem::addChild(QTreeWidgetItem *child)
1928 insertChild(children.size(), child);
1929 child->d->rowGuess = children.size() - 1;
1934
1935
1936
1937
1938void QTreeWidgetItem::insertChild(
int index, QTreeWidgetItem *child)
1940 if (index < 0 || index > children.size() || child ==
nullptr || child->view !=
nullptr || child->par !=
nullptr)
1943 if (QTreeModel *model = treeModel()) {
1944 QTreeModel::SkipSorting skipSorting(model);
1945 if (model->rootItem ==
this)
1946 child->par =
nullptr;
1949 if (view->isSortingEnabled()) {
1951 if (!model->sortPendingTimer.isActive())
1952 model->sortPendingTimer.start(0, model);
1954 model->beginInsertItems(
this, index, 1);
1955 int cols = model->columnCount();
1956 QStack<QTreeWidgetItem*> stack;
1958 while (!stack.isEmpty()) {
1959 QTreeWidgetItem *i = stack.pop();
1961 i->values.reserve(cols);
1962 for (
int c = 0; c < i->children.size(); ++c)
1963 stack.push(i->children.at(c));
1965 children.insert(index, child);
1966 d->updateHiddenStatus(child,
true);
1967 model->endInsertItems();
1970 children.insert(index, child);
1973 d->propagateDisabled(child);
1977
1978
1979
1980void QTreeWidgetItem::removeChild(QTreeWidgetItem *child)
1982 (
void)takeChild(children.indexOf(child));
1986
1987
1988QTreeWidgetItem *QTreeWidgetItem::takeChild(
int index)
1992 QTreeModel *model = treeModel();
1998 model->skipPendingSort =
false;
1999 model->executePendingSort();
2001 if (index >= 0 && index < children.size()) {
2002 if (model) model->beginRemoveItems(
this, index, 1);
2003 d->updateHiddenStatus(children.at(index),
false);
2004 QTreeWidgetItem *item = children.takeAt(index);
2005 item->par =
nullptr;
2006 QStack<QTreeWidgetItem*> stack;
2008 while (!stack.isEmpty()) {
2009 QTreeWidgetItem *i = stack.pop();
2011 for (
int c = 0; c < i->children.size(); ++c)
2012 stack.push(i->children.at(c));
2014 d->propagateDisabled(item);
2015 if (model) model->endRemoveRows();
2022
2023
2024
2025
2026void QTreeWidgetItem::addChildren(
const QList<QTreeWidgetItem*> &children)
2028 insertChildren(
this->children.size(), children);
2032
2033
2034
2035
2036void QTreeWidgetItem::insertChildren(
int index,
const QList<QTreeWidgetItem*> &children)
2038 if (index < 0 || index >
this->children.size() || children.isEmpty())
2041 if (view && view->isSortingEnabled()) {
2042 for (
int n = 0; n < children.size(); ++n)
2043 insertChild(index, children.at(n));
2046 QTreeModel *model = treeModel();
2047 QStack<QTreeWidgetItem*> stack;
2048 QList<QTreeWidgetItem*> itemsToInsert;
2049 for (
int n = 0; n < children.size(); ++n) {
2050 QTreeWidgetItem *child = children.at(n);
2051 if (child->view || child->par)
2053 itemsToInsert.append(child);
2054 if (view && model) {
2055 if (child->childCount() == 0)
2060 if (model && (model->rootItem ==
this))
2061 child->par =
nullptr;
2065 if (!itemsToInsert.isEmpty()) {
2066 while (!stack.isEmpty()) {
2067 QTreeWidgetItem *i = stack.pop();
2069 for (
int c = 0; c < i->children.size(); ++c)
2070 stack.push(i->children.at(c));
2072 if (model) model->beginInsertItems(
this, index, itemsToInsert.size());
2073 for (
int n = 0; n < itemsToInsert.size(); ++n) {
2074 QTreeWidgetItem *child = itemsToInsert.at(n);
2075 this->children.insert(index + n, child);
2077 d->propagateDisabled(child);
2078 d->updateHiddenStatus(child,
true);
2080 if (model) model->endInsertItems();
2085
2086
2087QList<QTreeWidgetItem*> QTreeWidgetItem::takeChildren()
2089 QList<QTreeWidgetItem*> removed;
2090 if (children.size() > 0) {
2091 QTreeModel *model = treeModel();
2097 model->executePendingSort();
2099 if (model) model->beginRemoveItems(
this, 0, children.size());
2100 for (
int n = 0; n < children.size(); ++n) {
2101 QTreeWidgetItem *item = children.at(n);
2102 item->par =
nullptr;
2103 QStack<QTreeWidgetItem*> stack;
2105 while (!stack.isEmpty()) {
2106 QTreeWidgetItem *i = stack.pop();
2108 for (
int c = 0; c < i->children.size(); ++c)
2109 stack.push(i->children.at(c));
2111 d->propagateDisabled(item);
2115 if (model) model->endRemoveItems();
2121void QTreeWidgetItemPrivate::sortChildren(
int column, Qt::SortOrder order,
bool climb)
2123 QTreeModel *model = q->treeModel();
2126 model->sortItems(&q->children, column, order);
2128 QList<QTreeWidgetItem*>::iterator it = q->children.begin();
2129 for (; it != q->children.end(); ++it) {
2132 (*it)->d->sortChildren(column, order, climb);
2138
2139
2140
2141
2142
2143
2144void QTreeWidgetItem::sortChildren(
int column, Qt::SortOrder order,
bool climb)
2146 QTreeModel *model = treeModel();
2149 if (model->isChanging())
2151 QTreeModel::SkipSorting skipSorting(model);
2152 int oldSortColumn = view->d_func()->explicitSortColumn;
2153 view->d_func()->explicitSortColumn = column;
2154 emit model->layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint);
2155 d->sortChildren(column, order, climb);
2156 emit model->layoutChanged({}, QAbstractItemModel::VerticalSortHint);
2157 view->d_func()->explicitSortColumn = oldSortColumn;
2161
2162
2163
2164
2165
2166
2167
2168QVariant QTreeWidgetItem::childrenCheckState(
int column)
const
2172 bool checkedChildren =
false;
2173 bool uncheckedChildren =
false;
2174 for (
const auto *child : children) {
2175 QVariant value = child->data(column, Qt::CheckStateRole);
2176 if (!value.isValid())
2179 switch (
static_cast<Qt::CheckState>(value.toInt()))
2182 uncheckedChildren =
true;
2185 checkedChildren =
true;
2187 case Qt::PartiallyChecked:
2189 return Qt::PartiallyChecked;
2192 if (uncheckedChildren && checkedChildren)
2193 return Qt::PartiallyChecked;
2196 if (uncheckedChildren)
2197 return Qt::Unchecked;
2198 else if (checkedChildren)
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214void QTreeWidgetItem::emitDataChanged()
2220
2221
2222void QTreeWidgetItem::itemChanged()
2224 if (QTreeModel *model = treeModel())
2225 model->itemChanged(
this);
2229
2230
2231void QTreeWidgetItem::executePendingSort()
const
2233 if (QTreeModel *model = treeModel())
2234 model->executePendingSort();
2238
2239
2240
2241QTreeModel *QTreeWidgetItem::treeModel(QTreeWidget *v)
const
2245 return (v ? qobject_cast<QTreeModel*>(v->model()) :
nullptr);
2249#ifndef QT_NO_DATASTREAM
2251
2252
2253
2254
2255
2256
2257
2258
2266
2267
2268
2269
2270
2271
2272
2273
2282void QTreeWidgetPrivate::clearConnections()
2284 for (QMetaObject::Connection &connection : connections)
2285 QObject::disconnect(connection);
2288void QTreeWidgetPrivate::emitItemPressed(
const QModelIndex &index)
2291 emit q->itemPressed(item(index), index.column());
2294void QTreeWidgetPrivate::emitItemClicked(
const QModelIndex &index)
2297 emit q->itemClicked(item(index), index.column());
2300void QTreeWidgetPrivate::emitItemDoubleClicked(
const QModelIndex &index)
2303 emit q->itemDoubleClicked(item(index), index.column());
2306void QTreeWidgetPrivate::emitItemActivated(
const QModelIndex &index)
2309 emit q->itemActivated(item(index), index.column());
2312void QTreeWidgetPrivate::emitItemEntered(
const QModelIndex &index)
2315 emit q->itemEntered(item(index), index.column());
2318void QTreeWidgetPrivate::emitItemChanged(
const QModelIndex &index)
2321 QTreeWidgetItem *indexItem = item(index);
2323 emit q->itemChanged(indexItem, index.column());
2326void QTreeWidgetPrivate::emitItemExpanded(
const QModelIndex &index)
2329 emit q->itemExpanded(item(index));
2332void QTreeWidgetPrivate::emitItemCollapsed(
const QModelIndex &index)
2335 emit q->itemCollapsed(item(index));
2338void QTreeWidgetPrivate::emitCurrentItemChanged(
const QModelIndex ¤t,
2339 const QModelIndex &previous)
2342 QTreeWidgetItem *currentItem = item(current);
2343 QTreeWidgetItem *previousItem = item(previous);
2344 emit q->currentItemChanged(currentItem, previousItem);
2347void QTreeWidgetPrivate::sort()
2349 if (sortingEnabled) {
2350 int column = header->sortIndicatorSection();
2351 Qt::SortOrder order = header->sortIndicatorOrder();
2352 treeModel()->sort(column, order);
2356void QTreeWidgetPrivate::selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected)
2359 QModelIndexList indices = selected.indexes();
2361 QTreeModel *m = treeModel();
2362 for (i = 0; i < indices.size(); ++i) {
2363 QTreeWidgetItem *item = m->item(indices.at(i));
2364 item->d->selected =
true;
2367 indices = deselected.indexes();
2368 for (i = 0; i < indices.size(); ++i) {
2369 QTreeWidgetItem *item = m->item(indices.at(i));
2370 item->d->selected =
false;
2373 emit q->itemSelectionChanged();
2376void QTreeWidgetPrivate::dataChanged(
const QModelIndex &topLeft,
2377 const QModelIndex &bottomRight)
2379 if (sortingEnabled && topLeft.isValid() && bottomRight.isValid()
2380 && !treeModel()->sortPendingTimer.isActive()) {
2381 int column = header->sortIndicatorSection();
2382 if (column >= topLeft.column() && column <= bottomRight.column()) {
2383 Qt::SortOrder order = header->sortIndicatorOrder();
2384 treeModel()->ensureSorted(column, order, topLeft.row(),
2385 bottomRight.row(), topLeft.parent());
2391
2392
2393
2394
2395
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
2439
2440
2441
2442
2443
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2459
2460
2461
2462
2463
2464
2465
2466
2467
2470
2471
2472
2473
2474
2475
2476
2477
2480
2481
2482
2483
2484
2485
2486
2487
2488
2491
2492
2493
2494
2495
2496
2497
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2512
2513
2514
2515
2516
2517
2518
2519
2522
2523
2524
2525
2526
2529
2530
2531
2532
2533
2534
2537
2538
2539
2540
2541
2544
2545
2546
2547
2548
2549
2552
2553
2554QTreeWidget::QTreeWidget(QWidget *parent)
2555 : QTreeView(*
new QTreeWidgetPrivate(), parent)
2558 QTreeView::setModel(
new QTreeModel(1,
this));
2560 QObjectPrivate::connect(
this, &QTreeWidget::pressed,
2561 d, &QTreeWidgetPrivate::emitItemPressed),
2562 QObjectPrivate::connect(
this, &QTreeWidget::clicked,
2563 d, &QTreeWidgetPrivate::emitItemClicked),
2564 QObjectPrivate::connect(
this, &QTreeWidget::doubleClicked,
2565 d, &QTreeWidgetPrivate::emitItemDoubleClicked),
2566 QObjectPrivate::connect(
this, &QTreeWidget::activated,
2567 d, &QTreeWidgetPrivate::emitItemActivated),
2568 QObjectPrivate::connect(
this, &QTreeWidget::entered,
2569 d, &QTreeWidgetPrivate::emitItemEntered),
2570 QObjectPrivate::connect(
this, &QTreeWidget::expanded,
2571 d, &QTreeWidgetPrivate::emitItemExpanded),
2572 QObjectPrivate::connect(
this, &QTreeWidget::collapsed,
2573 d, &QTreeWidgetPrivate::emitItemCollapsed),
2574 QObjectPrivate::connect(model(), &QAbstractItemModel::dataChanged,
2575 d, &QTreeWidgetPrivate::emitItemChanged),
2576 QObjectPrivate::connect(model(), &QAbstractItemModel::dataChanged,
2577 d, &QTreeWidgetPrivate::dataChanged),
2578 QObjectPrivate::connect(model(), &QAbstractItemModel::columnsRemoved,
2579 d, &QTreeWidgetPrivate::sort),
2580 QObjectPrivate::connect(selectionModel(), &QItemSelectionModel::currentChanged,
2581 d, &QTreeWidgetPrivate::emitCurrentItemChanged),
2582 QObjectPrivate::connect(selectionModel(), &QItemSelectionModel::selectionChanged,
2583 d, &QTreeWidgetPrivate::selectionChanged)
2585 header()->setSectionsClickable(
false);
2589
2590
2592QTreeWidget::~QTreeWidget()
2595 d->clearConnections();
2599
2600
2601
2602
2604int QTreeWidget::columnCount()
const
2606 Q_D(
const QTreeWidget);
2607 return d->model->columnCount();
2611
2612
2614void QTreeWidget::setColumnCount(
int columns)
2619 d->treeModel()->setColumnCount(columns);
2623
2624
2625
2626
2627
2628
2629
2631QTreeWidgetItem *QTreeWidget::invisibleRootItem()
const
2633 Q_D(
const QTreeWidget);
2634 return d->treeModel()->rootItem;
2638
2639
2640
2641
2642
2644QTreeWidgetItem *QTreeWidget::topLevelItem(
int index)
const
2646 Q_D(
const QTreeWidget);
2647 return d->treeModel()->rootItem->child(index);
2651
2652
2653
2654
2655
2656
2657
2659int QTreeWidget::topLevelItemCount()
const
2661 Q_D(
const QTreeWidget);
2662 return d->treeModel()->rootItem->childCount();
2666
2667
2668
2669
2670
2671
2673void QTreeWidget::insertTopLevelItem(
int index, QTreeWidgetItem *item)
2676 d->treeModel()->rootItem->insertChild(index, item);
2680
2681
2682
2683
2684void QTreeWidget::addTopLevelItem(QTreeWidgetItem *item)
2686 insertTopLevelItem(topLevelItemCount(), item);
2690
2691
2692
2693
2694
2696QTreeWidgetItem *QTreeWidget::takeTopLevelItem(
int index)
2699 return d->treeModel()->rootItem->takeChild(index);
2703
2704
2705
2706
2707
2708int QTreeWidget::indexOfTopLevelItem(QTreeWidgetItem *item)
const
2710 Q_D(
const QTreeWidget);
2711 d->treeModel()->executePendingSort();
2712 return d->treeModel()->rootItem->children.indexOf(item);
2716
2717
2718
2719
2720
2721
2722void QTreeWidget::insertTopLevelItems(
int index,
const QList<QTreeWidgetItem*> &items)
2725 d->treeModel()->rootItem->insertChildren(index, items);
2729
2730
2731
2732
2733void QTreeWidget::addTopLevelItems(
const QList<QTreeWidgetItem*> &items)
2735 insertTopLevelItems(topLevelItemCount(), items);
2739
2740
2741
2742
2744QTreeWidgetItem *QTreeWidget::headerItem()
const
2746 Q_D(
const QTreeWidget);
2747 return d->treeModel()->headerItem;
2751
2752
2753
2754
2755
2756
2757
2759void QTreeWidget::setHeaderItem(QTreeWidgetItem *item)
2766 int oldCount = columnCount();
2767 if (oldCount < item->columnCount())
2768 d->treeModel()->beginInsertColumns(QModelIndex(), oldCount, item->columnCount() - 1);
2769 else if (oldCount > item->columnCount())
2770 d->treeModel()->beginRemoveColumns(QModelIndex(), item->columnCount(), oldCount - 1);
2771 delete d->treeModel()->headerItem;
2772 d->treeModel()->headerItem = item;
2773 if (oldCount < item->columnCount())
2774 d->treeModel()->endInsertColumns();
2775 else if (oldCount > item->columnCount())
2776 d->treeModel()->endRemoveColumns();
2777 d->treeModel()->headerDataChanged(Qt::Horizontal, 0, oldCount);
2782
2783
2784
2785
2786
2787
2788
2789void QTreeWidget::setHeaderLabels(
const QStringList &labels)
2792 if (columnCount() < labels.size())
2793 setColumnCount(labels.size());
2794 QTreeWidgetItem *item = d->treeModel()->headerItem;
2795 for (
int i = 0; i < labels.size(); ++i)
2796 item->setText(i, labels.at(i));
2800
2801
2802
2803
2806
2807
2808
2809
2810QTreeWidgetItem *QTreeWidget::currentItem()
const
2812 Q_D(
const QTreeWidget);
2813 return d->item(currentIndex());
2817
2818
2819
2820
2821int QTreeWidget::currentColumn()
const
2823 return currentIndex().column();
2827
2828
2829
2830
2831
2832
2833
2834void QTreeWidget::setCurrentItem(QTreeWidgetItem *item)
2836 setCurrentItem(item, 0);
2840
2841
2842
2843
2844void QTreeWidget::setCurrentItem(QTreeWidgetItem *item,
int column)
2847 setCurrentIndex(d->index(item, column));
2851
2852
2853
2854
2855
2856void QTreeWidget::setCurrentItem(QTreeWidgetItem *item,
int column,
2857 QItemSelectionModel::SelectionFlags command)
2860 d->selectionModel->setCurrentIndex(d->index(item, column), command);
2865
2866
2867
2868
2869
2870QTreeWidgetItem *QTreeWidget::itemAt(
const QPoint &p)
const
2872 Q_D(
const QTreeWidget);
2873 return d->item(indexAt(p));
2877
2878
2879
2880
2881
2882
2885
2886
2887
2888
2889QRect QTreeWidget::visualItemRect(
const QTreeWidgetItem *item)
const
2891 Q_D(
const QTreeWidget);
2894 const QModelIndex base = d->index(item);
2895 const int firstVisiblesection = header()->logicalIndexAt(- header()->offset());
2896 const int lastVisibleSection = header()->logicalIndexAt(header()->length() - header()->offset() - 1);
2897 const QModelIndex first = base.sibling(base.row(), firstVisiblesection);
2898 const QModelIndex last = base.sibling(base.row(), lastVisibleSection);
2899 return visualRect(first) | visualRect(last);
2903
2904
2905
2906
2907int QTreeWidget::sortColumn()
const
2909 Q_D(
const QTreeWidget);
2910 return (d->explicitSortColumn != -1
2911 ? d->explicitSortColumn
2912 : header()->sortIndicatorSection());
2916
2917
2918
2919
2920
2922void QTreeWidget::sortItems(
int column, Qt::SortOrder order)
2925 header()->setSortIndicator(column, order);
2926 d->model->sort(column, order);
2930
2931
2933void QTreeWidget::editItem(QTreeWidgetItem *item,
int column)
2936 edit(d->index(item, column));
2940
2941
2942
2943
2945void QTreeWidget::openPersistentEditor(QTreeWidgetItem *item,
int column)
2948 QAbstractItemView::openPersistentEditor(d->index(item, column));
2952
2953
2954
2955
2956
2957
2958
2960void QTreeWidget::closePersistentEditor(QTreeWidgetItem *item,
int column)
2963 QAbstractItemView::closePersistentEditor(d->index(item, column));
2967
2968
2969
2970
2971
2972
2973
2975bool QTreeWidget::isPersistentEditorOpen(QTreeWidgetItem *item,
int column)
const
2977 Q_D(
const QTreeWidget);
2978 return QAbstractItemView::isPersistentEditorOpen(d->index(item, column));
2982
2983
2984
2985
2986QWidget *QTreeWidget::itemWidget(QTreeWidgetItem *item,
int column)
const
2988 Q_D(
const QTreeWidget);
2989 return QAbstractItemView::indexWidget(d->index(item, column));
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013void QTreeWidget::setItemWidget(QTreeWidgetItem *item,
int column, QWidget *widget)
3016 QAbstractItemView::setIndexWidget(d->index(item, column), widget);
3020
3021
3022
3023
3024QList<QTreeWidgetItem*> QTreeWidget::selectedItems()
const
3026 Q_D(
const QTreeWidget);
3027 const QModelIndexList indexes = selectionModel()->selectedIndexes();
3028 QList<QTreeWidgetItem*> items;
3029 items.reserve(indexes.size());
3030 QDuplicateTracker<QTreeWidgetItem *> seen(indexes.size());
3031 for (
const auto &index : indexes) {
3032 QTreeWidgetItem *item = d->item(index);
3033 if (item->isHidden() || seen.hasSeen(item))
3041
3042
3043QList<QTreeWidgetItem*> QTreeWidget::findItems(
const QString &text, Qt::MatchFlags flags,
int column)
const
3045 Q_D(
const QTreeWidget);
3046 QModelIndexList indexes = d->model->match(model()->index(0, column, QModelIndex()),
3047 Qt::DisplayRole, text, -1, flags);
3048 QList<QTreeWidgetItem*> items;
3049 const int indexesSize = indexes.size();
3050 items.reserve(indexesSize);
3051 for (
int i = 0; i < indexesSize; ++i)
3052 items.append(d->item(indexes.at(i)));
3058
3059
3060QTreeWidgetItem *QTreeWidget::itemAbove(
const QTreeWidgetItem *item)
const
3062 Q_D(
const QTreeWidget);
3063 if (item == d->treeModel()->headerItem)
3065 const QModelIndex index = d->index(item);
3066 const QModelIndex above = indexAbove(index);
3067 return d->item(above);
3071
3072
3073QTreeWidgetItem *QTreeWidget::itemBelow(
const QTreeWidgetItem *item)
const
3075 Q_D(
const QTreeWidget);
3076 if (item == d->treeModel()->headerItem)
3078 const QModelIndex index = d->index(item);
3079 const QModelIndex below = indexBelow(index);
3080 return d->item(below);
3084
3085
3086void QTreeWidget::setSelectionModel(QItemSelectionModel *selectionModel)
3089 QTreeView::setSelectionModel(selectionModel);
3090 QItemSelection newSelection = selectionModel->selection();
3091 if (!newSelection.isEmpty())
3092 d->selectionChanged(newSelection, QItemSelection());
3096
3097
3098
3099
3100
3101void QTreeWidget::scrollToItem(
const QTreeWidgetItem *item, QAbstractItemView::ScrollHint hint)
3104 QTreeView::scrollTo(d->index(item), hint);
3108
3109
3110
3111
3112
3113void QTreeWidget::expandItem(
const QTreeWidgetItem *item)
3116 QTreeModel::SkipSorting skipSorting(d->treeModel());
3117 expand(d->index(item));
3121
3122
3123
3124
3125
3126void QTreeWidget::collapseItem(
const QTreeWidgetItem *item)
3129 QTreeModel::SkipSorting skipSorting(d->treeModel());
3130 collapse(d->index(item));
3134
3135
3136
3137
3138
3139
3140
3141
3142void QTreeWidget::clear()
3145 selectionModel()->clear();
3146 d->treeModel()->clear();
3150
3151
3152
3153
3154
3155QStringList QTreeWidget::mimeTypes()
const
3157 return model()->QAbstractItemModel::mimeTypes();
3161
3162
3163
3164
3165
3166
3167
3168QMimeData *QTreeWidget::mimeData(
const QList<QTreeWidgetItem *> &items)
const
3170 Q_D(
const QTreeWidget);
3171 if (d->treeModel()->cachedIndexes.isEmpty()) {
3172 QList<QModelIndex> indexes;
3173 for (
const auto *item : items) {
3174 if (Q_UNLIKELY(!item)) {
3175 qWarning(
"QTreeWidget::mimeData: Null-item passed");
3179 for (
int c = 0; c < item->values.size(); ++c) {
3180 const QModelIndex index = indexFromItem(item, c);
3181 if (Q_UNLIKELY(!index.isValid())) {
3182 qWarning() <<
"QTreeWidget::mimeData: No index associated with item :" << item;
3188 return d->model->QAbstractItemModel::mimeData(indexes);
3190 return d->treeModel()->internalMimeData();
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203bool QTreeWidget::dropMimeData(QTreeWidgetItem *parent,
int index,
3204 const QMimeData *data, Qt::DropAction action)
3207 if (parent) idx = indexFromItem(parent);
3208 return model()->QAbstractItemModel::dropMimeData(data, action , index, 0, idx);
3212
3213
3214
3215
3216Qt::DropActions QTreeWidget::supportedDropActions()
const
3218 return model()->QAbstractItemModel::supportedDropActions() | Qt::MoveAction;
3221#if QT_CONFIG(draganddrop)
3223
3224
3225
3226
3227
3228
3229Qt::DropActions QTreeWidget::supportedDragActions()
const
3231 Q_D(
const QTreeWidget);
3232 return d->supportedDragActions.value_or(supportedDropActions());
3235void QTreeWidget::setSupportedDragActions(Qt::DropActions actions)
3238 d->supportedDragActions = actions;
3243
3244
3245
3246
3247
3248
3249QModelIndex QTreeWidget::indexFromItem(
const QTreeWidgetItem *item,
int column)
const
3251 Q_D(
const QTreeWidget);
3252 return d->index(item, column);
3256
3257
3258
3259
3260QTreeWidgetItem *QTreeWidget::itemFromIndex(
const QModelIndex &index)
const
3262 Q_D(
const QTreeWidget);
3263 return d->item(index);
3266#if QT_CONFIG(draganddrop)
3268void QTreeWidget::dropEvent(QDropEvent *event) {
3270 if (event->source() ==
this && (event->dropAction() == Qt::MoveAction ||
3271 dragDropMode() == QAbstractItemView::InternalMove)) {
3272 QModelIndex topIndex;
3276 if (!event->isAccepted() && d->dropOn(event, &row, &col, &topIndex)) {
3277 const QList<QModelIndex> idxs = selectedIndexes();
3278 QList<QPersistentModelIndex> indexes;
3279 const int indexesCount = idxs.size();
3280 indexes.reserve(indexesCount);
3281 for (
const auto &idx : idxs)
3282 indexes.append(idx);
3284 if (indexes.contains(topIndex))
3288 QPersistentModelIndex dropRow = model()->index(row, col, topIndex);
3291 QList<QTreeWidgetItem *> taken;
3292 for (
const auto &index : indexes) {
3293 QTreeWidgetItem *parent = itemFromIndex(index);
3294 if (!parent || !parent->parent()) {
3295 taken.append(takeTopLevelItem(index.row()));
3297 taken.append(parent->parent()->takeChild(index.row()));
3302 for (
int i = 0; i < indexes.size(); ++i) {
3305 if (topIndex.isValid()) {
3306 QTreeWidgetItem *parent = itemFromIndex(topIndex);
3307 parent->insertChild(parent->childCount(), taken.takeFirst());
3309 insertTopLevelItem(topLevelItemCount(), taken.takeFirst());
3312 int r = dropRow.row() >= 0 ? dropRow.row() : row;
3313 if (topIndex.isValid()) {
3314 QTreeWidgetItem *parent = itemFromIndex(topIndex);
3315 parent->insertChild(qMin(r, parent->childCount()), taken.takeFirst());
3317 insertTopLevelItem(qMin(r, topLevelItemCount()), taken.takeFirst());
3326 if (event->isAccepted())
3327 d->dropEventMoved =
true;
3330 QTreeView::dropEvent(event);
3335
3336
3338void QTreeWidget::setModel(QAbstractItemModel * )
3340 Q_ASSERT(!
"QTreeWidget::setModel() - Changing the model of the QTreeWidget is not allowed.");
3344
3345
3346bool QTreeWidget::event(QEvent *e)
3349 if (e->type() == QEvent::Polish)
3350 d->treeModel()->executePendingSort();
3351 return QTreeView::event(e);
3355
3356
3357void QTreeModelPrivate::executePendingOperations()
const
3359 q_func()->executePendingSort();
3364#include "moc_qtreewidget.cpp"
3365#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)