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()))
2194QMimeData *QAbstractItemModel::mimeData(
const QModelIndexList &indexes)
const
2196 if (indexes.size() <= 0)
2198 QStringList types = mimeTypes();
2199 if (types.isEmpty())
2201 QMimeData *data =
new QMimeData();
2202 QString format = types.at(0);
2204 QDataStream stream(&encoded, QDataStream::WriteOnly);
2205 encodeData(indexes, stream);
2206 data->setData(format, encoded);
2223bool QAbstractItemModel::canDropMimeData(
const QMimeData *data, Qt::DropAction action,
2224 int row,
int column,
2225 const QModelIndex &parent)
const
2231 if (!(action & supportedDropActions()))
2234 const QStringList modelTypes = mimeTypes();
2235 for (
int i = 0; i < modelTypes.size(); ++i) {
2236 if (data->hasFormat(modelTypes.at(i)))
2271bool QAbstractItemModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
2272 int row,
int column,
const QModelIndex &parent)
2275 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
2278 const QStringList types = mimeTypes();
2279 if (types.isEmpty())
2281 const QString format = types.at(0);
2282 if (!data->hasFormat(format))
2284 const bool dropOnItem = row == -1 && column == -1 && parent.isValid();
2285 if (!dropOnItem || !parent.flags().testFlag(Qt::ItemNeverHasChildren)) {
2288 if (row > rowCount(parent))
2289 row = rowCount(parent);
2291 row = rowCount(parent);
2296 QByteArray encoded = data->data(format);
2297 QDataStream stream(&encoded, QDataStream::ReadOnly);
2298 return decodeData(row, column, parent, stream);
2576QModelIndexList QAbstractItemModel::match(
const QModelIndex &start,
int role,
2577 const QVariant &value,
int hits,
2578 Qt::MatchFlags flags)
const
2580 QModelIndexList result;
2581 uint matchType = (flags & Qt::MatchTypeMask).toInt();
2582 Qt::CaseSensitivity cs = flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
2583 bool recurse = flags.testAnyFlag(Qt::MatchRecursive);
2584 bool wrap = flags.testAnyFlag(Qt::MatchWrap);
2585 bool allHits = (hits == -1);
2587#if QT_CONFIG(regularexpression)
2588 QRegularExpression rx;
2590 const int column = start.column();
2591 QModelIndex p = parent(start);
2592 int from = start.row();
2593 int to = rowCount(p);
2596 for (
int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) {
2597 for (
int r = from; (r < to) && (allHits || result.size() < hits); ++r) {
2598 QModelIndex idx = index(r, column, p);
2601 QVariant v = data(idx, role);
2603 if (matchType == Qt::MatchExactly) {
2607#if QT_CONFIG(regularexpression)
2608 if (matchType == Qt::MatchRegularExpression) {
2609 if (rx.pattern().isEmpty()) {
2610 if (value.userType() == QMetaType::QRegularExpression) {
2611 rx = value.toRegularExpression();
2613 rx.setPattern(value.toString());
2614 if (cs == Qt::CaseInsensitive)
2615 rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
2618 }
else if (matchType == Qt::MatchWildcard) {
2619 if (rx.pattern().isEmpty()) {
2620 const QString pattern = QRegularExpression::wildcardToRegularExpression(value.toString(), QRegularExpression::NonPathWildcardConversion);
2621 rx.setPattern(pattern);
2623 if (cs == Qt::CaseInsensitive)
2624 rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
2629 text = value.toString();
2632 QString t = v.toString();
2633 switch (matchType) {
2634#if QT_CONFIG(regularexpression)
2635 case Qt::MatchRegularExpression:
2637 case Qt::MatchWildcard:
2642 case Qt::MatchStartsWith:
2643 if (t.startsWith(text, cs))
2646 case Qt::MatchEndsWith:
2647 if (t.endsWith(text, cs))
2650 case Qt::MatchFixedString:
2651 if (t.compare(text, cs) == 0)
2654 case Qt::MatchContains:
2656 if (t.contains(text, cs))
2661 const auto parent = column != 0 ? idx.sibling(idx.row(), 0) : idx;
2662 if (hasChildren(parent)) {
2663 result += match(index(0, column, parent), role,
2664 (text.isEmpty() ? value : text),
2665 (allHits ? -1 : hits - result.size()), flags);
2831bool QAbstractItemModel::decodeData(
int row,
int column,
const QModelIndex &parent,
2832 QDataStream &stream)
2838 QList<
int> rows, columns;
2839 QList<QMap<
int, QVariant>> data;
2841 while (!stream.atEnd()) {
2843 QMap<
int, QVariant> v;
2844 stream >> r >> c >> v;
2849 left = qMin(c, left);
2850 bottom = qMax(r, bottom);
2851 right = qMax(c, right);
2856 int dragRowCount = 0;
2857 int dragColumnCount = right - left + 1;
2860 QList<
int> rowsToInsert(bottom + 1);
2861 for (
int i = 0; i < rows.size(); ++i)
2862 rowsToInsert[rows.at(i)] = 1;
2863 for (
int i = 0; i < rowsToInsert.size(); ++i) {
2864 if (rowsToInsert.at(i) == 1){
2865 rowsToInsert[i] = dragRowCount;
2869 for (
int i = 0; i < rows.size(); ++i)
2870 rows[i] = top + rowsToInsert.at(rows.at(i));
2872 QBitArray isWrittenTo(dragRowCount * dragColumnCount);
2875 int colCount = columnCount(parent);
2876 if (colCount == 0) {
2877 insertColumns(colCount, dragColumnCount - colCount, parent);
2878 colCount = columnCount(parent);
2880 insertRows(row, dragRowCount, parent);
2883 column = qMax(0, column);
2885 QList<QPersistentModelIndex> newIndexes(data.size());
2887 for (
int j = 0; j < data.size(); ++j) {
2888 int relativeRow = rows.at(j) - top;
2889 int relativeColumn = columns.at(j) - left;
2890 int destinationRow = relativeRow + row;
2891 int destinationColumn = relativeColumn + column;
2892 int flat = (relativeRow * dragColumnCount) + relativeColumn;
2894 if (destinationColumn >= colCount || isWrittenTo.testBit(flat)) {
2895 destinationColumn = qBound(column, destinationColumn, qMax(colCount - 1, column));
2896 destinationRow = row + dragRowCount;
2897 insertRows(row + dragRowCount, 1, parent);
2898 flat = (dragRowCount * dragColumnCount) + relativeColumn;
2899 isWrittenTo.resize(++dragRowCount * dragColumnCount);
2901 if (!isWrittenTo.testBit(flat)) {
2902 newIndexes[j] = index(destinationRow, destinationColumn, parent);
2903 isWrittenTo.setBit(flat);
2907 for(
int k = 0; k < newIndexes.size(); k++) {
2908 if (newIndexes.at(k).isValid())
2909 setItemData(newIndexes.at(k), data.at(k));
2957void QAbstractItemModel::beginInsertRows(
const QModelIndex &parent,
int first,
int last)
2959 Q_ASSERT(first >= 0);
2960 Q_ASSERT(first <= rowCount(parent));
2961 Q_ASSERT(last >= first);
2962 Q_D(QAbstractItemModel);
2963 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
2964 emit rowsAboutToBeInserted(parent, first, last, QPrivateSignal());
2965 d->rowsAboutToBeInserted(parent, first, last);
2976void QAbstractItemModel::endInsertRows()
2978 Q_D(QAbstractItemModel);
2979 QAbstractItemModelPrivate::Change change = d->changes.pop();
2980 d->rowsInserted(change.parent, change.first, change.last);
2981 emit rowsInserted(change.parent, change.first, change.last, QPrivateSignal());
3013void QAbstractItemModel::beginRemoveRows(
const QModelIndex &parent,
int first,
int last)
3015 Q_ASSERT(first >= 0);
3016 Q_ASSERT(last >= first);
3017 Q_ASSERT(last < rowCount(parent));
3018 Q_D(QAbstractItemModel);
3019 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3020 emit rowsAboutToBeRemoved(parent, first, last, QPrivateSignal());
3021 d->rowsAboutToBeRemoved(parent, first, last);
3032void QAbstractItemModel::endRemoveRows()
3034 Q_D(QAbstractItemModel);
3035 QAbstractItemModelPrivate::Change change = d->changes.pop();
3036 d->rowsRemoved(change.parent, change.first, change.last);
3037 emit rowsRemoved(change.parent, change.first, change.last, QPrivateSignal());
3048bool QAbstractItemModelPrivate::allowMove(
const QModelIndex &srcParent,
int start,
int end,
const QModelIndex &destinationParent,
int destinationStart, Qt::Orientation orientation)
3051 if (destinationParent == srcParent)
3052 return !(destinationStart >= start && destinationStart <= end + 1);
3054 QModelIndex destinationAncestor = destinationParent;
3055 int pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
3057 if (destinationAncestor == srcParent) {
3058 if (pos >= start && pos <= end)
3063 if (!destinationAncestor.isValid())
3066 pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
3067 destinationAncestor = destinationAncestor.parent();
3174bool QAbstractItemModel::beginMoveRows(
const QModelIndex &sourceParent,
int sourceFirst,
int sourceLast,
const QModelIndex &destinationParent,
int destinationChild)
3176 Q_ASSERT(sourceFirst >= 0);
3177 Q_ASSERT(sourceLast >= sourceFirst);
3178 Q_ASSERT(destinationChild >= 0);
3179 Q_D(QAbstractItemModel);
3181 if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical)) {
3185 QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
3186 sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
3187 d->changes.push(sourceChange);
3188 int destinationLast = destinationChild + (sourceLast - sourceFirst);
3189 QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
3190 destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
3191 d->changes.push(destinationChange);
3193 emit rowsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
3194 d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical);
3209void QAbstractItemModel::endMoveRows()
3211 Q_D(QAbstractItemModel);
3213 QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
3214 QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
3216 QModelIndex adjustedSource = removeChange.parent;
3217 QModelIndex adjustedDestination = insertChange.parent;
3219 const int numMoved = removeChange.last - removeChange.first + 1;
3220 if (insertChange.needsAdjust)
3221 adjustedDestination = createIndex(adjustedDestination.row() - numMoved, adjustedDestination.column(), adjustedDestination.internalPointer());
3223 if (removeChange.needsAdjust)
3224 adjustedSource = createIndex(adjustedSource.row() + numMoved, adjustedSource.column(), adjustedSource.internalPointer());
3226 d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Vertical);
3228 emit rowsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
3274void QAbstractItemModel::beginInsertColumns(
const QModelIndex &parent,
int first,
int last)
3276 Q_ASSERT(first >= 0);
3277 Q_ASSERT(first <= columnCount(parent));
3278 Q_ASSERT(last >= first);
3279 Q_D(QAbstractItemModel);
3280 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3281 emit columnsAboutToBeInserted(parent, first, last, QPrivateSignal());
3282 d->columnsAboutToBeInserted(parent, first, last);
3294void QAbstractItemModel::endInsertColumns()
3296 Q_D(QAbstractItemModel);
3297 QAbstractItemModelPrivate::Change change = d->changes.pop();
3298 d->columnsInserted(change.parent, change.first, change.last);
3299 emit columnsInserted(change.parent, change.first, change.last, QPrivateSignal());
3331void QAbstractItemModel::beginRemoveColumns(
const QModelIndex &parent,
int first,
int last)
3333 Q_ASSERT(first >= 0);
3334 Q_ASSERT(last >= first);
3335 Q_ASSERT(last < columnCount(parent));
3336 Q_D(QAbstractItemModel);
3337 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3338 emit columnsAboutToBeRemoved(parent, first, last, QPrivateSignal());
3339 d->columnsAboutToBeRemoved(parent, first, last);
3350void QAbstractItemModel::endRemoveColumns()
3352 Q_D(QAbstractItemModel);
3353 QAbstractItemModelPrivate::Change change = d->changes.pop();
3354 d->columnsRemoved(change.parent, change.first, change.last);
3355 emit columnsRemoved(change.parent, change.first, change.last, QPrivateSignal());
3396bool QAbstractItemModel::beginMoveColumns(
const QModelIndex &sourceParent,
int sourceFirst,
int sourceLast,
const QModelIndex &destinationParent,
int destinationChild)
3398 Q_ASSERT(sourceFirst >= 0);
3399 Q_ASSERT(sourceLast >= sourceFirst);
3400 Q_ASSERT(destinationChild >= 0);
3401 Q_D(QAbstractItemModel);
3403 if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal)) {
3407 QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
3408 sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
3409 d->changes.push(sourceChange);
3410 int destinationLast = destinationChild + (sourceLast - sourceFirst);
3411 QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
3412 destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
3413 d->changes.push(destinationChange);
3415 emit columnsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
3416 d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal);
3431void QAbstractItemModel::endMoveColumns()
3433 Q_D(QAbstractItemModel);
3435 QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
3436 QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
3438 QModelIndex adjustedSource = removeChange.parent;
3439 QModelIndex adjustedDestination = insertChange.parent;
3441 const int numMoved = removeChange.last - removeChange.first + 1;
3442 if (insertChange.needsAdjust)
3443 adjustedDestination = createIndex(adjustedDestination.row(), adjustedDestination.column() - numMoved, adjustedDestination.internalPointer());
3445 if (removeChange.needsAdjust)
3446 adjustedSource = createIndex(adjustedSource.row(), adjustedSource.column() + numMoved, adjustedSource.internalPointer());
3448 d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Horizontal);
3449 emit columnsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
3523void QAbstractItemModel::changePersistentIndex(
const QModelIndex &from,
const QModelIndex &to)
3525 Q_D(QAbstractItemModel);
3526 if (d->persistent.indexes.isEmpty())
3529 const auto it = d->persistent.indexes.constFind(from);
3530 if (it != d->persistent.indexes.cend()) {
3531 QPersistentModelIndexData *data = *it;
3532 d->persistent.indexes.erase(it);
3535 d->persistent.insertMultiAtEnd(to, data);
3550void QAbstractItemModel::changePersistentIndexList(
const QModelIndexList &from,
3551 const QModelIndexList &to)
3553 Q_D(QAbstractItemModel);
3554 if (d->persistent.indexes.isEmpty())
3556 QList<QPersistentModelIndexData *> toBeReinserted;
3557 toBeReinserted.reserve(to.size());
3558 for (
int i = 0; i < from.size(); ++i) {
3559 if (from.at(i) == to.at(i))
3561 const auto it = d->persistent.indexes.constFind(from.at(i));
3562 if (it != d->persistent.indexes.cend()) {
3563 QPersistentModelIndexData *data = *it;
3564 d->persistent.indexes.erase(it);
3565 data->index = to.at(i);
3566 if (data->index.isValid())
3567 toBeReinserted << data;
3571 for (
auto *data : std::as_const(toBeReinserted))
3572 d->persistent.insertMultiAtEnd(data->index, data);
3664bool QAbstractItemModel::checkIndex(
const QModelIndex &index, CheckIndexOptions options)
const
3666 if (!index.isValid()) {
3667 if (options & CheckIndexOption::IndexIsValid) {
3668 qCWarning(lcCheckIndex) <<
"Index" << index <<
"is not valid (expected valid)";
3674 if (index.model() !=
this) {
3675 qCWarning(lcCheckIndex) <<
"Index" << index
3676 <<
"is for model" << index.model()
3677 <<
"which is different from this model" <<
this;
3681 if (index.row() < 0) {
3682 qCWarning(lcCheckIndex) <<
"Index" << index
3683 <<
"has negative row" << index.row();
3687 if (index.column() < 0) {
3688 qCWarning(lcCheckIndex) <<
"Index" << index
3689 <<
"has negative column" << index.column();
3693 if (!(options & CheckIndexOption::DoNotUseParent)) {
3694 const QModelIndex parentIndex = index.parent();
3695 if (options & CheckIndexOption::ParentIsInvalid) {
3696 if (parentIndex.isValid()) {
3697 qCWarning(lcCheckIndex) <<
"Index" << index
3698 <<
"has valid parent" << parentIndex
3699 <<
"(expected an invalid parent)";
3704 const int rc = rowCount(parentIndex);
3705 if (index.row() >= rc) {
3706 qCWarning(lcCheckIndex) <<
"Index" << index
3707 <<
"has out of range row" << index.row()
3708 <<
"rowCount() is" << rc;
3712 const int cc = columnCount(parentIndex);
3713 if (index.column() >= cc) {
3714 qCWarning(lcCheckIndex) <<
"Index" << index
3715 <<
"has out of range column" << index.column()
3716 <<
"columnCount() is" << cc;
3772void QAbstractItemModel::multiData(
const QModelIndex &index, QModelRoleDataSpan roleDataSpan)
const
3774 Q_ASSERT(checkIndex(index, CheckIndexOption::IndexIsValid));
3776 for (QModelRoleData &d : roleDataSpan)
3777 d.setData(data(index, d.role()));
4092bool QAbstractItemModelPrivate::dropOnItem(
const QModelIndex &index, QDataStream &stream)
4094 Q_Q(QAbstractItemModel);
4098 QList<
int> rows, columns;
4099 QList<QMap<
int, QVariant>> data;
4101 while (!stream.atEnd()) {
4103 QMap<
int, QVariant> v;
4104 stream >> r >> c >> v;
4109 left = qMin(c, left);
4112 for (
int i = 0; i < data.size(); ++i) {
4113 int r = (rows.at(i) - top) + index.row();
4114 int c = (columns.at(i) - left) + index.column();
4115 if (q->hasIndex(r, c))
4116 q->setItemData(q->index(r, c), data.at(i));
4125bool QAbstractTableModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
4126 int row,
int column,
const QModelIndex &parent)
4128 Q_D(QAbstractItemModel);
4129 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
4132 QStringList types = mimeTypes();
4133 if (types.isEmpty())
4135 QString format = types.at(0);
4136 if (!data->hasFormat(format))
4139 QByteArray encoded = data->data(format);
4140 QDataStream stream(&encoded, QDataStream::ReadOnly);
4143 if (parent.isValid() && row == -1 && column == -1)
4144 return d->dropOnItem(parent, stream);
4147 row = rowCount(parent);
4150 return decodeData(row, column, parent, stream);
4156bool QAbstractListModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
4157 int row,
int column,
const QModelIndex &parent)
4159 Q_D(QAbstractItemModel);
4160 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
4163 QStringList types = mimeTypes();
4164 if (types.isEmpty())
4166 QString format = types.at(0);
4167 if (!data->hasFormat(format))
4170 QByteArray encoded = data->data(format);
4171 QDataStream stream(&encoded, QDataStream::ReadOnly);
4174 if (parent.isValid() && row == -1 && column == -1)
4175 return d->dropOnItem(parent, stream);
4178 row = rowCount(parent);
4181 return decodeData(row, column, parent, stream);