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
812Qt::weak_ordering QAbstractItemModel::compareDataImpl(
const QVariant &left,
const QVariant &right,
813 const QCollator *collator)
816 if (!left.isValid()) {
817 if (!right.isValid())
818 return Qt::weak_ordering::equivalent;
819 return Qt::weak_ordering::greater;
821 if (!right.isValid())
822 return Qt::weak_ordering::less;
824 if (left.userType() != QMetaType::QString) {
825 QPartialOrdering partialOrder = QVariant::compare(left, right);
826 if (partialOrder == Qt::partial_ordering::unordered && right.metaType() != left.metaType()) {
827 if (right.canConvert(left.metaType())) {
828 QVariant rightAsLeft = right;
829 rightAsLeft.convert(left.metaType());
830 partialOrder = QVariant::compare(left, rightAsLeft);
831 }
else if (left.canConvert(right.metaType())) {
832 QVariant leftAsRight = left;
833 leftAsRight.convert(right.metaType());
834 partialOrder = QVariant::compare(leftAsRight, right);
837 if (partialOrder == Qt::partial_ordering::equivalent)
838 return Qt::weak_ordering::equivalent;
839 if (partialOrder < 0)
840 return Qt::weak_ordering::less;
841 if (partialOrder > 0)
842 return Qt::weak_ordering::greater;
846 const int res = collator
847 ? collator->compare(left.toString(), right.toString())
848 : left.toString().compare(right.toString());
849 return Qt::compareThreeWay(res, 0);
855 switch (value.userType()) {
856 case QMetaType::Bool:
858 case QMetaType::UInt:
859 case QMetaType::LongLong:
860 case QMetaType::ULongLong:
861 case QMetaType::QChar:
862 case QMetaType::Short:
863 case QMetaType::UShort:
864 case QMetaType::UChar:
865 case QMetaType::ULong:
866 case QMetaType::Long:
868 case QMetaType::Double:
869 case QMetaType::Float:
877
878
879
880
881
882bool QAbstractItemModelPrivate::variantLessThan(
const QVariant &v1,
const QVariant &v2)
884 switch(qMax(typeOfVariant(v1), typeOfVariant(v2)))
887 return v1.toLongLong() < v2.toLongLong();
889 return v1.toReal() < v2.toReal();
891 return v1.toString().localeAwareCompare(v2.toString()) < 0;
895void QAbstractItemModelPrivate::removePersistentIndexData(QPersistentModelIndexData *data)
897 if (data->index.isValid()) {
898 int removed = persistent.indexes.remove(data->index);
899 Q_ASSERT_X(removed == 1,
"QPersistentModelIndex::~QPersistentModelIndex",
900 "persistent model indexes corrupted");
906 for (
int i = persistent.moved.size() - 1; i >= 0; --i) {
907 int idx = persistent.moved.at(i).indexOf(data);
909 persistent.moved[i].remove(idx);
912 for (
int i = persistent.invalidated.size() - 1; i >= 0; --i) {
913 int idx = persistent.invalidated.at(i).indexOf(data);
915 persistent.invalidated[i].remove(idx);
920void QAbstractItemModelPrivate::rowsAboutToBeInserted(
const QModelIndex &parent,
923 Q_Q(QAbstractItemModel);
925 QList<QPersistentModelIndexData *> persistent_moved;
926 if (first < q->rowCount(parent)) {
927 for (
auto *data : std::as_const(persistent.indexes)) {
928 const QModelIndex &index = data->index;
929 if (index.row() >= first && index.isValid() && index.parent() == parent) {
930 persistent_moved.append(data);
934 persistent.moved.push(persistent_moved);
937void QAbstractItemModelPrivate::rowsInserted(
const QModelIndex &parent,
940 const QList<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
941 const int count = (last - first) + 1;
942 for (
auto *data : persistent_moved) {
943 QModelIndex old = data->index;
944 persistent.indexes.erase(persistent.indexes.constFind(old));
945 data->index = q_func()->index(old.row() + count, old.column(), parent);
946 if (data->index.isValid()) {
947 persistent.insertMultiAtEnd(data->index, data);
949 qWarning() <<
"QAbstractItemModel::endInsertRows: Invalid index (" << old.row() + count <<
',' << old.column() <<
") in model" << q_func();
954void QAbstractItemModelPrivate::itemsAboutToBeMoved(
const QModelIndex &srcParent,
int srcFirst,
int srcLast,
const QModelIndex &destinationParent,
int destinationChild, Qt::Orientation orientation)
956 QList<QPersistentModelIndexData *> persistent_moved_explicitly;
957 QList<QPersistentModelIndexData *> persistent_moved_in_source;
958 QList<QPersistentModelIndexData *> persistent_moved_in_destination;
960 const bool sameParent = (srcParent == destinationParent);
961 const bool movingUp = (srcFirst > destinationChild);
963 for (
auto *data : std::as_const(persistent.indexes)) {
964 const QModelIndex &index = data->index;
965 const QModelIndex &parent = index.parent();
966 const bool isSourceIndex = (parent == srcParent);
967 const bool isDestinationIndex = (parent == destinationParent);
970 if (orientation == Qt::Vertical)
971 childPosition = index.row();
973 childPosition = index.column();
975 if (!index.isValid() || !(isSourceIndex || isDestinationIndex ) )
978 if (!sameParent && isDestinationIndex) {
979 if (childPosition >= destinationChild)
980 persistent_moved_in_destination.append(data);
984 if (sameParent && movingUp && childPosition < destinationChild)
987 if (sameParent && !movingUp && childPosition < srcFirst )
990 if (!sameParent && childPosition < srcFirst)
993 if (sameParent && (childPosition > srcLast) && (childPosition >= destinationChild ))
996 if ((childPosition <= srcLast) && (childPosition >= srcFirst)) {
997 persistent_moved_explicitly.append(data);
999 persistent_moved_in_source.append(data);
1002 persistent.moved.push(persistent_moved_explicitly);
1003 persistent.moved.push(persistent_moved_in_source);
1004 persistent.moved.push(persistent_moved_in_destination);
1008
1009
1010
1011
1012
1013
1014void QAbstractItemModelPrivate::movePersistentIndexes(
const QList<QPersistentModelIndexData *> &indexes,
int change,
1015 const QModelIndex &parent, Qt::Orientation orientation)
1017 for (
auto *data : indexes) {
1018 int row = data->index.row();
1019 int column = data->index.column();
1021 if (Qt::Vertical == orientation)
1026 persistent.indexes.erase(persistent.indexes.constFind(data->index));
1027 data->index = q_func()->index(row, column, parent);
1028 if (data->index.isValid()) {
1029 persistent.insertMultiAtEnd(data->index, data);
1031 qWarning() <<
"QAbstractItemModel::endMoveRows: Invalid index (" << row <<
"," << column <<
") in model" << q_func();
1036void QAbstractItemModelPrivate::itemsMoved(
const QModelIndex &sourceParent,
int sourceFirst,
int sourceLast,
const QModelIndex &destinationParent,
int destinationChild, Qt::Orientation orientation)
1038 const QList<QPersistentModelIndexData *> moved_in_destination = persistent.moved.pop();
1039 const QList<QPersistentModelIndexData *> moved_in_source = persistent.moved.pop();
1040 const QList<QPersistentModelIndexData *> moved_explicitly = persistent.moved.pop();
1042 const bool sameParent = (sourceParent == destinationParent);
1043 const bool movingUp = (sourceFirst > destinationChild);
1045 const int explicit_change = (!sameParent || movingUp) ? destinationChild - sourceFirst : destinationChild - sourceLast - 1 ;
1046 const int source_change = (!sameParent || !movingUp) ? -1*(sourceLast - sourceFirst + 1) : sourceLast - sourceFirst + 1 ;
1047 const int destination_change = sourceLast - sourceFirst + 1;
1049 movePersistentIndexes(moved_explicitly, explicit_change, destinationParent, orientation);
1050 movePersistentIndexes(moved_in_source, source_change, sourceParent, orientation);
1051 movePersistentIndexes(moved_in_destination, destination_change, destinationParent, orientation);
1054void QAbstractItemModelPrivate::rowsAboutToBeRemoved(
const QModelIndex &parent,
1055 int first,
int last)
1057 QList<QPersistentModelIndexData *> persistent_moved;
1058 QList<QPersistentModelIndexData *> persistent_invalidated;
1061 for (
auto *data : std::as_const(persistent.indexes)) {
1062 bool level_changed =
false;
1063 QModelIndex current = data->index;
1064 while (current.isValid()) {
1065 QModelIndex current_parent = current.parent();
1066 if (current_parent == parent) {
1067 if (!level_changed && current.row() > last)
1068 persistent_moved.append(data);
1069 else if (current.row() <= last && current.row() >= first)
1070 persistent_invalidated.append(data);
1073 current = current_parent;
1074 level_changed =
true;
1078 persistent.moved.push(persistent_moved);
1079 persistent.invalidated.push(persistent_invalidated);
1082void QAbstractItemModelPrivate::rowsRemoved(
const QModelIndex &parent,
1083 int first,
int last)
1085 const QList<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
1086 const int count = (last - first) + 1;
1087 for (
auto *data : persistent_moved) {
1088 QModelIndex old = data->index;
1089 persistent.indexes.erase(persistent.indexes.constFind(old));
1090 data->index = q_func()->index(old.row() - count, old.column(), parent);
1091 if (data->index.isValid()) {
1092 persistent.insertMultiAtEnd(data->index, data);
1094 qWarning() <<
"QAbstractItemModel::endRemoveRows: Invalid index (" << old.row() - count <<
',' << old.column() <<
") in model" << q_func();
1097 const QList<QPersistentModelIndexData *> persistent_invalidated = persistent.invalidated.pop();
1098 for (
auto *data : persistent_invalidated) {
1099 auto pit = persistent.indexes.constFind(data->index);
1100 if (pit != persistent.indexes.cend())
1101 persistent.indexes.erase(pit);
1102 data->index = QModelIndex();
1106void QAbstractItemModelPrivate::columnsAboutToBeInserted(
const QModelIndex &parent,
1107 int first,
int last)
1109 Q_Q(QAbstractItemModel);
1111 QList<QPersistentModelIndexData *> persistent_moved;
1112 if (first < q->columnCount(parent)) {
1113 for (
auto *data : std::as_const(persistent.indexes)) {
1114 const QModelIndex &index = data->index;
1115 if (index.column() >= first && index.isValid() && index.parent() == parent)
1116 persistent_moved.append(data);
1119 persistent.moved.push(persistent_moved);
1122void QAbstractItemModelPrivate::columnsInserted(
const QModelIndex &parent,
1123 int first,
int last)
1125 const QList<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
1126 const int count = (last - first) + 1;
1127 for (
auto *data : persistent_moved) {
1128 QModelIndex old = data->index;
1129 persistent.indexes.erase(persistent.indexes.constFind(old));
1130 data->index = q_func()->index(old.row(), old.column() + count, parent);
1131 if (data->index.isValid()) {
1132 persistent.insertMultiAtEnd(data->index, data);
1134 qWarning() <<
"QAbstractItemModel::endInsertColumns: Invalid index (" << old.row() <<
',' << old.column() + count <<
") in model" << q_func();
1139void QAbstractItemModelPrivate::columnsAboutToBeRemoved(
const QModelIndex &parent,
1140 int first,
int last)
1142 QList<QPersistentModelIndexData *> persistent_moved;
1143 QList<QPersistentModelIndexData *> persistent_invalidated;
1146 for (
auto *data : std::as_const(persistent.indexes)) {
1147 bool level_changed =
false;
1148 QModelIndex current = data->index;
1149 while (current.isValid()) {
1150 QModelIndex current_parent = current.parent();
1151 if (current_parent == parent) {
1152 if (!level_changed && current.column() > last)
1153 persistent_moved.append(data);
1154 else if (current.column() <= last && current.column() >= first)
1155 persistent_invalidated.append(data);
1158 current = current_parent;
1159 level_changed =
true;
1163 persistent.moved.push(persistent_moved);
1164 persistent.invalidated.push(persistent_invalidated);
1168void QAbstractItemModelPrivate::columnsRemoved(
const QModelIndex &parent,
1169 int first,
int last)
1171 const QList<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
1172 const int count = (last - first) + 1;
1173 for (
auto *data : persistent_moved) {
1174 QModelIndex old = data->index;
1175 persistent.indexes.erase(persistent.indexes.constFind(old));
1176 data->index = q_func()->index(old.row(), old.column() - count, parent);
1177 if (data->index.isValid()) {
1178 persistent.insertMultiAtEnd(data->index, data);
1180 qWarning() <<
"QAbstractItemModel::endRemoveColumns: Invalid index (" << old.row() <<
',' << old.column() - count <<
") in model" << q_func();
1183 const QList<QPersistentModelIndexData *> persistent_invalidated = persistent.invalidated.pop();
1184 for (
auto *data : persistent_invalidated) {
1185 auto index = persistent.indexes.constFind(data->index);
1186 if (index != persistent.indexes.constEnd())
1187 persistent.indexes.erase(index);
1188 data->index = QModelIndex();
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208void QAbstractItemModel::resetInternalData()
1214
1215
1216
1217
1218
1219
1220
1221
1222
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
1260
1261
1262
1263
1264
1265
1266
1269
1270
1271
1272
1273
1274
1275
1278
1279
1280
1281
1285
1286
1287
1288
1292
1293
1294
1295
1296
1297
1298
1301
1302
1303
1304
1305
1306
1307
1310
1311
1312
1313
1314
1315
1316
1319
1320
1321
1322
1323
1324
1325
1326
1327
1330
1331
1332
1333
1334
1335
1336
1337
1338
1341
1342
1343
1344
1345
1346
1347
1350
1351
1352
1353
1354
1355
1356
1357
1360
1361
1362
1363
1364
1365
1366
1367
1370
1371
1372
1373
1374
1375
1378
1379
1380
1381
1382
1383
1386
1387
1388
1389
1390
1393
1394
1395
1396
1397
1398
1399
1400
1403
1404
1405
1406
1407
1410
1411
1412
1413
1414
1415
1416
1419
1420
1421
1422
1423
1424
1425
1426
1427
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
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1586
1587
1588
1589
1590
1591
1592
1593
1594
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1629
1630
1631
1632
1633
1634
1635
1636
1637
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1763
1764
1765QAbstractItemModel::QAbstractItemModel(QObject *parent)
1766 : QObject(*
new QAbstractItemModelPrivate, parent)
1771
1772
1773QAbstractItemModel::QAbstractItemModel(QAbstractItemModelPrivate &dd, QObject *parent)
1774 : QObject(dd, parent)
1779
1780
1781QAbstractItemModel::~QAbstractItemModel()
1783 d_func()->invalidatePersistentIndexes();
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2019
2020
2021
2022bool QAbstractItemModel::hasIndex(
int row,
int column,
const QModelIndex &parent)
const
2024 if (row < 0 || column < 0)
2026 return row < rowCount(parent) && column < columnCount(parent);
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040bool QAbstractItemModel::hasChildren(
const QModelIndex &parent)
const
2042 return (rowCount(parent) > 0) && (columnCount(parent) > 0);
2074QMap<
int, QVariant> QAbstractItemModel::itemData(
const QModelIndex &index)
const
2076 QMap<
int, QVariant> roles;
2077 for (
int i = 0; i < Qt::UserRole; ++i) {
2078 QVariant variantData = data(index, i);
2079 if (variantData.isValid())
2080 roles.insert(i, variantData);
2143bool QAbstractItemModel::setItemData(
const QModelIndex &index,
const QMap<
int, QVariant> &roles)
2145 if (!index.isValid() || roles.isEmpty())
2154 for (
auto it = roles.begin(), e = roles.end(); it != e; ++it) {
2155 if (!setData(index, it.value(), it.key()))
2195QMimeData *QAbstractItemModel::mimeData(
const QModelIndexList &indexes)
const
2197 if (indexes.size() <= 0)
2199 QStringList types = mimeTypes();
2200 if (types.isEmpty())
2202 QMimeData *data =
new QMimeData();
2203 QString format = types.at(0);
2205 QDataStream stream(&encoded, QDataStream::WriteOnly);
2206 encodeData(indexes, stream);
2207 data->setData(format, encoded);
2224bool QAbstractItemModel::canDropMimeData(
const QMimeData *data, Qt::DropAction action,
2225 int row,
int column,
2226 const QModelIndex &parent)
const
2232 if (!(action & supportedDropActions()))
2235 const QStringList modelTypes = mimeTypes();
2236 for (
int i = 0; i < modelTypes.size(); ++i) {
2237 if (data->hasFormat(modelTypes.at(i)))
2272bool QAbstractItemModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
2273 int row,
int column,
const QModelIndex &parent)
2276 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
2279 const QStringList types = mimeTypes();
2280 if (types.isEmpty())
2282 const QString format = types.at(0);
2283 if (!data->hasFormat(format))
2285 const bool dropOnItem = row == -1 && column == -1 && parent.isValid();
2286 if (!dropOnItem || !parent.flags().testFlag(Qt::ItemNeverHasChildren)) {
2289 if (row > rowCount(parent))
2290 row = rowCount(parent);
2292 row = rowCount(parent);
2297 QByteArray encoded = data->data(format);
2298 QDataStream stream(&encoded, QDataStream::ReadOnly);
2299 return decodeData(row, column, parent, stream);
2577QModelIndexList QAbstractItemModel::match(
const QModelIndex &start,
int role,
2578 const QVariant &value,
int hits,
2579 Qt::MatchFlags flags)
const
2581 QModelIndexList result;
2582 uint matchType = (flags & Qt::MatchTypeMask).toInt();
2583 Qt::CaseSensitivity cs = flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
2584 bool recurse = flags.testAnyFlag(Qt::MatchRecursive);
2585 bool wrap = flags.testAnyFlag(Qt::MatchWrap);
2586 bool allHits = (hits == -1);
2588#if QT_CONFIG(regularexpression)
2589 QRegularExpression rx;
2591 const int column = start.column();
2592 QModelIndex p = parent(start);
2593 int from = start.row();
2594 int to = rowCount(p);
2597 for (
int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) {
2598 for (
int r = from; (r < to) && (allHits || result.size() < hits); ++r) {
2599 QModelIndex idx = index(r, column, p);
2602 QVariant v = data(idx, role);
2604 if (matchType == Qt::MatchExactly) {
2608#if QT_CONFIG(regularexpression)
2609 if (matchType == Qt::MatchRegularExpression) {
2610 if (rx.pattern().isEmpty()) {
2611 if (value.userType() == QMetaType::QRegularExpression) {
2612 rx = value.toRegularExpression();
2614 rx.setPattern(value.toString());
2615 if (cs == Qt::CaseInsensitive)
2616 rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
2619 }
else if (matchType == Qt::MatchWildcard) {
2620 if (rx.pattern().isEmpty()) {
2621 const QString pattern = QRegularExpression::wildcardToRegularExpression(value.toString(), QRegularExpression::NonPathWildcardConversion);
2622 rx.setPattern(pattern);
2624 if (cs == Qt::CaseInsensitive)
2625 rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
2630 text = value.toString();
2633 QString t = v.toString();
2634 switch (matchType) {
2635#if QT_CONFIG(regularexpression)
2636 case Qt::MatchRegularExpression:
2638 case Qt::MatchWildcard:
2643 case Qt::MatchStartsWith:
2644 if (t.startsWith(text, cs))
2647 case Qt::MatchEndsWith:
2648 if (t.endsWith(text, cs))
2651 case Qt::MatchFixedString:
2652 if (t.compare(text, cs) == 0)
2655 case Qt::MatchContains:
2657 if (t.contains(text, cs))
2662 const auto parent = column != 0 ? idx.sibling(idx.row(), 0) : idx;
2663 if (hasChildren(parent)) {
2664 result += match(index(0, column, parent), role,
2665 (text.isEmpty() ? value : text),
2666 (allHits ? -1 : hits - result.size()), flags);
2832bool QAbstractItemModel::decodeData(
int row,
int column,
const QModelIndex &parent,
2833 QDataStream &stream)
2839 QList<
int> rows, columns;
2840 QList<QMap<
int, QVariant>> data;
2842 while (!stream.atEnd()) {
2844 QMap<
int, QVariant> v;
2845 stream >> r >> c >> v;
2850 left = qMin(c, left);
2851 bottom = qMax(r, bottom);
2852 right = qMax(c, right);
2857 int dragRowCount = 0;
2858 int dragColumnCount = right - left + 1;
2861 QList<
int> rowsToInsert(bottom + 1);
2862 for (
int i = 0; i < rows.size(); ++i)
2863 rowsToInsert[rows.at(i)] = 1;
2864 for (
int i = 0; i < rowsToInsert.size(); ++i) {
2865 if (rowsToInsert.at(i) == 1){
2866 rowsToInsert[i] = dragRowCount;
2870 for (
int i = 0; i < rows.size(); ++i)
2871 rows[i] = top + rowsToInsert.at(rows.at(i));
2873 QBitArray isWrittenTo(dragRowCount * dragColumnCount);
2876 int colCount = columnCount(parent);
2877 if (colCount == 0) {
2878 insertColumns(colCount, dragColumnCount - colCount, parent);
2879 colCount = columnCount(parent);
2881 insertRows(row, dragRowCount, parent);
2884 column = qMax(0, column);
2886 QList<QPersistentModelIndex> newIndexes(data.size());
2888 for (
int j = 0; j < data.size(); ++j) {
2889 int relativeRow = rows.at(j) - top;
2890 int relativeColumn = columns.at(j) - left;
2891 int destinationRow = relativeRow + row;
2892 int destinationColumn = relativeColumn + column;
2893 int flat = (relativeRow * dragColumnCount) + relativeColumn;
2895 if (destinationColumn >= colCount || isWrittenTo.testBit(flat)) {
2896 destinationColumn = qBound(column, destinationColumn, qMax(colCount - 1, column));
2897 destinationRow = row + dragRowCount;
2898 insertRows(row + dragRowCount, 1, parent);
2899 flat = (dragRowCount * dragColumnCount) + relativeColumn;
2900 isWrittenTo.resize(++dragRowCount * dragColumnCount);
2902 if (!isWrittenTo.testBit(flat)) {
2903 newIndexes[j] = index(destinationRow, destinationColumn, parent);
2904 isWrittenTo.setBit(flat);
2908 for(
int k = 0; k < newIndexes.size(); k++) {
2909 if (newIndexes.at(k).isValid())
2910 setItemData(newIndexes.at(k), data.at(k));
2958void QAbstractItemModel::beginInsertRows(
const QModelIndex &parent,
int first,
int last)
2960 Q_ASSERT(first >= 0);
2961 Q_ASSERT(first <= rowCount(parent));
2962 Q_ASSERT(last >= first);
2963 Q_D(QAbstractItemModel);
2964 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
2965 emit rowsAboutToBeInserted(parent, first, last, QPrivateSignal());
2966 d->rowsAboutToBeInserted(parent, first, last);
2977void QAbstractItemModel::endInsertRows()
2979 Q_D(QAbstractItemModel);
2980 QAbstractItemModelPrivate::Change change = d->changes.pop();
2981 d->rowsInserted(change.parent, change.first, change.last);
2982 emit rowsInserted(change.parent, change.first, change.last, QPrivateSignal());
3014void QAbstractItemModel::beginRemoveRows(
const QModelIndex &parent,
int first,
int last)
3016 Q_ASSERT(first >= 0);
3017 Q_ASSERT(last >= first);
3018 Q_ASSERT(last < rowCount(parent));
3019 Q_D(QAbstractItemModel);
3020 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3021 emit rowsAboutToBeRemoved(parent, first, last, QPrivateSignal());
3022 d->rowsAboutToBeRemoved(parent, first, last);
3033void QAbstractItemModel::endRemoveRows()
3035 Q_D(QAbstractItemModel);
3036 QAbstractItemModelPrivate::Change change = d->changes.pop();
3037 d->rowsRemoved(change.parent, change.first, change.last);
3038 emit rowsRemoved(change.parent, change.first, change.last, QPrivateSignal());
3049bool QAbstractItemModelPrivate::allowMove(
const QModelIndex &srcParent,
int start,
int end,
const QModelIndex &destinationParent,
int destinationStart, Qt::Orientation orientation)
3052 if (destinationParent == srcParent)
3053 return !(destinationStart >= start && destinationStart <= end + 1);
3055 QModelIndex destinationAncestor = destinationParent;
3056 int pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
3058 if (destinationAncestor == srcParent) {
3059 if (pos >= start && pos <= end)
3064 if (!destinationAncestor.isValid())
3067 pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
3068 destinationAncestor = destinationAncestor.parent();
3175bool QAbstractItemModel::beginMoveRows(
const QModelIndex &sourceParent,
int sourceFirst,
int sourceLast,
const QModelIndex &destinationParent,
int destinationChild)
3177 Q_ASSERT(sourceFirst >= 0);
3178 Q_ASSERT(sourceLast >= sourceFirst);
3179 Q_ASSERT(destinationChild >= 0);
3180 Q_D(QAbstractItemModel);
3182 if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical)) {
3186 QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
3187 sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
3188 d->changes.push(sourceChange);
3189 int destinationLast = destinationChild + (sourceLast - sourceFirst);
3190 QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
3191 destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
3192 d->changes.push(destinationChange);
3194 emit rowsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
3195 d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical);
3210void QAbstractItemModel::endMoveRows()
3212 Q_D(QAbstractItemModel);
3214 QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
3215 QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
3217 QModelIndex adjustedSource = removeChange.parent;
3218 QModelIndex adjustedDestination = insertChange.parent;
3220 const int numMoved = removeChange.last - removeChange.first + 1;
3221 if (insertChange.needsAdjust)
3222 adjustedDestination = createIndex(adjustedDestination.row() - numMoved, adjustedDestination.column(), adjustedDestination.internalPointer());
3224 if (removeChange.needsAdjust)
3225 adjustedSource = createIndex(adjustedSource.row() + numMoved, adjustedSource.column(), adjustedSource.internalPointer());
3227 d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Vertical);
3229 emit rowsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
3275void QAbstractItemModel::beginInsertColumns(
const QModelIndex &parent,
int first,
int last)
3277 Q_ASSERT(first >= 0);
3278 Q_ASSERT(first <= columnCount(parent));
3279 Q_ASSERT(last >= first);
3280 Q_D(QAbstractItemModel);
3281 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3282 emit columnsAboutToBeInserted(parent, first, last, QPrivateSignal());
3283 d->columnsAboutToBeInserted(parent, first, last);
3295void QAbstractItemModel::endInsertColumns()
3297 Q_D(QAbstractItemModel);
3298 QAbstractItemModelPrivate::Change change = d->changes.pop();
3299 d->columnsInserted(change.parent, change.first, change.last);
3300 emit columnsInserted(change.parent, change.first, change.last, QPrivateSignal());
3332void QAbstractItemModel::beginRemoveColumns(
const QModelIndex &parent,
int first,
int last)
3334 Q_ASSERT(first >= 0);
3335 Q_ASSERT(last >= first);
3336 Q_ASSERT(last < columnCount(parent));
3337 Q_D(QAbstractItemModel);
3338 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3339 emit columnsAboutToBeRemoved(parent, first, last, QPrivateSignal());
3340 d->columnsAboutToBeRemoved(parent, first, last);
3351void QAbstractItemModel::endRemoveColumns()
3353 Q_D(QAbstractItemModel);
3354 QAbstractItemModelPrivate::Change change = d->changes.pop();
3355 d->columnsRemoved(change.parent, change.first, change.last);
3356 emit columnsRemoved(change.parent, change.first, change.last, QPrivateSignal());
3397bool QAbstractItemModel::beginMoveColumns(
const QModelIndex &sourceParent,
int sourceFirst,
int sourceLast,
const QModelIndex &destinationParent,
int destinationChild)
3399 Q_ASSERT(sourceFirst >= 0);
3400 Q_ASSERT(sourceLast >= sourceFirst);
3401 Q_ASSERT(destinationChild >= 0);
3402 Q_D(QAbstractItemModel);
3404 if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal)) {
3408 QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
3409 sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
3410 d->changes.push(sourceChange);
3411 int destinationLast = destinationChild + (sourceLast - sourceFirst);
3412 QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
3413 destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
3414 d->changes.push(destinationChange);
3416 emit columnsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
3417 d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal);
3432void QAbstractItemModel::endMoveColumns()
3434 Q_D(QAbstractItemModel);
3436 QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
3437 QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
3439 QModelIndex adjustedSource = removeChange.parent;
3440 QModelIndex adjustedDestination = insertChange.parent;
3442 const int numMoved = removeChange.last - removeChange.first + 1;
3443 if (insertChange.needsAdjust)
3444 adjustedDestination = createIndex(adjustedDestination.row(), adjustedDestination.column() - numMoved, adjustedDestination.internalPointer());
3446 if (removeChange.needsAdjust)
3447 adjustedSource = createIndex(adjustedSource.row(), adjustedSource.column() + numMoved, adjustedSource.internalPointer());
3449 d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Horizontal);
3450 emit columnsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
3524void QAbstractItemModel::changePersistentIndex(
const QModelIndex &from,
const QModelIndex &to)
3526 Q_D(QAbstractItemModel);
3527 if (d->persistent.indexes.isEmpty())
3530 const auto it = d->persistent.indexes.constFind(from);
3531 if (it != d->persistent.indexes.cend()) {
3532 QPersistentModelIndexData *data = *it;
3533 d->persistent.indexes.erase(it);
3536 d->persistent.insertMultiAtEnd(to, data);
3551void QAbstractItemModel::changePersistentIndexList(
const QModelIndexList &from,
3552 const QModelIndexList &to)
3554 Q_D(QAbstractItemModel);
3555 if (d->persistent.indexes.isEmpty())
3557 QList<QPersistentModelIndexData *> toBeReinserted;
3558 toBeReinserted.reserve(to.size());
3559 for (
int i = 0; i < from.size(); ++i) {
3560 if (from.at(i) == to.at(i))
3562 const auto it = d->persistent.indexes.constFind(from.at(i));
3563 if (it != d->persistent.indexes.cend()) {
3564 QPersistentModelIndexData *data = *it;
3565 d->persistent.indexes.erase(it);
3566 data->index = to.at(i);
3567 if (data->index.isValid())
3568 toBeReinserted << data;
3572 for (
auto *data : std::as_const(toBeReinserted))
3573 d->persistent.insertMultiAtEnd(data->index, data);
3665bool QAbstractItemModel::checkIndex(
const QModelIndex &index, CheckIndexOptions options)
const
3667 if (!index.isValid()) {
3668 if (options & CheckIndexOption::IndexIsValid) {
3669 qCWarning(lcCheckIndex) <<
"Index" << index <<
"is not valid (expected valid)";
3675 if (index.model() !=
this) {
3676 qCWarning(lcCheckIndex) <<
"Index" << index
3677 <<
"is for model" << index.model()
3678 <<
"which is different from this model" <<
this;
3682 if (index.row() < 0) {
3683 qCWarning(lcCheckIndex) <<
"Index" << index
3684 <<
"has negative row" << index.row();
3688 if (index.column() < 0) {
3689 qCWarning(lcCheckIndex) <<
"Index" << index
3690 <<
"has negative column" << index.column();
3694 if (!(options & CheckIndexOption::DoNotUseParent)) {
3695 const QModelIndex parentIndex = index.parent();
3696 if (options & CheckIndexOption::ParentIsInvalid) {
3697 if (parentIndex.isValid()) {
3698 qCWarning(lcCheckIndex) <<
"Index" << index
3699 <<
"has valid parent" << parentIndex
3700 <<
"(expected an invalid parent)";
3705 const int rc = rowCount(parentIndex);
3706 if (index.row() >= rc) {
3707 qCWarning(lcCheckIndex) <<
"Index" << index
3708 <<
"has out of range row" << index.row()
3709 <<
"rowCount() is" << rc;
3713 const int cc = columnCount(parentIndex);
3714 if (index.column() >= cc) {
3715 qCWarning(lcCheckIndex) <<
"Index" << index
3716 <<
"has out of range column" << index.column()
3717 <<
"columnCount() is" << cc;
3773void QAbstractItemModel::multiData(
const QModelIndex &index, QModelRoleDataSpan roleDataSpan)
const
3775 Q_ASSERT(checkIndex(index, CheckIndexOption::IndexIsValid));
3777 for (QModelRoleData &d : roleDataSpan)
3778 d.setData(data(index, d.role()));
4093bool QAbstractItemModelPrivate::dropOnItem(
const QModelIndex &index, QDataStream &stream)
4095 Q_Q(QAbstractItemModel);
4099 QList<
int> rows, columns;
4100 QList<QMap<
int, QVariant>> data;
4102 while (!stream.atEnd()) {
4104 QMap<
int, QVariant> v;
4105 stream >> r >> c >> v;
4110 left = qMin(c, left);
4113 for (
int i = 0; i < data.size(); ++i) {
4114 int r = (rows.at(i) - top) + index.row();
4115 int c = (columns.at(i) - left) + index.column();
4116 if (q->hasIndex(r, c))
4117 q->setItemData(q->index(r, c), data.at(i));
4126bool QAbstractTableModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
4127 int row,
int column,
const QModelIndex &parent)
4129 Q_D(QAbstractItemModel);
4130 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
4133 QStringList types = mimeTypes();
4134 if (types.isEmpty())
4136 QString format = types.at(0);
4137 if (!data->hasFormat(format))
4140 QByteArray encoded = data->data(format);
4141 QDataStream stream(&encoded, QDataStream::ReadOnly);
4144 if (parent.isValid() && row == -1 && column == -1)
4145 return d->dropOnItem(parent, stream);
4148 row = rowCount(parent);
4151 return decodeData(row, column, parent, stream);
4157bool QAbstractListModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
4158 int row,
int column,
const QModelIndex &parent)
4160 Q_D(QAbstractItemModel);
4161 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
4164 QStringList types = mimeTypes();
4165 if (types.isEmpty())
4167 QString format = types.at(0);
4168 if (!data->hasFormat(format))
4171 QByteArray encoded = data->data(format);
4172 QDataStream stream(&encoded, QDataStream::ReadOnly);
4175 if (parent.isValid() && row == -1 && column == -1)
4176 return d->dropOnItem(parent, stream);
4179 row = rowCount(parent);
4182 return decodeData(row, column, parent, stream);