2020QMap<
int, QVariant> QAbstractItemModel::itemData(
const QModelIndex &index)
const
2022 QMap<
int, QVariant> roles;
2023 for (
int i = 0; i < Qt::UserRole; ++i) {
2024 QVariant variantData = data(index, i);
2025 if (variantData.isValid())
2026 roles.insert(i, variantData);
2089bool QAbstractItemModel::setItemData(
const QModelIndex &index,
const QMap<
int, QVariant> &roles)
2091 if (!index.isValid() || roles.isEmpty())
2100 for (
auto it = roles.begin(), e = roles.end(); it != e; ++it) {
2101 if (!setData(index, it.value(), it.key()))
2142QMimeData *QAbstractItemModel::mimeData(
const QModelIndexList &indexes)
const
2144 if (indexes.size() <= 0)
2146 QStringList types = mimeTypes();
2147 if (types.isEmpty())
2149 QMimeData *data =
new QMimeData();
2150 QString format = types.at(0);
2152 QDataStream stream(&encoded, QDataStream::WriteOnly);
2153 encodeData(indexes, stream);
2154 data->setData(format, encoded);
2171bool QAbstractItemModel::canDropMimeData(
const QMimeData *data, Qt::DropAction action,
2172 int row,
int column,
2173 const QModelIndex &parent)
const
2179 if (!(action & supportedDropActions()))
2182 const QStringList modelTypes = mimeTypes();
2183 for (
int i = 0; i < modelTypes.size(); ++i) {
2184 if (data->hasFormat(modelTypes.at(i)))
2219bool QAbstractItemModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
2220 int row,
int column,
const QModelIndex &parent)
2223 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
2226 QStringList types = mimeTypes();
2227 if (types.isEmpty())
2229 QString format = types.at(0);
2230 if (!data->hasFormat(format))
2232 if (row > rowCount(parent))
2233 row = rowCount(parent);
2235 row = rowCount(parent);
2239 QByteArray encoded = data->data(format);
2240 QDataStream stream(&encoded, QDataStream::ReadOnly);
2241 return decodeData(row, column, parent, stream);
2519QModelIndexList QAbstractItemModel::match(
const QModelIndex &start,
int role,
2520 const QVariant &value,
int hits,
2521 Qt::MatchFlags flags)
const
2523 QModelIndexList result;
2524 uint matchType = (flags & Qt::MatchTypeMask).toInt();
2525 Qt::CaseSensitivity cs = flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
2526 bool recurse = flags.testAnyFlag(Qt::MatchRecursive);
2527 bool wrap = flags.testAnyFlag(Qt::MatchWrap);
2528 bool allHits = (hits == -1);
2530#if QT_CONFIG(regularexpression)
2531 QRegularExpression rx;
2533 const int column = start.column();
2534 QModelIndex p = parent(start);
2535 int from = start.row();
2536 int to = rowCount(p);
2539 for (
int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) {
2540 for (
int r = from; (r < to) && (allHits || result.size() < hits); ++r) {
2541 QModelIndex idx = index(r, column, p);
2544 QVariant v = data(idx, role);
2546 if (matchType == Qt::MatchExactly) {
2550#if QT_CONFIG(regularexpression)
2551 if (matchType == Qt::MatchRegularExpression) {
2552 if (rx.pattern().isEmpty()) {
2553 if (value.userType() == QMetaType::QRegularExpression) {
2554 rx = value.toRegularExpression();
2556 rx.setPattern(value.toString());
2557 if (cs == Qt::CaseInsensitive)
2558 rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
2561 }
else if (matchType == Qt::MatchWildcard) {
2562 if (rx.pattern().isEmpty()) {
2563 const QString pattern = QRegularExpression::wildcardToRegularExpression(value.toString(), QRegularExpression::NonPathWildcardConversion);
2564 rx.setPattern(pattern);
2566 if (cs == Qt::CaseInsensitive)
2567 rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
2572 text = value.toString();
2575 QString t = v.toString();
2576 switch (matchType) {
2577#if QT_CONFIG(regularexpression)
2578 case Qt::MatchRegularExpression:
2580 case Qt::MatchWildcard:
2585 case Qt::MatchStartsWith:
2586 if (t.startsWith(text, cs))
2589 case Qt::MatchEndsWith:
2590 if (t.endsWith(text, cs))
2593 case Qt::MatchFixedString:
2594 if (t.compare(text, cs) == 0)
2597 case Qt::MatchContains:
2599 if (t.contains(text, cs))
2604 const auto parent = column != 0 ? idx.sibling(idx.row(), 0) : idx;
2605 if (hasChildren(parent)) {
2606 result += match(index(0, column, parent), role,
2607 (text.isEmpty() ? value : text),
2608 (allHits ? -1 : hits - result.size()), flags);
2774bool QAbstractItemModel::decodeData(
int row,
int column,
const QModelIndex &parent,
2775 QDataStream &stream)
2781 QList<
int> rows, columns;
2782 QList<QMap<
int, QVariant>> data;
2784 while (!stream.atEnd()) {
2786 QMap<
int, QVariant> v;
2787 stream >> r >> c >> v;
2792 left = qMin(c, left);
2793 bottom = qMax(r, bottom);
2794 right = qMax(c, right);
2799 int dragRowCount = 0;
2800 int dragColumnCount = right - left + 1;
2803 QList<
int> rowsToInsert(bottom + 1);
2804 for (
int i = 0; i < rows.size(); ++i)
2805 rowsToInsert[rows.at(i)] = 1;
2806 for (
int i = 0; i < rowsToInsert.size(); ++i) {
2807 if (rowsToInsert.at(i) == 1){
2808 rowsToInsert[i] = dragRowCount;
2812 for (
int i = 0; i < rows.size(); ++i)
2813 rows[i] = top + rowsToInsert.at(rows.at(i));
2815 QBitArray isWrittenTo(dragRowCount * dragColumnCount);
2818 int colCount = columnCount(parent);
2819 if (colCount == 0) {
2820 insertColumns(colCount, dragColumnCount - colCount, parent);
2821 colCount = columnCount(parent);
2823 insertRows(row, dragRowCount, parent);
2826 column = qMax(0, column);
2828 QList<QPersistentModelIndex> newIndexes(data.size());
2830 for (
int j = 0; j < data.size(); ++j) {
2831 int relativeRow = rows.at(j) - top;
2832 int relativeColumn = columns.at(j) - left;
2833 int destinationRow = relativeRow + row;
2834 int destinationColumn = relativeColumn + column;
2835 int flat = (relativeRow * dragColumnCount) + relativeColumn;
2837 if (destinationColumn >= colCount || isWrittenTo.testBit(flat)) {
2838 destinationColumn = qBound(column, destinationColumn, colCount - 1);
2839 destinationRow = row + dragRowCount;
2840 insertRows(row + dragRowCount, 1, parent);
2841 flat = (dragRowCount * dragColumnCount) + relativeColumn;
2842 isWrittenTo.resize(++dragRowCount * dragColumnCount);
2844 if (!isWrittenTo.testBit(flat)) {
2845 newIndexes[j] = index(destinationRow, destinationColumn, parent);
2846 isWrittenTo.setBit(flat);
2850 for(
int k = 0; k < newIndexes.size(); k++) {
2851 if (newIndexes.at(k).isValid())
2852 setItemData(newIndexes.at(k), data.at(k));
2898void QAbstractItemModel::beginInsertRows(
const QModelIndex &parent,
int first,
int last)
2900 Q_ASSERT(first >= 0);
2901 Q_ASSERT(first <= rowCount(parent));
2902 Q_ASSERT(last >= first);
2903 Q_D(QAbstractItemModel);
2904 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
2905 emit rowsAboutToBeInserted(parent, first, last, QPrivateSignal());
2906 d->rowsAboutToBeInserted(parent, first, last);
2917void QAbstractItemModel::endInsertRows()
2919 Q_D(QAbstractItemModel);
2920 QAbstractItemModelPrivate::Change change = d->changes.pop();
2921 d->rowsInserted(change.parent, change.first, change.last);
2922 emit rowsInserted(change.parent, change.first, change.last, QPrivateSignal());
2953void QAbstractItemModel::beginRemoveRows(
const QModelIndex &parent,
int first,
int last)
2955 Q_ASSERT(first >= 0);
2956 Q_ASSERT(last >= first);
2957 Q_ASSERT(last < rowCount(parent));
2958 Q_D(QAbstractItemModel);
2959 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
2960 emit rowsAboutToBeRemoved(parent, first, last, QPrivateSignal());
2961 d->rowsAboutToBeRemoved(parent, first, last);
2972void QAbstractItemModel::endRemoveRows()
2974 Q_D(QAbstractItemModel);
2975 QAbstractItemModelPrivate::Change change = d->changes.pop();
2976 d->rowsRemoved(change.parent, change.first, change.last);
2977 emit rowsRemoved(change.parent, change.first, change.last, QPrivateSignal());
2988bool QAbstractItemModelPrivate::allowMove(
const QModelIndex &srcParent,
int start,
int end,
const QModelIndex &destinationParent,
int destinationStart, Qt::Orientation orientation)
2991 if (destinationParent == srcParent)
2992 return !(destinationStart >= start && destinationStart <= end + 1);
2994 QModelIndex destinationAncestor = destinationParent;
2995 int pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
2997 if (destinationAncestor == srcParent) {
2998 if (pos >= start && pos <= end)
3003 if (!destinationAncestor.isValid())
3006 pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
3007 destinationAncestor = destinationAncestor.parent();
3110bool QAbstractItemModel::beginMoveRows(
const QModelIndex &sourceParent,
int sourceFirst,
int sourceLast,
const QModelIndex &destinationParent,
int destinationChild)
3112 Q_ASSERT(sourceFirst >= 0);
3113 Q_ASSERT(sourceLast >= sourceFirst);
3114 Q_ASSERT(destinationChild >= 0);
3115 Q_D(QAbstractItemModel);
3117 if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical)) {
3121 QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
3122 sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
3123 d->changes.push(sourceChange);
3124 int destinationLast = destinationChild + (sourceLast - sourceFirst);
3125 QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
3126 destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
3127 d->changes.push(destinationChange);
3129 emit rowsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
3130 d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical);
3145void QAbstractItemModel::endMoveRows()
3147 Q_D(QAbstractItemModel);
3149 QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
3150 QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
3152 QModelIndex adjustedSource = removeChange.parent;
3153 QModelIndex adjustedDestination = insertChange.parent;
3155 const int numMoved = removeChange.last - removeChange.first + 1;
3156 if (insertChange.needsAdjust)
3157 adjustedDestination = createIndex(adjustedDestination.row() - numMoved, adjustedDestination.column(), adjustedDestination.internalPointer());
3159 if (removeChange.needsAdjust)
3160 adjustedSource = createIndex(adjustedSource.row() + numMoved, adjustedSource.column(), adjustedSource.internalPointer());
3162 d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Vertical);
3164 emit rowsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
3208void QAbstractItemModel::beginInsertColumns(
const QModelIndex &parent,
int first,
int last)
3210 Q_ASSERT(first >= 0);
3211 Q_ASSERT(first <= columnCount(parent));
3212 Q_ASSERT(last >= first);
3213 Q_D(QAbstractItemModel);
3214 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3215 emit columnsAboutToBeInserted(parent, first, last, QPrivateSignal());
3216 d->columnsAboutToBeInserted(parent, first, last);
3228void QAbstractItemModel::endInsertColumns()
3230 Q_D(QAbstractItemModel);
3231 QAbstractItemModelPrivate::Change change = d->changes.pop();
3232 d->columnsInserted(change.parent, change.first, change.last);
3233 emit columnsInserted(change.parent, change.first, change.last, QPrivateSignal());
3264void QAbstractItemModel::beginRemoveColumns(
const QModelIndex &parent,
int first,
int last)
3266 Q_ASSERT(first >= 0);
3267 Q_ASSERT(last >= first);
3268 Q_ASSERT(last < columnCount(parent));
3269 Q_D(QAbstractItemModel);
3270 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3271 emit columnsAboutToBeRemoved(parent, first, last, QPrivateSignal());
3272 d->columnsAboutToBeRemoved(parent, first, last);
3283void QAbstractItemModel::endRemoveColumns()
3285 Q_D(QAbstractItemModel);
3286 QAbstractItemModelPrivate::Change change = d->changes.pop();
3287 d->columnsRemoved(change.parent, change.first, change.last);
3288 emit columnsRemoved(change.parent, change.first, change.last, QPrivateSignal());
3329bool QAbstractItemModel::beginMoveColumns(
const QModelIndex &sourceParent,
int sourceFirst,
int sourceLast,
const QModelIndex &destinationParent,
int destinationChild)
3331 Q_ASSERT(sourceFirst >= 0);
3332 Q_ASSERT(sourceLast >= sourceFirst);
3333 Q_ASSERT(destinationChild >= 0);
3334 Q_D(QAbstractItemModel);
3336 if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal)) {
3340 QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
3341 sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
3342 d->changes.push(sourceChange);
3343 int destinationLast = destinationChild + (sourceLast - sourceFirst);
3344 QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
3345 destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
3346 d->changes.push(destinationChange);
3348 emit columnsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
3349 d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal);
3364void QAbstractItemModel::endMoveColumns()
3366 Q_D(QAbstractItemModel);
3368 QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
3369 QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
3371 QModelIndex adjustedSource = removeChange.parent;
3372 QModelIndex adjustedDestination = insertChange.parent;
3374 const int numMoved = removeChange.last - removeChange.first + 1;
3375 if (insertChange.needsAdjust)
3376 adjustedDestination = createIndex(adjustedDestination.row(), adjustedDestination.column() - numMoved, adjustedDestination.internalPointer());
3378 if (removeChange.needsAdjust)
3379 adjustedSource = createIndex(adjustedSource.row(), adjustedSource.column() + numMoved, adjustedSource.internalPointer());
3381 d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Horizontal);
3382 emit columnsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
3456void QAbstractItemModel::changePersistentIndex(
const QModelIndex &from,
const QModelIndex &to)
3458 Q_D(QAbstractItemModel);
3459 if (d->persistent.indexes.isEmpty())
3462 const auto it = d->persistent.indexes.constFind(from);
3463 if (it != d->persistent.indexes.cend()) {
3464 QPersistentModelIndexData *data = *it;
3465 d->persistent.indexes.erase(it);
3468 d->persistent.insertMultiAtEnd(to, data);
3483void QAbstractItemModel::changePersistentIndexList(
const QModelIndexList &from,
3484 const QModelIndexList &to)
3486 Q_D(QAbstractItemModel);
3487 if (d->persistent.indexes.isEmpty())
3489 QList<QPersistentModelIndexData *> toBeReinserted;
3490 toBeReinserted.reserve(to.size());
3491 for (
int i = 0; i < from.size(); ++i) {
3492 if (from.at(i) == to.at(i))
3494 const auto it = d->persistent.indexes.constFind(from.at(i));
3495 if (it != d->persistent.indexes.cend()) {
3496 QPersistentModelIndexData *data = *it;
3497 d->persistent.indexes.erase(it);
3498 data->index = to.at(i);
3499 if (data->index.isValid())
3500 toBeReinserted << data;
3504 for (
auto *data : std::as_const(toBeReinserted))
3505 d->persistent.insertMultiAtEnd(data->index, data);
3597bool QAbstractItemModel::checkIndex(
const QModelIndex &index, CheckIndexOptions options)
const
3599 if (!index.isValid()) {
3600 if (options & CheckIndexOption::IndexIsValid) {
3601 qCWarning(lcCheckIndex) <<
"Index" << index <<
"is not valid (expected valid)";
3607 if (index.model() !=
this) {
3608 qCWarning(lcCheckIndex) <<
"Index" << index
3609 <<
"is for model" << index.model()
3610 <<
"which is different from this model" <<
this;
3614 if (index.row() < 0) {
3615 qCWarning(lcCheckIndex) <<
"Index" << index
3616 <<
"has negative row" << index.row();
3620 if (index.column() < 0) {
3621 qCWarning(lcCheckIndex) <<
"Index" << index
3622 <<
"has negative column" << index.column();
3626 if (!(options & CheckIndexOption::DoNotUseParent)) {
3627 const QModelIndex parentIndex = index.parent();
3628 if (options & CheckIndexOption::ParentIsInvalid) {
3629 if (parentIndex.isValid()) {
3630 qCWarning(lcCheckIndex) <<
"Index" << index
3631 <<
"has valid parent" << parentIndex
3632 <<
"(expected an invalid parent)";
3637 const int rc = rowCount(parentIndex);
3638 if (index.row() >= rc) {
3639 qCWarning(lcCheckIndex) <<
"Index" << index
3640 <<
"has out of range row" << index.row()
3641 <<
"rowCount() is" << rc;
3645 const int cc = columnCount(parentIndex);
3646 if (index.column() >= cc) {
3647 qCWarning(lcCheckIndex) <<
"Index" << index
3648 <<
"has out of range column" << index.column()
3649 <<
"columnCount() is" << cc;
3705void QAbstractItemModel::multiData(
const QModelIndex &index, QModelRoleDataSpan roleDataSpan)
const
3707 Q_ASSERT(checkIndex(index, CheckIndexOption::IndexIsValid));
3709 for (QModelRoleData &d : roleDataSpan)
3710 d.setData(data(index, d.role()));
4028bool QAbstractTableModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
4029 int row,
int column,
const QModelIndex &parent)
4031 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
4034 QStringList types = mimeTypes();
4035 if (types.isEmpty())
4037 QString format = types.at(0);
4038 if (!data->hasFormat(format))
4041 QByteArray encoded = data->data(format);
4042 QDataStream stream(&encoded, QDataStream::ReadOnly);
4045 if (parent.isValid() && row == -1 && column == -1) {
4048 QList<
int> rows, columns;
4049 QList<QMap<
int, QVariant>> data;
4051 while (!stream.atEnd()) {
4053 QMap<
int, QVariant> v;
4054 stream >> r >> c >> v;
4059 left = qMin(c, left);
4062 for (
int i = 0; i < data.size(); ++i) {
4063 int r = (rows.at(i) - top) + parent.row();
4064 int c = (columns.at(i) - left) + parent.column();
4066 setItemData(index(r, c), data.at(i));
4073 return decodeData(row, column, parent, stream);
4079bool QAbstractListModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
4080 int row,
int column,
const QModelIndex &parent)
4082 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
4085 QStringList types = mimeTypes();
4086 if (types.isEmpty())
4088 QString format = types.at(0);
4089 if (!data->hasFormat(format))
4092 QByteArray encoded = data->data(format);
4093 QDataStream stream(&encoded, QDataStream::ReadOnly);
4096 if (parent.isValid() && row == -1 && column == -1) {
4099 QList<
int> rows, columns;
4100 QList<QMap<
int, QVariant>> data;
4102 while (!stream.atEnd()) {
4104 QMap<
int, QVariant> v;
4105 stream >> r >> c >> v;
4110 left = qMin(c, left);
4113 for (
int i = 0; i < data.size(); ++i) {
4114 int r = (rows.at(i) - top) + parent.row();
4115 if (columns.at(i) == left && hasIndex(r, 0))
4116 setItemData(index(r), data.at(i));
4123 row = rowCount(parent);
4126 return decodeData(row, column, parent, stream);