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
776
778void QTreeModel::emitDataChanged(QTreeWidgetItem *item,
int column,
const QList<
int> &roles)
780 if (signalsBlocked())
783 if (headerItem == item && column < item->columnCount()) {
785 emit headerDataChanged(Qt::Horizontal, 0, columnCount() - 1);
787 emit headerDataChanged(Qt::Horizontal, column, column);
791 SkipSorting skipSorting(
this);
793 QModelIndex bottomRight, topLeft;
795 topLeft = index(item, 0);
796 bottomRight = createIndex(topLeft.row(), columnCount() - 1, item);
798 topLeft = index(item, column);
799 bottomRight = topLeft;
801 emit dataChanged(topLeft, bottomRight, roles);
804void QTreeModel::beginInsertItems(QTreeWidgetItem *parent,
int row,
int count)
806 QModelIndex par = index(parent, 0);
807 beginInsertRows(par, row, row + count - 1);
810void QTreeModel::endInsertItems()
815void QTreeModel::beginRemoveItems(QTreeWidgetItem *parent,
int row,
int count)
819 beginRemoveRows(index(parent, 0), row, row + count - 1);
823 for (
int i = 0; i < iterators.size(); ++i) {
824 for (
int j = 0; j < count; j++) {
825 QTreeWidgetItem *c = parent->child(row + j);
826 iterators[i]->d_func()->ensureValidIterator(c);
831void QTreeModel::endRemoveItems()
836void QTreeModel::sortItems(QList<QTreeWidgetItem*> *items,
int column, Qt::SortOrder order)
844 QList<std::pair<QTreeWidgetItem *,
int>> sorting(items->size());
845 for (
int i = 0; i < sorting.size(); ++i) {
846 sorting[i].first = items->at(i);
847 sorting[i].second = i;
851 const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
852 std::stable_sort(sorting.begin(), sorting.end(), compare);
854 QModelIndexList fromList;
855 QModelIndexList toList;
856 int colCount = columnCount();
857 for (
int r = 0; r < sorting.size(); ++r) {
858 int oldRow = sorting.at(r).second;
861 QTreeWidgetItem *item = sorting.at(r).first;
862 items->replace(r, item);
863 for (
int c = 0; c < colCount; ++c) {
864 QModelIndex from = createIndex(oldRow, c, item);
865 if (
static_cast<QAbstractItemModelPrivate *>(d_ptr.data())->persistent.indexes.contains(from)) {
866 QModelIndex to = createIndex(r, c, item);
872 changePersistentIndexList(fromList, toList);
875void QTreeModel::timerEvent(QTimerEvent *ev)
877 if (ev->timerId() == sortPendingTimer.timerId()) {
878 executePendingSort();
880 QAbstractItemModel::timerEvent(ev);
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
940
941
942
943
944
945
948
949
950
951
952
953
954
955
956
957
958
959
960
963
964
965
966
969
970
971
972
973
974
975
976
979
980
981
982
985
986
987
988
989
990
991void QTreeWidgetItem::setSelected(
bool select)
993 const QTreeModel *model = treeModel();
994 if (!model || !view->selectionModel())
996 const QModelIndex index = model->index(
this, 0);
997 view->selectionModel()->select(index, (select ? QItemSelectionModel::Select
998 : QItemSelectionModel::Deselect)
999 | QItemSelectionModel::Rows);
1000 d->selected = select;
1004
1005
1006
1007
1008
1009
1010bool QTreeWidgetItem::isSelected()
const
1016
1017
1018
1019
1020
1021
1022
1023
1024
1026void QTreeWidgetItem::setHidden(
bool hide)
1028 const QTreeModel *model = treeModel();
1031 if (
this == model->headerItem) {
1032 view->header()->setHidden(hide);
1034 const QModelIndex index = view->d_func()->index(
this);
1035 view->setRowHidden(index.row(), index.parent(), hide);
1041
1042
1043
1044
1045
1046
1048bool QTreeWidgetItem::isHidden()
const
1050 const QTreeModel *model = treeModel();
1053 if (
this == model->headerItem)
1054 return view->header()->isHidden();
1055 if (view->d_func()->hiddenIndexes.isEmpty())
1057 QTreeModel::SkipSorting skipSorting(model);
1058 return view->d_func()->isRowHidden(view->d_func()->index(
this));
1062
1063
1064
1065
1066
1067
1068
1069void QTreeWidgetItem::setExpanded(
bool expand)
1071 const QTreeModel *model = treeModel();
1074 QTreeModel::SkipSorting skipSorting(model);
1075 view->setExpanded(view->d_func()->index(
this), expand);
1079
1080
1081
1082
1083
1084
1085bool QTreeWidgetItem::isExpanded()
const
1087 const QTreeModel *model = treeModel();
1090 QTreeModel::SkipSorting skipSorting(model);
1091 return view->isExpanded(view->d_func()->index(
this));
1095
1096
1097
1098
1099
1100
1101
1102void QTreeWidgetItem::setFirstColumnSpanned(
bool span)
1104 const QTreeModel *model = treeModel();
1105 if (!model ||
this == model->headerItem)
1107 const QModelIndex index = model->index(
this, 0);
1108 view->setFirstColumnSpanned(index.row(), index.parent(), span);
1112
1113
1114
1115
1116
1117
1118bool QTreeWidgetItem::isFirstColumnSpanned()
const
1120 const QTreeModel *model = treeModel();
1121 if (!model ||
this == model->headerItem)
1123 const QModelIndex index = model->index(
this, 0);
1124 return view->isFirstColumnSpanned(index.row(), index.parent());
1128
1129
1130
1131
1132
1133
1136
1137
1138
1139
1140
1141
1144
1145
1146
1147
1148
1149
1152
1153
1154
1155
1156
1157
1160
1161
1162
1163
1164
1165
1168
1169
1170
1171
1172
1173
1174
1177
1178
1179
1180
1181
1182
1185
1186
1187
1188
1189
1190
1193
1194
1195
1196
1197
1198
1201
1202
1203
1204
1205
1206
1209
1210
1211
1212
1213
1214
1217
1218
1219
1220
1221
1222
1223
1226
1227
1228
1229
1230
1231
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1249
1250
1251
1252
1253
1254
1255
1256
1257
1260
1261
1262
1263
1264
1265
1266
1269
1270
1271
1272
1273
1274
1277
1278
1279
1280
1281
1282
1285
1286
1287
1288
1289
1292
1293
1294
1295
1296
1297
1300
1301
1302
1303
1304
1305
1308
1309
1310
1311
1312
1313
1316
1317
1318
1319
1322
1323
1324
1325
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1349
1350
1351
1352
1353
1354
1355
1356
1357
1360
1361
1362
1363
1364
1365
1366
1369
1370
1371
1374
1375
1376
1377
1380
1381
1382
1383
1384
1385QTreeWidgetItem::QTreeWidgetItem(
int type) : rtti(type), d(
new QTreeWidgetItemPrivate(
this)) { }
1388
1389
1390
1391
1392
1393
1394
1395QTreeWidgetItem::QTreeWidgetItem(
const QStringList &strings,
int type)
1396 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1398 for (
int i = 0; i < strings.size(); ++i)
1399 setText(i, strings.at(i));
1403
1404
1405
1406
1407
1408
1409
1411QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *treeview,
int type)
1412 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1415 if (QTreeModel *model = treeModel(treeview)) {
1416 model->rootItem->addChild(
this);
1417 values.reserve(model->headerItem->columnCount());
1422
1423
1424
1425
1426
1427
1428
1429
1431QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *treeview,
const QStringList &strings,
int type)
1432 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1434 for (
int i = 0; i < strings.size(); ++i)
1435 setText(i, strings.at(i));
1437 if (QTreeModel *model = treeModel(treeview)) {
1438 model->rootItem->addChild(
this);
1439 values.reserve(model->headerItem->columnCount());
1444
1445
1446
1447
1448
1449
1450
1451QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *treeview, QTreeWidgetItem *after,
int type)
1452 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1455 if (QTreeModel *model = treeModel(treeview)) {
1456 int i = model->rootItem->children.indexOf(after) + 1;
1457 model->rootItem->insertChild(i,
this);
1458 values.reserve(model->headerItem->columnCount());
1463
1464
1465
1466
1467QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent,
int type)
1468 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1471 parent->addChild(
this);
1475
1476
1477
1478
1479
1480QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent,
const QStringList &strings,
int type)
1481 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1483 for (
int i = 0; i < strings.size(); ++i)
1484 setText(i, strings.at(i));
1486 parent->addChild(
this);
1490
1491
1492
1493
1494
1495
1496
1497QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, QTreeWidgetItem *after,
int type)
1498 : rtti(type), d(
new QTreeWidgetItemPrivate(
this))
1501 int i = parent->children.indexOf(after) + 1;
1502 parent->insertChild(i,
this);
1507
1508
1509
1510
1511
1512
1514QTreeWidgetItem::~QTreeWidgetItem()
1516 QTreeModel *model = treeModel();
1517 QTreeModel::SkipSorting skipSorting(model);
1520 int i = par->children.indexOf(
this);
1522 if (model) model->beginRemoveItems(par, i, 1);
1525 if (!par->children.isEmpty() && par->children.at(i) ==
this)
1526 par->children.takeAt(i);
1527 if (model) model->endRemoveItems();
1530 if (
this == model->headerItem) {
1531 model->headerItem =
nullptr;
1533 int i = model->rootItem->children.indexOf(
this);
1535 model->beginRemoveItems(
nullptr, i, 1);
1538 if (!model->rootItem->children.isEmpty() && model->rootItem->children.at(i) ==
this)
1539 model->rootItem->children.takeAt(i);
1540 model->endRemoveItems();
1546 for (
int i = 0; i < children.size(); ++i) {
1547 QTreeWidgetItem *child = children.at(i);
1549 child->par =
nullptr;
1551 child->view =
nullptr;
1560
1561
1562QTreeWidgetItem *QTreeWidgetItem::clone()
const
1564 QTreeWidgetItem *copy =
nullptr;
1566 QStack<
const QTreeWidgetItem*> stack;
1567 QStack<QTreeWidgetItem*> parentStack;
1569 parentStack.push(0);
1571 QTreeWidgetItem *root =
nullptr;
1572 const QTreeWidgetItem *item =
nullptr;
1573 QTreeWidgetItem *parent =
nullptr;
1574 while (!stack.isEmpty()) {
1577 parent = parentStack.pop();
1580 copy =
new QTreeWidgetItem(*item);
1587 parent->children.insert(0, copy);
1590 for (
int i = 0; i < item->childCount(); ++i) {
1591 stack.push(item->child(i));
1592 parentStack.push(copy);
1599
1600
1601
1602
1603
1604
1605void QTreeWidgetItem::setChildIndicatorPolicy(QTreeWidgetItem::ChildIndicatorPolicy policy)
1607 if (d->policy == policy)
1614 view->scheduleDelayedItemsLayout();
1618
1619
1620
1621
1622
1623QTreeWidgetItem::ChildIndicatorPolicy QTreeWidgetItem::childIndicatorPolicy()
const
1629
1630
1631
1632
1633
1634
1635
1636void QTreeWidgetItem::setFlags(Qt::ItemFlags flags)
1638 const bool enable = (flags & Qt::ItemIsEnabled);
1639 const bool changedState =
bool(itemFlags & Qt::ItemIsEnabled) != enable;
1640 const bool changedExplicit = d->disabled != !enable;
1642 d->disabled = !enable;
1644 if (enable && par && !(par->itemFlags & Qt::ItemIsEnabled))
1645 itemFlags = flags & ~Qt::ItemIsEnabled;
1649 if (changedState && changedExplicit) {
1650 QStack<QTreeWidgetItem*> parents;
1652 while (!parents.isEmpty()) {
1653 QTreeWidgetItem *parent = parents.pop();
1654 for (
int i = 0; i < parent->children.size(); ++i) {
1655 QTreeWidgetItem *child = parent->children.at(i);
1656 if (!child->d->disabled) {
1657 parents.push(child);
1659 child->itemFlags = child->itemFlags | Qt::ItemIsEnabled;
1661 child->itemFlags = child->itemFlags & ~Qt::ItemIsEnabled;
1662 child->itemChanged();
1670void QTreeWidgetItemPrivate::updateHiddenStatus(QTreeWidgetItem *item,
bool inserting)
1672 QTreeModel *model = item->treeModel();
1675 QStack<QTreeWidgetItem *> parents;
1677 while (!parents.isEmpty()) {
1678 QTreeWidgetItem *parent = parents.pop();
1679 if (parent->d->hidden) {
1680 const QModelIndex index = model->index(parent, 0);
1681 item->view->setRowHidden(index.row(), index.parent(), inserting);
1683 for (
int i = 0; i < parent->children.size(); ++i) {
1684 QTreeWidgetItem *child = parent->children.at(i);
1685 parents.push(child);
1690void QTreeWidgetItemPrivate::propagateDisabled(QTreeWidgetItem *item)
1693 const bool enable = item->par ? (item->par->itemFlags.testFlag(Qt::ItemIsEnabled)) :
true;
1695 QStack<QTreeWidgetItem*> parents;
1697 while (!parents.isEmpty()) {
1698 QTreeWidgetItem *parent = parents.pop();
1699 if (!parent->d->disabled) {
1700 Qt::ItemFlags oldFlags = parent->itemFlags;
1702 parent->itemFlags = parent->itemFlags | Qt::ItemIsEnabled;
1704 parent->itemFlags = parent->itemFlags & ~Qt::ItemIsEnabled;
1705 if (parent->itemFlags != oldFlags)
1706 parent->itemChanged();
1709 for (
int i = 0; i < parent->children.size(); ++i) {
1710 QTreeWidgetItem *child = parent->children.at(i);
1711 parents.push(child);
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727Qt::ItemFlags QTreeWidgetItem::flags()
const
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742void QTreeWidgetItem::setData(
int column,
int role,
const QVariant &value)
1747 QTreeModel *model = treeModel();
1750 case Qt::DisplayRole: {
1751 if (values.size() <= column) {
1752 if (model &&
this == model->headerItem)
1753 model->setColumnCount(column + 1);
1755 values.resize(column + 1);
1757 if (d->display.size() <= column) {
1758 for (
int i = d->display.size() - 1; i < column - 1; ++i)
1759 d->display.append(QVariant());
1760 d->display.append(value);
1761 }
else if (d->display[column] != value) {
1762 d->display[column] = value;
1767 case Qt::CheckStateRole:
1768 if ((itemFlags & Qt::ItemIsAutoTristate) && value != Qt::PartiallyChecked) {
1769 for (
int i = 0; i < children.size(); ++i) {
1770 QTreeWidgetItem *child = children.at(i);
1771 if (child->data(column, role).isValid()) {
1772 Qt::ItemFlags f = itemFlags;
1773 itemFlags &= ~Qt::ItemIsAutoTristate;
1774 child->setData(column, role, value);
1781 if (column < values.size()) {
1783 const QList<QWidgetItemData> column_values = values.at(column);
1784 for (
int i = 0; i < column_values.size(); ++i) {
1785 if (column_values.at(i).role == role) {
1786 if (column_values.at(i).value == value)
1788 values[column][i].value = value;
1794 values[column].append(QWidgetItemData(role, value));
1796 if (model &&
this == model->headerItem)
1797 model->setColumnCount(column + 1);
1799 values.resize(column + 1);
1800 values[column].append(QWidgetItemData(role, value));
1805 const QList<
int> roles((role == Qt::DisplayRole || role == Qt::EditRole)
1806 ? QList<
int>({ Qt::DisplayRole, Qt::EditRole })
1807 : QList<
int>({ role }));
1808 model->emitDataChanged(
this, column, roles);
1809 if (role == Qt::CheckStateRole) {
1811 for (p = par; p && (p->itemFlags & Qt::ItemIsAutoTristate); p = p->par)
1812 model->emitDataChanged(p, column, roles);
1818
1819
1820QVariant QTreeWidgetItem::data(
int column,
int role)
const
1824 case Qt::DisplayRole:
1825 if (column >= 0 && column < d->display.size())
1826 return d->display.at(column);
1828 case Qt::CheckStateRole:
1830 if (children.size() && (itemFlags & Qt::ItemIsAutoTristate))
1831 return childrenCheckState(column);
1834 if (column >= 0 && column < values.size()) {
1835 const QList<QWidgetItemData> &column_values = values.at(column);
1836 for (
const auto &column_value : column_values) {
1837 if (column_value.role == role)
1838 return column_value.value;
1846
1847
1848
1850bool QTreeWidgetItem::operator<(
const QTreeWidgetItem &other)
const
1852 int column = view ? view->sortColumn() : 0;
1853 const QVariant v1 = data(column, Qt::DisplayRole);
1854 const QVariant v2 = other.data(column, Qt::DisplayRole);
1855 return QAbstractItemModelPrivate::variantLessThan(v1, v2);
1858#ifndef QT_NO_DATASTREAM
1861
1862
1863
1864
1865void QTreeWidgetItem::read(QDataStream &in)
1868 if (in.version() < QDataStream::Qt_4_2) {
1872 for (
int column = 0; column < values.size(); ++column) {
1873 d->display << QVariant();
1874 for (
int i = 0; i < values.at(column).size(); ++i) {
1875 if (values.at(column).at(i).role == Qt::DisplayRole) {
1876 d->display[column] = values.at(column).at(i).value;
1877 values[column].remove(i--);
1882 in >> values >> d->display;
1887
1888
1889
1890
1891void QTreeWidgetItem::write(QDataStream &out)
const
1893 out << values << d->display;
1898
1899
1900
1901
1902
1903
1904
1905QTreeWidgetItem::QTreeWidgetItem(
const QTreeWidgetItem &other)
1907 values(other.values),
1908 d(
new QTreeWidgetItemPrivate(
this)),
1909 itemFlags(other.itemFlags)
1911 d->display = other.d->display;
1915
1916
1917
1918
1919
1920
1921
1922QTreeWidgetItem &QTreeWidgetItem::operator=(
const QTreeWidgetItem &other)
1924 values = other.values;
1925 d->display = other.d->display;
1926 d->policy = other.d->policy;
1927 itemFlags = other.itemFlags;
1932
1933
1934
1935
1936void QTreeWidgetItem::addChild(QTreeWidgetItem *child)
1939 insertChild(children.size(), child);
1940 child->d->rowGuess = children.size() - 1;
1945
1946
1947
1948
1949void QTreeWidgetItem::insertChild(
int index, QTreeWidgetItem *child)
1951 if (index < 0 || index > children.size() || child ==
nullptr || child->view !=
nullptr || child->par !=
nullptr)
1954 if (QTreeModel *model = treeModel()) {
1955 QTreeModel::SkipSorting skipSorting(model);
1956 if (model->rootItem ==
this)
1957 child->par =
nullptr;
1960 if (view->isSortingEnabled()) {
1962 if (!model->sortPendingTimer.isActive())
1963 model->sortPendingTimer.start(0, model);
1965 model->beginInsertItems(
this, index, 1);
1966 int cols = model->columnCount();
1967 QStack<QTreeWidgetItem*> stack;
1969 while (!stack.isEmpty()) {
1970 QTreeWidgetItem *i = stack.pop();
1972 i->values.reserve(cols);
1973 for (
int c = 0; c < i->children.size(); ++c)
1974 stack.push(i->children.at(c));
1976 children.insert(index, child);
1977 d->updateHiddenStatus(child,
true);
1978 model->endInsertItems();
1981 children.insert(index, child);
1984 d->propagateDisabled(child);
1988
1989
1990
1991void QTreeWidgetItem::removeChild(QTreeWidgetItem *child)
1993 (
void)takeChild(children.indexOf(child));
1997
1998
1999QTreeWidgetItem *QTreeWidgetItem::takeChild(
int index)
2003 QTreeModel *model = treeModel();
2009 model->skipPendingSort =
false;
2010 model->executePendingSort();
2012 if (index >= 0 && index < children.size()) {
2013 if (model) model->beginRemoveItems(
this, index, 1);
2014 d->updateHiddenStatus(children.at(index),
false);
2015 QTreeWidgetItem *item = children.takeAt(index);
2016 item->par =
nullptr;
2017 QStack<QTreeWidgetItem*> stack;
2019 while (!stack.isEmpty()) {
2020 QTreeWidgetItem *i = stack.pop();
2022 for (
int c = 0; c < i->children.size(); ++c)
2023 stack.push(i->children.at(c));
2025 d->propagateDisabled(item);
2026 if (model) model->endRemoveRows();
2033
2034
2035
2036
2037void QTreeWidgetItem::addChildren(
const QList<QTreeWidgetItem*> &children)
2039 insertChildren(
this->children.size(), children);
2043
2044
2045
2046
2047void QTreeWidgetItem::insertChildren(
int index,
const QList<QTreeWidgetItem*> &children)
2049 if (index < 0 || index >
this->children.size() || children.isEmpty())
2052 if (view && view->isSortingEnabled()) {
2053 for (
int n = 0; n < children.size(); ++n)
2054 insertChild(index, children.at(n));
2057 QTreeModel *model = treeModel();
2058 QStack<QTreeWidgetItem*> stack;
2059 QList<QTreeWidgetItem*> itemsToInsert;
2060 for (
int n = 0; n < children.size(); ++n) {
2061 QTreeWidgetItem *child = children.at(n);
2062 if (child->view || child->par)
2064 itemsToInsert.append(child);
2065 if (view && model) {
2066 if (child->childCount() == 0)
2071 if (model && (model->rootItem ==
this))
2072 child->par =
nullptr;
2076 if (!itemsToInsert.isEmpty()) {
2077 while (!stack.isEmpty()) {
2078 QTreeWidgetItem *i = stack.pop();
2080 for (
int c = 0; c < i->children.size(); ++c)
2081 stack.push(i->children.at(c));
2083 if (model) model->beginInsertItems(
this, index, itemsToInsert.size());
2084 for (
int n = 0; n < itemsToInsert.size(); ++n) {
2085 QTreeWidgetItem *child = itemsToInsert.at(n);
2086 this->children.insert(index + n, child);
2088 d->propagateDisabled(child);
2089 d->updateHiddenStatus(child,
true);
2091 if (model) model->endInsertItems();
2096
2097
2098QList<QTreeWidgetItem*> QTreeWidgetItem::takeChildren()
2100 QList<QTreeWidgetItem*> removed;
2101 if (children.size() > 0) {
2102 QTreeModel *model = treeModel();
2108 model->executePendingSort();
2110 if (model) model->beginRemoveItems(
this, 0, children.size());
2111 for (
int n = 0; n < children.size(); ++n) {
2112 QTreeWidgetItem *item = children.at(n);
2113 item->par =
nullptr;
2114 QStack<QTreeWidgetItem*> stack;
2116 while (!stack.isEmpty()) {
2117 QTreeWidgetItem *i = stack.pop();
2119 for (
int c = 0; c < i->children.size(); ++c)
2120 stack.push(i->children.at(c));
2122 d->propagateDisabled(item);
2126 if (model) model->endRemoveItems();
2132void QTreeWidgetItemPrivate::sortChildren(
int column, Qt::SortOrder order,
bool climb)
2134 QTreeModel *model = q->treeModel();
2137 model->sortItems(&q->children, column, order);
2139 QList<QTreeWidgetItem*>::iterator it = q->children.begin();
2140 for (; it != q->children.end(); ++it) {
2143 (*it)->d->sortChildren(column, order, climb);
2149
2150
2151
2152
2153
2154
2155void QTreeWidgetItem::sortChildren(
int column, Qt::SortOrder order,
bool climb)
2157 QTreeModel *model = treeModel();
2160 if (model->isChanging())
2162 QTreeModel::SkipSorting skipSorting(model);
2163 int oldSortColumn = view->d_func()->explicitSortColumn;
2164 view->d_func()->explicitSortColumn = column;
2165 emit model->layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint);
2166 d->sortChildren(column, order, climb);
2167 emit model->layoutChanged({}, QAbstractItemModel::VerticalSortHint);
2168 view->d_func()->explicitSortColumn = oldSortColumn;
2172
2173
2174
2175
2176
2177
2178
2179QVariant QTreeWidgetItem::childrenCheckState(
int column)
const
2183 bool checkedChildren =
false;
2184 bool uncheckedChildren =
false;
2185 for (
const auto *child : children) {
2186 QVariant value = child->data(column, Qt::CheckStateRole);
2187 if (!value.isValid())
2190 switch (
static_cast<Qt::CheckState>(value.toInt()))
2193 uncheckedChildren =
true;
2196 checkedChildren =
true;
2198 case Qt::PartiallyChecked:
2200 return Qt::PartiallyChecked;
2203 if (uncheckedChildren && checkedChildren)
2204 return Qt::PartiallyChecked;
2207 if (uncheckedChildren)
2208 return Qt::Unchecked;
2209 else if (checkedChildren)
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225void QTreeWidgetItem::emitDataChanged()
2231
2232
2233void QTreeWidgetItem::itemChanged()
2235 if (QTreeModel *model = treeModel())
2236 model->itemChanged(
this);
2240
2241
2242void QTreeWidgetItem::executePendingSort()
const
2244 if (QTreeModel *model = treeModel())
2245 model->executePendingSort();
2249
2250
2251
2252QTreeModel *QTreeWidgetItem::treeModel(QTreeWidget *v)
const
2256 return (v ? qobject_cast<QTreeModel*>(v->model()) :
nullptr);
2260#ifndef QT_NO_DATASTREAM
2262
2263
2264
2265
2266
2267
2268
2269
2277
2278
2279
2280
2281
2282
2283
2284
2293void QTreeWidgetPrivate::clearConnections()
2295 for (
const QMetaObject::Connection &connection : connections)
2296 QObject::disconnect(connection);
2299void QTreeWidgetPrivate::emitItemPressed(
const QModelIndex &index)
2302 emit q->itemPressed(item(index), index.column());
2305void QTreeWidgetPrivate::emitItemClicked(
const QModelIndex &index)
2308 emit q->itemClicked(item(index), index.column());
2311void QTreeWidgetPrivate::emitItemDoubleClicked(
const QModelIndex &index)
2314 emit q->itemDoubleClicked(item(index), index.column());
2317void QTreeWidgetPrivate::emitItemActivated(
const QModelIndex &index)
2320 emit q->itemActivated(item(index), index.column());
2323void QTreeWidgetPrivate::emitItemEntered(
const QModelIndex &index)
2326 emit q->itemEntered(item(index), index.column());
2329void QTreeWidgetPrivate::emitItemChanged(
const QModelIndex &index)
2332 QTreeWidgetItem *indexItem = item(index);
2334 emit q->itemChanged(indexItem, index.column());
2337void QTreeWidgetPrivate::emitItemExpanded(
const QModelIndex &index)
2340 emit q->itemExpanded(item(index));
2343void QTreeWidgetPrivate::emitItemCollapsed(
const QModelIndex &index)
2346 emit q->itemCollapsed(item(index));
2349void QTreeWidgetPrivate::emitCurrentItemChanged(
const QModelIndex ¤t,
2350 const QModelIndex &previous)
2353 QTreeWidgetItem *currentItem = item(current);
2354 QTreeWidgetItem *previousItem = item(previous);
2355 emit q->currentItemChanged(currentItem, previousItem);
2358void QTreeWidgetPrivate::sort()
2360 if (sortingEnabled) {
2361 int column = header->sortIndicatorSection();
2362 Qt::SortOrder order = header->sortIndicatorOrder();
2363 treeModel()->sort(column, order);
2367void QTreeWidgetPrivate::selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected)
2370 QModelIndexList indices = selected.indexes();
2372 QTreeModel *m = treeModel();
2373 for (i = 0; i < indices.size(); ++i) {
2374 QTreeWidgetItem *item = m->item(indices.at(i));
2375 item->d->selected =
true;
2378 indices = deselected.indexes();
2379 for (i = 0; i < indices.size(); ++i) {
2380 QTreeWidgetItem *item = m->item(indices.at(i));
2381 item->d->selected =
false;
2384 emit q->itemSelectionChanged();
2387void QTreeWidgetPrivate::dataChanged(
const QModelIndex &topLeft,
2388 const QModelIndex &bottomRight)
2390 if (sortingEnabled && topLeft.isValid() && bottomRight.isValid()
2391 && !treeModel()->sortPendingTimer.isActive()) {
2392 int column = header->sortIndicatorSection();
2393 if (column >= topLeft.column() && column <= bottomRight.column()) {
2394 Qt::SortOrder order = header->sortIndicatorOrder();
2395 treeModel()->ensureSorted(column, order, topLeft.row(),
2396 bottomRight.row(), topLeft.parent());
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
2442
2443
2444
2445
2446
2447
2450
2451
2452
2453
2454
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2470
2471
2472
2473
2474
2475
2476
2477
2478
2481
2482
2483
2484
2485
2486
2487
2488
2491
2492
2493
2494
2495
2496
2497
2498
2499
2502
2503
2504
2505
2506
2507
2508
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2523
2524
2525
2526
2527
2528
2529
2530
2533
2534
2535
2536
2537
2540
2541
2542
2543
2544
2545
2548
2549
2550
2551
2552
2555
2556
2557
2558
2559
2560
2563
2564
2565QTreeWidget::QTreeWidget(QWidget *parent)
2566 : QTreeView(*
new QTreeWidgetPrivate(), parent)
2569 QTreeView::setModel(
new QTreeModel(1,
this));
2571 QObjectPrivate::connect(
this, &QTreeWidget::pressed,
2572 d, &QTreeWidgetPrivate::emitItemPressed),
2573 QObjectPrivate::connect(
this, &QTreeWidget::clicked,
2574 d, &QTreeWidgetPrivate::emitItemClicked),
2575 QObjectPrivate::connect(
this, &QTreeWidget::doubleClicked,
2576 d, &QTreeWidgetPrivate::emitItemDoubleClicked),
2577 QObjectPrivate::connect(
this, &QTreeWidget::activated,
2578 d, &QTreeWidgetPrivate::emitItemActivated),
2579 QObjectPrivate::connect(
this, &QTreeWidget::entered,
2580 d, &QTreeWidgetPrivate::emitItemEntered),
2581 QObjectPrivate::connect(
this, &QTreeWidget::expanded,
2582 d, &QTreeWidgetPrivate::emitItemExpanded),
2583 QObjectPrivate::connect(
this, &QTreeWidget::collapsed,
2584 d, &QTreeWidgetPrivate::emitItemCollapsed),
2585 QObjectPrivate::connect(model(), &QAbstractItemModel::dataChanged,
2586 d, &QTreeWidgetPrivate::emitItemChanged),
2587 QObjectPrivate::connect(model(), &QAbstractItemModel::dataChanged,
2588 d, &QTreeWidgetPrivate::dataChanged),
2589 QObjectPrivate::connect(model(), &QAbstractItemModel::columnsRemoved,
2590 d, &QTreeWidgetPrivate::sort),
2591 QObjectPrivate::connect(selectionModel(), &QItemSelectionModel::currentChanged,
2592 d, &QTreeWidgetPrivate::emitCurrentItemChanged),
2593 QObjectPrivate::connect(selectionModel(), &QItemSelectionModel::selectionChanged,
2594 d, &QTreeWidgetPrivate::selectionChanged)
2596 header()->setSectionsClickable(
false);
2600
2601
2603QTreeWidget::~QTreeWidget()
2606 d->clearConnections();
2610
2611
2612
2613
2615int QTreeWidget::columnCount()
const
2617 Q_D(
const QTreeWidget);
2618 return d->model->columnCount();
2622
2623
2625void QTreeWidget::setColumnCount(
int columns)
2630 d->treeModel()->setColumnCount(columns);
2634
2635
2636
2637
2638
2639
2640
2642QTreeWidgetItem *QTreeWidget::invisibleRootItem()
const
2644 Q_D(
const QTreeWidget);
2645 return d->treeModel()->rootItem;
2649
2650
2651
2652
2653
2655QTreeWidgetItem *QTreeWidget::topLevelItem(
int index)
const
2657 Q_D(
const QTreeWidget);
2658 return d->treeModel()->rootItem->child(index);
2662
2663
2664
2665
2666
2667
2668
2670int QTreeWidget::topLevelItemCount()
const
2672 Q_D(
const QTreeWidget);
2673 return d->treeModel()->rootItem->childCount();
2677
2678
2679
2680
2681
2682
2684void QTreeWidget::insertTopLevelItem(
int index, QTreeWidgetItem *item)
2687 d->treeModel()->rootItem->insertChild(index, item);
2691
2692
2693
2694
2695void QTreeWidget::addTopLevelItem(QTreeWidgetItem *item)
2697 insertTopLevelItem(topLevelItemCount(), item);
2701
2702
2703
2704
2705
2707QTreeWidgetItem *QTreeWidget::takeTopLevelItem(
int index)
2710 return d->treeModel()->rootItem->takeChild(index);
2714
2715
2716
2717
2718
2719int QTreeWidget::indexOfTopLevelItem(QTreeWidgetItem *item)
const
2721 Q_D(
const QTreeWidget);
2722 d->treeModel()->executePendingSort();
2723 return d->treeModel()->rootItem->children.indexOf(item);
2727
2728
2729
2730
2731
2732
2733void QTreeWidget::insertTopLevelItems(
int index,
const QList<QTreeWidgetItem*> &items)
2736 d->treeModel()->rootItem->insertChildren(index, items);
2740
2741
2742
2743
2744void QTreeWidget::addTopLevelItems(
const QList<QTreeWidgetItem*> &items)
2746 insertTopLevelItems(topLevelItemCount(), items);
2750
2751
2752
2753
2755QTreeWidgetItem *QTreeWidget::headerItem()
const
2757 Q_D(
const QTreeWidget);
2758 return d->treeModel()->headerItem;
2762
2763
2764
2765
2766
2767
2768
2770void QTreeWidget::setHeaderItem(QTreeWidgetItem *item)
2777 int oldCount = columnCount();
2778 if (oldCount < item->columnCount())
2779 d->treeModel()->beginInsertColumns(QModelIndex(), oldCount, item->columnCount() - 1);
2780 else if (oldCount > item->columnCount())
2781 d->treeModel()->beginRemoveColumns(QModelIndex(), item->columnCount(), oldCount - 1);
2782 delete d->treeModel()->headerItem;
2783 d->treeModel()->headerItem = item;
2784 if (oldCount < item->columnCount())
2785 d->treeModel()->endInsertColumns();
2786 else if (oldCount > item->columnCount())
2787 d->treeModel()->endRemoveColumns();
2788 d->treeModel()->headerDataChanged(Qt::Horizontal, 0, oldCount);
2793
2794
2795
2796
2797
2798
2799
2800void QTreeWidget::setHeaderLabels(
const QStringList &labels)
2803 if (columnCount() < labels.size())
2804 setColumnCount(labels.size());
2805 QTreeWidgetItem *item = d->treeModel()->headerItem;
2806 for (
int i = 0; i < labels.size(); ++i)
2807 item->setText(i, labels.at(i));
2811
2812
2813
2814
2817
2818
2819
2820
2821QTreeWidgetItem *QTreeWidget::currentItem()
const
2823 Q_D(
const QTreeWidget);
2824 return d->item(currentIndex());
2828
2829
2830
2831
2832int QTreeWidget::currentColumn()
const
2834 return currentIndex().column();
2838
2839
2840
2841
2842
2843
2844
2845void QTreeWidget::setCurrentItem(QTreeWidgetItem *item)
2847 setCurrentItem(item, 0);
2851
2852
2853
2854
2855void QTreeWidget::setCurrentItem(QTreeWidgetItem *item,
int column)
2858 setCurrentIndex(d->index(item, column));
2862
2863
2864
2865
2866
2867void QTreeWidget::setCurrentItem(QTreeWidgetItem *item,
int column,
2868 QItemSelectionModel::SelectionFlags command)
2871 d->selectionModel->setCurrentIndex(d->index(item, column), command);
2876
2877
2878
2879
2880
2881QTreeWidgetItem *QTreeWidget::itemAt(
const QPoint &p)
const
2883 Q_D(
const QTreeWidget);
2884 return d->item(indexAt(p));
2888
2889
2890
2891
2892
2893
2896
2897
2898
2899
2900QRect QTreeWidget::visualItemRect(
const QTreeWidgetItem *item)
const
2902 Q_D(
const QTreeWidget);
2905 const QModelIndex base = d->index(item);
2906 const int firstVisiblesection = header()->logicalIndexAt(- header()->offset());
2907 const int lastVisibleSection = header()->logicalIndexAt(header()->length() - header()->offset() - 1);
2908 const QModelIndex first = base.sibling(base.row(), firstVisiblesection);
2909 const QModelIndex last = base.sibling(base.row(), lastVisibleSection);
2910 return visualRect(first) | visualRect(last);
2914
2915
2916
2917
2918int QTreeWidget::sortColumn()
const
2920 Q_D(
const QTreeWidget);
2921 return (d->explicitSortColumn != -1
2922 ? d->explicitSortColumn
2923 : header()->sortIndicatorSection());
2927
2928
2929
2930
2931
2933void QTreeWidget::sortItems(
int column, Qt::SortOrder order)
2936 header()->setSortIndicator(column, order);
2937 d->model->sort(column, order);
2941
2942
2944void QTreeWidget::editItem(QTreeWidgetItem *item,
int column)
2947 edit(d->index(item, column));
2951
2952
2953
2954
2956void QTreeWidget::openPersistentEditor(QTreeWidgetItem *item,
int column)
2959 QAbstractItemView::openPersistentEditor(d->index(item, column));
2963
2964
2965
2966
2967
2968
2969
2971void QTreeWidget::closePersistentEditor(QTreeWidgetItem *item,
int column)
2974 QAbstractItemView::closePersistentEditor(d->index(item, column));
2978
2979
2980
2981
2982
2983
2984
2986bool QTreeWidget::isPersistentEditorOpen(QTreeWidgetItem *item,
int column)
const
2988 Q_D(
const QTreeWidget);
2989 return QAbstractItemView::isPersistentEditorOpen(d->index(item, column));
2993
2994
2995
2996
2997QWidget *QTreeWidget::itemWidget(QTreeWidgetItem *item,
int column)
const
2999 Q_D(
const QTreeWidget);
3000 return QAbstractItemView::indexWidget(d->index(item, column));
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024void QTreeWidget::setItemWidget(QTreeWidgetItem *item,
int column, QWidget *widget)
3027 QAbstractItemView::setIndexWidget(d->index(item, column), widget);
3031
3032
3033
3034
3035QList<QTreeWidgetItem*> QTreeWidget::selectedItems()
const
3037 Q_D(
const QTreeWidget);
3038 const QModelIndexList indexes = selectionModel()->selectedIndexes();
3039 QList<QTreeWidgetItem*> items;
3040 items.reserve(indexes.size());
3041 QDuplicateTracker<QTreeWidgetItem *> seen(indexes.size());
3042 for (
const auto &index : indexes) {
3043 QTreeWidgetItem *item = d->item(index);
3044 if (item->isHidden() || seen.hasSeen(item))
3052
3053
3054QList<QTreeWidgetItem*> QTreeWidget::findItems(
const QString &text, Qt::MatchFlags flags,
int column)
const
3056 Q_D(
const QTreeWidget);
3057 QModelIndexList indexes = d->model->match(model()->index(0, column, QModelIndex()),
3058 Qt::DisplayRole, text, -1, flags);
3059 QList<QTreeWidgetItem*> items;
3060 const int indexesSize = indexes.size();
3061 items.reserve(indexesSize);
3062 for (
int i = 0; i < indexesSize; ++i)
3063 items.append(d->item(indexes.at(i)));
3069
3070
3071QTreeWidgetItem *QTreeWidget::itemAbove(
const QTreeWidgetItem *item)
const
3073 Q_D(
const QTreeWidget);
3074 if (item == d->treeModel()->headerItem)
3076 const QModelIndex index = d->index(item);
3077 const QModelIndex above = indexAbove(index);
3078 return d->item(above);
3082
3083
3084QTreeWidgetItem *QTreeWidget::itemBelow(
const QTreeWidgetItem *item)
const
3086 Q_D(
const QTreeWidget);
3087 if (item == d->treeModel()->headerItem)
3089 const QModelIndex index = d->index(item);
3090 const QModelIndex below = indexBelow(index);
3091 return d->item(below);
3095
3096
3097void QTreeWidget::setSelectionModel(QItemSelectionModel *selectionModel)
3100 QTreeView::setSelectionModel(selectionModel);
3101 QItemSelection newSelection = selectionModel->selection();
3102 if (!newSelection.isEmpty())
3103 d->selectionChanged(newSelection, QItemSelection());
3107
3108
3109
3110
3111
3112void QTreeWidget::scrollToItem(
const QTreeWidgetItem *item, QAbstractItemView::ScrollHint hint)
3115 QTreeView::scrollTo(d->index(item), hint);
3119
3120
3121
3122
3123
3124void QTreeWidget::expandItem(
const QTreeWidgetItem *item)
3127 QTreeModel::SkipSorting skipSorting(d->treeModel());
3128 expand(d->index(item));
3132
3133
3134
3135
3136
3137void QTreeWidget::collapseItem(
const QTreeWidgetItem *item)
3140 QTreeModel::SkipSorting skipSorting(d->treeModel());
3141 collapse(d->index(item));
3145
3146
3147
3148
3149
3150
3151
3152
3153void QTreeWidget::clear()
3156 selectionModel()->clear();
3157 d->treeModel()->clear();
3161
3162
3163
3164
3165
3166QStringList QTreeWidget::mimeTypes()
const
3168 return model()->QAbstractItemModel::mimeTypes();
3172
3173
3174
3175
3176
3177
3178
3179QMimeData *QTreeWidget::mimeData(
const QList<QTreeWidgetItem *> &items)
const
3181 Q_D(
const QTreeWidget);
3182 if (d->treeModel()->cachedIndexes.isEmpty()) {
3183 QList<QModelIndex> indexes;
3184 for (
const auto *item : items) {
3185 if (Q_UNLIKELY(!item)) {
3186 qWarning(
"QTreeWidget::mimeData: Null-item passed");
3190 for (
int c = 0; c < item->values.size(); ++c) {
3191 const QModelIndex index = indexFromItem(item, c);
3192 if (Q_UNLIKELY(!index.isValid())) {
3193 qWarning() <<
"QTreeWidget::mimeData: No index associated with item :" << item;
3199 return d->model->QAbstractItemModel::mimeData(indexes);
3201 return d->treeModel()->internalMimeData();
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214bool QTreeWidget::dropMimeData(QTreeWidgetItem *parent,
int index,
3215 const QMimeData *data, Qt::DropAction action)
3218 if (parent) idx = indexFromItem(parent);
3219 return model()->QAbstractItemModel::dropMimeData(data, action , index, 0, idx);
3223
3224
3225
3226
3227Qt::DropActions QTreeWidget::supportedDropActions()
const
3229 return model()->QAbstractItemModel::supportedDropActions() | Qt::MoveAction;
3232#if QT_CONFIG(draganddrop)
3234
3235
3236
3237
3238
3239
3240Qt::DropActions QTreeWidget::supportedDragActions()
const
3242 Q_D(
const QTreeWidget);
3243 return d->supportedDragActions.value_or(supportedDropActions());
3246void QTreeWidget::setSupportedDragActions(Qt::DropActions actions)
3249 d->supportedDragActions = actions;
3254
3255
3256
3257
3258
3259
3260QModelIndex QTreeWidget::indexFromItem(
const QTreeWidgetItem *item,
int column)
const
3262 Q_D(
const QTreeWidget);
3263 return d->index(item, column);
3267
3268
3269
3270
3271QTreeWidgetItem *QTreeWidget::itemFromIndex(
const QModelIndex &index)
const
3273 Q_D(
const QTreeWidget);
3274 return d->item(index);
3277#if QT_CONFIG(draganddrop)
3279void QTreeWidget::dropEvent(QDropEvent *event) {
3281 if (event->source() ==
this && (event->dropAction() == Qt::MoveAction ||
3282 dragDropMode() == QAbstractItemView::InternalMove)) {
3283 QModelIndex topIndex;
3287 if (!event->isAccepted() && d->dropOn(event, &row, &col, &topIndex)) {
3288 const QList<QModelIndex> idxs = selectedIndexes();
3289 QList<QPersistentModelIndex> indexes;
3290 const int indexesCount = idxs.size();
3291 indexes.reserve(indexesCount);
3292 for (
const auto &idx : idxs)
3293 indexes.append(idx);
3295 if (indexes.contains(topIndex))
3299 QPersistentModelIndex dropRow = model()->index(row, col, topIndex);
3302 QList<QTreeWidgetItem *> taken;
3303 for (
const auto &index : indexes) {
3304 QTreeWidgetItem *parent = itemFromIndex(index);
3305 if (!parent || !parent->parent()) {
3306 taken.append(takeTopLevelItem(index.row()));
3308 taken.append(parent->parent()->takeChild(index.row()));
3313 for (
int i = 0; i < indexes.size(); ++i) {
3316 if (topIndex.isValid()) {
3317 QTreeWidgetItem *parent = itemFromIndex(topIndex);
3318 parent->insertChild(parent->childCount(), taken.takeFirst());
3320 insertTopLevelItem(topLevelItemCount(), taken.takeFirst());
3323 int r = dropRow.row() >= 0 ? dropRow.row() : row;
3324 if (topIndex.isValid()) {
3325 QTreeWidgetItem *parent = itemFromIndex(topIndex);
3326 parent->insertChild(qMin(r, parent->childCount()), taken.takeFirst());
3328 insertTopLevelItem(qMin(r, topLevelItemCount()), taken.takeFirst());
3337 if (event->isAccepted())
3338 d->dropEventMoved =
true;
3341 QTreeView::dropEvent(event);
3346
3347
3349void QTreeWidget::setModel(QAbstractItemModel * )
3351 Q_ASSERT(!
"QTreeWidget::setModel() - Changing the model of the QTreeWidget is not allowed.");
3355
3356
3357bool QTreeWidget::event(QEvent *e)
3360 if (e->type() == QEvent::Polish)
3361 d->treeModel()->executePendingSort();
3362 return QTreeView::event(e);
3366
3367
3368void QTreeModelPrivate::executePendingOperations()
const
3370 q_func()->executePendingSort();
3375#include "moc_qtreewidget.cpp"
3376#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)