282
283
284
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
315
316
317
318
319
320
321
324
325
326
327
328
329
333
334
335
336
338QPersistentModelIndex::QPersistentModelIndex()
344
345
346
347
348
350QPersistentModelIndex::QPersistentModelIndex(
const QPersistentModelIndex &other)
357
358
360QPersistentModelIndex::QPersistentModelIndex(
const QModelIndex &index)
363 if (index.isValid()) {
364 d = QPersistentModelIndexData::create(index);
370
371
372
373
375QPersistentModelIndex::~QPersistentModelIndex()
377 if (d && !d->ref.deref()) {
378 QPersistentModelIndexData::destroy(d);
384
385
386
387
388
389
390
393
394
395
396
397
398
399bool comparesEqual(
const QPersistentModelIndex &lhs,
const QPersistentModelIndex &rhs)
noexcept
402 return lhs.d->index == rhs.d->index;
403 return lhs.d == rhs.d;
407
408
409
410
411
412
413
414
415
417 const QPersistentModelIndex &rhs)
noexcept
420 return compareThreeWay(lhs.d->index, rhs.d->index);
422 using Qt::totally_ordered_wrapper;
423 return compareThreeWay(totally_ordered_wrapper{lhs.d}, totally_ordered_wrapper{rhs.d});
429 return compareThreeWay(lhs.d ? lhs.d->index : QModelIndex{}, rhs);
433
434
435
437QPersistentModelIndex &QPersistentModelIndex::operator=(
const QPersistentModelIndex &other)
441 if (d && !d->ref.deref())
442 QPersistentModelIndexData::destroy(d);
448
449
450
451
454
455
456
458QPersistentModelIndex &QPersistentModelIndex::operator=(
const QModelIndex &other)
460 if (d && !d->ref.deref())
461 QPersistentModelIndexData::destroy(d);
462 if (other.isValid()) {
463 d = QPersistentModelIndexData::create(other);
472
473
474
475
477QPersistentModelIndex::operator QModelIndex()
const
481 return QModelIndex();
485
486
487
488
489
490
491
494
495
496
497
498
503 return lhs.d->index == rhs;
504 return !rhs.isValid();
508
509
510
511
513int QPersistentModelIndex::row()
const
516 return d->index.row();
521
522
523
524
526int QPersistentModelIndex::column()
const
529 return d->index.column();
534
535
536
537
538
539
540
542void *QPersistentModelIndex::internalPointer()
const
545 return d->index.internalPointer();
550
551
552
553
554
555
556
558const void *QPersistentModelIndex::constInternalPointer()
const
561 return d->index.constInternalPointer();
566
567
568
569
570
571
572
574quintptr QPersistentModelIndex::internalId()
const
577 return d->index.internalId();
582
583
584
585
586
587QModelIndex QPersistentModelIndex::parent()
const
590 return d->index.parent();
591 return QModelIndex();
595
596
597
598
599
601QModelIndex QPersistentModelIndex::sibling(
int row,
int column)
const
604 return d->index.sibling(row, column);
605 return QModelIndex();
609
610
611
612
613
614
615QVariant QPersistentModelIndex::data(
int role)
const
618 return d->index.data(role);
624
625
626
627
628
629
630void QPersistentModelIndex::multiData(QModelRoleDataSpan roleDataSpan)
const
633 d->index.multiData(roleDataSpan);
637
638
639
640
641Qt::ItemFlags QPersistentModelIndex::flags()
const
644 return d->index.flags();
649
650
651const QAbstractItemModel *QPersistentModelIndex::model()
const
654 return d->index.model();
659
660
661
662
663
664
665
666
667
668
670bool QPersistentModelIndex::isValid()
const
672 return d && d->index.isValid();
675#ifndef QT_NO_DEBUG_STREAM
678 QDebugStateSaver saver(dbg);
679 dbg.nospace() <<
"QModelIndex(" << idx.row() <<
',' << idx.column()
707Q_GLOBAL_STATIC(QEmptyItemModel, qEmptyModel)
710QAbstractItemModelPrivate::QAbstractItemModelPrivate()
715QAbstractItemModelPrivate::~QAbstractItemModelPrivate()
719QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel()
721 return qEmptyModel();
724void QAbstractItemModelPrivate::invalidatePersistentIndexes()
726 for (QPersistentModelIndexData *data : std::as_const(persistent.indexes))
727 data->index = QModelIndex();
728 persistent.indexes.clear();
732
733
734
735
736void QAbstractItemModelPrivate::invalidatePersistentIndex(
const QModelIndex &index) {
737 const auto it = persistent.indexes.constFind(index);
738 if (it != persistent.indexes.cend()) {
739 QPersistentModelIndexData *data = *it;
740 persistent.indexes.erase(it);
741 data->index = QModelIndex();
745using DefaultRoleNames = QHash<
int, QByteArray>;
748 { Qt::DisplayRole,
"display" },
749 { Qt::DecorationRole,
"decoration" },
750 { Qt::EditRole,
"edit" },
751 { Qt::ToolTipRole,
"toolTip" },
752 { Qt::StatusTipRole,
"statusTip" },
753 { Qt::WhatsThisRole,
"whatsThis" },
756const QHash<
int,QByteArray> &QAbstractItemModelPrivate::defaultRoleNames()
758 return *qDefaultRoleNames();
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813Qt::weak_ordering QAbstractItemModel::compareDataImpl(
const QVariant &left,
const QVariant &right,
814 const QCollator *collator)
817 if (!left.isValid()) {
818 if (!right.isValid())
819 return Qt::weak_ordering::equivalent;
820 return Qt::weak_ordering::greater;
822 if (!right.isValid())
823 return Qt::weak_ordering::less;
827 if (left.userType() != QMetaType::QString && right.userType() != QMetaType::QString) {
828 QPartialOrdering partialOrder = QVariant::compare(left, right);
829 if (partialOrder == Qt::partial_ordering::unordered && right.metaType() != left.metaType()) {
832 const bool convertRight = left.metaType().id() < right.metaType().id();
833 const QVariant &first = convertRight ? right : left;
834 const QVariant &second = convertRight ? left : right;
835 const auto compareConverted = [&](
const QVariant &from,
const QVariant &to) {
836 QVariant converted = from;
837 converted.convert(to.metaType());
838 return &from == &left ? QVariant::compare(converted, right)
839 : QVariant::compare(left, converted);
841 if (first.canConvert(second.metaType()))
842 partialOrder = compareConverted(first, second);
843 else if (second.canConvert(first.metaType()))
844 partialOrder = compareConverted(second, first);
846 if (partialOrder == Qt::partial_ordering::equivalent)
847 return Qt::weak_ordering::equivalent;
848 if (partialOrder < 0)
849 return Qt::weak_ordering::less;
850 if (partialOrder > 0)
851 return Qt::weak_ordering::greater;
855 const int res = collator
856 ? collator->compare(left.toString(), right.toString())
857 : left.toString().compare(right.toString());
858 return Qt::compareThreeWay(res, 0);
864 switch (value.userType()) {
865 case QMetaType::Bool:
867 case QMetaType::UInt:
868 case QMetaType::LongLong:
869 case QMetaType::ULongLong:
870 case QMetaType::QChar:
871 case QMetaType::Short:
872 case QMetaType::UShort:
873 case QMetaType::UChar:
874 case QMetaType::ULong:
875 case QMetaType::Long:
877 case QMetaType::Double:
878 case QMetaType::Float:
886
887
888
889
890
891bool QAbstractItemModelPrivate::variantLessThan(
const QVariant &v1,
const QVariant &v2)
893 switch(qMax(typeOfVariant(v1), typeOfVariant(v2)))
896 return v1.toLongLong() < v2.toLongLong();
898 return v1.toReal() < v2.toReal();
900 return v1.toString().localeAwareCompare(v2.toString()) < 0;
904void QAbstractItemModelPrivate::removePersistentIndexData(QPersistentModelIndexData *data)
906 if (data->index.isValid()) {
907 int removed = persistent.indexes.remove(data->index);
908 Q_ASSERT_X(removed == 1,
"QPersistentModelIndex::~QPersistentModelIndex",
909 "persistent model indexes corrupted");
915 for (
int i = persistent.moved.size() - 1; i >= 0; --i) {
916 int idx = persistent.moved.at(i).indexOf(data);
918 persistent.moved[i].remove(idx);
921 for (
int i = persistent.invalidated.size() - 1; i >= 0; --i) {
922 int idx = persistent.invalidated.at(i).indexOf(data);
924 persistent.invalidated[i].remove(idx);
929void QAbstractItemModelPrivate::rowsAboutToBeInserted(
const QModelIndex &parent,
932 Q_Q(QAbstractItemModel);
934 QList<QPersistentModelIndexData *> persistent_moved;
935 if (first < q->rowCount(parent)) {
936 for (
auto *data : std::as_const(persistent.indexes)) {
937 const QModelIndex &index = data->index;
938 if (index.row() >= first && index.isValid() && index.parent() == parent) {
939 persistent_moved.append(data);
943 persistent.moved.push(persistent_moved);
946void QAbstractItemModelPrivate::rowsInserted(
const QModelIndex &parent,
949 const QList<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
950 const int count = (last - first) + 1;
951 for (
auto *data : persistent_moved) {
952 QModelIndex old = data->index;
953 persistent.indexes.erase(persistent.indexes.constFind(old));
954 data->index = q_func()->index(old.row() + count, old.column(), parent);
955 if (data->index.isValid()) {
956 persistent.insertMultiAtEnd(data->index, data);
958 qWarning() <<
"QAbstractItemModel::endInsertRows: Invalid index (" << old.row() + count <<
',' << old.column() <<
") in model" << q_func();
963void QAbstractItemModelPrivate::itemsAboutToBeMoved(
const QModelIndex &srcParent,
int srcFirst,
int srcLast,
const QModelIndex &destinationParent,
int destinationChild, Qt::Orientation orientation)
965 QList<QPersistentModelIndexData *> persistent_moved_explicitly;
966 QList<QPersistentModelIndexData *> persistent_moved_in_source;
967 QList<QPersistentModelIndexData *> persistent_moved_in_destination;
969 const bool sameParent = (srcParent == destinationParent);
970 const bool movingUp = (srcFirst > destinationChild);
972 for (
auto *data : std::as_const(persistent.indexes)) {
973 const QModelIndex &index = data->index;
974 const QModelIndex &parent = index.parent();
975 const bool isSourceIndex = (parent == srcParent);
976 const bool isDestinationIndex = (parent == destinationParent);
979 if (orientation == Qt::Vertical)
980 childPosition = index.row();
982 childPosition = index.column();
984 if (!index.isValid() || !(isSourceIndex || isDestinationIndex ) )
987 if (!sameParent && isDestinationIndex) {
988 if (childPosition >= destinationChild)
989 persistent_moved_in_destination.append(data);
993 if (sameParent && movingUp && childPosition < destinationChild)
996 if (sameParent && !movingUp && childPosition < srcFirst )
999 if (!sameParent && childPosition < srcFirst)
1002 if (sameParent && (childPosition > srcLast) && (childPosition >= destinationChild ))
1005 if ((childPosition <= srcLast) && (childPosition >= srcFirst)) {
1006 persistent_moved_explicitly.append(data);
1008 persistent_moved_in_source.append(data);
1011 persistent.moved.push(persistent_moved_explicitly);
1012 persistent.moved.push(persistent_moved_in_source);
1013 persistent.moved.push(persistent_moved_in_destination);
1017
1018
1019
1020
1021
1022
1023void QAbstractItemModelPrivate::movePersistentIndexes(
const QList<QPersistentModelIndexData *> &indexes,
int change,
1024 const QModelIndex &parent, Qt::Orientation orientation)
1026 for (
auto *data : indexes) {
1027 int row = data->index.row();
1028 int column = data->index.column();
1030 if (Qt::Vertical == orientation)
1035 persistent.indexes.erase(persistent.indexes.constFind(data->index));
1036 data->index = q_func()->index(row, column, parent);
1037 if (data->index.isValid()) {
1038 persistent.insertMultiAtEnd(data->index, data);
1040 qWarning() <<
"QAbstractItemModel::endMoveRows: Invalid index (" << row <<
"," << column <<
") in model" << q_func();
1045void QAbstractItemModelPrivate::itemsMoved(
const QModelIndex &sourceParent,
int sourceFirst,
int sourceLast,
const QModelIndex &destinationParent,
int destinationChild, Qt::Orientation orientation)
1047 const QList<QPersistentModelIndexData *> moved_in_destination = persistent.moved.pop();
1048 const QList<QPersistentModelIndexData *> moved_in_source = persistent.moved.pop();
1049 const QList<QPersistentModelIndexData *> moved_explicitly = persistent.moved.pop();
1051 const bool sameParent = (sourceParent == destinationParent);
1052 const bool movingUp = (sourceFirst > destinationChild);
1054 const int explicit_change = (!sameParent || movingUp) ? destinationChild - sourceFirst : destinationChild - sourceLast - 1 ;
1055 const int source_change = (!sameParent || !movingUp) ? -1*(sourceLast - sourceFirst + 1) : sourceLast - sourceFirst + 1 ;
1056 const int destination_change = sourceLast - sourceFirst + 1;
1058 movePersistentIndexes(moved_explicitly, explicit_change, destinationParent, orientation);
1059 movePersistentIndexes(moved_in_source, source_change, sourceParent, orientation);
1060 movePersistentIndexes(moved_in_destination, destination_change, destinationParent, orientation);
1063void QAbstractItemModelPrivate::rowsAboutToBeRemoved(
const QModelIndex &parent,
1064 int first,
int last)
1066 QList<QPersistentModelIndexData *> persistent_moved;
1067 QList<QPersistentModelIndexData *> persistent_invalidated;
1070 for (
auto *data : std::as_const(persistent.indexes)) {
1071 bool level_changed =
false;
1072 QModelIndex current = data->index;
1073 while (current.isValid()) {
1074 QModelIndex current_parent = current.parent();
1075 if (current_parent == parent) {
1076 if (!level_changed && current.row() > last)
1077 persistent_moved.append(data);
1078 else if (current.row() <= last && current.row() >= first)
1079 persistent_invalidated.append(data);
1082 current = current_parent;
1083 level_changed =
true;
1087 persistent.moved.push(persistent_moved);
1088 persistent.invalidated.push(persistent_invalidated);
1091void QAbstractItemModelPrivate::rowsRemoved(
const QModelIndex &parent,
1092 int first,
int last)
1094 const QList<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
1095 const int count = (last - first) + 1;
1096 for (
auto *data : persistent_moved) {
1097 QModelIndex old = data->index;
1098 persistent.indexes.erase(persistent.indexes.constFind(old));
1099 data->index = q_func()->index(old.row() - count, old.column(), parent);
1100 if (data->index.isValid()) {
1101 persistent.insertMultiAtEnd(data->index, data);
1103 qWarning() <<
"QAbstractItemModel::endRemoveRows: Invalid index (" << old.row() - count <<
',' << old.column() <<
") in model" << q_func();
1106 const QList<QPersistentModelIndexData *> persistent_invalidated = persistent.invalidated.pop();
1107 for (
auto *data : persistent_invalidated) {
1108 auto pit = persistent.indexes.constFind(data->index);
1109 if (pit != persistent.indexes.cend())
1110 persistent.indexes.erase(pit);
1111 data->index = QModelIndex();
1115void QAbstractItemModelPrivate::columnsAboutToBeInserted(
const QModelIndex &parent,
1116 int first,
int last)
1118 Q_Q(QAbstractItemModel);
1120 QList<QPersistentModelIndexData *> persistent_moved;
1121 if (first < q->columnCount(parent)) {
1122 for (
auto *data : std::as_const(persistent.indexes)) {
1123 const QModelIndex &index = data->index;
1124 if (index.column() >= first && index.isValid() && index.parent() == parent)
1125 persistent_moved.append(data);
1128 persistent.moved.push(persistent_moved);
1131void QAbstractItemModelPrivate::columnsInserted(
const QModelIndex &parent,
1132 int first,
int last)
1134 const QList<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
1135 const int count = (last - first) + 1;
1136 for (
auto *data : persistent_moved) {
1137 QModelIndex old = data->index;
1138 persistent.indexes.erase(persistent.indexes.constFind(old));
1139 data->index = q_func()->index(old.row(), old.column() + count, parent);
1140 if (data->index.isValid()) {
1141 persistent.insertMultiAtEnd(data->index, data);
1143 qWarning() <<
"QAbstractItemModel::endInsertColumns: Invalid index (" << old.row() <<
',' << old.column() + count <<
") in model" << q_func();
1148void QAbstractItemModelPrivate::columnsAboutToBeRemoved(
const QModelIndex &parent,
1149 int first,
int last)
1151 QList<QPersistentModelIndexData *> persistent_moved;
1152 QList<QPersistentModelIndexData *> persistent_invalidated;
1155 for (
auto *data : std::as_const(persistent.indexes)) {
1156 bool level_changed =
false;
1157 QModelIndex current = data->index;
1158 while (current.isValid()) {
1159 QModelIndex current_parent = current.parent();
1160 if (current_parent == parent) {
1161 if (!level_changed && current.column() > last)
1162 persistent_moved.append(data);
1163 else if (current.column() <= last && current.column() >= first)
1164 persistent_invalidated.append(data);
1167 current = current_parent;
1168 level_changed =
true;
1172 persistent.moved.push(persistent_moved);
1173 persistent.invalidated.push(persistent_invalidated);
1177void QAbstractItemModelPrivate::columnsRemoved(
const QModelIndex &parent,
1178 int first,
int last)
1180 const QList<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
1181 const int count = (last - first) + 1;
1182 for (
auto *data : persistent_moved) {
1183 QModelIndex old = data->index;
1184 persistent.indexes.erase(persistent.indexes.constFind(old));
1185 data->index = q_func()->index(old.row(), old.column() - count, parent);
1186 if (data->index.isValid()) {
1187 persistent.insertMultiAtEnd(data->index, data);
1189 qWarning() <<
"QAbstractItemModel::endRemoveColumns: Invalid index (" << old.row() <<
',' << old.column() - count <<
") in model" << q_func();
1192 const QList<QPersistentModelIndexData *> persistent_invalidated = persistent.invalidated.pop();
1193 for (
auto *data : persistent_invalidated) {
1194 auto index = persistent.indexes.constFind(data->index);
1195 if (index != persistent.indexes.constEnd())
1196 persistent.indexes.erase(index);
1197 data->index = QModelIndex();
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217void QAbstractItemModel::resetInternalData()
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1269
1270
1271
1272
1273
1274
1275
1278
1279
1280
1281
1282
1283
1284
1287
1288
1289
1290
1294
1295
1296
1297
1301
1302
1303
1304
1305
1306
1307
1310
1311
1312
1313
1314
1315
1316
1319
1320
1321
1322
1323
1324
1325
1328
1329
1330
1331
1332
1333
1334
1335
1336
1339
1340
1341
1342
1343
1344
1345
1346
1347
1350
1351
1352
1353
1354
1355
1356
1359
1360
1361
1362
1363
1364
1365
1366
1369
1370
1371
1372
1373
1374
1375
1376
1379
1380
1381
1382
1383
1384
1387
1388
1389
1390
1391
1392
1395
1396
1397
1398
1399
1402
1403
1404
1405
1406
1407
1408
1409
1412
1413
1414
1415
1416
1419
1420
1421
1422
1423
1424
1425
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1595
1596
1597
1598
1599
1600
1601
1602
1603
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1638
1639
1640
1641
1642
1643
1644
1645
1646
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1772
1773
1774QAbstractItemModel::QAbstractItemModel(QObject *parent)
1775 : QObject(*
new QAbstractItemModelPrivate, parent)
1780
1781
1782QAbstractItemModel::QAbstractItemModel(QAbstractItemModelPrivate &dd, QObject *parent)
1783 : QObject(dd, parent)
1788
1789
1790QAbstractItemModel::~QAbstractItemModel()
1792 d_func()->invalidatePersistentIndexes();
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2028
2029
2030
2031bool QAbstractItemModel::hasIndex(
int row,
int column,
const QModelIndex &parent)
const
2033 if (row < 0 || column < 0)
2035 return row < rowCount(parent) && column < columnCount(parent);
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049bool QAbstractItemModel::hasChildren(
const QModelIndex &parent)
const
2051 return (rowCount(parent) > 0) && (columnCount(parent) > 0);
2083QMap<
int, QVariant> QAbstractItemModel::itemData(
const QModelIndex &index)
const
2085 QMap<
int, QVariant> roles;
2086 for (
int i = 0; i < Qt::UserRole; ++i) {
2087 QVariant variantData = data(index, i);
2088 if (variantData.isValid())
2089 roles.insert(i, variantData);
2152bool QAbstractItemModel::setItemData(
const QModelIndex &index,
const QMap<
int, QVariant> &roles)
2154 if (!index.isValid() || roles.isEmpty())
2163 for (
auto it = roles.begin(), e = roles.end(); it != e; ++it) {
2164 if (!setData(index, it.value(), it.key()))
2204QMimeData *QAbstractItemModel::mimeData(
const QModelIndexList &indexes)
const
2206 if (indexes.size() <= 0)
2208 QStringList types = mimeTypes();
2209 if (types.isEmpty())
2211 QMimeData *data =
new QMimeData();
2212 QString format = types.at(0);
2214 QDataStream stream(&encoded, QDataStream::WriteOnly);
2215 encodeData(indexes, stream);
2216 data->setData(format, encoded);
2233bool QAbstractItemModel::canDropMimeData(
const QMimeData *data, Qt::DropAction action,
2234 int row,
int column,
2235 const QModelIndex &parent)
const
2241 if (!(action & supportedDropActions()))
2244 const QStringList modelTypes = mimeTypes();
2245 for (
int i = 0; i < modelTypes.size(); ++i) {
2246 if (data->hasFormat(modelTypes.at(i)))
2281bool QAbstractItemModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
2282 int row,
int column,
const QModelIndex &parent)
2285 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
2288 const QStringList types = mimeTypes();
2289 if (types.isEmpty())
2291 const QString format = types.at(0);
2292 if (!data->hasFormat(format))
2294 const bool dropOnItem = row == -1 && column == -1 && parent.isValid();
2295 if (!dropOnItem || !parent.flags().testFlag(Qt::ItemNeverHasChildren)) {
2298 if (row > rowCount(parent))
2299 row = rowCount(parent);
2301 row = rowCount(parent);
2306 QByteArray encoded = data->data(format);
2307 QDataStream stream(&encoded, QDataStream::ReadOnly);
2308 return decodeData(row, column, parent, stream);
2586QModelIndexList QAbstractItemModel::match(
const QModelIndex &start,
int role,
2587 const QVariant &value,
int hits,
2588 Qt::MatchFlags flags)
const
2590 QModelIndexList result;
2591 uint matchType = (flags & Qt::MatchTypeMask).toInt();
2592 Qt::CaseSensitivity cs = flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
2593 bool recurse = flags.testAnyFlag(Qt::MatchRecursive);
2594 bool wrap = flags.testAnyFlag(Qt::MatchWrap);
2595 bool allHits = (hits == -1);
2597#if QT_CONFIG(regularexpression)
2598 QRegularExpression rx;
2600 const int column = start.column();
2601 QModelIndex p = parent(start);
2602 int from = start.row();
2603 int to = rowCount(p);
2606 for (
int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) {
2607 for (
int r = from; (r < to) && (allHits || result.size() < hits); ++r) {
2608 QModelIndex idx = index(r, column, p);
2611 QVariant v = data(idx, role);
2613 if (matchType == Qt::MatchExactly) {
2617#if QT_CONFIG(regularexpression)
2618 if (matchType == Qt::MatchRegularExpression) {
2619 if (rx.pattern().isEmpty()) {
2620 if (value.userType() == QMetaType::QRegularExpression) {
2621 rx = value.toRegularExpression();
2623 rx.setPattern(value.toString());
2624 if (cs == Qt::CaseInsensitive)
2625 rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
2628 }
else if (matchType == Qt::MatchWildcard) {
2629 if (rx.pattern().isEmpty()) {
2630 const QString pattern = QRegularExpression::wildcardToRegularExpression(value.toString(), QRegularExpression::NonPathWildcardConversion);
2631 rx.setPattern(pattern);
2633 if (cs == Qt::CaseInsensitive)
2634 rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
2639 text = value.toString();
2642 QString t = v.toString();
2643 switch (matchType) {
2644#if QT_CONFIG(regularexpression)
2645 case Qt::MatchRegularExpression:
2647 case Qt::MatchWildcard:
2652 case Qt::MatchStartsWith:
2653 if (t.startsWith(text, cs))
2656 case Qt::MatchEndsWith:
2657 if (t.endsWith(text, cs))
2660 case Qt::MatchFixedString:
2661 if (t.compare(text, cs) == 0)
2664 case Qt::MatchContains:
2666 if (t.contains(text, cs))
2671 const auto parent = column != 0 ? idx.sibling(idx.row(), 0) : idx;
2672 if (hasChildren(parent)) {
2673 result += match(index(0, column, parent), role,
2674 (text.isEmpty() ? value : text),
2675 (allHits ? -1 : hits - result.size()), flags);
2841bool QAbstractItemModel::decodeData(
int row,
int column,
const QModelIndex &parent,
2842 QDataStream &stream)
2848 QList<
int> rows, columns;
2849 QList<QMap<
int, QVariant>> data;
2851 while (!stream.atEnd()) {
2853 QMap<
int, QVariant> v;
2854 stream >> r >> c >> v;
2859 left = qMin(c, left);
2860 bottom = qMax(r, bottom);
2861 right = qMax(c, right);
2866 int dragRowCount = 0;
2867 int dragColumnCount = right - left + 1;
2870 QList<
int> rowsToInsert(bottom + 1);
2871 for (
int i = 0; i < rows.size(); ++i)
2872 rowsToInsert[rows.at(i)] = 1;
2873 for (
int i = 0; i < rowsToInsert.size(); ++i) {
2874 if (rowsToInsert.at(i) == 1){
2875 rowsToInsert[i] = dragRowCount;
2879 for (
int i = 0; i < rows.size(); ++i)
2880 rows[i] = top + rowsToInsert.at(rows.at(i));
2882 QBitArray isWrittenTo(dragRowCount * dragColumnCount);
2885 int colCount = columnCount(parent);
2886 if (colCount == 0) {
2887 insertColumns(colCount, dragColumnCount - colCount, parent);
2888 colCount = columnCount(parent);
2890 insertRows(row, dragRowCount, parent);
2893 column = qMax(0, column);
2895 QList<QPersistentModelIndex> newIndexes(data.size());
2897 for (
int j = 0; j < data.size(); ++j) {
2898 int relativeRow = rows.at(j) - top;
2899 int relativeColumn = columns.at(j) - left;
2900 int destinationRow = relativeRow + row;
2901 int destinationColumn = relativeColumn + column;
2902 int flat = (relativeRow * dragColumnCount) + relativeColumn;
2904 if (destinationColumn >= colCount || isWrittenTo.testBit(flat)) {
2905 destinationColumn = qBound(column, destinationColumn, qMax(colCount - 1, column));
2906 destinationRow = row + dragRowCount;
2907 insertRows(row + dragRowCount, 1, parent);
2908 flat = (dragRowCount * dragColumnCount) + relativeColumn;
2909 isWrittenTo.resize(++dragRowCount * dragColumnCount);
2911 if (!isWrittenTo.testBit(flat)) {
2912 newIndexes[j] = index(destinationRow, destinationColumn, parent);
2913 isWrittenTo.setBit(flat);
2917 for(
int k = 0; k < newIndexes.size(); k++) {
2918 if (newIndexes.at(k).isValid())
2919 setItemData(newIndexes.at(k), data.at(k));
2967void QAbstractItemModel::beginInsertRows(
const QModelIndex &parent,
int first,
int last)
2969 Q_ASSERT(first >= 0);
2970 Q_ASSERT(first <= rowCount(parent));
2971 Q_ASSERT(last >= first);
2972 Q_D(QAbstractItemModel);
2973 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
2974 emit rowsAboutToBeInserted(parent, first, last, QPrivateSignal());
2975 d->rowsAboutToBeInserted(parent, first, last);
2986void QAbstractItemModel::endInsertRows()
2988 Q_D(QAbstractItemModel);
2989 QAbstractItemModelPrivate::Change change = d->changes.pop();
2990 d->rowsInserted(change.parent, change.first, change.last);
2991 emit rowsInserted(change.parent, change.first, change.last, QPrivateSignal());
3023void QAbstractItemModel::beginRemoveRows(
const QModelIndex &parent,
int first,
int last)
3025 Q_ASSERT(first >= 0);
3026 Q_ASSERT(last >= first);
3027 Q_ASSERT(last < rowCount(parent));
3028 Q_D(QAbstractItemModel);
3029 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3030 emit rowsAboutToBeRemoved(parent, first, last, QPrivateSignal());
3031 d->rowsAboutToBeRemoved(parent, first, last);
3042void QAbstractItemModel::endRemoveRows()
3044 Q_D(QAbstractItemModel);
3045 QAbstractItemModelPrivate::Change change = d->changes.pop();
3046 d->rowsRemoved(change.parent, change.first, change.last);
3047 emit rowsRemoved(change.parent, change.first, change.last, QPrivateSignal());
3058bool QAbstractItemModelPrivate::allowMove(
const QModelIndex &srcParent,
int start,
int end,
const QModelIndex &destinationParent,
int destinationStart, Qt::Orientation orientation)
3061 if (destinationParent == srcParent)
3062 return !(destinationStart >= start && destinationStart <= end + 1);
3064 QModelIndex destinationAncestor = destinationParent;
3065 int pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
3067 if (destinationAncestor == srcParent) {
3068 if (pos >= start && pos <= end)
3073 if (!destinationAncestor.isValid())
3076 pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
3077 destinationAncestor = destinationAncestor.parent();
3184bool QAbstractItemModel::beginMoveRows(
const QModelIndex &sourceParent,
int sourceFirst,
int sourceLast,
const QModelIndex &destinationParent,
int destinationChild)
3186 Q_ASSERT(sourceFirst >= 0);
3187 Q_ASSERT(sourceLast >= sourceFirst);
3188 Q_ASSERT(destinationChild >= 0);
3189 Q_D(QAbstractItemModel);
3191 if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical)) {
3195 QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
3196 sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
3197 d->changes.push(sourceChange);
3198 int destinationLast = destinationChild + (sourceLast - sourceFirst);
3199 QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
3200 destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
3201 d->changes.push(destinationChange);
3203 emit rowsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
3204 d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical);
3219void QAbstractItemModel::endMoveRows()
3221 Q_D(QAbstractItemModel);
3223 QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
3224 QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
3226 QModelIndex adjustedSource = removeChange.parent;
3227 QModelIndex adjustedDestination = insertChange.parent;
3229 const int numMoved = removeChange.last - removeChange.first + 1;
3230 if (insertChange.needsAdjust)
3231 adjustedDestination = createIndex(adjustedDestination.row() - numMoved, adjustedDestination.column(), adjustedDestination.internalPointer());
3233 if (removeChange.needsAdjust)
3234 adjustedSource = createIndex(adjustedSource.row() + numMoved, adjustedSource.column(), adjustedSource.internalPointer());
3236 d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Vertical);
3238 emit rowsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
3284void QAbstractItemModel::beginInsertColumns(
const QModelIndex &parent,
int first,
int last)
3286 Q_ASSERT(first >= 0);
3287 Q_ASSERT(first <= columnCount(parent));
3288 Q_ASSERT(last >= first);
3289 Q_D(QAbstractItemModel);
3290 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3291 emit columnsAboutToBeInserted(parent, first, last, QPrivateSignal());
3292 d->columnsAboutToBeInserted(parent, first, last);
3304void QAbstractItemModel::endInsertColumns()
3306 Q_D(QAbstractItemModel);
3307 QAbstractItemModelPrivate::Change change = d->changes.pop();
3308 d->columnsInserted(change.parent, change.first, change.last);
3309 emit columnsInserted(change.parent, change.first, change.last, QPrivateSignal());
3341void QAbstractItemModel::beginRemoveColumns(
const QModelIndex &parent,
int first,
int last)
3343 Q_ASSERT(first >= 0);
3344 Q_ASSERT(last >= first);
3345 Q_ASSERT(last < columnCount(parent));
3346 Q_D(QAbstractItemModel);
3347 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3348 emit columnsAboutToBeRemoved(parent, first, last, QPrivateSignal());
3349 d->columnsAboutToBeRemoved(parent, first, last);
3360void QAbstractItemModel::endRemoveColumns()
3362 Q_D(QAbstractItemModel);
3363 QAbstractItemModelPrivate::Change change = d->changes.pop();
3364 d->columnsRemoved(change.parent, change.first, change.last);
3365 emit columnsRemoved(change.parent, change.first, change.last, QPrivateSignal());
3406bool QAbstractItemModel::beginMoveColumns(
const QModelIndex &sourceParent,
int sourceFirst,
int sourceLast,
const QModelIndex &destinationParent,
int destinationChild)
3408 Q_ASSERT(sourceFirst >= 0);
3409 Q_ASSERT(sourceLast >= sourceFirst);
3410 Q_ASSERT(destinationChild >= 0);
3411 Q_D(QAbstractItemModel);
3413 if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal)) {
3417 QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
3418 sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
3419 d->changes.push(sourceChange);
3420 int destinationLast = destinationChild + (sourceLast - sourceFirst);
3421 QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
3422 destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
3423 d->changes.push(destinationChange);
3425 emit columnsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
3426 d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal);
3441void QAbstractItemModel::endMoveColumns()
3443 Q_D(QAbstractItemModel);
3445 QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
3446 QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
3448 QModelIndex adjustedSource = removeChange.parent;
3449 QModelIndex adjustedDestination = insertChange.parent;
3451 const int numMoved = removeChange.last - removeChange.first + 1;
3452 if (insertChange.needsAdjust)
3453 adjustedDestination = createIndex(adjustedDestination.row(), adjustedDestination.column() - numMoved, adjustedDestination.internalPointer());
3455 if (removeChange.needsAdjust)
3456 adjustedSource = createIndex(adjustedSource.row(), adjustedSource.column() + numMoved, adjustedSource.internalPointer());
3458 d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Horizontal);
3459 emit columnsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
3533void QAbstractItemModel::changePersistentIndex(
const QModelIndex &from,
const QModelIndex &to)
3535 Q_D(QAbstractItemModel);
3536 if (d->persistent.indexes.isEmpty())
3539 const auto it = d->persistent.indexes.constFind(from);
3540 if (it != d->persistent.indexes.cend()) {
3541 QPersistentModelIndexData *data = *it;
3542 d->persistent.indexes.erase(it);
3545 d->persistent.insertMultiAtEnd(to, data);
3560void QAbstractItemModel::changePersistentIndexList(
const QModelIndexList &from,
3561 const QModelIndexList &to)
3563 Q_D(QAbstractItemModel);
3564 if (d->persistent.indexes.isEmpty())
3566 QList<QPersistentModelIndexData *> toBeReinserted;
3567 toBeReinserted.reserve(to.size());
3568 for (
int i = 0; i < from.size(); ++i) {
3569 if (from.at(i) == to.at(i))
3571 const auto it = d->persistent.indexes.constFind(from.at(i));
3572 if (it != d->persistent.indexes.cend()) {
3573 QPersistentModelIndexData *data = *it;
3574 d->persistent.indexes.erase(it);
3575 data->index = to.at(i);
3576 if (data->index.isValid())
3577 toBeReinserted << data;
3581 for (
auto *data : std::as_const(toBeReinserted))
3582 d->persistent.insertMultiAtEnd(data->index, data);
3674bool QAbstractItemModel::checkIndex(
const QModelIndex &index, CheckIndexOptions options)
const
3676 if (!index.isValid()) {
3677 if (options & CheckIndexOption::IndexIsValid) {
3678 qCWarning(lcCheckIndex) <<
"Index" << index <<
"is not valid (expected valid)";
3684 if (index.model() !=
this) {
3685 qCWarning(lcCheckIndex) <<
"Index" << index
3686 <<
"is for model" << index.model()
3687 <<
"which is different from this model" <<
this;
3691 if (index.row() < 0) {
3692 qCWarning(lcCheckIndex) <<
"Index" << index
3693 <<
"has negative row" << index.row();
3697 if (index.column() < 0) {
3698 qCWarning(lcCheckIndex) <<
"Index" << index
3699 <<
"has negative column" << index.column();
3703 if (!(options & CheckIndexOption::DoNotUseParent)) {
3704 const QModelIndex parentIndex = index.parent();
3705 if (options & CheckIndexOption::ParentIsInvalid) {
3706 if (parentIndex.isValid()) {
3707 qCWarning(lcCheckIndex) <<
"Index" << index
3708 <<
"has valid parent" << parentIndex
3709 <<
"(expected an invalid parent)";
3714 const int rc = rowCount(parentIndex);
3715 if (index.row() >= rc) {
3716 qCWarning(lcCheckIndex) <<
"Index" << index
3717 <<
"has out of range row" << index.row()
3718 <<
"rowCount() is" << rc;
3722 const int cc = columnCount(parentIndex);
3723 if (index.column() >= cc) {
3724 qCWarning(lcCheckIndex) <<
"Index" << index
3725 <<
"has out of range column" << index.column()
3726 <<
"columnCount() is" << cc;
3782void QAbstractItemModel::multiData(
const QModelIndex &index, QModelRoleDataSpan roleDataSpan)
const
3784 Q_ASSERT(checkIndex(index, CheckIndexOption::IndexIsValid));
3786 for (QModelRoleData &d : roleDataSpan)
3787 d.setData(data(index, d.role()));
4102bool QAbstractItemModelPrivate::dropOnItem(
const QModelIndex &index, QDataStream &stream)
4104 Q_Q(QAbstractItemModel);
4108 QList<
int> rows, columns;
4109 QList<QMap<
int, QVariant>> data;
4111 while (!stream.atEnd()) {
4113 QMap<
int, QVariant> v;
4114 stream >> r >> c >> v;
4119 left = qMin(c, left);
4122 for (
int i = 0; i < data.size(); ++i) {
4123 int r = (rows.at(i) - top) + index.row();
4124 int c = (columns.at(i) - left) + index.column();
4125 if (q->hasIndex(r, c))
4126 q->setItemData(q->index(r, c), data.at(i));
4135bool QAbstractTableModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
4136 int row,
int column,
const QModelIndex &parent)
4138 Q_D(QAbstractItemModel);
4139 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
4142 QStringList types = mimeTypes();
4143 if (types.isEmpty())
4145 QString format = types.at(0);
4146 if (!data->hasFormat(format))
4149 QByteArray encoded = data->data(format);
4150 QDataStream stream(&encoded, QDataStream::ReadOnly);
4153 if (parent.isValid() && row == -1 && column == -1)
4154 return d->dropOnItem(parent, stream);
4157 row = rowCount(parent);
4160 return decodeData(row, column, parent, stream);
4166bool QAbstractListModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
4167 int row,
int column,
const QModelIndex &parent)
4169 Q_D(QAbstractItemModel);
4170 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
4173 QStringList types = mimeTypes();
4174 if (types.isEmpty())
4176 QString format = types.at(0);
4177 if (!data->hasFormat(format))
4180 QByteArray encoded = data->data(format);
4181 QDataStream stream(&encoded, QDataStream::ReadOnly);
4184 if (parent.isValid() && row == -1 && column == -1)
4185 return d->dropOnItem(parent, stream);
4188 row = rowCount(parent);
4191 return decodeData(row, column, parent, stream);