2018QMap<
int, QVariant> QAbstractItemModel::itemData(
const QModelIndex &index)
const
2020 QMap<
int, QVariant> roles;
2021 for (
int i = 0; i < Qt::UserRole; ++i) {
2022 QVariant variantData = data(index, i);
2023 if (variantData.isValid())
2024 roles.insert(i, variantData);
2137QMimeData *QAbstractItemModel::mimeData(
const QModelIndexList &indexes)
const
2139 if (indexes.size() <= 0)
2141 QStringList types = mimeTypes();
2142 if (types.isEmpty())
2144 QMimeData *data =
new QMimeData();
2145 QString format = types.at(0);
2147 QDataStream stream(&encoded, QDataStream::WriteOnly);
2148 encodeData(indexes, stream);
2149 data->setData(format, encoded);
2166bool QAbstractItemModel::canDropMimeData(
const QMimeData *data, Qt::DropAction action,
2167 int row,
int column,
2168 const QModelIndex &parent)
const
2174 if (!(action & supportedDropActions()))
2177 const QStringList modelTypes = mimeTypes();
2178 for (
int i = 0; i < modelTypes.size(); ++i) {
2179 if (data->hasFormat(modelTypes.at(i)))
2214bool QAbstractItemModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
2215 int row,
int column,
const QModelIndex &parent)
2218 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
2221 QStringList types = mimeTypes();
2222 if (types.isEmpty())
2224 QString format = types.at(0);
2225 if (!data->hasFormat(format))
2227 if (row > rowCount(parent))
2228 row = rowCount(parent);
2230 row = rowCount(parent);
2234 QByteArray encoded = data->data(format);
2235 QDataStream stream(&encoded, QDataStream::ReadOnly);
2236 return decodeData(row, column, parent, stream);
2514QModelIndexList QAbstractItemModel::match(
const QModelIndex &start,
int role,
2515 const QVariant &value,
int hits,
2516 Qt::MatchFlags flags)
const
2518 QModelIndexList result;
2519 uint matchType = (flags & Qt::MatchTypeMask).toInt();
2520 Qt::CaseSensitivity cs = flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
2521 bool recurse = flags.testAnyFlag(Qt::MatchRecursive);
2522 bool wrap = flags.testAnyFlag(Qt::MatchWrap);
2523 bool allHits = (hits == -1);
2525#if QT_CONFIG(regularexpression)
2526 QRegularExpression rx;
2528 const int column = start.column();
2529 QModelIndex p = parent(start);
2530 int from = start.row();
2531 int to = rowCount(p);
2534 for (
int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) {
2535 for (
int r = from; (r < to) && (allHits || result.size() < hits); ++r) {
2536 QModelIndex idx = index(r, column, p);
2539 QVariant v = data(idx, role);
2541 if (matchType == Qt::MatchExactly) {
2545#if QT_CONFIG(regularexpression)
2546 if (matchType == Qt::MatchRegularExpression) {
2547 if (rx.pattern().isEmpty()) {
2548 if (value.userType() == QMetaType::QRegularExpression) {
2549 rx = value.toRegularExpression();
2551 rx.setPattern(value.toString());
2552 if (cs == Qt::CaseInsensitive)
2553 rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
2556 }
else if (matchType == Qt::MatchWildcard) {
2557 if (rx.pattern().isEmpty()) {
2558 const QString pattern = QRegularExpression::wildcardToRegularExpression(value.toString(), QRegularExpression::NonPathWildcardConversion);
2559 rx.setPattern(pattern);
2561 if (cs == Qt::CaseInsensitive)
2562 rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
2567 text = value.toString();
2570 QString t = v.toString();
2571 switch (matchType) {
2572#if QT_CONFIG(regularexpression)
2573 case Qt::MatchRegularExpression:
2575 case Qt::MatchWildcard:
2580 case Qt::MatchStartsWith:
2581 if (t.startsWith(text, cs))
2584 case Qt::MatchEndsWith:
2585 if (t.endsWith(text, cs))
2588 case Qt::MatchFixedString:
2589 if (t.compare(text, cs) == 0)
2592 case Qt::MatchContains:
2594 if (t.contains(text, cs))
2599 const auto parent = column != 0 ? idx.sibling(idx.row(), 0) : idx;
2600 if (hasChildren(parent)) {
2601 result += match(index(0, column, parent), role,
2602 (text.isEmpty() ? value : text),
2603 (allHits ? -1 : hits - result.size()), flags);
2766bool QAbstractItemModel::decodeData(
int row,
int column,
const QModelIndex &parent,
2767 QDataStream &stream)
2773 QList<
int> rows, columns;
2774 QList<QMap<
int, QVariant>> data;
2776 while (!stream.atEnd()) {
2778 QMap<
int, QVariant> v;
2779 stream >> r >> c >> v;
2784 left = qMin(c, left);
2785 bottom = qMax(r, bottom);
2786 right = qMax(c, right);
2791 int dragRowCount = 0;
2792 int dragColumnCount = right - left + 1;
2795 QList<
int> rowsToInsert(bottom + 1);
2796 for (
int i = 0; i < rows.size(); ++i)
2797 rowsToInsert[rows.at(i)] = 1;
2798 for (
int i = 0; i < rowsToInsert.size(); ++i) {
2799 if (rowsToInsert.at(i) == 1){
2800 rowsToInsert[i] = dragRowCount;
2804 for (
int i = 0; i < rows.size(); ++i)
2805 rows[i] = top + rowsToInsert.at(rows.at(i));
2807 QBitArray isWrittenTo(dragRowCount * dragColumnCount);
2810 int colCount = columnCount(parent);
2811 if (colCount == 0) {
2812 insertColumns(colCount, dragColumnCount - colCount, parent);
2813 colCount = columnCount(parent);
2815 insertRows(row, dragRowCount, parent);
2818 column = qMax(0, column);
2820 QList<QPersistentModelIndex> newIndexes(data.size());
2822 for (
int j = 0; j < data.size(); ++j) {
2823 int relativeRow = rows.at(j) - top;
2824 int relativeColumn = columns.at(j) - left;
2825 int destinationRow = relativeRow + row;
2826 int destinationColumn = relativeColumn + column;
2827 int flat = (relativeRow * dragColumnCount) + relativeColumn;
2829 if (destinationColumn >= colCount || isWrittenTo.testBit(flat)) {
2830 destinationColumn = qBound(column, destinationColumn, colCount - 1);
2831 destinationRow = row + dragRowCount;
2832 insertRows(row + dragRowCount, 1, parent);
2833 flat = (dragRowCount * dragColumnCount) + relativeColumn;
2834 isWrittenTo.resize(++dragRowCount * dragColumnCount);
2836 if (!isWrittenTo.testBit(flat)) {
2837 newIndexes[j] = index(destinationRow, destinationColumn, parent);
2838 isWrittenTo.setBit(flat);
2842 for(
int k = 0; k < newIndexes.size(); k++) {
2843 if (newIndexes.at(k).isValid())
2844 setItemData(newIndexes.at(k), data.at(k));
2890void QAbstractItemModel::beginInsertRows(
const QModelIndex &parent,
int first,
int last)
2892 Q_ASSERT(first >= 0);
2893 Q_ASSERT(first <= rowCount(parent));
2894 Q_ASSERT(last >= first);
2895 Q_D(QAbstractItemModel);
2896 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
2897 emit rowsAboutToBeInserted(parent, first, last, QPrivateSignal());
2898 d->rowsAboutToBeInserted(parent, first, last);
2909void QAbstractItemModel::endInsertRows()
2911 Q_D(QAbstractItemModel);
2912 QAbstractItemModelPrivate::Change change = d->changes.pop();
2913 d->rowsInserted(change.parent, change.first, change.last);
2914 emit rowsInserted(change.parent, change.first, change.last, QPrivateSignal());
2945void QAbstractItemModel::beginRemoveRows(
const QModelIndex &parent,
int first,
int last)
2947 Q_ASSERT(first >= 0);
2948 Q_ASSERT(last >= first);
2949 Q_ASSERT(last < rowCount(parent));
2950 Q_D(QAbstractItemModel);
2951 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
2952 emit rowsAboutToBeRemoved(parent, first, last, QPrivateSignal());
2953 d->rowsAboutToBeRemoved(parent, first, last);
2964void QAbstractItemModel::endRemoveRows()
2966 Q_D(QAbstractItemModel);
2967 QAbstractItemModelPrivate::Change change = d->changes.pop();
2968 d->rowsRemoved(change.parent, change.first, change.last);
2969 emit rowsRemoved(change.parent, change.first, change.last, QPrivateSignal());
2980bool QAbstractItemModelPrivate::allowMove(
const QModelIndex &srcParent,
int start,
int end,
const QModelIndex &destinationParent,
int destinationStart, Qt::Orientation orientation)
2983 if (destinationParent == srcParent)
2984 return !(destinationStart >= start && destinationStart <= end + 1);
2986 QModelIndex destinationAncestor = destinationParent;
2987 int pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
2989 if (destinationAncestor == srcParent) {
2990 if (pos >= start && pos <= end)
2995 if (!destinationAncestor.isValid())
2998 pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
2999 destinationAncestor = destinationAncestor.parent();
3102bool QAbstractItemModel::beginMoveRows(
const QModelIndex &sourceParent,
int sourceFirst,
int sourceLast,
const QModelIndex &destinationParent,
int destinationChild)
3104 Q_ASSERT(sourceFirst >= 0);
3105 Q_ASSERT(sourceLast >= sourceFirst);
3106 Q_ASSERT(destinationChild >= 0);
3107 Q_D(QAbstractItemModel);
3109 if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical)) {
3113 QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
3114 sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
3115 d->changes.push(sourceChange);
3116 int destinationLast = destinationChild + (sourceLast - sourceFirst);
3117 QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
3118 destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
3119 d->changes.push(destinationChange);
3121 emit rowsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
3122 d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical);
3137void QAbstractItemModel::endMoveRows()
3139 Q_D(QAbstractItemModel);
3141 QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
3142 QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
3144 QModelIndex adjustedSource = removeChange.parent;
3145 QModelIndex adjustedDestination = insertChange.parent;
3147 const int numMoved = removeChange.last - removeChange.first + 1;
3148 if (insertChange.needsAdjust)
3149 adjustedDestination = createIndex(adjustedDestination.row() - numMoved, adjustedDestination.column(), adjustedDestination.internalPointer());
3151 if (removeChange.needsAdjust)
3152 adjustedSource = createIndex(adjustedSource.row() + numMoved, adjustedSource.column(), adjustedSource.internalPointer());
3154 d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Vertical);
3156 emit rowsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
3200void QAbstractItemModel::beginInsertColumns(
const QModelIndex &parent,
int first,
int last)
3202 Q_ASSERT(first >= 0);
3203 Q_ASSERT(first <= columnCount(parent));
3204 Q_ASSERT(last >= first);
3205 Q_D(QAbstractItemModel);
3206 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3207 emit columnsAboutToBeInserted(parent, first, last, QPrivateSignal());
3208 d->columnsAboutToBeInserted(parent, first, last);
3220void QAbstractItemModel::endInsertColumns()
3222 Q_D(QAbstractItemModel);
3223 QAbstractItemModelPrivate::Change change = d->changes.pop();
3224 d->columnsInserted(change.parent, change.first, change.last);
3225 emit columnsInserted(change.parent, change.first, change.last, QPrivateSignal());
3256void QAbstractItemModel::beginRemoveColumns(
const QModelIndex &parent,
int first,
int last)
3258 Q_ASSERT(first >= 0);
3259 Q_ASSERT(last >= first);
3260 Q_ASSERT(last < columnCount(parent));
3261 Q_D(QAbstractItemModel);
3262 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3263 emit columnsAboutToBeRemoved(parent, first, last, QPrivateSignal());
3264 d->columnsAboutToBeRemoved(parent, first, last);
3275void QAbstractItemModel::endRemoveColumns()
3277 Q_D(QAbstractItemModel);
3278 QAbstractItemModelPrivate::Change change = d->changes.pop();
3279 d->columnsRemoved(change.parent, change.first, change.last);
3280 emit columnsRemoved(change.parent, change.first, change.last, QPrivateSignal());
3321bool QAbstractItemModel::beginMoveColumns(
const QModelIndex &sourceParent,
int sourceFirst,
int sourceLast,
const QModelIndex &destinationParent,
int destinationChild)
3323 Q_ASSERT(sourceFirst >= 0);
3324 Q_ASSERT(sourceLast >= sourceFirst);
3325 Q_ASSERT(destinationChild >= 0);
3326 Q_D(QAbstractItemModel);
3328 if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal)) {
3332 QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
3333 sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
3334 d->changes.push(sourceChange);
3335 int destinationLast = destinationChild + (sourceLast - sourceFirst);
3336 QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
3337 destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
3338 d->changes.push(destinationChange);
3340 emit columnsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
3341 d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal);
3356void QAbstractItemModel::endMoveColumns()
3358 Q_D(QAbstractItemModel);
3360 QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
3361 QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
3363 QModelIndex adjustedSource = removeChange.parent;
3364 QModelIndex adjustedDestination = insertChange.parent;
3366 const int numMoved = removeChange.last - removeChange.first + 1;
3367 if (insertChange.needsAdjust)
3368 adjustedDestination = createIndex(adjustedDestination.row(), adjustedDestination.column() - numMoved, adjustedDestination.internalPointer());
3370 if (removeChange.needsAdjust)
3371 adjustedSource = createIndex(adjustedSource.row(), adjustedSource.column() + numMoved, adjustedSource.internalPointer());
3373 d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Horizontal);
3374 emit columnsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
3448void QAbstractItemModel::changePersistentIndex(
const QModelIndex &from,
const QModelIndex &to)
3450 Q_D(QAbstractItemModel);
3451 if (d->persistent.indexes.isEmpty())
3454 const auto it = d->persistent.indexes.constFind(from);
3455 if (it != d->persistent.indexes.cend()) {
3456 QPersistentModelIndexData *data = *it;
3457 d->persistent.indexes.erase(it);
3460 d->persistent.insertMultiAtEnd(to, data);
3475void QAbstractItemModel::changePersistentIndexList(
const QModelIndexList &from,
3476 const QModelIndexList &to)
3478 Q_D(QAbstractItemModel);
3479 if (d->persistent.indexes.isEmpty())
3481 QList<QPersistentModelIndexData *> toBeReinserted;
3482 toBeReinserted.reserve(to.size());
3483 for (
int i = 0; i < from.size(); ++i) {
3484 if (from.at(i) == to.at(i))
3486 const auto it = d->persistent.indexes.constFind(from.at(i));
3487 if (it != d->persistent.indexes.cend()) {
3488 QPersistentModelIndexData *data = *it;
3489 d->persistent.indexes.erase(it);
3490 data->index = to.at(i);
3491 if (data->index.isValid())
3492 toBeReinserted << data;
3496 for (
auto *data : std::as_const(toBeReinserted))
3497 d->persistent.insertMultiAtEnd(data->index, data);
3589bool QAbstractItemModel::checkIndex(
const QModelIndex &index, CheckIndexOptions options)
const
3591 if (!index.isValid()) {
3592 if (options & CheckIndexOption::IndexIsValid) {
3593 qCWarning(lcCheckIndex) <<
"Index" << index <<
"is not valid (expected valid)";
3599 if (index.model() !=
this) {
3600 qCWarning(lcCheckIndex) <<
"Index" << index
3601 <<
"is for model" << index.model()
3602 <<
"which is different from this model" <<
this;
3606 if (index.row() < 0) {
3607 qCWarning(lcCheckIndex) <<
"Index" << index
3608 <<
"has negative row" << index.row();
3612 if (index.column() < 0) {
3613 qCWarning(lcCheckIndex) <<
"Index" << index
3614 <<
"has negative column" << index.column();
3618 if (!(options & CheckIndexOption::DoNotUseParent)) {
3619 const QModelIndex parentIndex = index.parent();
3620 if (options & CheckIndexOption::ParentIsInvalid) {
3621 if (parentIndex.isValid()) {
3622 qCWarning(lcCheckIndex) <<
"Index" << index
3623 <<
"has valid parent" << parentIndex
3624 <<
"(expected an invalid parent)";
3629 const int rc = rowCount(parentIndex);
3630 if (index.row() >= rc) {
3631 qCWarning(lcCheckIndex) <<
"Index" << index
3632 <<
"has out of range row" << index.row()
3633 <<
"rowCount() is" << rc;
3637 const int cc = columnCount(parentIndex);
3638 if (index.column() >= cc) {
3639 qCWarning(lcCheckIndex) <<
"Index" << index
3640 <<
"has out of range column" << index.column()
3641 <<
"columnCount() is" << cc;
3697void QAbstractItemModel::multiData(
const QModelIndex &index, QModelRoleDataSpan roleDataSpan)
const
3699 Q_ASSERT(checkIndex(index, CheckIndexOption::IndexIsValid));
3701 for (QModelRoleData &d : roleDataSpan)
3702 d.setData(data(index, d.role()));
4020bool QAbstractTableModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
4021 int row,
int column,
const QModelIndex &parent)
4023 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
4026 QStringList types = mimeTypes();
4027 if (types.isEmpty())
4029 QString format = types.at(0);
4030 if (!data->hasFormat(format))
4033 QByteArray encoded = data->data(format);
4034 QDataStream stream(&encoded, QDataStream::ReadOnly);
4037 if (parent.isValid() && row == -1 && column == -1) {
4040 QList<
int> rows, columns;
4041 QList<QMap<
int, QVariant>> data;
4043 while (!stream.atEnd()) {
4045 QMap<
int, QVariant> v;
4046 stream >> r >> c >> v;
4051 left = qMin(c, left);
4054 for (
int i = 0; i < data.size(); ++i) {
4055 int r = (rows.at(i) - top) + parent.row();
4056 int c = (columns.at(i) - left) + parent.column();
4058 setItemData(index(r, c), data.at(i));
4065 return decodeData(row, column, parent, stream);
4071bool QAbstractListModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
4072 int row,
int column,
const QModelIndex &parent)
4074 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
4077 QStringList types = mimeTypes();
4078 if (types.isEmpty())
4080 QString format = types.at(0);
4081 if (!data->hasFormat(format))
4084 QByteArray encoded = data->data(format);
4085 QDataStream stream(&encoded, QDataStream::ReadOnly);
4088 if (parent.isValid() && row == -1 && column == -1) {
4091 QList<
int> rows, columns;
4092 QList<QMap<
int, QVariant>> data;
4094 while (!stream.atEnd()) {
4096 QMap<
int, QVariant> v;
4097 stream >> r >> c >> v;
4102 left = qMin(c, left);
4105 for (
int i = 0; i < data.size(); ++i) {
4106 int r = (rows.at(i) - top) + parent.row();
4107 if (columns.at(i) == left && hasIndex(r, 0))
4108 setItemData(index(r), data.at(i));
4115 row = rowCount(parent);
4118 return decodeData(row, column, parent, stream);