2084QMap<
int, QVariant> QAbstractItemModel::itemData(
const QModelIndex &index)
const
2086 QMap<
int, QVariant> roles;
2087 for (
int i = 0; i < Qt::UserRole; ++i) {
2088 QVariant variantData = data(index, i);
2089 if (variantData.isValid())
2090 roles.insert(i, variantData);
2153bool QAbstractItemModel::setItemData(
const QModelIndex &index,
const QMap<
int, QVariant> &roles)
2155 if (!index.isValid() || roles.isEmpty())
2164 for (
auto it = roles.begin(), e = roles.end(); it != e; ++it) {
2165 if (!setData(index, it.value(), it.key()))
2206QMimeData *QAbstractItemModel::mimeData(
const QModelIndexList &indexes)
const
2208 if (indexes.size() <= 0)
2210 QStringList types = mimeTypes();
2211 if (types.isEmpty())
2213 QMimeData *data =
new QMimeData();
2214 QString format = types.at(0);
2216 QDataStream stream(&encoded, QDataStream::WriteOnly);
2217 encodeData(indexes, stream);
2218 data->setData(format, encoded);
2235bool QAbstractItemModel::canDropMimeData(
const QMimeData *data, Qt::DropAction action,
2236 int row,
int column,
2237 const QModelIndex &parent)
const
2243 if (!(action & supportedDropActions()))
2246 const QStringList modelTypes = mimeTypes();
2247 for (
int i = 0; i < modelTypes.size(); ++i) {
2248 if (data->hasFormat(modelTypes.at(i)))
2283bool QAbstractItemModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
2284 int row,
int column,
const QModelIndex &parent)
2287 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
2290 const QStringList types = mimeTypes();
2291 if (types.isEmpty())
2293 const QString format = types.at(0);
2294 if (!data->hasFormat(format))
2296 const bool dropOnItem = row == -1 && column == -1 && parent.isValid();
2297 if (!dropOnItem || !parent.flags().testFlag(Qt::ItemNeverHasChildren)) {
2300 if (row > rowCount(parent))
2301 row = rowCount(parent);
2303 row = rowCount(parent);
2308 QByteArray encoded = data->data(format);
2309 QDataStream stream(&encoded, QDataStream::ReadOnly);
2310 return decodeData(row, column, parent, stream);
2588QModelIndexList QAbstractItemModel::match(
const QModelIndex &start,
int role,
2589 const QVariant &value,
int hits,
2590 Qt::MatchFlags flags)
const
2592 QModelIndexList result;
2593 uint matchType = (flags & Qt::MatchTypeMask).toInt();
2594 Qt::CaseSensitivity cs = flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
2595 bool recurse = flags.testAnyFlag(Qt::MatchRecursive);
2596 bool wrap = flags.testAnyFlag(Qt::MatchWrap);
2597 bool allHits = (hits == -1);
2599#if QT_CONFIG(regularexpression)
2600 QRegularExpression rx;
2602 const int column = start.column();
2603 QModelIndex p = parent(start);
2604 int from = start.row();
2605 int to = rowCount(p);
2608 for (
int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) {
2609 for (
int r = from; (r < to) && (allHits || result.size() < hits); ++r) {
2610 QModelIndex idx = index(r, column, p);
2613 QVariant v = data(idx, role);
2615 if (matchType == Qt::MatchExactly) {
2619#if QT_CONFIG(regularexpression)
2620 if (matchType == Qt::MatchRegularExpression) {
2621 if (rx.pattern().isEmpty()) {
2622 if (value.userType() == QMetaType::QRegularExpression) {
2623 rx = value.toRegularExpression();
2625 rx.setPattern(value.toString());
2626 if (cs == Qt::CaseInsensitive)
2627 rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
2630 }
else if (matchType == Qt::MatchWildcard) {
2631 if (rx.pattern().isEmpty()) {
2632 const QString pattern = QRegularExpression::wildcardToRegularExpression(value.toString(), QRegularExpression::NonPathWildcardConversion);
2633 rx.setPattern(pattern);
2635 if (cs == Qt::CaseInsensitive)
2636 rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
2641 text = value.toString();
2644 QString t = v.toString();
2645 switch (matchType) {
2646#if QT_CONFIG(regularexpression)
2647 case Qt::MatchRegularExpression:
2649 case Qt::MatchWildcard:
2654 case Qt::MatchStartsWith:
2655 if (t.startsWith(text, cs))
2658 case Qt::MatchEndsWith:
2659 if (t.endsWith(text, cs))
2662 case Qt::MatchFixedString:
2663 if (t.compare(text, cs) == 0)
2666 case Qt::MatchContains:
2668 if (t.contains(text, cs))
2673 const auto parent = column != 0 ? idx.sibling(idx.row(), 0) : idx;
2674 if (hasChildren(parent)) {
2675 result += match(index(0, column, parent), role,
2676 (text.isEmpty() ? value : text),
2677 (allHits ? -1 : hits - result.size()), flags);
2843bool QAbstractItemModel::decodeData(
int row,
int column,
const QModelIndex &parent,
2844 QDataStream &stream)
2850 QList<
int> rows, columns;
2851 QList<QMap<
int, QVariant>> data;
2853 while (!stream.atEnd()) {
2855 QMap<
int, QVariant> v;
2856 stream >> r >> c >> v;
2861 left = qMin(c, left);
2862 bottom = qMax(r, bottom);
2863 right = qMax(c, right);
2868 int dragRowCount = 0;
2869 int dragColumnCount = right - left + 1;
2872 QList<
int> rowsToInsert(bottom + 1);
2873 for (
int i = 0; i < rows.size(); ++i)
2874 rowsToInsert[rows.at(i)] = 1;
2875 for (
int i = 0; i < rowsToInsert.size(); ++i) {
2876 if (rowsToInsert.at(i) == 1){
2877 rowsToInsert[i] = dragRowCount;
2881 for (
int i = 0; i < rows.size(); ++i)
2882 rows[i] = top + rowsToInsert.at(rows.at(i));
2884 QBitArray isWrittenTo(dragRowCount * dragColumnCount);
2887 int colCount = columnCount(parent);
2888 if (colCount == 0) {
2889 insertColumns(colCount, dragColumnCount - colCount, parent);
2890 colCount = columnCount(parent);
2892 insertRows(row, dragRowCount, parent);
2895 column = qMax(0, column);
2897 QList<QPersistentModelIndex> newIndexes(data.size());
2899 for (
int j = 0; j < data.size(); ++j) {
2900 int relativeRow = rows.at(j) - top;
2901 int relativeColumn = columns.at(j) - left;
2902 int destinationRow = relativeRow + row;
2903 int destinationColumn = relativeColumn + column;
2904 int flat = (relativeRow * dragColumnCount) + relativeColumn;
2906 if (destinationColumn >= colCount || isWrittenTo.testBit(flat)) {
2907 destinationColumn = qBound(column, destinationColumn, qMax(colCount - 1, column));
2908 destinationRow = row + dragRowCount;
2909 insertRows(row + dragRowCount, 1, parent);
2910 flat = (dragRowCount * dragColumnCount) + relativeColumn;
2911 isWrittenTo.resize(++dragRowCount * dragColumnCount);
2913 if (!isWrittenTo.testBit(flat)) {
2914 newIndexes[j] = index(destinationRow, destinationColumn, parent);
2915 isWrittenTo.setBit(flat);
2919 for(
int k = 0; k < newIndexes.size(); k++) {
2920 if (newIndexes.at(k).isValid())
2921 setItemData(newIndexes.at(k), data.at(k));
2967void QAbstractItemModel::beginInsertRows(
const QModelIndex &parent,
int first,
int last)
2969 Q_ASSERT(first >= 0);
2970 Q_ASSERT(first <= rowCount(parent));
2971 Q_ASSERT(last >= first);
2972 Q_D(QAbstractItemModel);
2973 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
2974 emit rowsAboutToBeInserted(parent, first, last, QPrivateSignal());
2975 d->rowsAboutToBeInserted(parent, first, last);
2986void QAbstractItemModel::endInsertRows()
2988 Q_D(QAbstractItemModel);
2989 QAbstractItemModelPrivate::Change change = d->changes.pop();
2990 d->rowsInserted(change.parent, change.first, change.last);
2991 emit rowsInserted(change.parent, change.first, change.last, QPrivateSignal());
3022void QAbstractItemModel::beginRemoveRows(
const QModelIndex &parent,
int first,
int last)
3024 Q_ASSERT(first >= 0);
3025 Q_ASSERT(last >= first);
3026 Q_ASSERT(last < rowCount(parent));
3027 Q_D(QAbstractItemModel);
3028 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3029 emit rowsAboutToBeRemoved(parent, first, last, QPrivateSignal());
3030 d->rowsAboutToBeRemoved(parent, first, last);
3041void QAbstractItemModel::endRemoveRows()
3043 Q_D(QAbstractItemModel);
3044 QAbstractItemModelPrivate::Change change = d->changes.pop();
3045 d->rowsRemoved(change.parent, change.first, change.last);
3046 emit rowsRemoved(change.parent, change.first, change.last, QPrivateSignal());
3057bool QAbstractItemModelPrivate::allowMove(
const QModelIndex &srcParent,
int start,
int end,
const QModelIndex &destinationParent,
int destinationStart, Qt::Orientation orientation)
3060 if (destinationParent == srcParent)
3061 return !(destinationStart >= start && destinationStart <= end + 1);
3063 QModelIndex destinationAncestor = destinationParent;
3064 int pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
3066 if (destinationAncestor == srcParent) {
3067 if (pos >= start && pos <= end)
3072 if (!destinationAncestor.isValid())
3075 pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
3076 destinationAncestor = destinationAncestor.parent();
3179bool QAbstractItemModel::beginMoveRows(
const QModelIndex &sourceParent,
int sourceFirst,
int sourceLast,
const QModelIndex &destinationParent,
int destinationChild)
3181 Q_ASSERT(sourceFirst >= 0);
3182 Q_ASSERT(sourceLast >= sourceFirst);
3183 Q_ASSERT(destinationChild >= 0);
3184 Q_D(QAbstractItemModel);
3186 if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical)) {
3190 QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
3191 sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
3192 d->changes.push(sourceChange);
3193 int destinationLast = destinationChild + (sourceLast - sourceFirst);
3194 QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
3195 destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
3196 d->changes.push(destinationChange);
3198 emit rowsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
3199 d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical);
3214void QAbstractItemModel::endMoveRows()
3216 Q_D(QAbstractItemModel);
3218 QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
3219 QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
3221 QModelIndex adjustedSource = removeChange.parent;
3222 QModelIndex adjustedDestination = insertChange.parent;
3224 const int numMoved = removeChange.last - removeChange.first + 1;
3225 if (insertChange.needsAdjust)
3226 adjustedDestination = createIndex(adjustedDestination.row() - numMoved, adjustedDestination.column(), adjustedDestination.internalPointer());
3228 if (removeChange.needsAdjust)
3229 adjustedSource = createIndex(adjustedSource.row() + numMoved, adjustedSource.column(), adjustedSource.internalPointer());
3231 d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Vertical);
3233 emit rowsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
3277void QAbstractItemModel::beginInsertColumns(
const QModelIndex &parent,
int first,
int last)
3279 Q_ASSERT(first >= 0);
3280 Q_ASSERT(first <= columnCount(parent));
3281 Q_ASSERT(last >= first);
3282 Q_D(QAbstractItemModel);
3283 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3284 emit columnsAboutToBeInserted(parent, first, last, QPrivateSignal());
3285 d->columnsAboutToBeInserted(parent, first, last);
3297void QAbstractItemModel::endInsertColumns()
3299 Q_D(QAbstractItemModel);
3300 QAbstractItemModelPrivate::Change change = d->changes.pop();
3301 d->columnsInserted(change.parent, change.first, change.last);
3302 emit columnsInserted(change.parent, change.first, change.last, QPrivateSignal());
3333void QAbstractItemModel::beginRemoveColumns(
const QModelIndex &parent,
int first,
int last)
3335 Q_ASSERT(first >= 0);
3336 Q_ASSERT(last >= first);
3337 Q_ASSERT(last < columnCount(parent));
3338 Q_D(QAbstractItemModel);
3339 d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
3340 emit columnsAboutToBeRemoved(parent, first, last, QPrivateSignal());
3341 d->columnsAboutToBeRemoved(parent, first, last);
3352void QAbstractItemModel::endRemoveColumns()
3354 Q_D(QAbstractItemModel);
3355 QAbstractItemModelPrivate::Change change = d->changes.pop();
3356 d->columnsRemoved(change.parent, change.first, change.last);
3357 emit columnsRemoved(change.parent, change.first, change.last, QPrivateSignal());
3398bool QAbstractItemModel::beginMoveColumns(
const QModelIndex &sourceParent,
int sourceFirst,
int sourceLast,
const QModelIndex &destinationParent,
int destinationChild)
3400 Q_ASSERT(sourceFirst >= 0);
3401 Q_ASSERT(sourceLast >= sourceFirst);
3402 Q_ASSERT(destinationChild >= 0);
3403 Q_D(QAbstractItemModel);
3405 if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal)) {
3409 QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
3410 sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
3411 d->changes.push(sourceChange);
3412 int destinationLast = destinationChild + (sourceLast - sourceFirst);
3413 QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
3414 destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
3415 d->changes.push(destinationChange);
3417 emit columnsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
3418 d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal);
3433void QAbstractItemModel::endMoveColumns()
3435 Q_D(QAbstractItemModel);
3437 QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
3438 QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
3440 QModelIndex adjustedSource = removeChange.parent;
3441 QModelIndex adjustedDestination = insertChange.parent;
3443 const int numMoved = removeChange.last - removeChange.first + 1;
3444 if (insertChange.needsAdjust)
3445 adjustedDestination = createIndex(adjustedDestination.row(), adjustedDestination.column() - numMoved, adjustedDestination.internalPointer());
3447 if (removeChange.needsAdjust)
3448 adjustedSource = createIndex(adjustedSource.row(), adjustedSource.column() + numMoved, adjustedSource.internalPointer());
3450 d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Horizontal);
3451 emit columnsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
3525void QAbstractItemModel::changePersistentIndex(
const QModelIndex &from,
const QModelIndex &to)
3527 Q_D(QAbstractItemModel);
3528 if (d->persistent.indexes.isEmpty())
3531 const auto it = d->persistent.indexes.constFind(from);
3532 if (it != d->persistent.indexes.cend()) {
3533 QPersistentModelIndexData *data = *it;
3534 d->persistent.indexes.erase(it);
3537 d->persistent.insertMultiAtEnd(to, data);
3552void QAbstractItemModel::changePersistentIndexList(
const QModelIndexList &from,
3553 const QModelIndexList &to)
3555 Q_D(QAbstractItemModel);
3556 if (d->persistent.indexes.isEmpty())
3558 QList<QPersistentModelIndexData *> toBeReinserted;
3559 toBeReinserted.reserve(to.size());
3560 for (
int i = 0; i < from.size(); ++i) {
3561 if (from.at(i) == to.at(i))
3563 const auto it = d->persistent.indexes.constFind(from.at(i));
3564 if (it != d->persistent.indexes.cend()) {
3565 QPersistentModelIndexData *data = *it;
3566 d->persistent.indexes.erase(it);
3567 data->index = to.at(i);
3568 if (data->index.isValid())
3569 toBeReinserted << data;
3573 for (
auto *data : std::as_const(toBeReinserted))
3574 d->persistent.insertMultiAtEnd(data->index, data);
3666bool QAbstractItemModel::checkIndex(
const QModelIndex &index, CheckIndexOptions options)
const
3668 if (!index.isValid()) {
3669 if (options & CheckIndexOption::IndexIsValid) {
3670 qCWarning(lcCheckIndex) <<
"Index" << index <<
"is not valid (expected valid)";
3676 if (index.model() !=
this) {
3677 qCWarning(lcCheckIndex) <<
"Index" << index
3678 <<
"is for model" << index.model()
3679 <<
"which is different from this model" <<
this;
3683 if (index.row() < 0) {
3684 qCWarning(lcCheckIndex) <<
"Index" << index
3685 <<
"has negative row" << index.row();
3689 if (index.column() < 0) {
3690 qCWarning(lcCheckIndex) <<
"Index" << index
3691 <<
"has negative column" << index.column();
3695 if (!(options & CheckIndexOption::DoNotUseParent)) {
3696 const QModelIndex parentIndex = index.parent();
3697 if (options & CheckIndexOption::ParentIsInvalid) {
3698 if (parentIndex.isValid()) {
3699 qCWarning(lcCheckIndex) <<
"Index" << index
3700 <<
"has valid parent" << parentIndex
3701 <<
"(expected an invalid parent)";
3706 const int rc = rowCount(parentIndex);
3707 if (index.row() >= rc) {
3708 qCWarning(lcCheckIndex) <<
"Index" << index
3709 <<
"has out of range row" << index.row()
3710 <<
"rowCount() is" << rc;
3714 const int cc = columnCount(parentIndex);
3715 if (index.column() >= cc) {
3716 qCWarning(lcCheckIndex) <<
"Index" << index
3717 <<
"has out of range column" << index.column()
3718 <<
"columnCount() is" << cc;
3774void QAbstractItemModel::multiData(
const QModelIndex &index, QModelRoleDataSpan roleDataSpan)
const
3776 Q_ASSERT(checkIndex(index, CheckIndexOption::IndexIsValid));
3778 for (QModelRoleData &d : roleDataSpan)
3779 d.setData(data(index, d.role()));
4094bool QAbstractItemModelPrivate::dropOnItem(
const QModelIndex &index, QDataStream &stream)
4096 Q_Q(QAbstractItemModel);
4100 QList<
int> rows, columns;
4101 QList<QMap<
int, QVariant>> data;
4103 while (!stream.atEnd()) {
4105 QMap<
int, QVariant> v;
4106 stream >> r >> c >> v;
4111 left = qMin(c, left);
4114 for (
int i = 0; i < data.size(); ++i) {
4115 int r = (rows.at(i) - top) + index.row();
4116 int c = (columns.at(i) - left) + index.column();
4117 if (q->hasIndex(r, c))
4118 q->setItemData(q->index(r, c), data.at(i));
4127bool QAbstractTableModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
4128 int row,
int column,
const QModelIndex &parent)
4130 Q_D(QAbstractItemModel);
4131 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
4134 QStringList types = mimeTypes();
4135 if (types.isEmpty())
4137 QString format = types.at(0);
4138 if (!data->hasFormat(format))
4141 QByteArray encoded = data->data(format);
4142 QDataStream stream(&encoded, QDataStream::ReadOnly);
4145 if (parent.isValid() && row == -1 && column == -1)
4146 return d->dropOnItem(parent, stream);
4149 row = rowCount(parent);
4152 return decodeData(row, column, parent, stream);
4158bool QAbstractListModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
4159 int row,
int column,
const QModelIndex &parent)
4161 Q_D(QAbstractItemModel);
4162 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
4165 QStringList types = mimeTypes();
4166 if (types.isEmpty())
4168 QString format = types.at(0);
4169 if (!data->hasFormat(format))
4172 QByteArray encoded = data->data(format);
4173 QDataStream stream(&encoded, QDataStream::ReadOnly);
4176 if (parent.isValid() && row == -1 && column == -1)
4177 return d->dropOnItem(parent, stream);
4180 row = rowCount(parent);
4183 return decodeData(row, column, parent, stream);