summaryrefslogtreecommitdiffstats
path: root/src/corelib/itemmodels
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/itemmodels')
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.cpp137
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.h13
2 files changed, 150 insertions, 0 deletions
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp
index 7e1ab851d7..af87f56255 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.cpp
+++ b/src/corelib/itemmodels/qabstractitemmodel.cpp
@@ -48,11 +48,14 @@
#include <qstack.h>
#include <qbitarray.h>
#include <qdatetime.h>
+#include <qloggingcategory.h>
#include <limits.h>
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcCheckIndex, "qt.core.qabstractitemmodel.checkindex")
+
QPersistentModelIndexData *QPersistentModelIndexData::create(const QModelIndex &index)
{
Q_ASSERT(index.isValid()); // we will _never_ insert an invalid index in the list
@@ -3320,6 +3323,140 @@ QModelIndexList QAbstractItemModel::persistentIndexList() const
return result;
}
+/*!
+ \enum QAbstractItemModel::CheckIndexOption
+ \since 5.11
+
+ This enum can be used to control the checks performed by
+ QAbstractItemModel::checkIndex().
+
+ \value CheckIndexOption::NoOption No check options are specified.
+
+ \value CheckIndexOption::IndexIsValid The model index passed to
+ QAbstractItemModel::checkIndex() is checked to be a valid model index.
+
+ \value CheckIndexOption::DoNotUseParent Does not perform any check
+ involving the usage of the parent of the index passed to
+ QAbstractItemModel::checkIndex().
+
+ \value CheckIndexOption::ParentIsInvalid The parent of the model index
+ passed to QAbstractItemModel::checkIndex() is checked to be an invalid
+ model index. If both this option and CheckIndexOption::DoNotUseParent
+ are specified, then this option is ignored.
+*/
+
+/*!
+ \since 5.11
+
+ This function checks whether \a index is a legal model index for
+ this model. A legal model index is either an invalid model index, or a
+ valid model index for which all the following holds:
+
+ \list
+
+ \li the index' model is \c{this};
+ \li the index' row is greater or equal than zero;
+ \li the index' row is less than the row count for the index' parent;
+ \li the index' column is greater or equal than zero;
+ \li the index' column is less than the column count for the index' parent.
+
+ \endlist
+
+ The \a options argument may change some of these checks. If \a options
+ contains \c{CheckIndexOption::IndexIsValid}, then \a index must be a valid
+ index; this is useful when reimplementing functions such as \l{data()} or
+ \l{setData()}, which expect valid indexes.
+
+ If \a options contains \c{CheckIndexOption::DoNotUseParent}, then the
+ checks that would call \l{parent()} are omitted; this allows calling this
+ function from a \l{parent()} reimplementation (otherwise, this would result
+ in endless recursion and a crash).
+
+ If \a options does not contain \c{CheckIndexOption::DoNotUseParent}, and it
+ contains \c{CheckIndexOption::ParentIsInvalid}, then an additional check is
+ performed: the parent index is checked for not being valid. This is useful
+ when implementing flat models such as lists or tables, where no model index
+ should have a valid parent index.
+
+ This function returns true if all the checks succeeded, and false otherwise.
+ This allows to use the function in \l{Q_ASSERT} and similar other debugging
+ mechanisms. If some check failed, a warning message will be printed in the
+ \c{qt.core.qabstractitemmodel.checkindex} logging category, containing
+ some information that may be useful for debugging the failure.
+
+ \note This function is a debugging helper for implementing your own item
+ models. When developing complex models, as well as when building
+ complicated model hierarchies (e.g. using proxy models), it is useful to
+ call this function in order to catch bugs relative to illegal model indices
+ (as defined above) accidentally passed to some QAbstractItemModel API.
+
+ \warning Note that it's undefined behavior to pass illegal indices to item
+ models, so applications must refrain from doing so, and not rely on any
+ "defensive" programming that item models could employ to handle illegal
+ indexes gracefully.
+
+ \sa QModelIndex
+*/
+bool QAbstractItemModel::checkIndex(const QModelIndex &index, CheckIndexOptions options) const
+{
+ if (!index.isValid()) {
+ if (options & CheckIndexOption::IndexIsValid) {
+ qCWarning(lcCheckIndex) << "Index" << index << "is not valid (expected valid)";
+ return false;
+ }
+ return true;
+ }
+
+ if (index.model() != this) {
+ qCWarning(lcCheckIndex) << "Index" << index
+ << "is for model" << index.model()
+ << "which is different from this model" << this;
+ return false;
+ }
+
+ if (index.row() < 0) {
+ qCWarning(lcCheckIndex) << "Index" << index
+ << "has negative row" << index.row();
+ return false;
+ }
+
+ if (index.column() < 0) {
+ qCWarning(lcCheckIndex) << "Index" << index
+ << "has negative column" << index.column();
+ return false;
+ }
+
+ if (!(options & CheckIndexOption::DoNotUseParent)) {
+ const QModelIndex parentIndex = index.parent();
+ if (options & CheckIndexOption::ParentIsInvalid) {
+ if (parentIndex.isValid()) {
+ qCWarning(lcCheckIndex) << "Index" << index
+ << "has valid parent" << parentIndex
+ << "(expected an invalid parent)";
+ return false;
+ }
+ }
+
+ const int rc = rowCount(parentIndex);
+ if (index.row() >= rc) {
+ qCWarning(lcCheckIndex) << "Index" << index
+ << "has out of range row" << index.row()
+ << "rowCount() is" << rc;
+ return false;
+ }
+
+ const int cc = columnCount(parentIndex);
+ if (index.column() >= cc) {
+ qCWarning(lcCheckIndex) << "Index" << index
+ << "has out of range column" << index.column()
+ << "columnCount() is" << cc;
+ return false;
+
+ }
+ }
+
+ return true;
+}
/*!
\class QAbstractTableModel
diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h
index cd294ef8fa..621f284c34 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.h
+++ b/src/corelib/itemmodels/qabstractitemmodel.h
@@ -250,6 +250,17 @@ public:
};
Q_ENUM(LayoutChangeHint)
+ enum class CheckIndexOption {
+ NoOption = 0x0000,
+ IndexIsValid = 0x0001,
+ DoNotUseParent = 0x0002,
+ ParentIsInvalid = 0x0004,
+ };
+ Q_ENUM(CheckIndexOption)
+ Q_DECLARE_FLAGS(CheckIndexOptions, CheckIndexOption)
+
+ Q_REQUIRED_RESULT bool checkIndex(const QModelIndex &index, CheckIndexOptions options = CheckIndexOption::NoOption) const;
+
Q_SIGNALS:
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>());
void headerDataChanged(Qt::Orientation orientation, int first, int last);
@@ -343,6 +354,8 @@ private:
Q_DISABLE_COPY(QAbstractItemModel)
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstractItemModel::CheckIndexOptions)
+
inline bool QAbstractItemModel::insertRow(int arow, const QModelIndex &aparent)
{ return insertRows(arow, 1, aparent); }
inline bool QAbstractItemModel::insertColumn(int acolumn, const QModelIndex &aparent)