diff options
Diffstat (limited to 'src/corelib/itemmodels/qabstractitemmodel.h')
-rw-r--r-- | src/corelib/itemmodels/qabstractitemmodel.h | 240 |
1 files changed, 160 insertions, 80 deletions
diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h index a7fb429cf3..8f22f14989 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.h +++ b/src/corelib/itemmodels/qabstractitemmodel.h @@ -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) 2016 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 #ifndef QABSTRACTITEMMODEL_H #define QABSTRACTITEMMODEL_H @@ -49,6 +14,108 @@ QT_REQUIRE_CONFIG(itemmodel); QT_BEGIN_NAMESPACE +class QModelRoleData +{ + int m_role; + QVariant m_data; + +public: + explicit QModelRoleData(int role) noexcept + : m_role(role) + {} + + constexpr int role() const noexcept { return m_role; } + constexpr QVariant &data() noexcept { return m_data; } + constexpr const QVariant &data() const noexcept { return m_data; } + + template <typename T> + constexpr void setData(T &&value) noexcept(noexcept(m_data.setValue(std::forward<T>(value)))) + { m_data.setValue(std::forward<T>(value)); } + + void clearData() noexcept { m_data.clear(); } +}; + +Q_DECLARE_TYPEINFO(QModelRoleData, Q_RELOCATABLE_TYPE); + +class QModelRoleDataSpan; + +namespace QtPrivate { +template <typename T, typename Enable = void> +struct IsContainerCompatibleWithModelRoleDataSpan : std::false_type {}; + +template <typename T> +struct IsContainerCompatibleWithModelRoleDataSpan<T, std::enable_if_t<std::conjunction_v< + // lacking concepts and ranges, we accept any T whose std::data yields a suitable pointer ... + std::is_convertible<decltype( std::data(std::declval<T &>()) ), QModelRoleData *>, + // ... and that has a suitable size ... + std::is_convertible<decltype( std::size(std::declval<T &>()) ), qsizetype>, + // ... and it's a range as it defines an iterator-like API + std::is_convertible< + typename std::iterator_traits<decltype( std::begin(std::declval<T &>()) )>::value_type, + QModelRoleData + >, + std::is_convertible< + decltype( std::begin(std::declval<T &>()) != std::end(std::declval<T &>()) ), + bool>, + // Don't make an accidental copy constructor + std::negation<std::is_same<std::decay_t<T>, QModelRoleDataSpan>> + >>> : std::true_type {}; +} // namespace QtPrivate + +class QModelRoleDataSpan +{ + QModelRoleData *m_modelRoleData = nullptr; + qsizetype m_len = 0; + + template <typename T> + using if_compatible_container = std::enable_if_t<QtPrivate::IsContainerCompatibleWithModelRoleDataSpan<T>::value, bool>; + +public: + constexpr QModelRoleDataSpan() noexcept {} + + constexpr QModelRoleDataSpan(QModelRoleData &modelRoleData) noexcept + : m_modelRoleData(&modelRoleData), + m_len(1) + {} + + constexpr QModelRoleDataSpan(QModelRoleData *modelRoleData, qsizetype len) + : m_modelRoleData(modelRoleData), + m_len(len) + {} + + template <typename Container, if_compatible_container<Container> = true> + constexpr QModelRoleDataSpan(Container &c) noexcept(noexcept(std::data(c)) && noexcept(std::size(c))) + : m_modelRoleData(std::data(c)), + m_len(qsizetype(std::size(c))) + {} + + constexpr qsizetype size() const noexcept { return m_len; } + constexpr qsizetype length() const noexcept { return m_len; } + constexpr QModelRoleData *data() const noexcept { return m_modelRoleData; } + constexpr QModelRoleData *begin() const noexcept { return m_modelRoleData; } + constexpr QModelRoleData *end() const noexcept { return m_modelRoleData + m_len; } + constexpr QModelRoleData &operator[](qsizetype index) const { return m_modelRoleData[index]; } + + constexpr QVariant *dataForRole(int role) const + { +#ifdef __cpp_lib_constexpr_algorithms + auto result = std::find_if(begin(), end(), [role](const QModelRoleData &roleData) { + return roleData.role() == role; + }); +#else + auto result = begin(); + const auto e = end(); + for (; result != e; ++result) { + if (result->role() == role) + break; + } +#endif + + return Q_ASSERT(result != end()), &result->data(); + } +}; + +Q_DECLARE_TYPEINFO(QModelRoleDataSpan, Q_RELOCATABLE_TYPE); class QAbstractItemModel; class QPersistentModelIndex; @@ -57,11 +124,11 @@ class QModelIndex { friend class QAbstractItemModel; public: - Q_DECL_CONSTEXPR inline QModelIndex() noexcept : r(-1), c(-1), i(0), m(nullptr) {} + constexpr inline QModelIndex() noexcept : r(-1), c(-1), i(0), m(nullptr) {} // compiler-generated copy/move ctors/assignment operators are fine! - Q_DECL_CONSTEXPR inline int row() const noexcept { return r; } - Q_DECL_CONSTEXPR inline int column() const noexcept { return c; } - Q_DECL_CONSTEXPR inline quintptr internalId() const noexcept { return i; } + constexpr inline int row() const noexcept { return r; } + constexpr inline int column() const noexcept { return c; } + constexpr inline quintptr internalId() const noexcept { return i; } inline void *internalPointer() const noexcept { return reinterpret_cast<void*>(i); } inline const void *constInternalPointer() const noexcept { return reinterpret_cast<const void *>(i); } inline QModelIndex parent() const; @@ -69,14 +136,15 @@ public: inline QModelIndex siblingAtColumn(int column) const; inline QModelIndex siblingAtRow(int row) const; inline QVariant data(int role = Qt::DisplayRole) const; + inline void multiData(QModelRoleDataSpan roleDataSpan) const; inline Qt::ItemFlags flags() const; - Q_DECL_CONSTEXPR inline const QAbstractItemModel *model() const noexcept { return m; } - Q_DECL_CONSTEXPR inline bool isValid() const noexcept { return (r >= 0) && (c >= 0) && (m != nullptr); } - Q_DECL_CONSTEXPR inline bool operator==(const QModelIndex &other) const noexcept + constexpr inline const QAbstractItemModel *model() const noexcept { return m; } + constexpr inline bool isValid() const noexcept { return (r >= 0) && (c >= 0) && (m != nullptr); } + constexpr inline bool operator==(const QModelIndex &other) const noexcept { return (other.r == r) && (other.i == i) && (other.c == c) && (other.m == m); } - Q_DECL_CONSTEXPR inline bool operator!=(const QModelIndex &other) const noexcept + constexpr inline bool operator!=(const QModelIndex &other) const noexcept { return !(*this == other); } - Q_DECL_CONSTEXPR inline bool operator<(const QModelIndex &other) const noexcept + constexpr inline bool operator<(const QModelIndex &other) const noexcept { return r < other.r || (r == other.r && (c < other.c @@ -86,13 +154,13 @@ public: private: inline QModelIndex(int arow, int acolumn, const void *ptr, const QAbstractItemModel *amodel) noexcept : r(arow), c(acolumn), i(reinterpret_cast<quintptr>(ptr)), m(amodel) {} - Q_DECL_CONSTEXPR inline QModelIndex(int arow, int acolumn, quintptr id, const QAbstractItemModel *amodel) noexcept + constexpr inline QModelIndex(int arow, int acolumn, quintptr id, const QAbstractItemModel *amodel) noexcept : r(arow), c(acolumn), i(id), m(amodel) {} int r, c; quintptr i; const QAbstractItemModel *m; }; -Q_DECLARE_TYPEINFO(QModelIndex, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QModelIndex, Q_RELOCATABLE_TYPE); #ifndef QT_NO_DEBUG_STREAM Q_CORE_EXPORT QDebug operator<<(QDebug, const QModelIndex &); @@ -110,20 +178,19 @@ public: QPersistentModelIndex(const QModelIndex &index); QPersistentModelIndex(const QPersistentModelIndex &other); ~QPersistentModelIndex(); - bool operator<(const QPersistentModelIndex &other) const; - bool operator==(const QPersistentModelIndex &other) const; - inline bool operator!=(const QPersistentModelIndex &other) const + bool operator<(const QPersistentModelIndex &other) const noexcept; + bool operator==(const QPersistentModelIndex &other) const noexcept; + inline bool operator!=(const QPersistentModelIndex &other) const noexcept { return !operator==(other); } QPersistentModelIndex &operator=(const QPersistentModelIndex &other); inline QPersistentModelIndex(QPersistentModelIndex &&other) noexcept - : d(other.d) { other.d = nullptr; } - inline QPersistentModelIndex &operator=(QPersistentModelIndex &&other) noexcept - { qSwap(d, other.d); return *this; } - inline void swap(QPersistentModelIndex &other) noexcept { qSwap(d, other.d); } - bool operator==(const QModelIndex &other) const; - bool operator!=(const QModelIndex &other) const; + : d(std::exchange(other.d, nullptr)) {} + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QPersistentModelIndex) + void swap(QPersistentModelIndex &other) noexcept { qt_ptr_swap(d, other.d); } + bool operator==(const QModelIndex &other) const noexcept; + bool operator!=(const QModelIndex &other) const noexcept; QPersistentModelIndex &operator=(const QModelIndex &other); - operator const QModelIndex&() const; + operator QModelIndex() const; int row() const; int column() const; void *internalPointer() const; @@ -132,12 +199,15 @@ public: QModelIndex parent() const; QModelIndex sibling(int row, int column) const; QVariant data(int role = Qt::DisplayRole) const; + void multiData(QModelRoleDataSpan roleDataSpan) const; Qt::ItemFlags flags() const; const QAbstractItemModel *model() const; bool isValid() const; private: QPersistentModelIndexData *d; friend size_t qHash(const QPersistentModelIndex &, size_t seed) noexcept; + friend bool qHashEquals(const QPersistentModelIndex &a, const QPersistentModelIndex &b) noexcept + { return a.d == b.d; } #ifndef QT_NO_DEBUG_STREAM friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QPersistentModelIndex &); #endif @@ -166,8 +236,7 @@ class Q_CORE_EXPORT QAbstractItemModel : public QObject friend class QPersistentModelIndexData; friend class QAbstractItemViewPrivate; - friend class QIdentityProxyModel; - friend class QTransposeProxyModelPrivate; + friend class QAbstractProxyModel; public: explicit QAbstractItemModel(QObject *parent = nullptr); @@ -204,28 +273,28 @@ public: virtual Qt::DropActions supportedDropActions() const; virtual Qt::DropActions supportedDragActions() const; - virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()); - virtual bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()); - virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); - virtual bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()); - virtual bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, + Q_INVOKABLE Q_REVISION(6, 4) virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()); + Q_INVOKABLE Q_REVISION(6, 4) virtual bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()); + Q_INVOKABLE Q_REVISION(6, 4) virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); + Q_INVOKABLE Q_REVISION(6, 4) virtual bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()); + Q_INVOKABLE Q_REVISION(6, 4) virtual bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild); - virtual bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, + Q_INVOKABLE Q_REVISION(6, 4) virtual bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationChild); - inline bool insertRow(int row, const QModelIndex &parent = QModelIndex()); - inline bool insertColumn(int column, const QModelIndex &parent = QModelIndex()); - inline bool removeRow(int row, const QModelIndex &parent = QModelIndex()); - inline bool removeColumn(int column, const QModelIndex &parent = QModelIndex()); - inline bool moveRow(const QModelIndex &sourceParent, int sourceRow, + Q_INVOKABLE Q_REVISION(6, 4) inline bool insertRow(int row, const QModelIndex &parent = QModelIndex()); + Q_INVOKABLE Q_REVISION(6, 4) inline bool insertColumn(int column, const QModelIndex &parent = QModelIndex()); + Q_INVOKABLE Q_REVISION(6, 4) inline bool removeRow(int row, const QModelIndex &parent = QModelIndex()); + Q_INVOKABLE Q_REVISION(6, 4) inline bool removeColumn(int column, const QModelIndex &parent = QModelIndex()); + Q_INVOKABLE Q_REVISION(6, 4) inline bool moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild); - inline bool moveColumn(const QModelIndex &sourceParent, int sourceColumn, + Q_INVOKABLE Q_REVISION(6, 4) inline bool moveColumn(const QModelIndex &sourceParent, int sourceColumn, const QModelIndex &destinationParent, int destinationChild); Q_INVOKABLE virtual void fetchMore(const QModelIndex &parent); Q_INVOKABLE virtual bool canFetchMore(const QModelIndex &parent) const; Q_INVOKABLE virtual Qt::ItemFlags flags(const QModelIndex &index) const; - virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); + Q_INVOKABLE Q_REVISION(6, 4) virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); virtual QModelIndex buddy(const QModelIndex &index) const; Q_INVOKABLE virtual QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits = 1, @@ -254,7 +323,9 @@ public: Q_ENUM(CheckIndexOption) Q_DECLARE_FLAGS(CheckIndexOptions, CheckIndexOption) - Q_REQUIRED_RESULT bool checkIndex(const QModelIndex &index, CheckIndexOptions options = CheckIndexOption::NoOption) const; + [[nodiscard]] bool checkIndex(const QModelIndex &index, CheckIndexOptions options = CheckIndexOption::NoOption) const; + + virtual void multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const; Q_SIGNALS: void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, @@ -279,10 +350,10 @@ Q_SIGNALS: void modelReset(QPrivateSignal); void rowsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow, QPrivateSignal); - void rowsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row, QPrivateSignal); + void rowsMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow, QPrivateSignal); void columnsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn, QPrivateSignal); - void columnsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column, QPrivateSignal); + void columnsMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn, QPrivateSignal); public Q_SLOTS: virtual bool submit(); @@ -421,14 +492,23 @@ inline QModelIndex QModelIndex::siblingAtRow(int arow) const inline QVariant QModelIndex::data(int arole) const { return m ? m->data(*this, arole) : QVariant(); } +inline void QModelIndex::multiData(QModelRoleDataSpan roleDataSpan) const +{ if (m) m->multiData(*this, roleDataSpan); } + inline Qt::ItemFlags QModelIndex::flags() const { return m ? m->flags(*this) : Qt::ItemFlags(); } -inline size_t qHash(const QModelIndex &index, size_t seed) noexcept -{ return size_t((size_t(index.row()) << 4) + size_t(index.column()) + index.internalId()) ^ seed; } +inline size_t qHash(const QModelIndex &index, size_t seed = 0) noexcept +{ +#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) + return qHashMulti(seed, index.row(), index.column(), index.internalId()); +#else + return size_t((size_t(index.row()) << 4) + size_t(index.column()) + index.internalId()) ^ seed; +#endif +} QT_END_NAMESPACE -Q_DECLARE_METATYPE(QModelIndexList) +QT_DECL_METATYPE_EXTERN(QModelIndexList, Q_CORE_EXPORT) #endif // QABSTRACTITEMMODEL_H |