2072QMap<
int, QVariant> QAbstractItemModel::itemData(
const QModelIndex &index)
const
2074 QMap<
int, QVariant> roles;
2075 for (
int i = 0; i < Qt::UserRole; ++i) {
2076 QVariant variantData = data(index, i);
2077 if (variantData.isValid())
2078 roles.insert(i, variantData);
2141bool QAbstractItemModel::setItemData(
const QModelIndex &index,
const QMap<
int, QVariant> &roles)
2143 if (!index.isValid() || roles.isEmpty())
2152 for (
auto it = roles.begin(), e = roles.end(); it != e; ++it) {
2153 if (!setData(index, it.value(), it.key()))
2193QMimeData *QAbstractItemModel::mimeData(
const QModelIndexList &indexes)
const
2195 if (indexes.size() <= 0)
2197 QStringList types = mimeTypes();
2198 if (types.isEmpty())
2200 QMimeData *data =
new QMimeData();
2201 QString format = types.at(0);
2203 QDataStream stream(&encoded, QDataStream::WriteOnly);
2204 encodeData(indexes, stream);
2205 data->setData(format, encoded);
2222bool QAbstractItemModel::canDropMimeData(
const QMimeData *data, Qt::DropAction action,
2223 int row,
int column,
2224 const QModelIndex &parent)
const
2230 if (!(action & supportedDropActions()))
2233 const QStringList modelTypes = mimeTypes();
2234 for (
int i = 0; i < modelTypes.size(); ++i) {
2235 if (data->hasFormat(modelTypes.at(i)))
2270bool QAbstractItemModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
2271 int row,
int column,
const QModelIndex &parent)
2274 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
2277 const QStringList types = mimeTypes();
2278 if (types.isEmpty())
2280 const QString format = types.at(0);
2281 if (!data->hasFormat(format))
2283 const bool dropOnItem = row == -1 && column == -1 && parent.isValid();
2284 if (!dropOnItem || !parent.flags().testFlag(Qt::ItemNeverHasChildren)) {
2287 if (row > rowCount(parent))
2288 row = rowCount(parent);
2290 row = rowCount(parent);
2295 QByteArray encoded = data->data(format);
2296 QDataStream stream(&encoded, QDataStream::ReadOnly);
2297 return decodeData(row, column, parent, stream);
2575QModelIndexList QAbstractItemModel::match(
const QModelIndex &start,
int role,
2576 const QVariant &value,
int hits,
2577 Qt::MatchFlags flags)
const
2579 QModelIndexList result;
2580 uint matchType = (flags & Qt::MatchTypeMask).toInt();
2581 Qt::CaseSensitivity cs = flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
2582 bool recurse = flags.testAnyFlag(Qt::MatchRecursive);
2583 bool wrap = flags.testAnyFlag(Qt::MatchWrap);
2584 bool allHits = (hits == -1);
2586#if QT_CONFIG(regularexpression)
2587 QRegularExpression rx;
2589 const int column = start.column();
2590 QModelIndex p = parent(start);
2591 int from = start.row();
2592 int to = rowCount(p);
2595 for (
int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) {
2596 for (
int r = from; (r < to) && (allHits || result.size() < hits); ++r) {
2597 QModelIndex idx = index(r, column, p);
2600 QVariant v = data(idx, role);
2602 if (matchType == Qt::MatchExactly) {
2606#if QT_CONFIG(regularexpression)
2607 if (matchType == Qt::MatchRegularExpression) {
2608 if (rx.pattern().isEmpty()) {
2609 if (value.userType() == QMetaType::QRegularExpression) {
2610 rx = value.toRegularExpression();
2612 rx.setPattern(value.toString());
2613 if (cs == Qt::CaseInsensitive)
2614 rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
2617 }
else if (matchType == Qt::MatchWildcard) {
2618 if (rx.pattern().isEmpty()) {
2619 const QString pattern = QRegularExpression::wildcardToRegularExpression(value.toString(), QRegularExpression::NonPathWildcardConversion);
2620 rx.setPattern(pattern);
2622 if (cs == Qt::CaseInsensitive)
2623 rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
2628 text = value.toString();
2631 QString t = v.toString();
2632 switch (matchType) {
2633#if QT_CONFIG(regularexpression)
2634 case Qt::MatchRegularExpression:
2636 case Qt::MatchWildcard:
2641 case Qt::MatchStartsWith:
2642 if (t.startsWith(text, cs))
2645 case Qt::MatchEndsWith:
2646 if (t.endsWith(text, cs))
2649 case Qt::MatchFixedString:
2650 if (t.compare(text, cs) == 0)
2653 case Qt::MatchContains:
2655 if (t.contains(text, cs))
2660 const auto parent = column != 0 ? idx.sibling(idx.row(), 0) : idx;
2661 if (hasChildren(parent)) {
2662 result += match(index(0, column, parent), role,
2663 (text.isEmpty() ? value : text),
2664 (allHits ? -1 : hits - result.size()), flags);
2830bool QAbstractItemModel::decodeData(
int row,
int column,
const QModelIndex &parent,
2831 QDataStream &stream)
2837 QList<
int> rows, columns;
2838 QList<QMap<
int, QVariant>> data;
2840 while (!stream.atEnd()) {
2842 QMap<
int, QVariant> v;
2843 stream >> r >> c >> v;
2848 left = qMin(c, left);
2849 bottom = qMax(r, bottom);
2850 right = qMax(c, right);
2855 int dragRowCount = 0;
2856 int dragColumnCount = right - left + 1;
2859 QList<
int> rowsToInsert(bottom + 1);
2860 for (
int i = 0; i < rows.size(); ++i)
2861 rowsToInsert[rows.at(i)] = 1;
2862 for (
int i = 0; i < rowsToInsert.size(); ++i) {
2863 if (rowsToInsert.at(i) == 1){
2864 rowsToInsert[i] = dragRowCount;
2868 for (
int i = 0; i < rows.size(); ++i)
2869 rows[i] = top + rowsToInsert.at(rows.at(i));
2871 QBitArray isWrittenTo(dragRowCount * dragColumnCount);
2874 int colCount = columnCount(parent);
2875 if (colCount == 0) {
2876 insertColumns(colCount, dragColumnCount - colCount, parent);
2877 colCount = columnCount(parent);
2879 insertRows(row, dragRowCount, parent);
2882 column = qMax(0, column);
2884 QList<QPersistentModelIndex> newIndexes(data.size());
2886 for (
int j = 0; j < data.size(); ++j) {
2887 int relativeRow = rows.at(j) - top;
2888 int relativeColumn = columns.at(j) - left;
2889 int destinationRow = relativeRow + row;
2890 int destinationColumn = relativeColumn + column;
2891 int flat = (relativeRow * dragColumnCount) + relativeColumn;
2893 if (destinationColumn >= colCount || isWrittenTo.testBit(flat)) {
2894 destinationColumn = qBound(column, destinationColumn, qMax(colCount - 1, column));
2895 destinationRow = row + dragRowCount;
2896 insertRows(row + dragRowCount, 1, parent);
2897 flat = (dragRowCount * dragColumnCount) + relativeColumn;
2898 isWrittenTo.resize(++dragRowCount * dragColumnCount);
2900 if (!isWrittenTo.testBit(flat)) {
2901 newIndexes[j] = index(destinationRow, destinationColumn, parent);
2902 isWrittenTo.setBit(flat);
2906 for(
int k = 0; k < newIndexes.size(); k++) {
2907 if (newIndexes.at(k).isValid())
2908 setItemData(newIndexes.at(k), data.at(k));
2956void QAbstractItemModel::beginInsertRows(
const QModelIndex &parent,
int first,
int last)
2958 Q_ASSERT(first >= 0);
2959 Q_ASSERT(first <= rowCount(parent));
2960 Q_ASSERT(last >= first);
2961 Q_D(QAbstractItemModel);
2962 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
2963 emit rowsAboutToBeInserted(parent, first, last, QPrivateSignal());
2964 d->rowsAboutToBeInserted(parent, first, last);
2975void QAbstractItemModel::endInsertRows()
2977 Q_D(QAbstractItemModel);
2978 QAbstractItemModelPrivate::Change change = d->changes.pop();
2979 d->rowsInserted(change.parent, change.first, change.last);
2980 emit rowsInserted(change.parent, change.first, change.last, QPrivateSignal());
3012void QAbstractItemModel::beginRemoveRows(
const QModelIndex &parent,
int first,
int last)
3014 Q_ASSERT(first >= 0);
3015 Q_ASSERT(last >= first);
3016 Q_ASSERT(last < rowCount(parent));
3017 Q_D(QAbstractItemModel);
3018 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3019 emit rowsAboutToBeRemoved(parent, first, last, QPrivateSignal());
3020 d->rowsAboutToBeRemoved(parent, first, last);
3031void QAbstractItemModel::endRemoveRows()
3033 Q_D(QAbstractItemModel);
3034 QAbstractItemModelPrivate::Change change = d->changes.pop();
3035 d->rowsRemoved(change.parent, change.first, change.last);
3036 emit rowsRemoved(change.parent, change.first, change.last, QPrivateSignal());
3047bool QAbstractItemModelPrivate::allowMove(
const QModelIndex &srcParent,
int start,
int end,
const QModelIndex &destinationParent,
int destinationStart, Qt::Orientation orientation)
3050 if (destinationParent == srcParent)
3051 return !(destinationStart >= start && destinationStart <= end + 1);
3053 QModelIndex destinationAncestor = destinationParent;
3054 int pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
3056 if (destinationAncestor == srcParent) {
3057 if (pos >= start && pos <= end)
3062 if (!destinationAncestor.isValid())
3065 pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
3066 destinationAncestor = destinationAncestor.parent();
3173bool QAbstractItemModel::beginMoveRows(
const QModelIndex &sourceParent,
int sourceFirst,
int sourceLast,
const QModelIndex &destinationParent,
int destinationChild)
3175 Q_ASSERT(sourceFirst >= 0);
3176 Q_ASSERT(sourceLast >= sourceFirst);
3177 Q_ASSERT(destinationChild >= 0);
3178 Q_D(QAbstractItemModel);
3180 if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical)) {
3184 QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
3185 sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
3186 d->changes.push(sourceChange);
3187 int destinationLast = destinationChild + (sourceLast - sourceFirst);
3188 QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
3189 destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
3190 d->changes.push(destinationChange);
3192 emit rowsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
3193 d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical);
3208void QAbstractItemModel::endMoveRows()
3210 Q_D(QAbstractItemModel);
3212 QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
3213 QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
3215 QModelIndex adjustedSource = removeChange.parent;
3216 QModelIndex adjustedDestination = insertChange.parent;
3218 const int numMoved = removeChange.last - removeChange.first + 1;
3219 if (insertChange.needsAdjust)
3220 adjustedDestination = createIndex(adjustedDestination.row() - numMoved, adjustedDestination.column(), adjustedDestination.internalPointer());
3222 if (removeChange.needsAdjust)
3223 adjustedSource = createIndex(adjustedSource.row() + numMoved, adjustedSource.column(), adjustedSource.internalPointer());
3225 d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Vertical);
3227 emit rowsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
3273void QAbstractItemModel::beginInsertColumns(
const QModelIndex &parent,
int first,
int last)
3275 Q_ASSERT(first >= 0);
3276 Q_ASSERT(first <= columnCount(parent));
3277 Q_ASSERT(last >= first);
3278 Q_D(QAbstractItemModel);
3279 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3280 emit columnsAboutToBeInserted(parent, first, last, QPrivateSignal());
3281 d->columnsAboutToBeInserted(parent, first, last);
3293void QAbstractItemModel::endInsertColumns()
3295 Q_D(QAbstractItemModel);
3296 QAbstractItemModelPrivate::Change change = d->changes.pop();
3297 d->columnsInserted(change.parent, change.first, change.last);
3298 emit columnsInserted(change.parent, change.first, change.last, QPrivateSignal());
3330void QAbstractItemModel::beginRemoveColumns(
const QModelIndex &parent,
int first,
int last)
3332 Q_ASSERT(first >= 0);
3333 Q_ASSERT(last >= first);
3334 Q_ASSERT(last < columnCount(parent));
3335 Q_D(QAbstractItemModel);
3336 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3337 emit columnsAboutToBeRemoved(parent, first, last, QPrivateSignal());
3338 d->columnsAboutToBeRemoved(parent, first, last);
3349void QAbstractItemModel::endRemoveColumns()
3351 Q_D(QAbstractItemModel);
3352 QAbstractItemModelPrivate::Change change = d->changes.pop();
3353 d->columnsRemoved(change.parent, change.first, change.last);
3354 emit columnsRemoved(change.parent, change.first, change.last, QPrivateSignal());
3395bool QAbstractItemModel::beginMoveColumns(
const QModelIndex &sourceParent,
int sourceFirst,
int sourceLast,
const QModelIndex &destinationParent,
int destinationChild)
3397 Q_ASSERT(sourceFirst >= 0);
3398 Q_ASSERT(sourceLast >= sourceFirst);
3399 Q_ASSERT(destinationChild >= 0);
3400 Q_D(QAbstractItemModel);
3402 if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal)) {
3406 QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
3407 sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
3408 d->changes.push(sourceChange);
3409 int destinationLast = destinationChild + (sourceLast - sourceFirst);
3410 QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
3411 destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
3412 d->changes.push(destinationChange);
3414 emit columnsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
3415 d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal);
3430void QAbstractItemModel::endMoveColumns()
3432 Q_D(QAbstractItemModel);
3434 QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
3435 QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
3437 QModelIndex adjustedSource = removeChange.parent;
3438 QModelIndex adjustedDestination = insertChange.parent;
3440 const int numMoved = removeChange.last - removeChange.first + 1;
3441 if (insertChange.needsAdjust)
3442 adjustedDestination = createIndex(adjustedDestination.row(), adjustedDestination.column() - numMoved, adjustedDestination.internalPointer());
3444 if (removeChange.needsAdjust)
3445 adjustedSource = createIndex(adjustedSource.row(), adjustedSource.column() + numMoved, adjustedSource.internalPointer());
3447 d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Horizontal);
3448 emit columnsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
3522void QAbstractItemModel::changePersistentIndex(
const QModelIndex &from,
const QModelIndex &to)
3524 Q_D(QAbstractItemModel);
3525 if (d->persistent.indexes.isEmpty())
3528 const auto it = d->persistent.indexes.constFind(from);
3529 if (it != d->persistent.indexes.cend()) {
3530 QPersistentModelIndexData *data = *it;
3531 d->persistent.indexes.erase(it);
3534 d->persistent.insertMultiAtEnd(to, data);
3549void QAbstractItemModel::changePersistentIndexList(
const QModelIndexList &from,
3550 const QModelIndexList &to)
3552 Q_D(QAbstractItemModel);
3553 if (d->persistent.indexes.isEmpty())
3555 QList<QPersistentModelIndexData *> toBeReinserted;
3556 toBeReinserted.reserve(to.size());
3557 for (
int i = 0; i < from.size(); ++i) {
3558 if (from.at(i) == to.at(i))
3560 const auto it = d->persistent.indexes.constFind(from.at(i));
3561 if (it != d->persistent.indexes.cend()) {
3562 QPersistentModelIndexData *data = *it;
3563 d->persistent.indexes.erase(it);
3564 data->index = to.at(i);
3565 if (data->index.isValid())
3566 toBeReinserted << data;
3570 for (
auto *data : std::as_const(toBeReinserted))
3571 d->persistent.insertMultiAtEnd(data->index, data);
3663bool QAbstractItemModel::checkIndex(
const QModelIndex &index, CheckIndexOptions options)
const
3665 if (!index.isValid()) {
3666 if (options & CheckIndexOption::IndexIsValid) {
3667 qCWarning(lcCheckIndex) <<
"Index" << index <<
"is not valid (expected valid)";
3673 if (index.model() !=
this) {
3674 qCWarning(lcCheckIndex) <<
"Index" << index
3675 <<
"is for model" << index.model()
3676 <<
"which is different from this model" <<
this;
3680 if (index.row() < 0) {
3681 qCWarning(lcCheckIndex) <<
"Index" << index
3682 <<
"has negative row" << index.row();
3686 if (index.column() < 0) {
3687 qCWarning(lcCheckIndex) <<
"Index" << index
3688 <<
"has negative column" << index.column();
3692 if (!(options & CheckIndexOption::DoNotUseParent)) {
3693 const QModelIndex parentIndex = index.parent();
3694 if (options & CheckIndexOption::ParentIsInvalid) {
3695 if (parentIndex.isValid()) {
3696 qCWarning(lcCheckIndex) <<
"Index" << index
3697 <<
"has valid parent" << parentIndex
3698 <<
"(expected an invalid parent)";
3703 const int rc = rowCount(parentIndex);
3704 if (index.row() >= rc) {
3705 qCWarning(lcCheckIndex) <<
"Index" << index
3706 <<
"has out of range row" << index.row()
3707 <<
"rowCount() is" << rc;
3711 const int cc = columnCount(parentIndex);
3712 if (index.column() >= cc) {
3713 qCWarning(lcCheckIndex) <<
"Index" << index
3714 <<
"has out of range column" << index.column()
3715 <<
"columnCount() is" << cc;
3771void QAbstractItemModel::multiData(
const QModelIndex &index, QModelRoleDataSpan roleDataSpan)
const
3773 Q_ASSERT(checkIndex(index, CheckIndexOption::IndexIsValid));
3775 for (QModelRoleData &d : roleDataSpan)
3776 d.setData(data(index, d.role()));
4091bool QAbstractItemModelPrivate::dropOnItem(
const QModelIndex &index, QDataStream &stream)
4093 Q_Q(QAbstractItemModel);
4097 QList<
int> rows, columns;
4098 QList<QMap<
int, QVariant>> data;
4100 while (!stream.atEnd()) {
4102 QMap<
int, QVariant> v;
4103 stream >> r >> c >> v;
4108 left = qMin(c, left);
4111 for (
int i = 0; i < data.size(); ++i) {
4112 int r = (rows.at(i) - top) + index.row();
4113 int c = (columns.at(i) - left) + index.column();
4114 if (q->hasIndex(r, c))
4115 q->setItemData(q->index(r, c), data.at(i));
4124bool QAbstractTableModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
4125 int row,
int column,
const QModelIndex &parent)
4127 Q_D(QAbstractItemModel);
4128 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
4131 QStringList types = mimeTypes();
4132 if (types.isEmpty())
4134 QString format = types.at(0);
4135 if (!data->hasFormat(format))
4138 QByteArray encoded = data->data(format);
4139 QDataStream stream(&encoded, QDataStream::ReadOnly);
4142 if (parent.isValid() && row == -1 && column == -1)
4143 return d->dropOnItem(parent, stream);
4146 row = rowCount(parent);
4149 return decodeData(row, column, parent, stream);
4155bool QAbstractListModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
4156 int row,
int column,
const QModelIndex &parent)
4158 Q_D(QAbstractItemModel);
4159 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
4162 QStringList types = mimeTypes();
4163 if (types.isEmpty())
4165 QString format = types.at(0);
4166 if (!data->hasFormat(format))
4169 QByteArray encoded = data->data(format);
4170 QDataStream stream(&encoded, QDataStream::ReadOnly);
4173 if (parent.isValid() && row == -1 && column == -1)
4174 return d->dropOnItem(parent, stream);
4177 row = rowCount(parent);
4180 return decodeData(row, column, parent, stream);