Qt 6.x
The Qt SDK
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 <limits.h>
23
25
26Q_LOGGING_CATEGORY(lcCheckIndex, "qt.core.qabstractitemmodel.checkindex")
27
29
31{
32 Q_ASSERT(index.isValid()); // we will _never_ insert an invalid index in the list
34 QAbstractItemModel *model = const_cast<QAbstractItemModel *>(index.model());
35 QMultiHash<QModelIndex, QPersistentModelIndexData *> &indexes = model->d_func()->persistent.indexes;
36 const auto it = indexes.constFind(index);
37 if (it != indexes.cend()) {
38 d = (*it);
39 } else {
41 indexes.insert(index, d);
42 }
43 Q_ASSERT(d);
44 return d;
45}
46
48{
50 Q_ASSERT(data->ref.loadRelaxed() == 0);
51 QAbstractItemModel *model = const_cast<QAbstractItemModel *>(data->index.model());
52 // a valid persistent model index with a null model pointer can only happen if the model was destroyed
53 if (model) {
55 Q_ASSERT(p);
56 p->removePersistentIndexData(data);
57 }
58 delete data;
59}
60
331 : d(nullptr)
332{
333}
334
343 : d(other.d)
344{
345 if (d) d->ref.ref();
346}
347
353 : d(nullptr)
354{
355 if (index.isValid()) {
357 d->ref.ref();
358 }
359}
360
368{
369 if (d && !d->ref.deref()) {
371 d = nullptr;
372 }
373}
374
384{
385 if (d && other.d)
386 return d->index == other.d->index;
387 return d == other.d;
388}
389
401{
402 if (d && other.d)
403 return d->index < other.d->index;
404
405 return d < other.d;
406}
407
422{
423 if (d == other.d)
424 return *this;
425 if (d && !d->ref.deref())
427 d = other.d;
428 if (d) d->ref.ref();
429 return *this;
430}
445{
446 if (d && !d->ref.deref())
448 if (other.isValid()) {
450 if (d) d->ref.ref();
451 } else {
452 d = nullptr;
453 }
454 return *this;
455}
456
463QPersistentModelIndex::operator QModelIndex() const
464{
465 if (d)
466 return d->index;
467 return QModelIndex();
468}
469
479{
480 if (d)
481 return d->index == other;
482 return !other.isValid();
483}
484
493{
494 if (d)
495 return d->index != other;
496 return other.isValid();
497}
498
506{
507 if (d)
508 return d->index.row();
509 return -1;
510}
511
519{
520 if (d)
521 return d->index.column();
522 return -1;
523}
524
535{
536 if (d)
537 return d->index.internalPointer();
538 return nullptr;
539}
540
551{
552 if (d)
553 return d->index.constInternalPointer();
554 return nullptr;
555}
556
567{
568 if (d)
569 return d->index.internalId();
570 return 0;
571}
572
580{
581 if (d)
582 return d->index.parent();
583 return QModelIndex();
584}
585
594{
595 if (d)
596 return d->index.sibling(row, column);
597 return QModelIndex();
598}
599
607{
608 if (d)
609 return d->index.data(role);
610 return QVariant();
611}
612
613
622{
623 if (d)
624 d->index.multiData(roleDataSpan);
625}
626
632Qt::ItemFlags QPersistentModelIndex::flags() const
633{
634 if (d)
635 return d->index.flags();
636 return { };
637}
638
643{
644 if (d)
645 return d->index.model();
646 return nullptr;
647}
648
662{
663 return d && d->index.isValid();
664}
665
666#ifndef QT_NO_DEBUG_STREAM
668{
669 QDebugStateSaver saver(dbg);
670 dbg.nospace() << "QModelIndex(" << idx.row() << ',' << idx.column()
671 << ',' << idx.internalPointer() << ',' << idx.model() << ')';
672 return dbg;
673}
674
676{
677 if (idx.d)
678 dbg << idx.d->index;
679 else
680 dbg << QModelIndex();
681 return dbg;
682}
683#endif
684
686{
687public:
689 QModelIndex index(int, int, const QModelIndex &) const override { return QModelIndex(); }
690 QModelIndex parent(const QModelIndex &) const override { return QModelIndex(); }
691 int rowCount(const QModelIndex &) const override { return 0; }
692 int columnCount(const QModelIndex &) const override { return 0; }
693 bool hasChildren(const QModelIndex &) const override { return false; }
694 QVariant data(const QModelIndex &, int) const override { return QVariant(); }
695};
696
698
699
702{
703}
704
706{
707}
708
710{
711 return qEmptyModel();
712}
713
715{
716 for (QPersistentModelIndexData *data : std::as_const(persistent.indexes))
717 data->index = QModelIndex();
719}
720
727 const auto it = persistent.indexes.constFind(index);
728 if (it != persistent.indexes.cend()) {
731 data->index = QModelIndex();
732 }
733}
734
737 {
738 { Qt::DisplayRole, "display" },
739 { Qt::DecorationRole, "decoration" },
740 { Qt::EditRole, "edit" },
741 { Qt::ToolTipRole, "toolTip" },
742 { Qt::StatusTipRole, "statusTip" },
743 { Qt::WhatsThisRole, "whatsThis" },
744 })
745
747{
748 return *qDefaultRoleNames();
749}
750
752 Qt::CaseSensitivity cs, bool isLocaleAware)
753{
754 if (left.userType() == QMetaType::UnknownType)
755 return false;
756 if (right.userType() == QMetaType::UnknownType)
757 return true;
758 switch (left.userType()) {
759 case QMetaType::Int:
760 return left.toInt() < right.toInt();
761 case QMetaType::UInt:
762 return left.toUInt() < right.toUInt();
763 case QMetaType::LongLong:
764 return left.toLongLong() < right.toLongLong();
765 case QMetaType::ULongLong:
766 return left.toULongLong() < right.toULongLong();
767 case QMetaType::Float:
768 return left.toFloat() < right.toFloat();
769 case QMetaType::Double:
770 return left.toDouble() < right.toDouble();
771 case QMetaType::QChar:
772 return left.toChar() < right.toChar();
773 case QMetaType::QDate:
774 return left.toDate() < right.toDate();
775 case QMetaType::QTime:
776 return left.toTime() < right.toTime();
777 case QMetaType::QDateTime:
778 return left.toDateTime() < right.toDateTime();
779 case QMetaType::QString:
780 default:
781 if (isLocaleAware)
782 return left.toString().localeAwareCompare(right.toString()) < 0;
783 else
784 return left.toString().compare(right.toString(), cs) < 0;
785 }
786}
787
788
790{
791 //return 0 for integer, 1 for floating point and 2 for other
792 switch (value.userType()) {
793 case QMetaType::Bool:
794 case QMetaType::Int:
795 case QMetaType::UInt:
796 case QMetaType::LongLong:
797 case QMetaType::ULongLong:
798 case QMetaType::QChar:
799 case QMetaType::Short:
800 case QMetaType::UShort:
801 case QMetaType::UChar:
802 case QMetaType::ULong:
803 case QMetaType::Long:
804 return 0;
805 case QMetaType::Double:
806 case QMetaType::Float:
807 return 1;
808 default:
809 return 2;
810 }
811}
812
820{
822 {
823 case 0: //integer type
824 return v1.toLongLong() < v2.toLongLong();
825 case 1: //floating point
826 return v1.toReal() < v2.toReal();
827 default:
828 return v1.toString().localeAwareCompare(v2.toString()) < 0;
829 }
830}
831
833{
834 if (data->index.isValid()) {
835 int removed = persistent.indexes.remove(data->index);
836 Q_ASSERT_X(removed == 1, "QPersistentModelIndex::~QPersistentModelIndex",
837 "persistent model indexes corrupted"); //maybe the index was somewhat invalid?
838 // This assert may happen if the model use changePersistentIndex in a way that could result on two
839 // QPersistentModelIndex pointing to the same index.
840 Q_UNUSED(removed);
841 }
842 // make sure our optimization still works
843 for (int i = persistent.moved.size() - 1; i >= 0; --i) {
844 int idx = persistent.moved.at(i).indexOf(data);
845 if (idx >= 0)
846 persistent.moved[i].remove(idx);
847 }
848 // update the references to invalidated persistent indexes
849 for (int i = persistent.invalidated.size() - 1; i >= 0; --i) {
850 int idx = persistent.invalidated.at(i).indexOf(data);
851 if (idx >= 0)
853 }
854
855}
856
858 int first, int last)
859{
861 Q_UNUSED(last);
862 QList<QPersistentModelIndexData *> persistent_moved;
863 if (first < q->rowCount(parent)) {
864 for (auto *data : std::as_const(persistent.indexes)) {
865 const QModelIndex &index = data->index;
866 if (index.row() >= first && index.isValid() && index.parent() == parent) {
867 persistent_moved.append(data);
868 }
869 }
870 }
871 persistent.moved.push(persistent_moved);
872}
873
875 int first, int last)
876{
877 const QList<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
878 const int count = (last - first) + 1; // it is important to only use the delta, because the change could be nested
879 for (auto *data : persistent_moved) {
880 QModelIndex old = data->index;
882 data->index = q_func()->index(old.row() + count, old.column(), parent);
883 if (data->index.isValid()) {
885 } else {
886 qWarning() << "QAbstractItemModel::endInsertRows: Invalid index (" << old.row() + count << ',' << old.column() << ") in model" << q_func();
887 }
888 }
889}
890
891void QAbstractItemModelPrivate::itemsAboutToBeMoved(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation)
892{
893 QList<QPersistentModelIndexData *> persistent_moved_explicitly;
894 QList<QPersistentModelIndexData *> persistent_moved_in_source;
895 QList<QPersistentModelIndexData *> persistent_moved_in_destination;
896
897 const bool sameParent = (srcParent == destinationParent);
898 const bool movingUp = (srcFirst > destinationChild);
899
900 for (auto *data : std::as_const(persistent.indexes)) {
901 const QModelIndex &index = data->index;
902 const QModelIndex &parent = index.parent();
903 const bool isSourceIndex = (parent == srcParent);
904 const bool isDestinationIndex = (parent == destinationParent);
905
906 int childPosition;
907 if (orientation == Qt::Vertical)
908 childPosition = index.row();
909 else
910 childPosition = index.column();
911
912 if (!index.isValid() || !(isSourceIndex || isDestinationIndex ) )
913 continue;
914
915 if (!sameParent && isDestinationIndex) {
916 if (childPosition >= destinationChild)
917 persistent_moved_in_destination.append(data);
918 continue;
919 }
920
921 if (sameParent && movingUp && childPosition < destinationChild)
922 continue;
923
924 if (sameParent && !movingUp && childPosition < srcFirst )
925 continue;
926
927 if (!sameParent && childPosition < srcFirst)
928 continue;
929
930 if (sameParent && (childPosition > srcLast) && (childPosition >= destinationChild ))
931 continue;
932
933 if ((childPosition <= srcLast) && (childPosition >= srcFirst)) {
934 persistent_moved_explicitly.append(data);
935 } else {
936 persistent_moved_in_source.append(data);
937 }
938 }
939 persistent.moved.push(persistent_moved_explicitly);
940 persistent.moved.push(persistent_moved_in_source);
941 persistent.moved.push(persistent_moved_in_destination);
942}
943
952 const QModelIndex &parent, Qt::Orientation orientation)
953{
954 for (auto *data : indexes) {
955 int row = data->index.row();
956 int column = data->index.column();
957
958 if (Qt::Vertical == orientation)
959 row += change;
960 else
961 column += change;
962
964 data->index = q_func()->index(row, column, parent);
965 if (data->index.isValid()) {
967 } else {
968 qWarning() << "QAbstractItemModel::endMoveRows: Invalid index (" << row << "," << column << ") in model" << q_func();
969 }
970 }
971}
972
973void QAbstractItemModelPrivate::itemsMoved(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation)
974{
975 const QList<QPersistentModelIndexData *> moved_in_destination = persistent.moved.pop();
976 const QList<QPersistentModelIndexData *> moved_in_source = persistent.moved.pop();
977 const QList<QPersistentModelIndexData *> moved_explicitly = persistent.moved.pop();
978
979 const bool sameParent = (sourceParent == destinationParent);
980 const bool movingUp = (sourceFirst > destinationChild);
981
982 const int explicit_change = (!sameParent || movingUp) ? destinationChild - sourceFirst : destinationChild - sourceLast - 1 ;
983 const int source_change = (!sameParent || !movingUp) ? -1*(sourceLast - sourceFirst + 1) : sourceLast - sourceFirst + 1 ;
984 const int destination_change = sourceLast - sourceFirst + 1;
985
986 movePersistentIndexes(moved_explicitly, explicit_change, destinationParent, orientation);
987 movePersistentIndexes(moved_in_source, source_change, sourceParent, orientation);
988 movePersistentIndexes(moved_in_destination, destination_change, destinationParent, orientation);
989}
990
992 int first, int last)
993{
994 QList<QPersistentModelIndexData *> persistent_moved;
995 QList<QPersistentModelIndexData *> persistent_invalidated;
996 // find the persistent indexes that are affected by the change, either by being in the removed subtree
997 // or by being on the same level and below the removed rows
998 for (auto *data : std::as_const(persistent.indexes)) {
999 bool level_changed = false;
1000 QModelIndex current = data->index;
1001 while (current.isValid()) {
1002 QModelIndex current_parent = current.parent();
1003 if (current_parent == parent) { // on the same level as the change
1004 if (!level_changed && current.row() > last) // below the removed rows
1005 persistent_moved.append(data);
1006 else if (current.row() <= last && current.row() >= first) // in the removed subtree
1007 persistent_invalidated.append(data);
1008 break;
1009 }
1010 current = current_parent;
1011 level_changed = true;
1012 }
1013 }
1014
1015 persistent.moved.push(persistent_moved);
1016 persistent.invalidated.push(persistent_invalidated);
1017}
1018
1020 int first, int last)
1021{
1022 const QList<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
1023 const int count = (last - first) + 1; // it is important to only use the delta, because the change could be nested
1024 for (auto *data : persistent_moved) {
1025 QModelIndex old = data->index;
1027 data->index = q_func()->index(old.row() - count, old.column(), parent);
1028 if (data->index.isValid()) {
1030 } else {
1031 qWarning() << "QAbstractItemModel::endRemoveRows: Invalid index (" << old.row() - count << ',' << old.column() << ") in model" << q_func();
1032 }
1033 }
1034 const QList<QPersistentModelIndexData *> persistent_invalidated = persistent.invalidated.pop();
1035 for (auto *data : persistent_invalidated) {
1036 auto pit = persistent.indexes.constFind(data->index);
1037 if (pit != persistent.indexes.cend())
1039 data->index = QModelIndex();
1040 }
1041}
1042
1044 int first, int last)
1045{
1046 Q_Q(QAbstractItemModel);
1047 Q_UNUSED(last);
1048 QList<QPersistentModelIndexData *> persistent_moved;
1049 if (first < q->columnCount(parent)) {
1050 for (auto *data : std::as_const(persistent.indexes)) {
1051 const QModelIndex &index = data->index;
1052 if (index.column() >= first && index.isValid() && index.parent() == parent)
1053 persistent_moved.append(data);
1054 }
1055 }
1056 persistent.moved.push(persistent_moved);
1057}
1058
1060 int first, int last)
1061{
1062 const QList<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
1063 const int count = (last - first) + 1; // it is important to only use the delta, because the change could be nested
1064 for (auto *data : persistent_moved) {
1065 QModelIndex old = data->index;
1067 data->index = q_func()->index(old.row(), old.column() + count, parent);
1068 if (data->index.isValid()) {
1070 } else {
1071 qWarning() << "QAbstractItemModel::endInsertColumns: Invalid index (" << old.row() << ',' << old.column() + count << ") in model" << q_func();
1072 }
1073 }
1074}
1075
1077 int first, int last)
1078{
1079 QList<QPersistentModelIndexData *> persistent_moved;
1080 QList<QPersistentModelIndexData *> persistent_invalidated;
1081 // find the persistent indexes that are affected by the change, either by being in the removed subtree
1082 // or by being on the same level and to the right of the removed columns
1083 for (auto *data : std::as_const(persistent.indexes)) {
1084 bool level_changed = false;
1085 QModelIndex current = data->index;
1086 while (current.isValid()) {
1087 QModelIndex current_parent = current.parent();
1088 if (current_parent == parent) { // on the same level as the change
1089 if (!level_changed && current.column() > last) // right of the removed columns
1090 persistent_moved.append(data);
1091 else if (current.column() <= last && current.column() >= first) // in the removed subtree
1092 persistent_invalidated.append(data);
1093 break;
1094 }
1095 current = current_parent;
1096 level_changed = true;
1097 }
1098 }
1099
1100 persistent.moved.push(persistent_moved);
1101 persistent.invalidated.push(persistent_invalidated);
1102
1103}
1104
1106 int first, int last)
1107{
1108 const QList<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
1109 const int count = (last - first) + 1; // it is important to only use the delta, because the change could be nested
1110 for (auto *data : persistent_moved) {
1111 QModelIndex old = data->index;
1113 data->index = q_func()->index(old.row(), old.column() - count, parent);
1114 if (data->index.isValid()) {
1116 } else {
1117 qWarning() << "QAbstractItemModel::endRemoveColumns: Invalid index (" << old.row() << ',' << old.column() - count << ") in model" << q_func();
1118 }
1119 }
1120 const QList<QPersistentModelIndexData *> persistent_invalidated = persistent.invalidated.pop();
1121 for (auto *data : persistent_invalidated) {
1122 auto index = persistent.indexes.constFind(data->index);
1125 data->index = QModelIndex();
1126 }
1127}
1128
1146{
1147
1148}
1149
1701{
1702}
1703
1708 : QObject(dd, parent)
1709{
1710}
1711
1716{
1717 d_func()->invalidatePersistentIndexes();
1718}
1719
1720
1951{
1952 if (row < 0 || column < 0)
1953 return false;
1954 return row < rowCount(parent) && column < columnCount(parent);
1955}
1956
1957
1969{
1970 return (rowCount(parent) > 0) && (columnCount(parent) > 0);
1971}
1972
1988{
1989 return (row == idx.row() && column == idx.column()) ? idx : index(row, column, parent(idx));
1990}
1991
1992
2003{
2004 QMap<int, QVariant> roles;
2005 for (int i = 0; i < Qt::UserRole; ++i) {
2006 QVariant variantData = data(index, i);
2007 if (variantData.isValid())
2008 roles.insert(i, variantData);
2009 }
2010 return roles;
2011}
2012
2027{
2028 Q_UNUSED(index);
2029 Q_UNUSED(value);
2030 Q_UNUSED(role);
2031 return false;
2032}
2033
2044{
2045 Q_UNUSED(index);
2046 return false;
2047}
2048
2072{
2073 // ### TODO: Consider change the semantics of this function,
2074 // or deprecating/removing it altogether.
2075 //
2076 // For instance, it should try setting *all* the data
2077 // in \a roles, and not bail out at the first setData that returns
2078 // false. It should also have a transactional approach.
2079 for (auto it = roles.begin(), e = roles.end(); it != e; ++it) {
2080 if (!setData(index, it.value(), it.key()))
2081 return false;
2082 }
2083 return true;
2084}
2085
2102{
2104 types << QStringLiteral("application/x-qabstractitemmodeldatalist");
2105 return types;
2106}
2107
2122{
2123 if (indexes.size() <= 0)
2124 return nullptr;
2126 if (types.isEmpty())
2127 return nullptr;
2128 QMimeData *data = new QMimeData();
2129 QString format = types.at(0);
2132 encodeData(indexes, stream);
2133 data->setData(format, encoded);
2134 return data;
2135}
2136
2151 int row, int column,
2152 const QModelIndex &parent) const
2153{
2154 Q_UNUSED(row);
2157
2158 if (!(action & supportedDropActions()))
2159 return false;
2160
2161 const QStringList modelTypes = mimeTypes();
2162 for (int i = 0; i < modelTypes.size(); ++i) {
2163 if (data->hasFormat(modelTypes.at(i)))
2164 return true;
2165 }
2166 return false;
2167}
2168
2199 int row, int column, const QModelIndex &parent)
2200{
2201 // check if the action is supported
2202 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
2203 return false;
2204 // check if the format is supported
2206 if (types.isEmpty())
2207 return false;
2208 QString format = types.at(0);
2209 if (!data->hasFormat(format))
2210 return false;
2211 if (row > rowCount(parent))
2212 row = rowCount(parent);
2213 if (row == -1)
2214 row = rowCount(parent);
2215 if (column == -1)
2216 column = 0;
2217 // decode and insert
2220 return decodeData(row, column, parent, stream);
2221}
2222
2237{
2238 return Qt::CopyAction;
2239}
2240
2253{
2254 return supportedDropActions();
2255}
2256
2284bool QAbstractItemModel::insertRows(int, int, const QModelIndex &)
2285{
2286 return false;
2287}
2288
2313bool QAbstractItemModel::insertColumns(int, int, const QModelIndex &)
2314{
2315 return false;
2316}
2317
2334bool QAbstractItemModel::removeRows(int, int, const QModelIndex &)
2335{
2336 return false;
2337}
2338
2355bool QAbstractItemModel::removeColumns(int, int, const QModelIndex &)
2356{
2357 return false;
2358}
2359
2376bool QAbstractItemModel::moveRows(const QModelIndex &, int , int , const QModelIndex &, int)
2377{
2378 return false;
2379}
2380
2397bool QAbstractItemModel::moveColumns(const QModelIndex &, int , int , const QModelIndex &, int)
2398{
2399 return false;
2400}
2401
2413{
2414 // do nothing
2415}
2416
2429{
2430 return false;
2431}
2432
2443{
2444 Q_D(const QAbstractItemModel);
2445 if (!d->indexValid(index))
2446 return { };
2447
2449}
2450
2456void QAbstractItemModel::sort(int column, Qt::SortOrder order)
2457{
2459 Q_UNUSED(order);
2460 // do nothing
2461}
2462
2473{
2474 return index;
2475}
2476
2499 const QVariant &value, int hits,
2500 Qt::MatchFlags flags) const
2501{
2503 uint matchType = (flags & Qt::MatchTypeMask).toInt();
2505 bool recurse = flags.testAnyFlag(Qt::MatchRecursive);
2506 bool wrap = flags.testAnyFlag(Qt::MatchWrap);
2507 bool allHits = (hits == -1);
2508 QString text; // only convert to a string if it is needed
2509#if QT_CONFIG(regularexpression)
2510 QRegularExpression rx; // only create it if needed
2511#endif
2512 const int column = start.column();
2514 int from = start.row();
2515 int to = rowCount(p);
2516
2517 // iterates twice if wrapping
2518 for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) {
2519 for (int r = from; (r < to) && (allHits || result.size() < hits); ++r) {
2520 QModelIndex idx = index(r, column, p);
2521 if (!idx.isValid())
2522 continue;
2523 QVariant v = data(idx, role);
2524 // QVariant based matching
2525 if (matchType == Qt::MatchExactly) {
2526 if (value == v)
2527 result.append(idx);
2528 } else { // QString or regular expression based matching
2529#if QT_CONFIG(regularexpression)
2530 if (matchType == Qt::MatchRegularExpression) {
2531 if (rx.pattern().isEmpty()) {
2532 if (value.userType() == QMetaType::QRegularExpression) {
2533 rx = value.toRegularExpression();
2534 } else {
2535 rx.setPattern(value.toString());
2536 if (cs == Qt::CaseInsensitive)
2538 }
2539 }
2540 } else if (matchType == Qt::MatchWildcard) {
2541 if (rx.pattern().isEmpty()) {
2543 rx.setPattern(pattern);
2544 }
2545 if (cs == Qt::CaseInsensitive)
2547 } else
2548#endif
2549 {
2550 if (text.isEmpty()) // lazy conversion
2551 text = value.toString();
2552 }
2553
2554 QString t = v.toString();
2555 switch (matchType) {
2556#if QT_CONFIG(regularexpression)
2558 Q_FALLTHROUGH();
2559 case Qt::MatchWildcard:
2560 if (t.contains(rx))
2561 result.append(idx);
2562 break;
2563#endif
2565 if (t.startsWith(text, cs))
2566 result.append(idx);
2567 break;
2568 case Qt::MatchEndsWith:
2569 if (t.endsWith(text, cs))
2570 result.append(idx);
2571 break;
2573 if (t.compare(text, cs) == 0)
2574 result.append(idx);
2575 break;
2576 case Qt::MatchContains:
2577 default:
2578 if (t.contains(text, cs))
2579 result.append(idx);
2580 }
2581 }
2582 if (recurse) {
2583 const auto parent = column != 0 ? idx.sibling(idx.row(), 0) : idx;
2584 if (hasChildren(parent)) { // search the hierarchy
2585 result += match(index(0, column, parent), role,
2586 (text.isEmpty() ? value : text),
2587 (allHits ? -1 : hits - result.size()), flags);
2588 }
2589 }
2590 }
2591 // prepare for the next iteration
2592 from = 0;
2593 to = start.row();
2594 }
2595 return result;
2596}
2597
2605{
2606 return QSize(1, 1);
2607}
2608
2641{
2643}
2644
2655{
2656 return true;
2657}
2658
2667{
2668 // do nothing
2669}
2670
2682QVariant QAbstractItemModel::headerData(int section, Qt::Orientation orientation, int role) const
2683{
2684 Q_UNUSED(orientation);
2685 if (role == Qt::DisplayRole)
2686 return section + 1;
2687 return QVariant();
2688}
2689
2703 const QVariant &value, int role)
2704{
2705 Q_UNUSED(section);
2706 Q_UNUSED(orientation);
2707 Q_UNUSED(value);
2708 Q_UNUSED(role);
2709 return false;
2710}
2711
2742{
2743 for (const auto &index : indexes)
2744 stream << index.row() << index.column() << itemData(index);
2745}
2746
2752{
2753 int top = INT_MAX;
2754 int left = INT_MAX;
2755 int bottom = 0;
2756 int right = 0;
2757 QList<int> rows, columns;
2759
2760 while (!stream.atEnd()) {
2761 int r, c;
2763 stream >> r >> c >> v;
2764 rows.append(r);
2765 columns.append(c);
2766 data.append(v);
2767 top = qMin(r, top);
2768 left = qMin(c, left);
2769 bottom = qMax(r, bottom);
2770 right = qMax(c, right);
2771 }
2772
2773 // insert the dragged items into the table, use a bit array to avoid overwriting items,
2774 // since items from different tables can have the same row and column
2775 int dragRowCount = 0;
2776 int dragColumnCount = right - left + 1;
2777
2778 // Compute the number of continuous rows upon insertion and modify the rows to match
2779 QList<int> rowsToInsert(bottom + 1);
2780 for (int i = 0; i < rows.size(); ++i)
2781 rowsToInsert[rows.at(i)] = 1;
2782 for (int i = 0; i < rowsToInsert.size(); ++i) {
2783 if (rowsToInsert.at(i) == 1){
2784 rowsToInsert[i] = dragRowCount;
2785 ++dragRowCount;
2786 }
2787 }
2788 for (int i = 0; i < rows.size(); ++i)
2789 rows[i] = top + rowsToInsert.at(rows.at(i));
2790
2791 QBitArray isWrittenTo(dragRowCount * dragColumnCount);
2792
2793 // make space in the table for the dropped data
2794 int colCount = columnCount(parent);
2795 if (colCount == 0) {
2796 insertColumns(colCount, dragColumnCount - colCount, parent);
2797 colCount = columnCount(parent);
2798 }
2799 insertRows(row, dragRowCount, parent);
2800
2801 row = qMax(0, row);
2802 column = qMax(0, column);
2803
2804 QList<QPersistentModelIndex> newIndexes(data.size());
2805 // set the data in the table
2806 for (int j = 0; j < data.size(); ++j) {
2807 int relativeRow = rows.at(j) - top;
2808 int relativeColumn = columns.at(j) - left;
2809 int destinationRow = relativeRow + row;
2810 int destinationColumn = relativeColumn + column;
2811 int flat = (relativeRow * dragColumnCount) + relativeColumn;
2812 // if the item was already written to, or we just can't fit it in the table, create a new row
2813 if (destinationColumn >= colCount || isWrittenTo.testBit(flat)) {
2814 destinationColumn = qBound(column, destinationColumn, colCount - 1);
2815 destinationRow = row + dragRowCount;
2816 insertRows(row + dragRowCount, 1, parent);
2817 flat = (dragRowCount * dragColumnCount) + relativeColumn;
2818 isWrittenTo.resize(++dragRowCount * dragColumnCount);
2819 }
2820 if (!isWrittenTo.testBit(flat)) {
2821 newIndexes[j] = index(destinationRow, destinationColumn, parent);
2822 isWrittenTo.setBit(flat);
2823 }
2824 }
2825
2826 for(int k = 0; k < newIndexes.size(); k++) {
2827 if (newIndexes.at(k).isValid())
2828 setItemData(newIndexes.at(k), data.at(k));
2829 }
2830
2831 return true;
2832}
2833
2875{
2876 Q_ASSERT(first >= 0);
2877 Q_ASSERT(first <= rowCount(parent)); // == is allowed, to insert at the end
2878 Q_ASSERT(last >= first);
2879 Q_D(QAbstractItemModel);
2880 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
2881 emit rowsAboutToBeInserted(parent, first, last, QPrivateSignal());
2882 d->rowsAboutToBeInserted(parent, first, last);
2883}
2884
2894{
2895 Q_D(QAbstractItemModel);
2896 QAbstractItemModelPrivate::Change change = d->changes.pop();
2897 d->rowsInserted(change.parent, change.first, change.last);
2898 emit rowsInserted(change.parent, change.first, change.last, QPrivateSignal());
2899}
2900
2930{
2931 Q_ASSERT(first >= 0);
2932 Q_ASSERT(last >= first);
2933 Q_ASSERT(last < rowCount(parent));
2934 Q_D(QAbstractItemModel);
2935 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
2936 emit rowsAboutToBeRemoved(parent, first, last, QPrivateSignal());
2937 d->rowsAboutToBeRemoved(parent, first, last);
2938}
2939
2949{
2950 Q_D(QAbstractItemModel);
2951 QAbstractItemModelPrivate::Change change = d->changes.pop();
2952 d->rowsRemoved(change.parent, change.first, change.last);
2953 emit rowsRemoved(change.parent, change.first, change.last, QPrivateSignal());
2954}
2955
2964bool QAbstractItemModelPrivate::allowMove(const QModelIndex &srcParent, int start, int end, const QModelIndex &destinationParent, int destinationStart, Qt::Orientation orientation)
2965{
2966 // Don't move the range within itself.
2967 if (destinationParent == srcParent)
2968 return !(destinationStart >= start && destinationStart <= end + 1);
2969
2970 QModelIndex destinationAncestor = destinationParent;
2971 int pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
2972 forever {
2973 if (destinationAncestor == srcParent) {
2974 if (pos >= start && pos <= end)
2975 return false;
2976 break;
2977 }
2978
2979 if (!destinationAncestor.isValid())
2980 break;
2981
2982 pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
2983 destinationAncestor = destinationAncestor.parent();
2984 }
2985
2986 return true;
2987}
2988
2995
3086bool QAbstractItemModel::beginMoveRows(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild)
3087{
3088 Q_ASSERT(sourceFirst >= 0);
3089 Q_ASSERT(sourceLast >= sourceFirst);
3091 Q_D(QAbstractItemModel);
3092
3093 if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical)) {
3094 return false;
3095 }
3096
3097 QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
3098 sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
3099 d->changes.push(sourceChange);
3100 int destinationLast = destinationChild + (sourceLast - sourceFirst);
3101 QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
3102 destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
3103 d->changes.push(destinationChange);
3104
3105 emit rowsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
3106 d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical);
3107 return true;
3108}
3109
3122{
3123 Q_D(QAbstractItemModel);
3124
3125 QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
3126 QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
3127
3128 QModelIndex adjustedSource = removeChange.parent;
3129 QModelIndex adjustedDestination = insertChange.parent;
3130
3131 const int numMoved = removeChange.last - removeChange.first + 1;
3132 if (insertChange.needsAdjust)
3133 adjustedDestination = createIndex(adjustedDestination.row() - numMoved, adjustedDestination.column(), adjustedDestination.internalPointer());
3134
3135 if (removeChange.needsAdjust)
3136 adjustedSource = createIndex(adjustedSource.row() + numMoved, adjustedSource.column(), adjustedSource.internalPointer());
3137
3138 d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Vertical);
3139
3140 emit rowsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
3141}
3142
3185{
3186 Q_ASSERT(first >= 0);
3187 Q_ASSERT(first <= columnCount(parent)); // == is allowed, to insert at the end
3188 Q_ASSERT(last >= first);
3189 Q_D(QAbstractItemModel);
3190 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3191 emit columnsAboutToBeInserted(parent, first, last, QPrivateSignal());
3192 d->columnsAboutToBeInserted(parent, first, last);
3193}
3194
3205{
3206 Q_D(QAbstractItemModel);
3207 QAbstractItemModelPrivate::Change change = d->changes.pop();
3208 d->columnsInserted(change.parent, change.first, change.last);
3209 emit columnsInserted(change.parent, change.first, change.last, QPrivateSignal());
3210}
3211
3241{
3242 Q_ASSERT(first >= 0);
3243 Q_ASSERT(last >= first);
3244 Q_ASSERT(last < columnCount(parent));
3245 Q_D(QAbstractItemModel);
3246 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3247 emit columnsAboutToBeRemoved(parent, first, last, QPrivateSignal());
3248 d->columnsAboutToBeRemoved(parent, first, last);
3249}
3250
3260{
3261 Q_D(QAbstractItemModel);
3262 QAbstractItemModelPrivate::Change change = d->changes.pop();
3263 d->columnsRemoved(change.parent, change.first, change.last);
3264 emit columnsRemoved(change.parent, change.first, change.last, QPrivateSignal());
3265}
3266
3305bool QAbstractItemModel::beginMoveColumns(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild)
3306{
3307 Q_ASSERT(sourceFirst >= 0);
3308 Q_ASSERT(sourceLast >= sourceFirst);
3310 Q_D(QAbstractItemModel);
3311
3312 if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal)) {
3313 return false;
3314 }
3315
3316 QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
3317 sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
3318 d->changes.push(sourceChange);
3319 int destinationLast = destinationChild + (sourceLast - sourceFirst);
3320 QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
3321 destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
3322 d->changes.push(destinationChange);
3323
3324 emit columnsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
3325 d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal);
3326 return true;
3327}
3328
3341{
3342 Q_D(QAbstractItemModel);
3343
3344 QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
3345 QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
3346
3347 QModelIndex adjustedSource = removeChange.parent;
3348 QModelIndex adjustedDestination = insertChange.parent;
3349
3350 const int numMoved = removeChange.last - removeChange.first + 1;
3351 if (insertChange.needsAdjust)
3352 adjustedDestination = createIndex(adjustedDestination.row(), adjustedDestination.column() - numMoved, adjustedDestination.internalPointer());
3353
3354 if (removeChange.needsAdjust)
3355 adjustedSource = createIndex(adjustedSource.row(), adjustedSource.column() + numMoved, adjustedSource.internalPointer());
3356
3357 d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Horizontal);
3358 emit columnsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
3359}
3360
3385{
3386 emit modelAboutToBeReset(QPrivateSignal());
3387}
3388
3401{
3402 Q_D(QAbstractItemModel);
3403 d->invalidatePersistentIndexes();
3405 emit modelReset(QPrivateSignal());
3406}
3407
3418{
3419 Q_D(QAbstractItemModel);
3420 if (d->persistent.indexes.isEmpty())
3421 return;
3422 // find the data and reinsert it sorted
3423 const auto it = d->persistent.indexes.constFind(from);
3424 if (it != d->persistent.indexes.cend()) {
3426 d->persistent.indexes.erase(it);
3427 data->index = to;
3428 if (to.isValid())
3429 d->persistent.insertMultiAtEnd(to, data);
3430 }
3431}
3432
3445 const QModelIndexList &to)
3446{
3447 Q_D(QAbstractItemModel);
3448 if (d->persistent.indexes.isEmpty())
3449 return;
3451 toBeReinserted.reserve(to.size());
3452 for (int i = 0; i < from.size(); ++i) {
3453 if (from.at(i) == to.at(i))
3454 continue;
3455 const auto it = d->persistent.indexes.constFind(from.at(i));
3456 if (it != d->persistent.indexes.cend()) {
3458 d->persistent.indexes.erase(it);
3459 data->index = to.at(i);
3460 if (data->index.isValid())
3461 toBeReinserted << data;
3462 }
3463 }
3464
3465 for (auto *data : std::as_const(toBeReinserted))
3466 d->persistent.insertMultiAtEnd(data->index, data);
3467}
3468
3475{
3476 Q_D(const QAbstractItemModel);
3478 result.reserve(d->persistent.indexes.size());
3479 for (auto *data : std::as_const(d->persistent.indexes))
3480 result.append(data->index);
3481 return result;
3482}
3483
3558bool QAbstractItemModel::checkIndex(const QModelIndex &index, CheckIndexOptions options) const
3559{
3560 if (!index.isValid()) {
3561 if (options & CheckIndexOption::IndexIsValid) {
3562 qCWarning(lcCheckIndex) << "Index" << index << "is not valid (expected valid)";
3563 return false;
3564 }
3565 return true;
3566 }
3567
3568 if (index.model() != this) {
3569 qCWarning(lcCheckIndex) << "Index" << index
3570 << "is for model" << index.model()
3571 << "which is different from this model" << this;
3572 return false;
3573 }
3574
3575 if (index.row() < 0) {
3576 qCWarning(lcCheckIndex) << "Index" << index
3577 << "has negative row" << index.row();
3578 return false;
3579 }
3580
3581 if (index.column() < 0) {
3582 qCWarning(lcCheckIndex) << "Index" << index
3583 << "has negative column" << index.column();
3584 return false;
3585 }
3586
3587 if (!(options & CheckIndexOption::DoNotUseParent)) {
3588 const QModelIndex parentIndex = index.parent();
3589 if (options & CheckIndexOption::ParentIsInvalid) {
3590 if (parentIndex.isValid()) {
3591 qCWarning(lcCheckIndex) << "Index" << index
3592 << "has valid parent" << parentIndex
3593 << "(expected an invalid parent)";
3594 return false;
3595 }
3596 }
3597
3598 const int rc = rowCount(parentIndex);
3599 if (index.row() >= rc) {
3600 qCWarning(lcCheckIndex) << "Index" << index
3601 << "has out of range row" << index.row()
3602 << "rowCount() is" << rc;
3603 return false;
3604 }
3605
3606 const int cc = columnCount(parentIndex);
3607 if (index.column() >= cc) {
3608 qCWarning(lcCheckIndex) << "Index" << index
3609 << "has out of range column" << index.column()
3610 << "columnCount() is" << cc;
3611 return false;
3612
3613 }
3614 }
3615
3616 return true;
3617}
3618
3667{
3669
3670 for (QModelRoleData &d : roleDataSpan)
3671 d.setData(data(index, d.role()));
3672}
3673
3743{
3744
3745}
3746
3755{
3756
3757}
3758
3764{
3765
3766}
3767
3777{
3779}
3780
3790{
3791 return QModelIndex();
3792}
3793
3798{
3799 return index(row, column);
3800}
3801
3803{
3804 if (!parent.isValid())
3805 return rowCount(parent) > 0 && columnCount(parent) > 0;
3806 return false;
3807}
3808
3813{
3814 Qt::ItemFlags f = QAbstractItemModel::flags(index);
3815 if (index.isValid())
3817 return f;
3818}
3819
3894{
3895
3896}
3897
3906{
3907
3908}
3909
3915{
3916
3917}
3918
3928{
3930}
3931
3939{
3940 return QModelIndex();
3941}
3942
3947{
3948 return index(row, column);
3949}
3950
3955{
3956 Qt::ItemFlags f = QAbstractItemModel::flags(index);
3957 if (index.isValid())
3959 return f;
3960}
3961
3971{
3972 return parent.isValid() ? 0 : 1;
3973}
3974
3976{
3977 return parent.isValid() ? false : (rowCount() > 0);
3978}
3979
3991 int row, int column, const QModelIndex &parent)
3992{
3993 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
3994 return false;
3995
3997 if (types.isEmpty())
3998 return false;
3999 QString format = types.at(0);
4000 if (!data->hasFormat(format))
4001 return false;
4002
4005
4006 // if the drop is on an item, replace the data in the items
4007 if (parent.isValid() && row == -1 && column == -1) {
4008 int top = INT_MAX;
4009 int left = INT_MAX;
4010 QList<int> rows, columns;
4012
4013 while (!stream.atEnd()) {
4014 int r, c;
4016 stream >> r >> c >> v;
4017 rows.append(r);
4018 columns.append(c);
4019 data.append(v);
4020 top = qMin(r, top);
4021 left = qMin(c, left);
4022 }
4023
4024 for (int i = 0; i < data.size(); ++i) {
4025 int r = (rows.at(i) - top) + parent.row();
4026 int c = (columns.at(i) - left) + parent.column();
4027 if (hasIndex(r, c))
4028 setItemData(index(r, c), data.at(i));
4029 }
4030
4031 return true;
4032 }
4033
4034 // otherwise insert new rows for the data
4035 return decodeData(row, column, parent, stream);
4036}
4037
4042 int row, int column, const QModelIndex &parent)
4043{
4044 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
4045 return false;
4046
4048 if (types.isEmpty())
4049 return false;
4050 QString format = types.at(0);
4051 if (!data->hasFormat(format))
4052 return false;
4053
4056
4057 // if the drop is on an item, replace the data in the items
4058 if (parent.isValid() && row == -1 && column == -1) {
4059 int top = INT_MAX;
4060 int left = INT_MAX;
4061 QList<int> rows, columns;
4063
4064 while (!stream.atEnd()) {
4065 int r, c;
4067 stream >> r >> c >> v;
4068 rows.append(r);
4069 columns.append(c);
4070 data.append(v);
4071 top = qMin(r, top);
4072 left = qMin(c, left);
4073 }
4074
4075 for (int i = 0; i < data.size(); ++i) {
4076 int r = (rows.at(i) - top) + parent.row();
4077 if (columns.at(i) == left && hasIndex(r, 0))
4078 setItemData(index(r), data.at(i));
4079 }
4080
4081 return true;
4082 }
4083
4084 if (row == -1)
4085 row = rowCount(parent);
4086
4087 // otherwise insert new rows for the data
4088 return decodeData(row, column, parent, stream);
4089}
4090
4149{
4150 auto newIt = indexes.insert(key, data);
4151 auto it = newIt;
4152 ++it;
4153 while (it != indexes.end() && it.key() == key) {
4154 qSwap(*newIt,*it);
4155 newIt = it;
4156 ++it;
4157 }
4158}
4159
4161
4162#include "moc_qabstractitemmodel.cpp"
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:311
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:311
~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
bool testBit(qsizetype i) const
Returns true if the bit at index position i is 1; otherwise returns false.
Definition qbitarray.h:84
void resize(qsizetype size)
Resizes the bit array to size bits.
void setBit(qsizetype i)
Sets the bit at index position i to 1.
Definition qbitarray.h:88
\inmodule QtCore
Definition qbytearray.h:57
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
Definition qbytearray.h:534
\inmodule QtCore\reentrant
Definition qdatastream.h:30
\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:386
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
void remove(qsizetype i, qsizetype n=1)
Definition qlist.h:787
void reserve(qsizetype size)
Definition qlist.h:746
void append(parameter_type t)
Definition qlist.h:441
Definition qmap.h:186
iterator insert(const Key &key, const T &value)
Definition qmap.h:687
iterator begin()
Definition qmap.h:597
iterator end()
Definition qmap.h:601
\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
\inmodule QtCore
Definition qhash.h:1348
const_iterator constEnd() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the ...
Definition qhash.h:1833
const_iterator cend() const noexcept
Definition qhash.h:1832
qsizetype remove(const Key &key)
Definition qhash.h:1519
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1930
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Definition qhash.h:1511
iterator erase(const_iterator it)
Definition qhash.h:1873
iterator end() noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
Definition qhash.h:1830
const_iterator constFind(const Key &key) const noexcept
Definition qhash.h:1921
QObject * parent
Definition qobject.h:61
\inmodule QtCore
Definition qobject.h:90
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:311
static void destroy(QPersistentModelIndexData *data)
static QPersistentModelIndexData * create(const QModelIndex &index)
bool operator!=(const QPersistentModelIndex &other) const
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
bool operator<(const QPersistentModelIndex &other) 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
Returns {true} if this persistent model index is equal to the other persistent model index; otherwise...
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...
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)
\inmodule QtCore
Definition qsize.h:25
T pop()
Removes the top item from the stack and returns it.
Definition qstack.h:18
void push(const T &t)
Adds element t to the top of the stack.
Definition qstack.h:17
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1079
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
\inmodule QtCore
Definition qvariant.h:64
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:707
QString text
qSwap(pi, e)
double e
QSet< QString >::iterator it
Combined button and popup list for selecting options.
Orientation
Definition qnamespace.h:97
@ Horizontal
Definition qnamespace.h:98
@ Vertical
Definition qnamespace.h:99
@ WhatsThisRole
@ UserRole
@ DecorationRole
@ EditRole
@ StatusTipRole
@ ToolTipRole
@ DisplayRole
SortOrder
Definition qnamespace.h:120
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:162
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define QT_IMPL_METATYPE_EXTERN(TYPE)
Definition qmetatype.h:1369
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
GLfloat GLfloat f
GLint left
GLint GLint bottom
GLbitfield flags
GLint GLfloat GLfloat v1
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
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)
#define emit
#define Q_UNUSED(x)
size_t quintptr
Definition qtypes.h:72
unsigned int uint
Definition qtypes.h:29
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
QStack< QList< QPersistentModelIndexData * > > moved
QStack< QList< QPersistentModelIndexData * > > invalidated
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent