summaryrefslogtreecommitdiffstats
path: root/src/corelib/itemmodels/qabstractitemmodel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/itemmodels/qabstractitemmodel.cpp')
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.cpp484
1 files changed, 383 insertions, 101 deletions
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp
index 1bb65336bf..cd29f2fcc2 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.cpp
+++ b/src/corelib/itemmodels/qabstractitemmodel.cpp
@@ -1,41 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qabstractitemmodel.h"
#include <private/qabstractitemmodel_p.h>
@@ -49,16 +14,21 @@
# include <qregularexpression.h>
#endif
#include <qstack.h>
+#include <qmap.h>
#include <qbitarray.h>
#include <qdatetime.h>
#include <qloggingcategory.h>
+#include <functional>
+
#include <limits.h>
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcCheckIndex, "qt.core.qabstractitemmodel.checkindex")
+QT_IMPL_METATYPE_EXTERN(QModelIndexList)
+
QPersistentModelIndexData *QPersistentModelIndexData::create(const QModelIndex &index)
{
Q_ASSERT(index.isValid()); // we will _never_ insert an invalid index in the list
@@ -91,6 +61,226 @@ void QPersistentModelIndexData::destroy(QPersistentModelIndexData *data)
}
/*!
+ \class QModelRoleData
+ \inmodule QtCore
+ \since 6.0
+ \ingroup model-view
+ \brief The QModelRoleData class holds a role and the data associated to that role.
+
+ QModelRoleData objects store an item role (which is a value from the
+ Qt::ItemDataRole enumeration, or an arbitrary integer for a custom role)
+ as well as the data associated with that role.
+
+ A QModelRoleData object is typically created by views or delegates,
+ setting which role they want to fetch the data for. The object
+ is then passed to models (see QAbstractItemModel::multiData()),
+ which populate the data corresponding to the role stored. Finally,
+ the view visualizes the data retrieved from the model.
+
+ \sa {Model/View Programming}, QModelRoleDataSpan
+*/
+
+/*!
+ \fn QModelRoleData::QModelRoleData(int role) noexcept
+
+ Constructs a QModelRoleData object for the given \a role.
+
+ \sa Qt::ItemDataRole
+*/
+
+/*!
+ \fn int QModelRoleData::role() const noexcept
+
+ Returns the role held by this object.
+
+ \sa Qt::ItemDataRole
+*/
+
+/*!
+ \fn const QVariant &QModelRoleData::data() const noexcept
+
+ Returns the data held by this object.
+
+ \sa setData()
+*/
+
+/*!
+ \fn QVariant &QModelRoleData::data() noexcept
+
+ Returns the data held by this object as a modifiable reference.
+
+ \sa setData()
+*/
+
+/*!
+ \fn template <typename T> void QModelRoleData::setData(T &&value)
+
+ Sets the data held by this object to \a value.
+ \a value must be of a datatype which can be stored in a QVariant.
+
+ \sa data(), clearData(), Q_DECLARE_METATYPE
+*/
+
+/*!
+ \fn void QModelRoleData::clearData() noexcept
+
+ Clears the data held by this object. Note that the role is
+ unchanged; only the data is cleared.
+
+ \sa data()
+*/
+
+/*!
+ \class QModelRoleDataSpan
+ \inmodule QtCore
+ \since 6.0
+ \ingroup model-view
+ \brief The QModelRoleDataSpan class provides a span over QModelRoleData objects.
+
+ A QModelRoleDataSpan is used as an abstraction over an array of
+ QModelRoleData objects.
+
+ Like a view, QModelRoleDataSpan provides a small object (pointer
+ and size) that can be passed to functions that need to examine the
+ contents of the array. A QModelRoleDataSpan can be constructed from
+ any array-like sequence (plain arrays, QVector, std::vector,
+ QVarLengthArray, and so on). Moreover, it does not own the
+ sequence, which must therefore be kept alive longer than any
+ QModelRoleDataSpan objects referencing it.
+
+ Unlike a view, QModelRoleDataSpan is a span, so it allows for
+ modifications to the underlying elements.
+
+ QModelRoleDataSpan's main use case is making it possible
+ for a model to return the data corresponding to different roles
+ in one call.
+
+ In order to draw one element from a model, a view (through its
+ delegates) will generally request multiple roles for the same index
+ by calling \c{data()} as many times as needed:
+
+ \snippet code/src_corelib_kernel_qabstractitemmodel.cpp 13
+
+ QModelRoleDataSpan allows a view to request the same data
+ using just one function call.
+
+ This is achieved by having the view prepare a suitable array of
+ QModelRoleData objects, each initialized with the role that should
+ be fetched. The array is then wrapped in a QModelRoleDataSpan
+ object, which is then passed to a model's \c{multiData()} function.
+
+ \snippet code/src_corelib_kernel_qabstractitemmodel.cpp 14
+
+ Views are encouraged to store the array of QModelRoleData objects
+ (and, possibly, the corresponding span) and re-use it in subsequent
+ calls to the model. This allows to reduce the memory allocations
+ related with creating and returning QVariant objects.
+
+ Finally, given a QModelRoleDataSpan object, the model's
+ responsibility is to fill in the data corresponding to each role in
+ the span. How this is done depends on the concrete model class.
+ Here's a sketch of a possible implementation that iterates over the
+ span and uses \c{setData()} on each element:
+
+ \snippet code/src_corelib_kernel_qabstractitemmodel.cpp 15
+
+ \sa {Model/View Programming}, QAbstractItemModel::multiData()
+*/
+
+/*!
+ \fn QModelRoleDataSpan::QModelRoleDataSpan() noexcept
+
+ Constructs an empty QModelRoleDataSpan. Its data() will be set to
+ \nullptr, and its length to zero.
+*/
+
+/*!
+ \fn QModelRoleDataSpan::QModelRoleDataSpan(QModelRoleData &modelRoleData) noexcept
+
+ Constructs an QModelRoleDataSpan spanning over \a modelRoleData,
+ seen as a 1-element array.
+*/
+
+/*!
+ \fn QModelRoleDataSpan::QModelRoleDataSpan(QModelRoleData *modelRoleData, qsizetype len)
+
+ Constructs an QModelRoleDataSpan spanning over the array beginning
+ at \a modelRoleData and with length \a len.
+
+ \note The array must be kept alive as long as this object has not
+ been destructed.
+*/
+
+/*!
+ \fn template <typename Container, QModelRoleDataSpan::if_compatible_container<Container> = true> QModelRoleDataSpan::QModelRoleDataSpan(Container &c) noexcept
+
+ Constructs an QModelRoleDataSpan spanning over the container \a c,
+ which can be any contiguous container of QModelRoleData objects.
+ For instance, it can be a \c{QVector<QModelRoleData>},
+ a \c{std::array<QModelRoleData, 10>} and so on.
+
+ \note The container must be kept alive as long as this object has not
+ been destructed.
+*/
+
+/*!
+ \fn qsizetype QModelRoleDataSpan::size() const noexcept
+
+ Returns the length of the span represented by this object.
+*/
+
+/*!
+ \fn qsizetype QModelRoleDataSpan::length() const noexcept
+
+ Returns the length of the span represented by this object.
+*/
+
+/*!
+ \fn QModelRoleData *QModelRoleDataSpan::data() const noexcept
+
+ Returns a pointer to the beginning of the span represented by this
+ object.
+*/
+
+/*!
+ \fn QModelRoleData *QModelRoleDataSpan::begin() const noexcept
+
+ Returns a pointer to the beginning of the span represented by this
+ object.
+*/
+
+/*!
+ \fn QModelRoleData *QModelRoleDataSpan::end() const noexcept
+
+ Returns a pointer to the imaginary element one past the end of the
+ span represented by this object.
+*/
+
+/*!
+ \fn QModelRoleData &QModelRoleDataSpan::operator[](qsizetype index) const
+
+ Returns a modifiable reference to the QModelRoleData at position
+ \a index in the span.
+
+ \note \a index must be a valid index for this span (0 <= \a index < size()).
+*/
+
+/*!
+ \fn const QVariant *QModelRoleDataSpan::dataForRole(int role) const
+
+ Returns the data associated with the first QModelRoleData in the
+ span that has its role equal to \a role. If such a QModelRoleData
+ object does not exist, the behavior is undefined.
+
+ \note Avoid calling this function from the model's side, as a
+ model cannot possibly know in advance which roles are in a given
+ QModelRoleDataSpan. This function is instead suitable for views and
+ delegates, which have control over the roles in the span.
+
+ \sa QModelRoleData::data()
+*/
+
+/*!
\class QPersistentModelIndex
\inmodule QtCore
\ingroup shared
@@ -192,7 +382,7 @@ QPersistentModelIndex::~QPersistentModelIndex()
model index are used when comparing with another persistent model index.
*/
-bool QPersistentModelIndex::operator==(const QPersistentModelIndex &other) const
+bool QPersistentModelIndex::operator==(const QPersistentModelIndex &other) const noexcept
{
if (d && other.d)
return d->index == other.d->index;
@@ -209,12 +399,12 @@ bool QPersistentModelIndex::operator==(const QPersistentModelIndex &other) const
model index are used when comparing with another persistent model index.
*/
-bool QPersistentModelIndex::operator<(const QPersistentModelIndex &other) const
+bool QPersistentModelIndex::operator<(const QPersistentModelIndex &other) const noexcept
{
if (d && other.d)
return d->index < other.d->index;
- return d < other.d;
+ return std::less<>{}(d, other.d);
}
/*!
@@ -267,17 +457,16 @@ QPersistentModelIndex &QPersistentModelIndex::operator=(const QModelIndex &other
}
/*!
- \fn QPersistentModelIndex::operator const QModelIndex&() const
+ \fn QPersistentModelIndex::operator QModelIndex() const
- Cast operator that returns a const QModelIndex&.
+ Cast operator that returns a QModelIndex.
*/
-QPersistentModelIndex::operator const QModelIndex&() const
+QPersistentModelIndex::operator QModelIndex() const
{
- static const QModelIndex invalid;
if (d)
return d->index;
- return invalid;
+ return QModelIndex();
}
/*!
@@ -288,7 +477,7 @@ QPersistentModelIndex::operator const QModelIndex&() const
model index are used when comparing with another model index.
*/
-bool QPersistentModelIndex::operator==(const QModelIndex &other) const
+bool QPersistentModelIndex::operator==(const QModelIndex &other) const noexcept
{
if (d)
return d->index == other;
@@ -302,7 +491,7 @@ bool QPersistentModelIndex::operator==(const QModelIndex &other) const
location as the \a other model index; otherwise returns \c{false}.
*/
-bool QPersistentModelIndex::operator!=(const QModelIndex &other) const
+bool QPersistentModelIndex::operator!=(const QModelIndex &other) const noexcept
{
if (d)
return d->index != other;
@@ -423,6 +612,20 @@ QVariant QPersistentModelIndex::data(int role) const
return QVariant();
}
+
+/*!
+ Populates the given \a roleDataSpan for the item referred to by the
+ index.
+
+ \since 6.0
+ \sa Qt::ItemDataRole, QAbstractItemModel::setData()
+*/
+void QPersistentModelIndex::multiData(QModelRoleDataSpan roleDataSpan) const
+{
+ if (d)
+ d->index.multiData(roleDataSpan);
+}
+
/*!
\since 4.2
@@ -483,6 +686,7 @@ QDebug operator<<(QDebug dbg, const QPersistentModelIndex &idx)
class QEmptyItemModel : public QAbstractItemModel
{
+ Q_OBJECT
public:
explicit QEmptyItemModel(QObject *parent = nullptr) : QAbstractItemModel(parent) {}
QModelIndex index(int, int, const QModelIndex &) const override { return QModelIndex(); }
@@ -512,7 +716,7 @@ QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel()
void QAbstractItemModelPrivate::invalidatePersistentIndexes()
{
- for (QPersistentModelIndexData *data : qAsConst(persistent.indexes))
+ for (QPersistentModelIndexData *data : std::as_const(persistent.indexes))
data->index = QModelIndex();
persistent.indexes.clear();
}
@@ -532,7 +736,7 @@ void QAbstractItemModelPrivate::invalidatePersistentIndex(const QModelIndex &ind
}
using DefaultRoleNames = QHash<int, QByteArray>;
-Q_GLOBAL_STATIC_WITH_ARGS(DefaultRoleNames, qDefaultRoleNames, (
+Q_GLOBAL_STATIC(DefaultRoleNames, qDefaultRoleNames,
{
{ Qt::DisplayRole, "display" },
{ Qt::DecorationRole, "decoration" },
@@ -540,7 +744,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(DefaultRoleNames, qDefaultRoleNames, (
{ Qt::ToolTipRole, "toolTip" },
{ Qt::StatusTipRole, "statusTip" },
{ Qt::WhatsThisRole, "whatsThis" },
- }))
+ })
const QHash<int,QByteArray> &QAbstractItemModelPrivate::defaultRoleNames()
{
@@ -639,13 +843,13 @@ void QAbstractItemModelPrivate::removePersistentIndexData(QPersistentModelIndexD
Q_UNUSED(removed);
}
// make sure our optimization still works
- for (int i = persistent.moved.count() - 1; i >= 0; --i) {
+ for (int i = persistent.moved.size() - 1; i >= 0; --i) {
int idx = persistent.moved.at(i).indexOf(data);
if (idx >= 0)
persistent.moved[i].remove(idx);
}
// update the references to invalidated persistent indexes
- for (int i = persistent.invalidated.count() - 1; i >= 0; --i) {
+ for (int i = persistent.invalidated.size() - 1; i >= 0; --i) {
int idx = persistent.invalidated.at(i).indexOf(data);
if (idx >= 0)
persistent.invalidated[i].remove(idx);
@@ -660,7 +864,7 @@ void QAbstractItemModelPrivate::rowsAboutToBeInserted(const QModelIndex &parent,
Q_UNUSED(last);
QList<QPersistentModelIndexData *> persistent_moved;
if (first < q->rowCount(parent)) {
- for (auto *data : qAsConst(persistent.indexes)) {
+ for (auto *data : std::as_const(persistent.indexes)) {
const QModelIndex &index = data->index;
if (index.row() >= first && index.isValid() && index.parent() == parent) {
persistent_moved.append(data);
@@ -696,7 +900,7 @@ void QAbstractItemModelPrivate::itemsAboutToBeMoved(const QModelIndex &srcParent
const bool sameParent = (srcParent == destinationParent);
const bool movingUp = (srcFirst > destinationChild);
- for (auto *data : qAsConst(persistent.indexes)) {
+ for (auto *data : std::as_const(persistent.indexes)) {
const QModelIndex &index = data->index;
const QModelIndex &parent = index.parent();
const bool isSourceIndex = (parent == srcParent);
@@ -794,7 +998,7 @@ void QAbstractItemModelPrivate::rowsAboutToBeRemoved(const QModelIndex &parent,
QList<QPersistentModelIndexData *> persistent_invalidated;
// find the persistent indexes that are affected by the change, either by being in the removed subtree
// or by being on the same level and below the removed rows
- for (auto *data : qAsConst(persistent.indexes)) {
+ for (auto *data : std::as_const(persistent.indexes)) {
bool level_changed = false;
QModelIndex current = data->index;
while (current.isValid()) {
@@ -846,7 +1050,7 @@ void QAbstractItemModelPrivate::columnsAboutToBeInserted(const QModelIndex &pare
Q_UNUSED(last);
QList<QPersistentModelIndexData *> persistent_moved;
if (first < q->columnCount(parent)) {
- for (auto *data : qAsConst(persistent.indexes)) {
+ for (auto *data : std::as_const(persistent.indexes)) {
const QModelIndex &index = data->index;
if (index.column() >= first && index.isValid() && index.parent() == parent)
persistent_moved.append(data);
@@ -879,7 +1083,7 @@ void QAbstractItemModelPrivate::columnsAboutToBeRemoved(const QModelIndex &paren
QList<QPersistentModelIndexData *> persistent_invalidated;
// find the persistent indexes that are affected by the change, either by being in the removed subtree
// or by being on the same level and to the right of the removed columns
- for (auto *data : qAsConst(persistent.indexes)) {
+ for (auto *data : std::as_const(persistent.indexes)) {
bool level_changed = false;
QModelIndex current = data->index;
while (current.isValid()) {
@@ -1109,6 +1313,14 @@ void QAbstractItemModel::resetInternalData()
*/
/*!
+ \fn void QModelIndex::multiData(QModelRoleDataSpan roleDataSpan) const
+ \since 6.0
+
+ Populates the given \a roleDataSpan for the item referred to by the
+ index.
+*/
+
+/*!
\fn Qt::ItemFlags QModelIndex::flags() const
\since 4.2
@@ -1288,10 +1500,12 @@ void QAbstractItemModel::resetInternalData()
rows to the model, \l{QAbstractItemModel::}{beginInsertRows()} and
\l{QAbstractItemModel::}{endInsertRows()} must be called.
+ \include models.qdocinc {thread-safety-section1}{QAbstractItemModel}
+
\sa {Model Classes}, {Model Subclassing Reference}, QModelIndex,
QAbstractItemView, {Using drag and drop with item views},
- {Simple DOM Model Example}, {Simple Tree Model Example},
- {Editable Tree Model Example}, {Fetch More Example}
+ {Simple Tree Model Example}, {Editable Tree Model Example},
+ {Fetch More Example}
*/
/*!
@@ -1530,7 +1744,13 @@ QAbstractItemModel::~QAbstractItemModel()
For example:
- \snippet ../widgets/itemviews/simpledommodel/dommodel.cpp 2
+ \code
+ int MyModel::columnCount(const QModelIndex &parent) const
+ {
+ Q_UNUSED(parent);
+ return 3;
+ }
+ \endcode
\note When implementing a table based model, columnCount() should return 0
when the parent is valid.
@@ -1615,13 +1835,13 @@ QAbstractItemModel::~QAbstractItemModel()
*/
/*!
- \fn void QAbstractItemModel::rowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row)
+ \fn void QAbstractItemModel::rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
\since 4.6
This signal is emitted after rows have been moved within the
- model. The items between \a start and \a end
- inclusive, under the given \a parent item have been moved to \a destination
- starting at the row \a row.
+ model. The items between \a sourceStart and \a sourceEnd
+ inclusive, under the given \a sourceParent item have been moved to \a destinationParent
+ starting at the row \a destinationRow.
\b{Note:} Components connected to this signal use it to adapt to changes
in the model's dimensions. It can only be emitted by the QAbstractItemModel
@@ -1647,13 +1867,13 @@ QAbstractItemModel::~QAbstractItemModel()
*/
/*!
- \fn void QAbstractItemModel::columnsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column)
+ \fn void QAbstractItemModel::columnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn)
\since 4.6
This signal is emitted after columns have been moved within the
- model. The items between \a start and \a end
- inclusive, under the given \a parent item have been moved to \a destination
- starting at the column \a column.
+ model. The items between \a sourceStart and \a sourceEnd
+ inclusive, under the given \a sourceParent item have been moved to \a destinationParent
+ starting at the column \a destinationColumn.
\b{Note:} Components connected to this signal use it to adapt to changes
in the model's dimensions. It can only be emitted by the QAbstractItemModel
@@ -1844,7 +2064,7 @@ bool QAbstractItemModel::clearItemData(const QModelIndex &index)
by the \a index.
\note If you do not have a value to return, return an \b invalid
- QVariant instead of returning 0.
+ (default-constructed) QVariant.
\sa Qt::ItemDataRole, setData(), headerData()
*/
@@ -1861,7 +2081,7 @@ bool QAbstractItemModel::clearItemData(const QModelIndex &index)
*/
bool QAbstractItemModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles)
{
- // ### Qt 6: Consider change the semantics of this function,
+ // ### TODO: Consider change the semantics of this function,
// or deprecating/removing it altogether.
//
// For instance, it should try setting *all* the data
@@ -1904,14 +2124,14 @@ QStringList QAbstractItemModel::mimeTypes() const
mimeTypes(). If you reimplement mimeTypes() in your custom model to return
more MIME types, reimplement this function to make use of them.
- If the list of \a indexes is empty, or there are no supported MIME types, 0
- is returned rather than a serialized empty list.
+ If the list of \a indexes is empty, or there are no supported MIME types,
+ \nullptr is returned rather than a serialized empty list.
\sa mimeTypes(), dropMimeData()
*/
QMimeData *QAbstractItemModel::mimeData(const QModelIndexList &indexes) const
{
- if (indexes.count() <= 0)
+ if (indexes.size() <= 0)
return nullptr;
QStringList types = mimeTypes();
if (types.isEmpty())
@@ -1919,7 +2139,7 @@ QMimeData *QAbstractItemModel::mimeData(const QModelIndexList &indexes) const
QMimeData *data = new QMimeData();
QString format = types.at(0);
QByteArray encoded;
- QDataStream stream(&encoded, QIODevice::WriteOnly);
+ QDataStream stream(&encoded, QDataStream::WriteOnly);
encodeData(indexes, stream);
data->setData(format, encoded);
return data;
@@ -1950,7 +2170,7 @@ bool QAbstractItemModel::canDropMimeData(const QMimeData *data, Qt::DropAction a
return false;
const QStringList modelTypes = mimeTypes();
- for (int i = 0; i < modelTypes.count(); ++i) {
+ for (int i = 0; i < modelTypes.size(); ++i) {
if (data->hasFormat(modelTypes.at(i)))
return true;
}
@@ -2007,7 +2227,7 @@ bool QAbstractItemModel::dropMimeData(const QMimeData *data, Qt::DropAction acti
column = 0;
// decode and insert
QByteArray encoded = data->data(format);
- QDataStream stream(&encoded, QIODevice::ReadOnly);
+ QDataStream stream(&encoded, QDataStream::ReadOnly);
return decodeData(row, column, parent, stream);
}
@@ -2291,10 +2511,10 @@ QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role,
Qt::MatchFlags flags) const
{
QModelIndexList result;
- uint matchType = flags & 0x0F;
+ uint matchType = (flags & Qt::MatchTypeMask).toInt();
Qt::CaseSensitivity cs = flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
- bool recurse = flags & Qt::MatchRecursive;
- bool wrap = flags & Qt::MatchWrap;
+ bool recurse = flags.testAnyFlag(Qt::MatchRecursive);
+ bool wrap = flags.testAnyFlag(Qt::MatchWrap);
bool allHits = (hits == -1);
QString text; // only convert to a string if it is needed
#if QT_CONFIG(regularexpression)
@@ -2307,7 +2527,7 @@ QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role,
// iterates twice if wrapping
for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) {
- for (int r = from; (r < to) && (allHits || result.count() < hits); ++r) {
+ for (int r = from; (r < to) && (allHits || result.size() < hits); ++r) {
QModelIndex idx = index(r, column, p);
if (!idx.isValid())
continue;
@@ -2329,8 +2549,10 @@ QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role,
}
}
} else if (matchType == Qt::MatchWildcard) {
- if (rx.pattern().isEmpty())
- rx.setPattern(QRegularExpression::wildcardToRegularExpression(value.toString()));
+ if (rx.pattern().isEmpty()) {
+ const QString pattern = QRegularExpression::wildcardToRegularExpression(value.toString(), QRegularExpression::NonPathWildcardConversion);
+ rx.setPattern(pattern);
+ }
if (cs == Qt::CaseInsensitive)
rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
} else
@@ -2373,7 +2595,7 @@ QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role,
if (hasChildren(parent)) { // search the hierarchy
result += match(index(0, column, parent), role,
(text.isEmpty() ? value : text),
- (allHits ? -1 : hits - result.count()), flags);
+ (allHits ? -1 : hits - result.size()), flags);
}
}
}
@@ -2566,15 +2788,15 @@ bool QAbstractItemModel::decodeData(int row, int column, const QModelIndex &pare
// Compute the number of continuous rows upon insertion and modify the rows to match
QList<int> rowsToInsert(bottom + 1);
- for (int i = 0; i < rows.count(); ++i)
+ for (int i = 0; i < rows.size(); ++i)
rowsToInsert[rows.at(i)] = 1;
- for (int i = 0; i < rowsToInsert.count(); ++i) {
+ for (int i = 0; i < rowsToInsert.size(); ++i) {
if (rowsToInsert.at(i) == 1){
rowsToInsert[i] = dragRowCount;
++dragRowCount;
}
}
- for (int i = 0; i < rows.count(); ++i)
+ for (int i = 0; i < rows.size(); ++i)
rows[i] = top + rowsToInsert.at(rows.at(i));
QBitArray isWrittenTo(dragRowCount * dragColumnCount);
@@ -2776,6 +2998,13 @@ bool QAbstractItemModelPrivate::allowMove(const QModelIndex &srcParent, int star
}
/*!
+ \internal
+
+ see QTBUG-94546
+ */
+void QAbstractItemModelPrivate::executePendingOperations() const { }
+
+/*!
\since 4.6
Begins a row move operation.
@@ -3103,9 +3332,8 @@ bool QAbstractItemModel::beginMoveColumns(const QModelIndex &sourceParent, int s
destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
d->changes.push(destinationChange);
- d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal);
-
emit columnsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
+ d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal);
return true;
}
@@ -3138,7 +3366,6 @@ void QAbstractItemModel::endMoveColumns()
adjustedSource = createIndex(adjustedSource.row(), adjustedSource.column() + numMoved, adjustedSource.internalPointer());
d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Horizontal);
-
emit columnsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
}
@@ -3232,8 +3459,8 @@ void QAbstractItemModel::changePersistentIndexList(const QModelIndexList &from,
if (d->persistent.indexes.isEmpty())
return;
QList<QPersistentModelIndexData *> toBeReinserted;
- toBeReinserted.reserve(to.count());
- for (int i = 0; i < from.count(); ++i) {
+ toBeReinserted.reserve(to.size());
+ for (int i = 0; i < from.size(); ++i) {
if (from.at(i) == to.at(i))
continue;
const auto it = d->persistent.indexes.constFind(from.at(i));
@@ -3246,7 +3473,7 @@ void QAbstractItemModel::changePersistentIndexList(const QModelIndexList &from,
}
}
- for (auto *data : qAsConst(toBeReinserted))
+ for (auto *data : std::as_const(toBeReinserted))
d->persistent.insertMultiAtEnd(data->index, data);
}
@@ -3259,8 +3486,8 @@ QModelIndexList QAbstractItemModel::persistentIndexList() const
{
Q_D(const QAbstractItemModel);
QModelIndexList result;
- result.reserve(d->persistent.indexes.count());
- for (auto *data : qAsConst(d->persistent.indexes))
+ result.reserve(d->persistent.indexes.size());
+ for (auto *data : std::as_const(d->persistent.indexes))
result.append(data->index);
return result;
}
@@ -3401,6 +3628,61 @@ bool QAbstractItemModel::checkIndex(const QModelIndex &index, CheckIndexOptions
}
/*!
+ \since 6.0
+
+ Fills the \a roleDataSpan with the requested data for the given \a index.
+
+ The default implementation will call simply data() for each role in
+ the span. A subclass can reimplement this function to provide data
+ to views more efficiently:
+
+ \snippet code/src_corelib_kernel_qabstractitemmodel.cpp 15
+
+ In the snippet above, \c{index} is the same for the entire call.
+ This means that accessing to the necessary data structures in order
+ to retrieve the information for \c{index} can be done only once
+ (hoisting the relevant code out of the loop).
+
+ The usage of QModelRoleData::setData(), or similarly
+ QVariant::setValue(), is encouraged over constructing a QVariant
+ separately and using a plain assignment operator; this is
+ because the former allow to re-use the memory already allocated for
+ the QVariant object stored inside a QModelRoleData, while the latter
+ always allocates the new variant and then destroys the old one.
+
+ Note that views may call multiData() with spans that have been used
+ in previous calls, and therefore may already contain some data.
+ Therefore, it is imperative that if the model cannot return the
+ data for a given role, then it must clear the data in the
+ corresponding QModelRoleData object. This can be done by calling
+ QModelRoleData::clearData(), or similarly by setting a default
+ constructed QVariant, and so on. Failure to clear the data will
+ result in the view believing that the "old" data is meant to be
+ used for the corresponding role.
+
+ Finally, in order to avoid code duplication, a subclass may also
+ decide to reimplement data() in terms of multiData(), by supplying
+ a span of just one element:
+
+ \snippet code/src_corelib_kernel_qabstractitemmodel.cpp 16
+
+ \note Models are not allowed to modify the roles in the span, or
+ to rearrange the span elements. Doing so results in undefined
+ behavior.
+
+ \note It is illegal to pass an invalid model index to this function.
+
+ \sa QModelRoleDataSpan, data()
+*/
+void QAbstractItemModel::multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const
+{
+ Q_ASSERT(checkIndex(index, CheckIndexOption::IndexIsValid));
+
+ for (QModelRoleData &d : roleDataSpan)
+ d.setData(data(index, d.role()));
+}
+
+/*!
\class QAbstractTableModel
\inmodule QtCore
\brief The QAbstractTableModel class provides an abstract model that can be
@@ -3457,10 +3739,9 @@ bool QAbstractItemModel::checkIndex(const QModelIndex &index, CheckIndexOptions
\note Some general guidelines for subclassing models are available in the
\l{Model Subclassing Reference}.
- \note
+ \include models.qdocinc {thread-safety-section1}{QAbstractTableModel}
- \sa {Model Classes}, QAbstractItemModel, QAbstractListModel,
- {Pixelator Example}
+ \sa {Model Classes}, QAbstractItemModel, QAbstractListModel
*/
/*!
@@ -3611,7 +3892,7 @@ Qt::ItemFlags QAbstractTableModel::flags(const QModelIndex &index) const
\l{Model Subclassing Reference}.
\sa {Model Classes}, {Model Subclassing Reference}, QAbstractItemView,
- QAbstractTableModel, {Item Views Puzzle Example}
+ QAbstractTableModel
*/
/*!
@@ -3730,7 +4011,7 @@ bool QAbstractTableModel::dropMimeData(const QMimeData *data, Qt::DropAction act
return false;
QByteArray encoded = data->data(format);
- QDataStream stream(&encoded, QIODevice::ReadOnly);
+ QDataStream stream(&encoded, QDataStream::ReadOnly);
// if the drop is on an item, replace the data in the items
if (parent.isValid() && row == -1 && column == -1) {
@@ -3781,7 +4062,7 @@ bool QAbstractListModel::dropMimeData(const QMimeData *data, Qt::DropAction acti
return false;
QByteArray encoded = data->data(format);
- QDataStream stream(&encoded, QIODevice::ReadOnly);
+ QDataStream stream(&encoded, QDataStream::ReadOnly);
// if the drop is on an item, replace the data in the items
if (parent.isValid() && row == -1 && column == -1) {
@@ -3889,3 +4170,4 @@ void QAbstractItemModelPrivate::Persistent::insertMultiAtEnd(const QModelIndex&
QT_END_NAMESPACE
#include "moc_qabstractitemmodel.cpp"
+#include "qabstractitemmodel.moc"