Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qabstractitemmodel.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
6#include <private/qabstractitemmodel_p.h>
7#include <qdatastream.h>
8#include <qstringlist.h>
9#include <qsize.h>
10#include <qmimedata.h>
11#include <qdebug.h>
12#include <qlist.h>
13#if QT_CONFIG(regularexpression)
14# include <qregularexpression.h>
15#endif
16#include <qstack.h>
17#include <qmap.h>
18#include <qbitarray.h>
19#include <qdatetime.h>
20#include <qloggingcategory.h>
21
22#include <functional>
23
24#include <limits.h>
25
27
28Q_LOGGING_CATEGORY(lcCheckIndex, "qt.core.qabstractitemmodel.checkindex")
29
31
33{
34 Q_ASSERT(index.isValid()); // we will _never_ insert an invalid index in the list
36 QAbstractItemModel *model = const_cast<QAbstractItemModel *>(index.model());
37 QMultiHash<QModelIndex, QPersistentModelIndexData *> &indexes = model->d_func()->persistent.indexes;
38 const auto it = indexes.constFind(index);
39 if (it != indexes.cend()) {
40 d = (*it);
41 } else {
43 indexes.insert(index, d);
44 }
45 Q_ASSERT(d);
46 return d;
47}
48
50{
52 Q_ASSERT(data->ref.loadRelaxed() == 0);
53 QAbstractItemModel *model = const_cast<QAbstractItemModel *>(data->index.model());
54 // a valid persistent model index with a null model pointer can only happen if the model was destroyed
55 if (model) {
57 Q_ASSERT(p);
58 p->removePersistentIndexData(data);
59 }
60 delete data;
61}
62
336
349
355 : d(nullptr)
356{
357 if (index.isValid()) {
359 d->ref.ref();
360 }
361}
362
370{
371 if (d && !d->ref.deref()) {
373 d = nullptr;
374 }
375}
376
386{
387 if (d && other.d)
388 return d->index == other.d->index;
389 return d == other.d;
390}
391
403{
404 if (d && other.d)
405 return d->index < other.d->index;
406
407 return std::less<>{}(d, other.d);
408}
409
424{
425 if (d == other.d)
426 return *this;
427 if (d && !d->ref.deref())
429 d = other.d;
430 if (d) d->ref.ref();
431 return *this;
432}
447{
448 if (d && !d->ref.deref())
450 if (other.isValid()) {
452 if (d) d->ref.ref();
453 } else {
454 d = nullptr;
455 }
456 return *this;
457}
458
465QPersistentModelIndex::operator QModelIndex() const
466{
467 if (d)
468 return d->index;
469 return QModelIndex();
470}
471
481{
482 if (d)
483 return d->index == other;
484 return !other.isValid();
485}
486
495{
496 if (d)
497 return d->index != other;
498 return other.isValid();
499}
500
508{
509 if (d)
510 return d->index.row();
511 return -1;
512}
513
521{
522 if (d)
523 return d->index.column();
524 return -1;
525}
526
537{
538 if (d)
539 return d->index.internalPointer();
540 return nullptr;
541}
542
553{
554 if (d)
555 return d->index.constInternalPointer();
556 return nullptr;
557}
558
569{
570 if (d)
571 return d->index.internalId();
572 return 0;
573}
574
582{
583 if (d)
584 return d->index.parent();
585 return QModelIndex();
586}
587
596{
597 if (d)
598 return d->index.sibling(row, column);
599 return QModelIndex();
600}
601
609{
610 if (d)
611 return d->index.data(role);
612 return QVariant();
613}
614
615
624{
625 if (d)
626 d->index.multiData(roleDataSpan);
627}
628
634Qt::ItemFlags QPersistentModelIndex::flags() const
635{
636 if (d)
637 return d->index.flags();
638 return { };
639}
640
645{
646 if (d)
647 return d->index.model();
648 return nullptr;
649}
650
664{
665 return d && d->index.isValid();
666}
667
668#ifndef QT_NO_DEBUG_STREAM
670{
671 QDebugStateSaver saver(dbg);
672 dbg.nospace() << "QModelIndex(" << idx.row() << ',' << idx.column()
673 << ',' << idx.internalPointer() << ',' << idx.model() << ')';
674 return dbg;
675}
676
678{
679 if (idx.d)
680 dbg << idx.d->index;
681 else
682 dbg << QModelIndex();
683 return dbg;
684}
685#endif
686
688{
690public:
692 QModelIndex index(int, int, const QModelIndex &) const override { return QModelIndex(); }
693 QModelIndex parent(const QModelIndex &) const override { return QModelIndex(); }
694 int rowCount(const QModelIndex &) const override { return 0; }
695 int columnCount(const QModelIndex &) const override { return 0; }
696 bool hasChildren(const QModelIndex &) const override { return false; }
697 QVariant data(const QModelIndex &, int) const override { return QVariant(); }
698};
699
701
702
707
711
716
718{
719 for (QPersistentModelIndexData *data : std::as_const(persistent.indexes))
720 data->index = QModelIndex();
721 persistent.indexes.clear();
722}
723
730 const auto it = persistent.indexes.constFind(index);
731 if (it != persistent.indexes.cend()) {
733 persistent.indexes.erase(it);
734 data->index = QModelIndex();
735 }
736}
737
738using DefaultRoleNames = QHash<int, QByteArray>;
740 {
741 { Qt::DisplayRole, "display" },
742 { Qt::DecorationRole, "decoration" },
743 { Qt::EditRole, "edit" },
744 { Qt::ToolTipRole, "toolTip" },
745 { Qt::StatusTipRole, "statusTip" },
746 { Qt::WhatsThisRole, "whatsThis" },
747 })
748
750{
751 return *qDefaultRoleNames();
752}
753
755 Qt::CaseSensitivity cs, bool isLocaleAware)
756{
757 if (left.userType() == QMetaType::UnknownType)
758 return false;
759 if (right.userType() == QMetaType::UnknownType)
760 return true;
761 switch (left.userType()) {
762 case QMetaType::Int:
763 return left.toInt() < right.toInt();
764 case QMetaType::UInt:
765 return left.toUInt() < right.toUInt();
766 case QMetaType::LongLong:
767 return left.toLongLong() < right.toLongLong();
768 case QMetaType::ULongLong:
769 return left.toULongLong() < right.toULongLong();
770 case QMetaType::Float:
771 return left.toFloat() < right.toFloat();
772 case QMetaType::Double:
773 return left.toDouble() < right.toDouble();
774 case QMetaType::QChar:
775 return left.toChar() < right.toChar();
776 case QMetaType::QDate:
777 return left.toDate() < right.toDate();
778 case QMetaType::QTime:
779 return left.toTime() < right.toTime();
780 case QMetaType::QDateTime:
781 return left.toDateTime() < right.toDateTime();
782 case QMetaType::QString:
783 default:
784 if (isLocaleAware)
785 return left.toString().localeAwareCompare(right.toString()) < 0;
786 else
787 return left.toString().compare(right.toString(), cs) < 0;
788 }
789}
790
791
793{
794 //return 0 for integer, 1 for floating point and 2 for other
795 switch (value.userType()) {
796 case QMetaType::Bool:
797 case QMetaType::Int:
798 case QMetaType::UInt:
799 case QMetaType::LongLong:
800 case QMetaType::ULongLong:
801 case QMetaType::QChar:
802 case QMetaType::Short:
803 case QMetaType::UShort:
804 case QMetaType::UChar:
805 case QMetaType::ULong:
806 case QMetaType::Long:
807 return 0;
808 case QMetaType::Double:
809 case QMetaType::Float:
810 return 1;
811 default:
812 return 2;
813 }
814}
815
823{
825 {
826 case 0: //integer type
827 return v1.toLongLong() < v2.toLongLong();
828 case 1: //floating point
829 return v1.toReal() < v2.toReal();
830 default:
831 return v1.toString().localeAwareCompare(v2.toString()) < 0;
832 }
833}
834
836{
837 if (data->index.isValid()) {
838 int removed = persistent.indexes.remove(data->index);
839 Q_ASSERT_X(removed == 1, "QPersistentModelIndex::~QPersistentModelIndex",
840 "persistent model indexes corrupted"); //maybe the index was somewhat invalid?
841 // This assert may happen if the model use changePersistentIndex in a way that could result on two
842 // QPersistentModelIndex pointing to the same index.
843 Q_UNUSED(removed);
844 }
845 // make sure our optimization still works
846 for (int i = persistent.moved.size() - 1; i >= 0; --i) {
847 int idx = persistent.moved.at(i).indexOf(data);
848 if (idx >= 0)
849 persistent.moved[i].remove(idx);
850 }
851 // update the references to invalidated persistent indexes
852 for (int i = persistent.invalidated.size() - 1; i >= 0; --i) {
853 int idx = persistent.invalidated.at(i).indexOf(data);
854 if (idx >= 0)
855 persistent.invalidated[i].remove(idx);
856 }
857
858}
859
861 int first, int last)
862{
864 Q_UNUSED(last);
865 QList<QPersistentModelIndexData *> persistent_moved;
866 if (first < q->rowCount(parent)) {
867 for (auto *data : std::as_const(persistent.indexes)) {
868 const QModelIndex &index = data->index;
869 if (index.row() >= first && index.isValid() && index.parent() == parent) {
870 persistent_moved.append(data);
871 }
872 }
873 }
874 persistent.moved.push(persistent_moved);
875}
876
878 int first, int last)
879{
880 const QList<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
881 const int count = (last - first) + 1; // it is important to only use the delta, because the change could be nested
882 for (auto *data : persistent_moved) {
883 QModelIndex old = data->index;
884 persistent.indexes.erase(persistent.indexes.constFind(old));
885 data->index = q_func()->index(old.row() + count, old.column(), parent);
886 if (data->index.isValid()) {
887 persistent.insertMultiAtEnd(data->index, data);
888 } else {
889 qWarning() << "QAbstractItemModel::endInsertRows: Invalid index (" << old.row() + count << ',' << old.column() << ") in model" << q_func();
890 }
891 }
892}
893
894void QAbstractItemModelPrivate::itemsAboutToBeMoved(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation)
895{
896 QList<QPersistentModelIndexData *> persistent_moved_explicitly;
897 QList<QPersistentModelIndexData *> persistent_moved_in_source;
898 QList<QPersistentModelIndexData *> persistent_moved_in_destination;
899
900 const bool sameParent = (srcParent == destinationParent);
901 const bool movingUp = (srcFirst > destinationChild);
902
903 for (auto *data : std::as_const(persistent.indexes)) {
904 const QModelIndex &index = data->index;
905 const QModelIndex &parent = index.parent();
906 const bool isSourceIndex = (parent == srcParent);
907 const bool isDestinationIndex = (parent == destinationParent);
908
909 int childPosition;
910 if (orientation == Qt::Vertical)
911 childPosition = index.row();
912 else
913 childPosition = index.column();
914
915 if (!index.isValid() || !(isSourceIndex || isDestinationIndex ) )
916 continue;
917
918 if (!sameParent && isDestinationIndex) {
919 if (childPosition >= destinationChild)
920 persistent_moved_in_destination.append(data);
921 continue;
922 }
923
924 if (sameParent && movingUp && childPosition < destinationChild)
925 continue;
926
927 if (sameParent && !movingUp && childPosition < srcFirst )
928 continue;
929
930 if (!sameParent && childPosition < srcFirst)
931 continue;
932
933 if (sameParent && (childPosition > srcLast) && (childPosition >= destinationChild ))
934 continue;
935
936 if ((childPosition <= srcLast) && (childPosition >= srcFirst)) {
937 persistent_moved_explicitly.append(data);
938 } else {
939 persistent_moved_in_source.append(data);
940 }
941 }
942 persistent.moved.push(persistent_moved_explicitly);
943 persistent.moved.push(persistent_moved_in_source);
944 persistent.moved.push(persistent_moved_in_destination);
945}
946
954void QAbstractItemModelPrivate::movePersistentIndexes(const QList<QPersistentModelIndexData *> &indexes, int change,
955 const QModelIndex &parent, Qt::Orientation orientation)
956{
957 for (auto *data : indexes) {
958 int row = data->index.row();
959 int column = data->index.column();
960
961 if (Qt::Vertical == orientation)
962 row += change;
963 else
964 column += change;
965
966 persistent.indexes.erase(persistent.indexes.constFind(data->index));
967 data->index = q_func()->index(row, column, parent);
968 if (data->index.isValid()) {
969 persistent.insertMultiAtEnd(data->index, data);
970 } else {
971 qWarning() << "QAbstractItemModel::endMoveRows: Invalid index (" << row << "," << column << ") in model" << q_func();
972 }
973 }
974}
975
976void QAbstractItemModelPrivate::itemsMoved(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation)
977{
978 const QList<QPersistentModelIndexData *> moved_in_destination = persistent.moved.pop();
979 const QList<QPersistentModelIndexData *> moved_in_source = persistent.moved.pop();
980 const QList<QPersistentModelIndexData *> moved_explicitly = persistent.moved.pop();
981
982 const bool sameParent = (sourceParent == destinationParent);
983 const bool movingUp = (sourceFirst > destinationChild);
984
985 const int explicit_change = (!sameParent || movingUp) ? destinationChild - sourceFirst : destinationChild - sourceLast - 1 ;
986 const int source_change = (!sameParent || !movingUp) ? -1*(sourceLast - sourceFirst + 1) : sourceLast - sourceFirst + 1 ;
987 const int destination_change = sourceLast - sourceFirst + 1;
988
989 movePersistentIndexes(moved_explicitly, explicit_change, destinationParent, orientation);
990 movePersistentIndexes(moved_in_source, source_change, sourceParent, orientation);
991 movePersistentIndexes(moved_in_destination, destination_change, destinationParent, orientation);
992}
993
995 int first, int last)
996{
997 QList<QPersistentModelIndexData *> persistent_moved;
998 QList<QPersistentModelIndexData *> persistent_invalidated;
999 // find the persistent indexes that are affected by the change, either by being in the removed subtree
1000 // or by being on the same level and below the removed rows
1001 for (auto *data : std::as_const(persistent.indexes)) {
1002 bool level_changed = false;
1003 QModelIndex current = data->index;
1004 while (current.isValid()) {
1005 QModelIndex current_parent = current.parent();
1006 if (current_parent == parent) { // on the same level as the change
1007 if (!level_changed && current.row() > last) // below the removed rows
1008 persistent_moved.append(data);
1009 else if (current.row() <= last && current.row() >= first) // in the removed subtree
1010 persistent_invalidated.append(data);
1011 break;
1012 }
1013 current = current_parent;
1014 level_changed = true;
1015 }
1016 }
1017
1018 persistent.moved.push(persistent_moved);
1019 persistent.invalidated.push(persistent_invalidated);
1020}
1021
1023 int first, int last)
1024{
1025 const QList<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
1026 const int count = (last - first) + 1; // it is important to only use the delta, because the change could be nested
1027 for (auto *data : persistent_moved) {
1028 QModelIndex old = data->index;
1029 persistent.indexes.erase(persistent.indexes.constFind(old));
1030 data->index = q_func()->index(old.row() - count, old.column(), parent);
1031 if (data->index.isValid()) {
1032 persistent.insertMultiAtEnd(data->index, data);
1033 } else {
1034 qWarning() << "QAbstractItemModel::endRemoveRows: Invalid index (" << old.row() - count << ',' << old.column() << ") in model" << q_func();
1035 }
1036 }
1037 const QList<QPersistentModelIndexData *> persistent_invalidated = persistent.invalidated.pop();
1038 for (auto *data : persistent_invalidated) {
1039 auto pit = persistent.indexes.constFind(data->index);
1040 if (pit != persistent.indexes.cend())
1041 persistent.indexes.erase(pit);
1042 data->index = QModelIndex();
1043 }
1044}
1045
1047 int first, int last)
1048{
1049 Q_Q(QAbstractItemModel);
1050 Q_UNUSED(last);
1051 QList<QPersistentModelIndexData *> persistent_moved;
1052 if (first < q->columnCount(parent)) {
1053 for (auto *data : std::as_const(persistent.indexes)) {
1054 const QModelIndex &index = data->index;
1055 if (index.column() >= first && index.isValid() && index.parent() == parent)
1056 persistent_moved.append(data);
1057 }
1058 }
1059 persistent.moved.push(persistent_moved);
1060}
1061
1063 int first, int last)
1064{
1065 const QList<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
1066 const int count = (last - first) + 1; // it is important to only use the delta, because the change could be nested
1067 for (auto *data : persistent_moved) {
1068 QModelIndex old = data->index;
1069 persistent.indexes.erase(persistent.indexes.constFind(old));
1070 data->index = q_func()->index(old.row(), old.column() + count, parent);
1071 if (data->index.isValid()) {
1072 persistent.insertMultiAtEnd(data->index, data);
1073 } else {
1074 qWarning() << "QAbstractItemModel::endInsertColumns: Invalid index (" << old.row() << ',' << old.column() + count << ") in model" << q_func();
1075 }
1076 }
1077}
1078
1080 int first, int last)
1081{
1082 QList<QPersistentModelIndexData *> persistent_moved;
1083 QList<QPersistentModelIndexData *> persistent_invalidated;
1084 // find the persistent indexes that are affected by the change, either by being in the removed subtree
1085 // or by being on the same level and to the right of the removed columns
1086 for (auto *data : std::as_const(persistent.indexes)) {
1087 bool level_changed = false;
1088 QModelIndex current = data->index;
1089 while (current.isValid()) {
1090 QModelIndex current_parent = current.parent();
1091 if (current_parent == parent) { // on the same level as the change
1092 if (!level_changed && current.column() > last) // right of the removed columns
1093 persistent_moved.append(data);
1094 else if (current.column() <= last && current.column() >= first) // in the removed subtree
1095 persistent_invalidated.append(data);
1096 break;
1097 }
1098 current = current_parent;
1099 level_changed = true;
1100 }
1101 }
1102
1103 persistent.moved.push(persistent_moved);
1104 persistent.invalidated.push(persistent_invalidated);
1105
1106}
1107
1109 int first, int last)
1110{
1111 const QList<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
1112 const int count = (last - first) + 1; // it is important to only use the delta, because the change could be nested
1113 for (auto *data : persistent_moved) {
1114 QModelIndex old = data->index;
1115 persistent.indexes.erase(persistent.indexes.constFind(old));
1116 data->index = q_func()->index(old.row(), old.column() - count, parent);
1117 if (data->index.isValid()) {
1118 persistent.insertMultiAtEnd(data->index, data);
1119 } else {
1120 qWarning() << "QAbstractItemModel::endRemoveColumns: Invalid index (" << old.row() << ',' << old.column() - count << ") in model" << q_func();
1121 }
1122 }
1123 const QList<QPersistentModelIndexData *> persistent_invalidated = persistent.invalidated.pop();
1124 for (auto *data : persistent_invalidated) {
1125 auto index = persistent.indexes.constFind(data->index);
1126 if (index != persistent.indexes.constEnd())
1127 persistent.indexes.erase(index);
1128 data->index = QModelIndex();
1129 }
1130}
1131
1152
1708
1716
1721{
1722 d_func()->invalidatePersistentIndexes();
1723}
1724
1725
1961bool QAbstractItemModel::hasIndex(int row, int column, const QModelIndex &parent) const
1962{
1963 if (row < 0 || column < 0)
1964 return false;
1965 return row < rowCount(parent) && column < columnCount(parent);
1966}
1967
1968
1980{
1981 return (rowCount(parent) > 0) && (columnCount(parent) > 0);
1982}
1983
1999{
2000 return (row == idx.row() && column == idx.column()) ? idx : index(row, column, parent(idx));
2001}
2002
2003
2013QMap<int, QVariant> QAbstractItemModel::itemData(const QModelIndex &index) const
2014{
2015 QMap<int, QVariant> roles;
2016 for (int i = 0; i < Qt::UserRole; ++i) {
2017 QVariant variantData = data(index, i);
2018 if (variantData.isValid())
2019 roles.insert(i, variantData);
2020 }
2021 return roles;
2022}
2023
2038{
2039 Q_UNUSED(index);
2040 Q_UNUSED(value);
2041 Q_UNUSED(role);
2042 return false;
2043}
2044
2055{
2056 Q_UNUSED(index);
2057 return false;
2058}
2059
2082bool QAbstractItemModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles)
2083{
2084 // ### TODO: Consider change the semantics of this function,
2085 // or deprecating/removing it altogether.
2086 //
2087 // For instance, it should try setting *all* the data
2088 // in \a roles, and not bail out at the first setData that returns
2089 // false. It should also have a transactional approach.
2090 for (auto it = roles.begin(), e = roles.end(); it != e; ++it) {
2091 if (!setData(index, it.value(), it.key()))
2092 return false;
2093 }
2094 return true;
2095}
2096
2113{
2115 types << QStringLiteral("application/x-qabstractitemmodeldatalist");
2116 return types;
2117}
2118
2133{
2134 if (indexes.size() <= 0)
2135 return nullptr;
2137 if (types.isEmpty())
2138 return nullptr;
2139 QMimeData *data = new QMimeData();
2140 QString format = types.at(0);
2143 encodeData(indexes, stream);
2144 data->setData(format, encoded);
2145 return data;
2146}
2147
2162 int row, int column,
2163 const QModelIndex &parent) const
2164{
2165 Q_UNUSED(row);
2168
2169 if (!(action & supportedDropActions()))
2170 return false;
2171
2172 const QStringList modelTypes = mimeTypes();
2173 for (int i = 0; i < modelTypes.size(); ++i) {
2174 if (data->hasFormat(modelTypes.at(i)))
2175 return true;
2176 }
2177 return false;
2178}
2179
2210 int row, int column, const QModelIndex &parent)
2211{
2212 // check if the action is supported
2213 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
2214 return false;
2215 // check if the format is supported
2217 if (types.isEmpty())
2218 return false;
2219 QString format = types.at(0);
2220 if (!data->hasFormat(format))
2221 return false;
2222 if (row > rowCount(parent))
2223 row = rowCount(parent);
2224 if (row == -1)
2225 row = rowCount(parent);
2226 if (column == -1)
2227 column = 0;
2228 // decode and insert
2231 return decodeData(row, column, parent, stream);
2232}
2233
2248{
2249 return Qt::CopyAction;
2250}
2251
2264{
2265 return supportedDropActions();
2266}
2267
2295bool QAbstractItemModel::insertRows(int, int, const QModelIndex &)
2296{
2297 return false;
2298}
2299
2324bool QAbstractItemModel::insertColumns(int, int, const QModelIndex &)
2325{
2326 return false;
2327}
2328
2345bool QAbstractItemModel::removeRows(int, int, const QModelIndex &)
2346{
2347 return false;
2348}
2349
2366bool QAbstractItemModel::removeColumns(int, int, const QModelIndex &)
2367{
2368 return false;
2369}
2370
2387bool QAbstractItemModel::moveRows(const QModelIndex &, int , int , const QModelIndex &, int)
2388{
2389 return false;
2390}
2391
2408bool QAbstractItemModel::moveColumns(const QModelIndex &, int , int , const QModelIndex &, int)
2409{
2410 return false;
2411}
2412
2424{
2425 // do nothing
2426}
2427
2440{
2441 return false;
2442}
2443
2454{
2455 Q_D(const QAbstractItemModel);
2456 if (!d->indexValid(index))
2457 return { };
2458
2460}
2461
2467void QAbstractItemModel::sort(int column, Qt::SortOrder order)
2468{
2470 Q_UNUSED(order);
2471 // do nothing
2472}
2473
2484{
2485 return index;
2486}
2487
2510 const QVariant &value, int hits,
2511 Qt::MatchFlags flags) const
2512{
2514 uint matchType = (flags & Qt::MatchTypeMask).toInt();
2516 bool recurse = flags.testAnyFlag(Qt::MatchRecursive);
2517 bool wrap = flags.testAnyFlag(Qt::MatchWrap);
2518 bool allHits = (hits == -1);
2519 QString text; // only convert to a string if it is needed
2520#if QT_CONFIG(regularexpression)
2521 QRegularExpression rx; // only create it if needed
2522#endif
2523 const int column = start.column();
2525 int from = start.row();
2526 int to = rowCount(p);
2527
2528 // iterates twice if wrapping
2529 for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) {
2530 for (int r = from; (r < to) && (allHits || result.size() < hits); ++r) {
2531 QModelIndex idx = index(r, column, p);
2532 if (!idx.isValid())
2533 continue;
2534 QVariant v = data(idx, role);
2535 // QVariant based matching
2536 if (matchType == Qt::MatchExactly) {
2537 if (value == v)
2538 result.append(idx);
2539 } else { // QString or regular expression based matching
2540#if QT_CONFIG(regularexpression)
2541 if (matchType == Qt::MatchRegularExpression) {
2542 if (rx.pattern().isEmpty()) {
2543 if (value.userType() == QMetaType::QRegularExpression) {
2544 rx = value.toRegularExpression();
2545 } else {
2546 rx.setPattern(value.toString());
2547 if (cs == Qt::CaseInsensitive)
2549 }
2550 }
2551 } else if (matchType == Qt::MatchWildcard) {
2552 if (rx.pattern().isEmpty()) {
2554 rx.setPattern(pattern);
2555 }
2556 if (cs == Qt::CaseInsensitive)
2558 } else
2559#endif
2560 {
2561 if (text.isEmpty()) // lazy conversion
2562 text = value.toString();
2563 }
2564
2565 QString t = v.toString();
2566 switch (matchType) {
2567#if QT_CONFIG(regularexpression)
2569 Q_FALLTHROUGH();
2570 case Qt::MatchWildcard:
2571 if (t.contains(rx))
2572 result.append(idx);
2573 break;
2574#endif
2576 if (t.startsWith(text, cs))
2577 result.append(idx);
2578 break;
2579 case Qt::MatchEndsWith:
2580 if (t.endsWith(text, cs))
2581 result.append(idx);
2582 break;
2584 if (t.compare(text, cs) == 0)
2585 result.append(idx);
2586 break;
2587 case Qt::MatchContains:
2588 default:
2589 if (t.contains(text, cs))
2590 result.append(idx);
2591 }
2592 }
2593 if (recurse) {
2594 const auto parent = column != 0 ? idx.sibling(idx.row(), 0) : idx;
2595 if (hasChildren(parent)) { // search the hierarchy
2596 result += match(index(0, column, parent), role,
2597 (text.isEmpty() ? value : text),
2598 (allHits ? -1 : hits - result.size()), flags);
2599 }
2600 }
2601 }
2602 // prepare for the next iteration
2603 from = 0;
2604 to = start.row();
2605 }
2606 return result;
2607}
2608
2616{
2617 return QSize(1, 1);
2618}
2619
2651QHash<int,QByteArray> QAbstractItemModel::roleNames() const
2652{
2654}
2655
2666{
2667 return true;
2668}
2669
2678{
2679 // do nothing
2680}
2681
2693QVariant QAbstractItemModel::headerData(int section, Qt::Orientation orientation, int role) const
2694{
2695 Q_UNUSED(orientation);
2696 if (role == Qt::DisplayRole)
2697 return section + 1;
2698 return QVariant();
2699}
2700
2714 const QVariant &value, int role)
2715{
2716 Q_UNUSED(section);
2717 Q_UNUSED(orientation);
2718 Q_UNUSED(value);
2719 Q_UNUSED(role);
2720 return false;
2721}
2722
2753{
2754 for (const auto &index : indexes)
2755 stream << index.row() << index.column() << itemData(index);
2756}
2757
2763{
2764 int top = INT_MAX;
2765 int left = INT_MAX;
2766 int bottom = 0;
2767 int right = 0;
2768 QList<int> rows, columns;
2769 QList<QMap<int, QVariant>> data;
2770
2771 while (!stream.atEnd()) {
2772 int r, c;
2773 QMap<int, QVariant> v;
2774 stream >> r >> c >> v;
2775 rows.append(r);
2776 columns.append(c);
2777 data.append(v);
2778 top = qMin(r, top);
2779 left = qMin(c, left);
2780 bottom = qMax(r, bottom);
2781 right = qMax(c, right);
2782 }
2783
2784 // insert the dragged items into the table, use a bit array to avoid overwriting items,
2785 // since items from different tables can have the same row and column
2786 int dragRowCount = 0;
2787 int dragColumnCount = right - left + 1;
2788
2789 // Compute the number of continuous rows upon insertion and modify the rows to match
2790 QList<int> rowsToInsert(bottom + 1);
2791 for (int i = 0; i < rows.size(); ++i)
2792 rowsToInsert[rows.at(i)] = 1;
2793 for (int i = 0; i < rowsToInsert.size(); ++i) {
2794 if (rowsToInsert.at(i) == 1){
2795 rowsToInsert[i] = dragRowCount;
2796 ++dragRowCount;
2797 }
2798 }
2799 for (int i = 0; i < rows.size(); ++i)
2800 rows[i] = top + rowsToInsert.at(rows.at(i));
2801
2802 QBitArray isWrittenTo(dragRowCount * dragColumnCount);
2803
2804 // make space in the table for the dropped data
2805 int colCount = columnCount(parent);
2806 if (colCount == 0) {
2807 insertColumns(colCount, dragColumnCount - colCount, parent);
2808 colCount = columnCount(parent);
2809 }
2810 insertRows(row, dragRowCount, parent);
2811
2812 row = qMax(0, row);
2813 column = qMax(0, column);
2814
2815 QList<QPersistentModelIndex> newIndexes(data.size());
2816 // set the data in the table
2817 for (int j = 0; j < data.size(); ++j) {
2818 int relativeRow = rows.at(j) - top;
2819 int relativeColumn = columns.at(j) - left;
2820 int destinationRow = relativeRow + row;
2821 int destinationColumn = relativeColumn + column;
2822 int flat = (relativeRow * dragColumnCount) + relativeColumn;
2823 // if the item was already written to, or we just can't fit it in the table, create a new row
2824 if (destinationColumn >= colCount || isWrittenTo.testBit(flat)) {
2825 destinationColumn = qBound(column, destinationColumn, colCount - 1);
2826 destinationRow = row + dragRowCount;
2827 insertRows(row + dragRowCount, 1, parent);
2828 flat = (dragRowCount * dragColumnCount) + relativeColumn;
2829 isWrittenTo.resize(++dragRowCount * dragColumnCount);
2830 }
2831 if (!isWrittenTo.testBit(flat)) {
2832 newIndexes[j] = index(destinationRow, destinationColumn, parent);
2833 isWrittenTo.setBit(flat);
2834 }
2835 }
2836
2837 for(int k = 0; k < newIndexes.size(); k++) {
2838 if (newIndexes.at(k).isValid())
2839 setItemData(newIndexes.at(k), data.at(k));
2840 }
2841
2842 return true;
2843}
2844
2886{
2887 Q_ASSERT(first >= 0);
2888 Q_ASSERT(first <= rowCount(parent)); // == is allowed, to insert at the end
2889 Q_ASSERT(last >= first);
2890 Q_D(QAbstractItemModel);
2891 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
2892 emit rowsAboutToBeInserted(parent, first, last, QPrivateSignal());
2893 d->rowsAboutToBeInserted(parent, first, last);
2894}
2895
2905{
2906 Q_D(QAbstractItemModel);
2907 QAbstractItemModelPrivate::Change change = d->changes.pop();
2908 d->rowsInserted(change.parent, change.first, change.last);
2909 emit rowsInserted(change.parent, change.first, change.last, QPrivateSignal());
2910}
2911
2941{
2942 Q_ASSERT(first >= 0);
2943 Q_ASSERT(last >= first);
2944 Q_ASSERT(last < rowCount(parent));
2945 Q_D(QAbstractItemModel);
2946 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
2947 emit rowsAboutToBeRemoved(parent, first, last, QPrivateSignal());
2948 d->rowsAboutToBeRemoved(parent, first, last);
2949}
2950
2960{
2961 Q_D(QAbstractItemModel);
2962 QAbstractItemModelPrivate::Change change = d->changes.pop();
2963 d->rowsRemoved(change.parent, change.first, change.last);
2964 emit rowsRemoved(change.parent, change.first, change.last, QPrivateSignal());
2965}
2966
2975bool QAbstractItemModelPrivate::allowMove(const QModelIndex &srcParent, int start, int end, const QModelIndex &destinationParent, int destinationStart, Qt::Orientation orientation)
2976{
2977 // Don't move the range within itself.
2978 if (destinationParent == srcParent)
2979 return !(destinationStart >= start && destinationStart <= end + 1);
2980
2981 QModelIndex destinationAncestor = destinationParent;
2982 int pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
2983 forever {
2984 if (destinationAncestor == srcParent) {
2985 if (pos >= start && pos <= end)
2986 return false;
2987 break;
2988 }
2989
2990 if (!destinationAncestor.isValid())
2991 break;
2992
2993 pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
2994 destinationAncestor = destinationAncestor.parent();
2995 }
2996
2997 return true;
2998}
2999
3006
3097bool QAbstractItemModel::beginMoveRows(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild)
3098{
3099 Q_ASSERT(sourceFirst >= 0);
3100 Q_ASSERT(sourceLast >= sourceFirst);
3102 Q_D(QAbstractItemModel);
3103
3104 if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical)) {
3105 return false;
3106 }
3107
3108 QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
3109 sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
3110 d->changes.push(sourceChange);
3111 int destinationLast = destinationChild + (sourceLast - sourceFirst);
3112 QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
3113 destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
3114 d->changes.push(destinationChange);
3115
3116 emit rowsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
3117 d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical);
3118 return true;
3119}
3120
3133{
3134 Q_D(QAbstractItemModel);
3135
3136 QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
3137 QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
3138
3139 QModelIndex adjustedSource = removeChange.parent;
3140 QModelIndex adjustedDestination = insertChange.parent;
3141
3142 const int numMoved = removeChange.last - removeChange.first + 1;
3143 if (insertChange.needsAdjust)
3144 adjustedDestination = createIndex(adjustedDestination.row() - numMoved, adjustedDestination.column(), adjustedDestination.internalPointer());
3145
3146 if (removeChange.needsAdjust)
3147 adjustedSource = createIndex(adjustedSource.row() + numMoved, adjustedSource.column(), adjustedSource.internalPointer());
3148
3149 d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Vertical);
3150
3151 emit rowsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
3152}
3153
3196{
3197 Q_ASSERT(first >= 0);
3198 Q_ASSERT(first <= columnCount(parent)); // == is allowed, to insert at the end
3199 Q_ASSERT(last >= first);
3200 Q_D(QAbstractItemModel);
3201 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3202 emit columnsAboutToBeInserted(parent, first, last, QPrivateSignal());
3203 d->columnsAboutToBeInserted(parent, first, last);
3204}
3205
3216{
3217 Q_D(QAbstractItemModel);
3218 QAbstractItemModelPrivate::Change change = d->changes.pop();
3219 d->columnsInserted(change.parent, change.first, change.last);
3220 emit columnsInserted(change.parent, change.first, change.last, QPrivateSignal());
3221}
3222
3252{
3253 Q_ASSERT(first >= 0);
3254 Q_ASSERT(last >= first);
3255 Q_ASSERT(last < columnCount(parent));
3256 Q_D(QAbstractItemModel);
3257 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3258 emit columnsAboutToBeRemoved(parent, first, last, QPrivateSignal());
3259 d->columnsAboutToBeRemoved(parent, first, last);
3260}
3261
3271{
3272 Q_D(QAbstractItemModel);
3273 QAbstractItemModelPrivate::Change change = d->changes.pop();
3274 d->columnsRemoved(change.parent, change.first, change.last);
3275 emit columnsRemoved(change.parent, change.first, change.last, QPrivateSignal());
3276}
3277
3316bool QAbstractItemModel::beginMoveColumns(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild)
3317{
3318 Q_ASSERT(sourceFirst >= 0);
3319 Q_ASSERT(sourceLast >= sourceFirst);
3321 Q_D(QAbstractItemModel);
3322
3323 if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal)) {
3324 return false;
3325 }
3326
3327 QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
3328 sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
3329 d->changes.push(sourceChange);
3330 int destinationLast = destinationChild + (sourceLast - sourceFirst);
3331 QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
3332 destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
3333 d->changes.push(destinationChange);
3334
3335 emit columnsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
3336 d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal);
3337 return true;
3338}
3339
3352{
3353 Q_D(QAbstractItemModel);
3354
3355 QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
3356 QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
3357
3358 QModelIndex adjustedSource = removeChange.parent;
3359 QModelIndex adjustedDestination = insertChange.parent;
3360
3361 const int numMoved = removeChange.last - removeChange.first + 1;
3362 if (insertChange.needsAdjust)
3363 adjustedDestination = createIndex(adjustedDestination.row(), adjustedDestination.column() - numMoved, adjustedDestination.internalPointer());
3364
3365 if (removeChange.needsAdjust)
3366 adjustedSource = createIndex(adjustedSource.row(), adjustedSource.column() + numMoved, adjustedSource.internalPointer());
3367
3368 d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Horizontal);
3369 emit columnsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
3370}
3371
3396{
3397 emit modelAboutToBeReset(QPrivateSignal());
3398}
3399
3412{
3413 Q_D(QAbstractItemModel);
3414 d->invalidatePersistentIndexes();
3416 emit modelReset(QPrivateSignal());
3417}
3418
3429{
3430 Q_D(QAbstractItemModel);
3431 if (d->persistent.indexes.isEmpty())
3432 return;
3433 // find the data and reinsert it sorted
3434 const auto it = d->persistent.indexes.constFind(from);
3435 if (it != d->persistent.indexes.cend()) {
3437 d->persistent.indexes.erase(it);
3438 data->index = to;
3439 if (to.isValid())
3440 d->persistent.insertMultiAtEnd(to, data);
3441 }
3442}
3443
3456 const QModelIndexList &to)
3457{
3458 Q_D(QAbstractItemModel);
3459 if (d->persistent.indexes.isEmpty())
3460 return;
3461 QList<QPersistentModelIndexData *> toBeReinserted;
3462 toBeReinserted.reserve(to.size());
3463 for (int i = 0; i < from.size(); ++i) {
3464 if (from.at(i) == to.at(i))
3465 continue;
3466 const auto it = d->persistent.indexes.constFind(from.at(i));
3467 if (it != d->persistent.indexes.cend()) {
3469 d->persistent.indexes.erase(it);
3470 data->index = to.at(i);
3471 if (data->index.isValid())
3472 toBeReinserted << data;
3473 }
3474 }
3475
3476 for (auto *data : std::as_const(toBeReinserted))
3477 d->persistent.insertMultiAtEnd(data->index, data);
3478}
3479
3486{
3487 Q_D(const QAbstractItemModel);
3489 result.reserve(d->persistent.indexes.size());
3490 for (auto *data : std::as_const(d->persistent.indexes))
3491 result.append(data->index);
3492 return result;
3493}
3494
3569bool QAbstractItemModel::checkIndex(const QModelIndex &index, CheckIndexOptions options) const
3570{
3571 if (!index.isValid()) {
3572 if (options & CheckIndexOption::IndexIsValid) {
3573 qCWarning(lcCheckIndex) << "Index" << index << "is not valid (expected valid)";
3574 return false;
3575 }
3576 return true;
3577 }
3578
3579 if (index.model() != this) {
3580 qCWarning(lcCheckIndex) << "Index" << index
3581 << "is for model" << index.model()
3582 << "which is different from this model" << this;
3583 return false;
3584 }
3585
3586 if (index.row() < 0) {
3587 qCWarning(lcCheckIndex) << "Index" << index
3588 << "has negative row" << index.row();
3589 return false;
3590 }
3591
3592 if (index.column() < 0) {
3593 qCWarning(lcCheckIndex) << "Index" << index
3594 << "has negative column" << index.column();
3595 return false;
3596 }
3597
3598 if (!(options & CheckIndexOption::DoNotUseParent)) {
3599 const QModelIndex parentIndex = index.parent();
3600 if (options & CheckIndexOption::ParentIsInvalid) {
3601 if (parentIndex.isValid()) {
3602 qCWarning(lcCheckIndex) << "Index" << index
3603 << "has valid parent" << parentIndex
3604 << "(expected an invalid parent)";
3605 return false;
3606 }
3607 }
3608
3609 const int rc = rowCount(parentIndex);
3610 if (index.row() >= rc) {
3611 qCWarning(lcCheckIndex) << "Index" << index
3612 << "has out of range row" << index.row()
3613 << "rowCount() is" << rc;
3614 return false;
3615 }
3616
3617 const int cc = columnCount(parentIndex);
3618 if (index.column() >= cc) {
3619 qCWarning(lcCheckIndex) << "Index" << index
3620 << "has out of range column" << index.column()
3621 << "columnCount() is" << cc;
3622 return false;
3623
3624 }
3625 }
3626
3627 return true;
3628}
3629
3678{
3680
3681 for (QModelRoleData &d : roleDataSpan)
3682 d.setData(data(index, d.role()));
3683}
3684
3756
3768
3777
3787{
3789}
3790
3800{
3801 return QModelIndex();
3802}
3803
3808{
3809 return index(row, column);
3810}
3811
3813{
3814 if (!parent.isValid())
3815 return rowCount(parent) > 0 && columnCount(parent) > 0;
3816 return false;
3817}
3818
3823{
3824 Qt::ItemFlags f = QAbstractItemModel::flags(index);
3825 if (index.isValid())
3827 return f;
3828}
3829
3907
3919
3928
3938{
3940}
3941
3949{
3950 return QModelIndex();
3951}
3952
3957{
3958 return index(row, column);
3959}
3960
3965{
3966 Qt::ItemFlags f = QAbstractItemModel::flags(index);
3967 if (index.isValid())
3969 return f;
3970}
3971
3981{
3982 return parent.isValid() ? 0 : 1;
3983}
3984
3986{
3987 return parent.isValid() ? false : (rowCount() > 0);
3988}
3989
4001 int row, int column, const QModelIndex &parent)
4002{
4003 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
4004 return false;
4005
4007 if (types.isEmpty())
4008 return false;
4009 QString format = types.at(0);
4010 if (!data->hasFormat(format))
4011 return false;
4012
4015
4016 // if the drop is on an item, replace the data in the items
4017 if (parent.isValid() && row == -1 && column == -1) {
4018 int top = INT_MAX;
4019 int left = INT_MAX;
4020 QList<int> rows, columns;
4021 QList<QMap<int, QVariant>> data;
4022
4023 while (!stream.atEnd()) {
4024 int r, c;
4025 QMap<int, QVariant> v;
4026 stream >> r >> c >> v;
4027 rows.append(r);
4028 columns.append(c);
4029 data.append(v);
4030 top = qMin(r, top);
4031 left = qMin(c, left);
4032 }
4033
4034 for (int i = 0; i < data.size(); ++i) {
4035 int r = (rows.at(i) - top) + parent.row();
4036 int c = (columns.at(i) - left) + parent.column();
4037 if (hasIndex(r, c))
4038 setItemData(index(r, c), data.at(i));
4039 }
4040
4041 return true;
4042 }
4043
4044 // otherwise insert new rows for the data
4045 return decodeData(row, column, parent, stream);
4046}
4047
4052 int row, int column, const QModelIndex &parent)
4053{
4054 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
4055 return false;
4056
4058 if (types.isEmpty())
4059 return false;
4060 QString format = types.at(0);
4061 if (!data->hasFormat(format))
4062 return false;
4063
4066
4067 // if the drop is on an item, replace the data in the items
4068 if (parent.isValid() && row == -1 && column == -1) {
4069 int top = INT_MAX;
4070 int left = INT_MAX;
4071 QList<int> rows, columns;
4072 QList<QMap<int, QVariant>> data;
4073
4074 while (!stream.atEnd()) {
4075 int r, c;
4076 QMap<int, QVariant> v;
4077 stream >> r >> c >> v;
4078 rows.append(r);
4079 columns.append(c);
4080 data.append(v);
4081 top = qMin(r, top);
4082 left = qMin(c, left);
4083 }
4084
4085 for (int i = 0; i < data.size(); ++i) {
4086 int r = (rows.at(i) - top) + parent.row();
4087 if (columns.at(i) == left && hasIndex(r, 0))
4088 setItemData(index(r), data.at(i));
4089 }
4090
4091 return true;
4092 }
4093
4094 if (row == -1)
4095 row = rowCount(parent);
4096
4097 // otherwise insert new rows for the data
4098 return decodeData(row, column, parent, stream);
4099}
4100
4159{
4160 auto newIt = indexes.insert(key, data);
4161 auto it = newIt;
4162 ++it;
4163 while (it != indexes.end() && it.key() == key) {
4164 qSwap(*newIt,*it);
4165 newIt = it;
4166 ++it;
4167 }
4168}
4169
4171
4172#include "moc_qabstractitemmodel.cpp"
4173#include "qabstractitemmodel.moc"
void itemsAboutToBeMoved(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation)
void rowsRemoved(const QModelIndex &parent, int first, int last)
static bool variantLessThan(const QVariant &v1, const QVariant &v2)
void columnsInserted(const QModelIndex &parent, int first, int last)
static const QHash< int, QByteArray > & defaultRoleNames()
void removePersistentIndexData(QPersistentModelIndexData *data)
void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
void itemsMoved(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation)
static QAbstractItemModel * staticEmptyModel()
virtual void executePendingOperations() const
void movePersistentIndexes(const QList< QPersistentModelIndexData * > &indexes, int change, const QModelIndex &parent, Qt::Orientation orientation)
void columnsRemoved(const QModelIndex &parent, int first, int last)
struct QAbstractItemModelPrivate::Persistent persistent
bool allowMove(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation)
Returns whether a move operation is valid.
void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
void invalidatePersistentIndex(const QModelIndex &index)
void rowsInserted(const QModelIndex &parent, int first, int last)
void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last)
static bool isVariantLessThan(const QVariant &left, const QVariant &right, Qt::CaseSensitivity cs=Qt::CaseSensitive, bool isLocaleAware=false)
void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last)
virtual ~QAbstractItemModel()
Destroys the abstract item model.
virtual Qt::DropActions supportedDropActions() const
void rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow, QPrivateSignal)
Q_INVOKABLE int const QModelIndex & parent
Returns the parent of the model item with the given index.
void endResetModel()
Completes a model reset operation.
void modelAboutToBeReset(QPrivateSignal)
virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const
Returns {true} if a model can accept a drop of the data.
bool beginMoveRows(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationRow)
virtual Q_INVOKABLE QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits=1, Qt::MatchFlags flags=Qt::MatchFlags(Qt::MatchStartsWith|Qt::MatchWrap)) const
Returns a list of indexes for the items in the column of the start index where data stored under the ...
void endMoveColumns()
Ends a column move operation.
void columnsRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted after columns have been removed from the model.
void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted just before rows are inserted into the model.
virtual Q_INVOKABLE QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const
Returns the data for the given role and section in the header with the specified orientation.
void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted just before columns are inserted into the model.
Q_INVOKABLE bool hasIndex(int row, int column, const QModelIndex &parent=QModelIndex()) const
Returns {true} if the model returns a valid QModelIndex for row and column with parent,...
virtual Q_INVOKABLE Qt::ItemFlags flags(const QModelIndex &index) const
Returns the item flags for the given index.
void modelReset(QPrivateSignal)
void endRemoveRows()
Ends a row removal operation.
QModelIndexList persistentIndexList() const
virtual void resetInternalData()
void endMoveRows()
Ends a row move operation.
void beginRemoveColumns(const QModelIndex &parent, int first, int last)
Begins a column removal operation.
Q_INVOKABLE int int const QModelIndex & destinationParent
void changePersistentIndex(const QModelIndex &from, const QModelIndex &to)
Changes the QPersistentModelIndex that is equal to the given from model index to the given to model i...
void changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to)
virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
Handles the data supplied by a drag and drop operation that ended with the given action.
virtual Q_INVOKABLE bool hasChildren(const QModelIndex &parent=QModelIndex()) const
Returns {true} if parent has any children; otherwise returns {false}.
virtual Q_INVOKABLE int rowCount(const QModelIndex &parent=QModelIndex()) const =0
Returns the number of rows under the given parent.
void columnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn, QPrivateSignal)
virtual Q_INVOKABLE void fetchMore(const QModelIndex &parent)
Fetches any available data for the items with the parent specified by the parent index.
void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted just before columns are removed from the model.
virtual bool clearItemData(const QModelIndex &index)
virtual QMimeData * mimeData(const QModelIndexList &indexes) const
Returns an object that contains serialized items of data corresponding to the list of indexes specifi...
Q_INVOKABLE int int const QModelIndex int destinationChild
virtual QModelIndex buddy(const QModelIndex &index) const
Returns a model index for the buddy of the item represented by index.
bool checkIndex(const QModelIndex &index, CheckIndexOptions options=CheckIndexOption::NoOption) const
virtual Q_INVOKABLE bool canFetchMore(const QModelIndex &parent) const
Returns {true} if there is more data available for parent; otherwise returns {false}.
virtual void revert()
Lets the model know that it should discard cached information.
virtual Q_INVOKABLE bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole)
Sets the role data for the item at index to value.
virtual Q_INVOKABLE QModelIndex sibling(int row, int column, const QModelIndex &idx) const
Returns the sibling at row and column for the item at index, or an invalid QModelIndex if there is no...
void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted just before rows are removed from the model.
bool beginMoveColumns(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationColumn)
Begins a column move operation.
virtual QHash< int, QByteArray > roleNames() const
void beginInsertColumns(const QModelIndex &parent, int first, int last)
Begins a column insertion operation.
void endInsertRows()
Ends a row insertion operation.
void beginResetModel()
Begins a model reset operation.
void encodeData(const QModelIndexList &indexes, QDataStream &stream) const
virtual QMap< int, QVariant > itemData(const QModelIndex &index) const
Returns a map with values for all predefined roles in the model for the item at the given index.
virtual bool setItemData(const QModelIndex &index, const QMap< int, QVariant > &roles)
Sets the role data for the item at index to the associated value in roles, for every Qt::ItemDataRole...
virtual Qt::DropActions supportedDragActions() const
Returns the actions supported by the data in this model.
void endRemoveColumns()
Ends a column removal operation.
void rowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow, QPrivateSignal)
virtual Q_INVOKABLE int columnCount(const QModelIndex &parent=QModelIndex()) const =0
Returns the number of columns for the children of the given parent.
void rowsInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted after rows have been inserted into the model.
virtual QStringList mimeTypes() const
Returns the list of allowed MIME types.
void columnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn, QPrivateSignal)
bool decodeData(int row, int column, const QModelIndex &parent, QDataStream &stream)
QAbstractItemModel(QObject *parent=nullptr)
Constructs an abstract item model with the given parent.
QModelIndex createIndex(int row, int column, const void *data=nullptr) const
Creates a model index for the given row and column with the internal pointer ptr.
void endInsertColumns()
Ends a column insertion operation.
void columnsInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted after columns have been inserted into the model.
virtual QSize span(const QModelIndex &index) const
Returns the row and column span of the item represented by index.
virtual void multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const
void beginRemoveRows(const QModelIndex &parent, int first, int last)
Begins a row removal operation.
void beginInsertRows(const QModelIndex &parent, int first, int last)
Begins a row insertion operation.
void rowsRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted after rows have been removed from the model.
virtual bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role=Qt::EditRole)
Sets the data for the given role and section in the header with the specified orientation to the valu...
virtual bool submit()
Lets the model know that it should submit cached information to permanent storage.
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
\reimp
Qt::ItemFlags flags(const QModelIndex &index) const override
\reimp
QModelIndex index(int row, int column=0, const QModelIndex &parent=QModelIndex()) const override
Returns the index of the data in row and column with parent.
QModelIndex sibling(int row, int column, const QModelIndex &idx) const override
\reimp
~QAbstractListModel()
Destroys the abstract list model.
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
int columnCount(const QModelIndex &parent) const override
QAbstractListModel(QObject *parent=nullptr)
Constructs an abstract list model with the given parent.
bool hasChildren(const QModelIndex &parent) const override
Returns {true} if parent has any children; otherwise returns {false}.
bool hasChildren(const QModelIndex &parent) const override
Returns {true} if parent has any children; otherwise returns {false}.
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
\reimp
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Returns the index of the data in row and column with parent.
QAbstractTableModel(QObject *parent=nullptr)
Constructs an abstract table model for the given parent.
QModelIndex sibling(int row, int column, const QModelIndex &idx) const override
\reimp
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
~QAbstractTableModel()
Destroys the abstract table model.
Qt::ItemFlags flags(const QModelIndex &index) const override
\reimp
bool ref() noexcept
bool deref() noexcept
\inmodule QtCore
Definition qbitarray.h:13
\inmodule QtCore
Definition qbytearray.h:57
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
Definition qbytearray.h:611
\inmodule QtCore\reentrant
Definition qdatastream.h:46
\inmodule QtCore
\inmodule QtCore
int columnCount(const QModelIndex &) const override
Returns the number of columns for the children of the given parent.
QEmptyItemModel(QObject *parent=nullptr)
bool hasChildren(const QModelIndex &) const override
Returns {true} if parent has any children; otherwise returns {false}.
QModelIndex index(int, int, const QModelIndex &) const override
Returns the index of the item in the model specified by the given row, column and parent index.
int rowCount(const QModelIndex &) const override
Returns the number of rows under the given parent.
QVariant data(const QModelIndex &, int) const override
Returns the data stored under the given role for the item referred to by the index.
QModelIndex parent(const QModelIndex &) const override
qsizetype size() const noexcept
Definition qlist.h:397
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
void reserve(qsizetype size)
Definition qlist.h:753
\inmodule QtCore
Definition qmimedata.h:16
\inmodule QtCore
QVariant data(int role=Qt::DisplayRole) const
Returns the data for the given role for the item referred to by the index.
constexpr int row() const noexcept
Returns the row this model index refers to.
QModelIndex parent() const
Returns the parent of the model index, or QModelIndex() if it has no parent.
constexpr const QAbstractItemModel * model() const noexcept
Returns a pointer to the model containing the item that this index refers to.
Qt::ItemFlags flags() const
constexpr int column() const noexcept
Returns the column this model index refers to.
void * internalPointer() const noexcept
Returns a {void} {*} pointer used by the model to associate the index with the internal data structur...
constexpr bool isValid() const noexcept
Returns {true} if this model index is valid; otherwise returns {false}.
void multiData(QModelRoleDataSpan roleDataSpan) const
QModelIndex sibling(int row, int column) const
Returns the sibling at row and column.
const void * constInternalPointer() const noexcept
Returns a {const void} {*} pointer used by the model to associate the index with the internal data st...
constexpr quintptr internalId() const noexcept
Returns a {quintptr} used by the model to associate the index with the internal data structure.
\inmodule QtCore
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:2034
iterator end() noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
Definition qhash.h:1922
QObject * parent
Definition qobject.h:73
\inmodule QtCore
Definition qobject.h:103
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
static void destroy(QPersistentModelIndexData *data)
static QPersistentModelIndexData * create(const QModelIndex &index)
bool operator==(const QPersistentModelIndex &other) const noexcept
Returns {true} if this persistent model index is equal to the other persistent model index; otherwise...
const QAbstractItemModel * model() const
Returns the model that the index belongs to.
bool isValid() const
Returns {true} if this persistent model index is valid; otherwise returns {false}.
Qt::ItemFlags flags() const
QVariant data(int role=Qt::DisplayRole) const
Returns the data for the given role for the item referred to by the index.
bool operator!=(const QPersistentModelIndex &other) const noexcept
QModelIndex sibling(int row, int column) const
Returns the sibling at row and column or an invalid QModelIndex if there is no sibling at this positi...
QPersistentModelIndex & operator=(const QPersistentModelIndex &other)
Sets the persistent model index to refer to the same item in a model as the other persistent model in...
bool operator<(const QPersistentModelIndex &other) const noexcept
QModelIndex parent() const
Returns the parent QModelIndex for this persistent index, or an invalid QModelIndex if it has no pare...
const void * constInternalPointer() const
int column() const
Returns the column this persistent model index refers to.
void multiData(QModelRoleDataSpan roleDataSpan) const
Populates the given roleDataSpan for the item referred to by the index.
int row() const
Returns the row this persistent model index refers to.
\inmodule QtCore \reentrant
static QString wildcardToRegularExpression(const QString &str, WildcardConversionOptions options=DefaultWildcardConversion)
const_iterator cend() const noexcept
Definition qset.h:142
iterator erase(const_iterator i)
Definition qset.h:145
const_iterator constFind(const T &value) const
Definition qset.h:161
\inmodule QtCore
Definition qsize.h:25
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1226
\inmodule QtCore
Definition qvariant.h:65
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:714
QString text
QSet< QString >::iterator it
Combined button and popup list for selecting options.
Orientation
Definition qnamespace.h:98
@ Horizontal
Definition qnamespace.h:99
@ Vertical
Definition qnamespace.h:100
@ WhatsThisRole
@ UserRole
@ DecorationRole
@ EditRole
@ StatusTipRole
@ ToolTipRole
@ DisplayRole
SortOrder
Definition qnamespace.h:121
CaseSensitivity
@ CaseInsensitive
@ CaseSensitive
DropAction
@ CopyAction
@ MoveAction
@ ItemNeverHasChildren
@ ItemIsSelectable
@ ItemIsEnabled
@ MatchTypeMask
@ MatchWildcard
@ MatchRecursive
@ MatchCaseSensitive
@ MatchExactly
@ MatchFixedString
@ MatchRegularExpression
@ MatchEndsWith
@ MatchWrap
@ MatchContains
@ MatchStartsWith
static uint typeOfVariant(const QVariant &value)
QDebug operator<<(QDebug dbg, const QModelIndex &idx)
#define Q_FALLTHROUGH()
EGLStreamKHR stream
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define forever
Definition qforeach.h:78
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qWarning
Definition qlogging.h:166
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define QT_IMPL_METATYPE_EXTERN(TYPE)
Definition qmetatype.h:1390
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLint GLfloat GLfloat GLfloat v2
GLsizei const GLfloat * v
[13]
GLuint64 key
GLuint index
[2]
GLboolean r
[2]
GLuint GLuint end
GLsizei GLenum GLenum * types
GLdouble GLdouble GLdouble GLdouble top
GLenum GLenum GLsizei count
GLdouble GLdouble right
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat f
GLint left
GLint GLint bottom
GLbitfield flags
GLint GLfloat GLfloat v1
GLuint start
GLint first
GLint GLsizei GLsizei GLenum format
GLenum GLenum GLsizei void GLsizei void * column
const GLubyte * c
GLdouble GLdouble t
Definition qopenglext.h:243
GLenum GLenum GLsizei void * row
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLfixed GLfixed GLint GLint order
GLubyte * pattern
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
static QT_BEGIN_NAMESPACE QAsn1Element wrap(quint8 type, const QAsn1Element &child)
#define QStringLiteral(str)
QT_BEGIN_NAMESPACE constexpr void qSwap(T &value1, T &value2) noexcept(std::is_nothrow_swappable_v< T >)
Definition qswap.h:20
#define Q_OBJECT
#define emit
#define Q_UNUSED(x)
size_t quintptr
Definition qtypes.h:167
unsigned int uint
Definition qtypes.h:34
static int toInt(const QChar &qc, int R)
QSqlQueryModel * model
[16]
QObject::connect nullptr
p rx()++
QSharedPointer< T > other(t)
[5]
view create()
void insertMultiAtEnd(const QModelIndex &key, QPersistentModelIndexData *data)
QMultiHash< QModelIndex, QPersistentModelIndexData * > indexes