diff options
Diffstat (limited to 'src/corelib/itemmodels')
21 files changed, 874 insertions, 1425 deletions
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp index c716648427..cd29f2fcc2 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.cpp +++ b/src/corelib/itemmodels/qabstractitemmodel.cpp @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** 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> -** 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> @@ -50,10 +14,13 @@ # 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 @@ -245,7 +212,7 @@ void QPersistentModelIndexData::destroy(QPersistentModelIndexData *data) */ /*! - \fn template <typename Container> QModelRoleDataSpan::QModelRoleDataSpan(Container &c) noexcept + \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. @@ -415,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; @@ -432,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); } /*! @@ -510,7 +477,7 @@ QPersistentModelIndex::operator 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; @@ -524,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; @@ -719,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(); } @@ -748,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(); } @@ -768,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" }, @@ -776,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() { @@ -875,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); @@ -896,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); @@ -932,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); @@ -1030,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()) { @@ -1082,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); @@ -1115,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()) { @@ -1532,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} */ /*! @@ -1774,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. @@ -1859,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 @@ -1891,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 @@ -2155,7 +2131,7 @@ QStringList QAbstractItemModel::mimeTypes() const */ QMimeData *QAbstractItemModel::mimeData(const QModelIndexList &indexes) const { - if (indexes.count() <= 0) + if (indexes.size() <= 0) return nullptr; QStringList types = mimeTypes(); if (types.isEmpty()) @@ -2194,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; } @@ -2551,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; @@ -2573,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 @@ -2617,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); } } } @@ -2810,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); @@ -3354,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; } @@ -3389,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()); } @@ -3483,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)); @@ -3497,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); } @@ -3510,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; } @@ -3763,10 +3739,9 @@ void QAbstractItemModel::multiData(const QModelIndex &index, QModelRoleDataSpan \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 */ /*! @@ -3917,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 */ /*! @@ -4195,3 +4170,4 @@ void QAbstractItemModelPrivate::Persistent::insertMultiAtEnd(const QModelIndex& QT_END_NAMESPACE #include "moc_qabstractitemmodel.cpp" +#include "qabstractitemmodel.moc" diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h index f86a945c52..8f22f14989 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.h +++ b/src/corelib/itemmodels/qabstractitemmodel.h @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** 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> -** 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 @@ -214,17 +178,17 @@ 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(qExchange(other.d, nullptr)) {} + : 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; - bool operator!=(const QModelIndex &other) const; + bool operator==(const QModelIndex &other) const noexcept; + bool operator!=(const QModelIndex &other) const noexcept; QPersistentModelIndex &operator=(const QModelIndex &other); operator QModelIndex() const; int row() const; @@ -309,28 +273,28 @@ public: virtual Qt::DropActions supportedDropActions() const; virtual Qt::DropActions supportedDragActions() const; - Q_INVOKABLE virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()); - Q_INVOKABLE virtual bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()); - Q_INVOKABLE virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); - Q_INVOKABLE virtual bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()); - Q_INVOKABLE 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); - Q_INVOKABLE 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); - Q_INVOKABLE inline bool insertRow(int row, const QModelIndex &parent = QModelIndex()); - Q_INVOKABLE inline bool insertColumn(int column, const QModelIndex &parent = QModelIndex()); - Q_INVOKABLE inline bool removeRow(int row, const QModelIndex &parent = QModelIndex()); - Q_INVOKABLE inline bool removeColumn(int column, const QModelIndex &parent = QModelIndex()); - Q_INVOKABLE 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); - Q_INVOKABLE 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; - Q_INVOKABLE 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, @@ -386,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(); @@ -535,7 +499,13 @@ inline Qt::ItemFlags QModelIndex::flags() const { return m ? m->flags(*this) : Qt::ItemFlags(); } inline size_t qHash(const QModelIndex &index, size_t seed = 0) noexcept -{ return size_t((size_t(index.row()) << 4) + size_t(index.column()) + index.internalId()) ^ seed; } +{ +#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 diff --git a/src/corelib/itemmodels/qabstractitemmodel_p.h b/src/corelib/itemmodels/qabstractitemmodel_p.h index e8f00975ed..e34dc3262c 100644 --- a/src/corelib/itemmodels/qabstractitemmodel_p.h +++ b/src/corelib/itemmodels/qabstractitemmodel_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QABSTRACTITEMMODEL_P_H #define QABSTRACTITEMMODEL_P_H @@ -157,6 +121,56 @@ public: }; Q_DECLARE_TYPEINFO(QAbstractItemModelPrivate::Change, Q_RELOCATABLE_TYPE); +namespace QtPrivate { + +/*! + \internal + This is a workaround for QTBUG-75172. + + Some predefined model roles are supposed to use certain enum/flag + types (e.g. fetching Qt::TextAlignmentRole is supposed to return a + variant containing a Qt::Alignment object). + + For historical reasons, a plain `int` was used sometimes. This is + surprising to end-users and also sloppy on Qt's part; users were + forced to use `int` rather than the correct datatype. + + This function tries both the "right" type and plain `int`, for a + given QVariant. This fixes the problem (using the correct datatype) + but also keeps compatibility with existing code using `int`. + + ### Qt 7: get rid of this. Always use the correct datatype. +*/ +template <typename T> +T legacyEnumValueFromModelData(const QVariant &data) +{ + static_assert(std::is_enum_v<T>); + if (data.userType() == qMetaTypeId<T>()) { + return data.value<T>(); + } else if (std::is_same_v<std::underlying_type_t<T>, int> || + std::is_same_v<std::underlying_type_t<T>, uint>) { + return T(data.toInt()); + } + + return T(); +} + +template <typename T> +T legacyFlagValueFromModelData(const QVariant &data) +{ + if (data.userType() == qMetaTypeId<T>()) { + return data.value<T>(); + } else if (std::is_same_v<std::underlying_type_t<typename T::enum_type>, int> || + std::is_same_v<std::underlying_type_t<typename T::enum_type>, uint>) { + return T::fromInt(data.toInt()); + } + + return T(); +} + +} // namespace QtPrivate + + QT_END_NAMESPACE #endif // QABSTRACTITEMMODEL_P_H diff --git a/src/corelib/itemmodels/qabstractproxymodel.cpp b/src/corelib/itemmodels/qabstractproxymodel.cpp index d8a93eee36..abdeefb4da 100644 --- a/src/corelib/itemmodels/qabstractproxymodel.cpp +++ b/src/corelib/itemmodels/qabstractproxymodel.cpp @@ -1,47 +1,12 @@ -/**************************************************************************** -** -** 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. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qabstractproxymodel.h" #include "qitemselectionmodel.h" #include <private/qabstractproxymodel_p.h> #include <QtCore/QSize> #include <QtCore/QStringList> +#include <QtCore/QMap> QT_BEGIN_NAMESPACE @@ -90,6 +55,87 @@ void QAbstractProxyModelPrivate::_q_sourceModelDestroyed() model = QAbstractItemModelPrivate::staticEmptyModel(); } +void QAbstractProxyModelPrivate::emitHeaderDataChanged() +{ + Q_Q(QAbstractProxyModel); + + if (updateHorizontalHeader) { + if (auto columnCount = q->columnCount(); columnCount > 0) + emit q->headerDataChanged(Qt::Horizontal, 0, columnCount - 1); + } + + if (updateVerticalHeader) { + if (auto rowCount = q->rowCount(); rowCount > 0) + emit q->headerDataChanged(Qt::Vertical, 0, rowCount - 1); + } + + updateHorizontalHeader = false; + updateVerticalHeader = false; +} + +void QAbstractProxyModelPrivate::scheduleHeaderUpdate(Qt::Orientation orientation) +{ + const bool isUpdateScheduled = updateHorizontalHeader || updateVerticalHeader; + + if (orientation == Qt::Horizontal && !updateHorizontalHeader) + updateHorizontalHeader = true; + else if (orientation == Qt::Vertical && !updateVerticalHeader) + updateVerticalHeader = true; + else + return; + + if (!isUpdateScheduled) { + Q_Q(QAbstractProxyModel); + QMetaObject::invokeMethod(q, [this]() { emitHeaderDataChanged(); }, Qt::QueuedConnection); + } +} + +void QAbstractProxyModelPrivate::_q_sourceModelRowsAboutToBeInserted(const QModelIndex &parent, int, int) +{ + if (parent.isValid()) + return; + sourceHadZeroRows = model->rowCount() == 0; +} + +void QAbstractProxyModelPrivate::_q_sourceModelRowsInserted(const QModelIndex &parent, int, int) +{ + if (parent.isValid()) + return; + if (sourceHadZeroRows) + scheduleHeaderUpdate(Qt::Horizontal); +} + +void QAbstractProxyModelPrivate::_q_sourceModelRowsRemoved(const QModelIndex &parent, int, int) +{ + if (parent.isValid()) + return; + if (model->rowCount() == 0) + scheduleHeaderUpdate(Qt::Horizontal); +} + +void QAbstractProxyModelPrivate::_q_sourceModelColumnsAboutToBeInserted(const QModelIndex &parent, int, int) +{ + if (parent.isValid()) + return; + sourceHadZeroColumns = model->columnCount() == 0; +} + +void QAbstractProxyModelPrivate::_q_sourceModelColumnsInserted(const QModelIndex &parent, int, int) +{ + if (parent.isValid()) + return; + if (sourceHadZeroColumns) + scheduleHeaderUpdate(Qt::Vertical); +} + +void QAbstractProxyModelPrivate::_q_sourceModelColumnsRemoved(const QModelIndex &parent, int, int) +{ + if (parent.isValid()) + return; + if (model->columnCount() == 0) + scheduleHeaderUpdate(Qt::Vertical); +} + /*! Constructs a proxy model with the given \a parent. */ @@ -131,15 +177,34 @@ void QAbstractProxyModel::setSourceModel(QAbstractItemModel *sourceModel) d->model.removeBindingUnlessInWrapper(); // Special case to handle nullptr models. Otherwise we will have unwanted // notifications. - if (!sourceModel && d->model == QAbstractItemModelPrivate::staticEmptyModel()) + const QAbstractItemModel *currentModel = d->model.valueBypassingBindings(); + if (!sourceModel && currentModel == QAbstractItemModelPrivate::staticEmptyModel()) return; - if (sourceModel != d->model) { - if (d->model) - disconnect(d->model, SIGNAL(destroyed()), this, SLOT(_q_sourceModelDestroyed())); + static const struct { + const char *signalName; + const char *slotName; + } connectionTable[] = { + // clang-format off + { SIGNAL(destroyed()), SLOT(_q_sourceModelDestroyed()) }, + { SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), SLOT(_q_sourceModelRowsAboutToBeInserted(QModelIndex,int,int)) }, + { SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(_q_sourceModelRowsInserted(QModelIndex,int,int)) }, + { SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(_q_sourceModelRowsRemoved(QModelIndex,int,int)) }, + { SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), SLOT(_q_sourceModelColumnsAboutToBeInserted(QModelIndex,int,int)) }, + { SIGNAL(columnsInserted(QModelIndex,int,int)), SLOT(_q_sourceModelColumnsInserted(QModelIndex,int,int)) }, + { SIGNAL(columnsRemoved(QModelIndex,int,int)), SLOT(_q_sourceModelColumnsRemoved(QModelIndex,int,int)) } + // clang-format on + }; + + if (sourceModel != currentModel) { + if (currentModel) { + for (const auto &c : connectionTable) + disconnect(currentModel, c.signalName, this, c.slotName); + } if (sourceModel) { d->model.setValueBypassingBindings(sourceModel); - connect(d->model, SIGNAL(destroyed()), this, SLOT(_q_sourceModelDestroyed())); + for (const auto &c : connectionTable) + connect(sourceModel, c.signalName, this, c.slotName); } else { d->model.setValueBypassingBindings(QAbstractItemModelPrivate::staticEmptyModel()); } @@ -252,13 +317,17 @@ QVariant QAbstractProxyModel::data(const QModelIndex &proxyIndex, int role) cons QVariant QAbstractProxyModel::headerData(int section, Qt::Orientation orientation, int role) const { Q_D(const QAbstractProxyModel); - int sourceSection; + int sourceSection = section; if (orientation == Qt::Horizontal) { - const QModelIndex proxyIndex = index(0, section); - sourceSection = mapToSource(proxyIndex).column(); + if (rowCount() > 0) { + const QModelIndex proxyIndex = index(0, section); + sourceSection = mapToSource(proxyIndex).column(); + } } else { - const QModelIndex proxyIndex = index(section, 0); - sourceSection = mapToSource(proxyIndex).row(); + if (columnCount() > 0) { + const QModelIndex proxyIndex = index(section, 0); + sourceSection = mapToSource(proxyIndex).row(); + } } return d->model->headerData(sourceSection, orientation, role); } @@ -395,7 +464,7 @@ QMimeData* QAbstractProxyModel::mimeData(const QModelIndexList &indexes) const { Q_D(const QAbstractProxyModel); QModelIndexList list; - list.reserve(indexes.count()); + list.reserve(indexes.size()); for (const QModelIndex &index : indexes) list << mapToSource(index); return d->model->mimeData(list); diff --git a/src/corelib/itemmodels/qabstractproxymodel.h b/src/corelib/itemmodels/qabstractproxymodel.h index bb8c5400dc..8652f500df 100644 --- a/src/corelib/itemmodels/qabstractproxymodel.h +++ b/src/corelib/itemmodels/qabstractproxymodel.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QABSTRACTPROXYMODEL_H #define QABSTRACTPROXYMODEL_H @@ -111,6 +75,12 @@ private: Q_DECLARE_PRIVATE(QAbstractProxyModel) Q_DISABLE_COPY(QAbstractProxyModel) Q_PRIVATE_SLOT(d_func(), void _q_sourceModelDestroyed()) + Q_PRIVATE_SLOT(d_func(), void _q_sourceModelRowsAboutToBeInserted(QModelIndex, int, int)) + Q_PRIVATE_SLOT(d_func(), void _q_sourceModelRowsInserted(QModelIndex, int, int)) + Q_PRIVATE_SLOT(d_func(), void _q_sourceModelRowsRemoved(QModelIndex, int, int)) + Q_PRIVATE_SLOT(d_func(), void _q_sourceModelColumnsAboutToBeInserted(QModelIndex, int, int)) + Q_PRIVATE_SLOT(d_func(), void _q_sourceModelColumnsInserted(QModelIndex, int, int)) + Q_PRIVATE_SLOT(d_func(), void _q_sourceModelColumnsRemoved(QModelIndex, int, int)) }; QT_END_NAMESPACE diff --git a/src/corelib/itemmodels/qabstractproxymodel_p.h b/src/corelib/itemmodels/qabstractproxymodel_p.h index 2ddd2428dc..d33666d00b 100644 --- a/src/corelib/itemmodels/qabstractproxymodel_p.h +++ b/src/corelib/itemmodels/qabstractproxymodel_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QABSTRACTPROXYMODEL_P_H #define QABSTRACTPROXYMODEL_P_H @@ -52,6 +16,7 @@ // // +#include "qabstractproxymodel.h" #include "private/qabstractitemmodel_p.h" #include "private/qproperty_p.h" @@ -63,7 +28,13 @@ class Q_CORE_EXPORT QAbstractProxyModelPrivate : public QAbstractItemModelPrivat { Q_DECLARE_PUBLIC(QAbstractProxyModel) public: - QAbstractProxyModelPrivate() : QAbstractItemModelPrivate() { } + QAbstractProxyModelPrivate() + : QAbstractItemModelPrivate(), + sourceHadZeroRows(false), + sourceHadZeroColumns(false), + updateVerticalHeader(false), + updateHorizontalHeader(false) + {} void setModelForwarder(QAbstractItemModel *sourceModel) { q_func()->setSourceModel(sourceModel); @@ -79,8 +50,23 @@ public: &QAbstractProxyModelPrivate::modelChangedForwarder, &QAbstractProxyModelPrivate::getModelForwarder, nullptr) virtual void _q_sourceModelDestroyed(); + void _q_sourceModelRowsAboutToBeInserted(const QModelIndex &parent, int first, int last); + void _q_sourceModelRowsInserted(const QModelIndex &parent, int first, int last); + void _q_sourceModelRowsRemoved(const QModelIndex &parent, int first, int last); + void _q_sourceModelColumnsAboutToBeInserted(const QModelIndex &parent, int first, int last); + void _q_sourceModelColumnsInserted(const QModelIndex &parent, int first, int last); + void _q_sourceModelColumnsRemoved(const QModelIndex &parent, int first, int last); + void mapDropCoordinatesToSource(int row, int column, const QModelIndex &parent, int *source_row, int *source_column, QModelIndex *source_parent) const; + + void scheduleHeaderUpdate(Qt::Orientation orientation); + void emitHeaderDataChanged(); + + unsigned int sourceHadZeroRows : 1; + unsigned int sourceHadZeroColumns : 1; + unsigned int updateVerticalHeader : 1; + unsigned int updateHorizontalHeader : 1; }; QT_END_NAMESPACE diff --git a/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp b/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp index 72ff6c1f36..3a49d37cff 100644 --- a/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp +++ b/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp @@ -1,45 +1,10 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> -** 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 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qconcatenatetablesproxymodel.h" #include <private/qabstractitemmodel_p.h> #include "qsize.h" +#include "qmap.h" #include "qdebug.h" QT_BEGIN_NAMESPACE @@ -61,26 +26,43 @@ public: }; SourceModelForRowResult sourceModelForRow(int row) const; - void _q_slotRowsAboutToBeInserted(const QModelIndex &, int start, int end); - void _q_slotRowsInserted(const QModelIndex &, int start, int end); - void _q_slotRowsAboutToBeRemoved(const QModelIndex &, int start, int end); - void _q_slotRowsRemoved(const QModelIndex &, int start, int end); - void _q_slotColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end); - void _q_slotColumnsInserted(const QModelIndex &parent, int, int); - void _q_slotColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end); - void _q_slotColumnsRemoved(const QModelIndex &parent, int, int); - void _q_slotDataChanged(const QModelIndex &from, const QModelIndex &to, const QList<int> &roles); - void _q_slotSourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint); - void _q_slotSourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint); - void _q_slotModelAboutToBeReset(); - void _q_slotModelReset(); + void slotRowsAboutToBeInserted(const QModelIndex &, int start, int end); + void slotRowsInserted(const QModelIndex &, int start, int end); + void slotRowsAboutToBeRemoved(const QModelIndex &, int start, int end); + void slotRowsRemoved(const QModelIndex &, int start, int end); + void slotColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end); + void slotColumnsInserted(const QModelIndex &parent, int, int); + void slotColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end); + void slotColumnsRemoved(const QModelIndex &parent, int, int); + void slotDataChanged(const QModelIndex &from, const QModelIndex &to, const QList<int> &roles); + void slotSourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint); + void slotSourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint); + void slotModelAboutToBeReset(); + void slotModelReset(); int columnCountAfterChange(const QAbstractItemModel *model, int newCount) const; int calculatedColumnCount() const; void updateColumnCount(); bool mapDropCoordinatesToSource(int row, int column, const QModelIndex &parent, int *sourceRow, int *sourceColumn, QModelIndex *sourceParent, QAbstractItemModel **sourceModel) const; - QList<QAbstractItemModel *> m_models; + struct ModelInfo { + using ConnArray = std::array<QMetaObject::Connection, 13>; + ModelInfo(QAbstractItemModel *m, ConnArray &&con) + : model(m), connections(std::move(con)) {} + QAbstractItemModel *model = nullptr; + ConnArray connections; + }; + QList<ModelInfo> m_models; + + QList<ModelInfo>::const_iterator findSourceModel(const QAbstractItemModel *m) const + { + auto byModelPtr = [m](const auto &modInfo) { return modInfo.model == m; }; + return std::find_if(m_models.cbegin(), m_models.cend(), byModelPtr); + } + + bool containsSourceModel(const QAbstractItemModel *m) const + { return findSourceModel(m) != m_models.cend(); } + int m_rowCount; // have to maintain it here since we can't compute during model destruction int m_columnCount; @@ -151,7 +133,7 @@ QModelIndex QConcatenateTablesProxyModel::mapFromSource(const QModelIndex &sourc if (!sourceIndex.isValid()) return QModelIndex(); const QAbstractItemModel *sourceModel = sourceIndex.model(); - if (!d->m_models.contains(const_cast<QAbstractItemModel *>(sourceModel))) { + if (!d->containsSourceModel(sourceModel)) { qWarning("QConcatenateTablesProxyModel: index from wrong model passed to mapFromSource"); Q_ASSERT(!"QConcatenateTablesProxyModel: index from wrong model passed to mapFromSource"); return QModelIndex(); @@ -243,7 +225,7 @@ Qt::ItemFlags QConcatenateTablesProxyModel::flags(const QModelIndex &index) cons return Qt::NoItemFlags; Q_ASSERT(checkIndex(index)); if (!index.isValid()) - return d->m_models.at(0)->flags(index); + return d->m_models.at(0).model->flags(index); const QModelIndex sourceIndex = mapToSource(index); Q_ASSERT(sourceIndex.isValid()); return sourceIndex.model()->flags(sourceIndex); @@ -261,7 +243,7 @@ QVariant QConcatenateTablesProxyModel::headerData(int section, Qt::Orientation o return QVariant(); switch (orientation) { case Qt::Horizontal: - return d->m_models.at(0)->headerData(section, orientation, role); + return d->m_models.at(0).model->headerData(section, orientation, role); case Qt::Vertical: { const auto result = d->sourceModelForRow(section); Q_ASSERT(result.sourceModel); @@ -327,7 +309,7 @@ QStringList QConcatenateTablesProxyModel::mimeTypes() const Q_D(const QConcatenateTablesProxyModel); if (d->m_models.isEmpty()) return QStringList(); - return d->m_models.at(0)->mimeTypes(); + return d->m_models.at(0).model->mimeTypes(); } /*! @@ -350,7 +332,7 @@ QMimeData *QConcatenateTablesProxyModel::mimeData(const QModelIndexList &indexes Q_ASSERT(checkIndex(firstIndex, CheckIndexOption::IndexIsValid)); const auto result = d->sourceModelForRow(firstIndex.row()); QModelIndexList sourceIndexes; - sourceIndexes.reserve(indexes.count()); + sourceIndexes.reserve(indexes.size()); for (const QModelIndex &index : indexes) { const QModelIndex sourceIndex = mapToSource(index); Q_ASSERT(sourceIndex.model() == result.sourceModel); // see documentation above @@ -369,7 +351,7 @@ bool QConcatenateTablesProxyModelPrivate::mapDropCoordinatesToSource(int row, in // Drop after the last item if (row == -1 || row == m_rowCount) { *sourceRow = -1; - *sourceModel = m_models.constLast(); + *sourceModel = m_models.constLast().model; return true; } // Drop between toplevel items @@ -455,7 +437,11 @@ QSize QConcatenateTablesProxyModel::span(const QModelIndex &index) const QList<QAbstractItemModel *> QConcatenateTablesProxyModel::sourceModels() const { Q_D(const QConcatenateTablesProxyModel); - return d->m_models.toList(); + QList<QAbstractItemModel *> ret; + ret.reserve(d->m_models.size()); + for (const auto &info : d->m_models) + ret.push_back(info.model); + return ret; } /*! @@ -469,30 +455,42 @@ void QConcatenateTablesProxyModel::addSourceModel(QAbstractItemModel *sourceMode { Q_D(QConcatenateTablesProxyModel); Q_ASSERT(sourceModel); - Q_ASSERT(!d->m_models.contains(sourceModel)); - connect(sourceModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)), this, SLOT(_q_slotDataChanged(QModelIndex,QModelIndex,QList<int>))); - connect(sourceModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(_q_slotRowsInserted(QModelIndex,int,int))); - connect(sourceModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(_q_slotRowsRemoved(QModelIndex,int,int))); - connect(sourceModel, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(_q_slotRowsAboutToBeInserted(QModelIndex,int,int))); - connect(sourceModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(_q_slotRowsAboutToBeRemoved(QModelIndex,int,int))); - - connect(sourceModel, SIGNAL(columnsInserted(QModelIndex,int,int)), this, SLOT(_q_slotColumnsInserted(QModelIndex,int,int))); - connect(sourceModel, SIGNAL(columnsRemoved(QModelIndex,int,int)), this, SLOT(_q_slotColumnsRemoved(QModelIndex,int,int))); - connect(sourceModel, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(_q_slotColumnsAboutToBeInserted(QModelIndex,int,int))); - connect(sourceModel, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(_q_slotColumnsAboutToBeRemoved(QModelIndex,int,int))); - - connect(sourceModel, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint)), - this, SLOT(_q_slotSourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint))); - connect(sourceModel, SIGNAL(layoutChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint)), - this, SLOT(_q_slotSourceLayoutChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint))); - connect(sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_slotModelAboutToBeReset())); - connect(sourceModel, SIGNAL(modelReset()), this, SLOT(_q_slotModelReset())); + Q_ASSERT(!d->containsSourceModel(sourceModel)); const int newRows = sourceModel->rowCount(); if (newRows > 0) beginInsertRows(QModelIndex(), d->m_rowCount, d->m_rowCount + newRows - 1); d->m_rowCount += newRows; - d->m_models.append(sourceModel); + d->m_models.emplace_back(sourceModel, std::array{ + QObjectPrivate::connect(sourceModel, &QAbstractItemModel::dataChanged, + d, &QConcatenateTablesProxyModelPrivate::slotDataChanged), + QObjectPrivate::connect(sourceModel, &QAbstractItemModel::rowsInserted, + d, &QConcatenateTablesProxyModelPrivate::slotRowsInserted), + QObjectPrivate::connect(sourceModel, &QAbstractItemModel::rowsRemoved, + d, &QConcatenateTablesProxyModelPrivate::slotRowsRemoved), + QObjectPrivate::connect(sourceModel, &QAbstractItemModel::rowsAboutToBeInserted, + d, &QConcatenateTablesProxyModelPrivate::slotRowsAboutToBeInserted), + QObjectPrivate::connect(sourceModel, &QAbstractItemModel::rowsAboutToBeRemoved, + d, &QConcatenateTablesProxyModelPrivate::slotRowsAboutToBeRemoved), + + QObjectPrivate::connect(sourceModel, &QAbstractItemModel::columnsInserted, + d, &QConcatenateTablesProxyModelPrivate::slotColumnsInserted), + QObjectPrivate::connect(sourceModel, &QAbstractItemModel::columnsRemoved, + d, &QConcatenateTablesProxyModelPrivate::slotColumnsRemoved), + QObjectPrivate::connect(sourceModel, &QAbstractItemModel::columnsAboutToBeInserted, + d, &QConcatenateTablesProxyModelPrivate::slotColumnsAboutToBeInserted), + QObjectPrivate::connect(sourceModel, &QAbstractItemModel::columnsAboutToBeRemoved, + d, &QConcatenateTablesProxyModelPrivate::slotColumnsAboutToBeRemoved), + + QObjectPrivate::connect(sourceModel, &QAbstractItemModel::layoutAboutToBeChanged, + d, &QConcatenateTablesProxyModelPrivate::slotSourceLayoutAboutToBeChanged), + QObjectPrivate::connect(sourceModel, &QAbstractItemModel::layoutChanged, + d, &QConcatenateTablesProxyModelPrivate::slotSourceLayoutChanged), + QObjectPrivate::connect(sourceModel, &QAbstractItemModel::modelAboutToBeReset, + d, &QConcatenateTablesProxyModelPrivate::slotModelAboutToBeReset), + QObjectPrivate::connect(sourceModel, &QAbstractItemModel::modelReset, + d, &QConcatenateTablesProxyModelPrivate::slotModelReset), + }); if (newRows > 0) endInsertRows(); @@ -507,15 +505,18 @@ void QConcatenateTablesProxyModel::addSourceModel(QAbstractItemModel *sourceMode void QConcatenateTablesProxyModel::removeSourceModel(QAbstractItemModel *sourceModel) { Q_D(QConcatenateTablesProxyModel); - Q_ASSERT(d->m_models.contains(sourceModel)); - disconnect(sourceModel, nullptr, this, nullptr); + + auto it = d->findSourceModel(sourceModel); + Q_ASSERT(it != d->m_models.cend()); + for (auto &c : it->connections) + disconnect(c); const int rowsRemoved = sourceModel->rowCount(); const int rowsPrior = d->computeRowsPrior(sourceModel); // location of removed section if (rowsRemoved > 0) beginRemoveRows(QModelIndex(), rowsPrior, rowsPrior + rowsRemoved - 1); - d->m_models.removeOne(sourceModel); + d->m_models.erase(it); d->m_rowCount -= rowsRemoved; if (rowsRemoved > 0) endRemoveRows(); @@ -523,7 +524,8 @@ void QConcatenateTablesProxyModel::removeSourceModel(QAbstractItemModel *sourceM d->updateColumnCount(); } -void QConcatenateTablesProxyModelPrivate::_q_slotRowsAboutToBeInserted(const QModelIndex &parent, int start, int end) +void QConcatenateTablesProxyModelPrivate::slotRowsAboutToBeInserted(const QModelIndex &parent, + int start, int end) { Q_Q(QConcatenateTablesProxyModel); if (parent.isValid()) // not supported, the proxy is a flat model @@ -533,7 +535,8 @@ void QConcatenateTablesProxyModelPrivate::_q_slotRowsAboutToBeInserted(const QMo q->beginInsertRows(QModelIndex(), rowsPrior + start, rowsPrior + end); } -void QConcatenateTablesProxyModelPrivate::_q_slotRowsInserted(const QModelIndex &parent, int start, int end) +void QConcatenateTablesProxyModelPrivate::slotRowsInserted(const QModelIndex &parent, int start, + int end) { Q_Q(QConcatenateTablesProxyModel); if (parent.isValid()) // flat model @@ -542,7 +545,8 @@ void QConcatenateTablesProxyModelPrivate::_q_slotRowsInserted(const QModelIndex q->endInsertRows(); } -void QConcatenateTablesProxyModelPrivate::_q_slotRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +void QConcatenateTablesProxyModelPrivate::slotRowsAboutToBeRemoved(const QModelIndex &parent, + int start, int end) { Q_Q(QConcatenateTablesProxyModel); if (parent.isValid()) // flat model @@ -552,7 +556,7 @@ void QConcatenateTablesProxyModelPrivate::_q_slotRowsAboutToBeRemoved(const QMod q->beginRemoveRows(QModelIndex(), rowsPrior + start, rowsPrior + end); } -void QConcatenateTablesProxyModelPrivate::_q_slotRowsRemoved(const QModelIndex &parent, int start, int end) +void QConcatenateTablesProxyModelPrivate::slotRowsRemoved(const QModelIndex &parent, int start, int end) { Q_Q(QConcatenateTablesProxyModel); if (parent.isValid()) // flat model @@ -561,7 +565,8 @@ void QConcatenateTablesProxyModelPrivate::_q_slotRowsRemoved(const QModelIndex & q->endRemoveRows(); } -void QConcatenateTablesProxyModelPrivate::_q_slotColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end) +void QConcatenateTablesProxyModelPrivate::slotColumnsAboutToBeInserted(const QModelIndex &parent, + int start, int end) { Q_Q(QConcatenateTablesProxyModel); if (parent.isValid()) // flat model @@ -577,7 +582,8 @@ void QConcatenateTablesProxyModelPrivate::_q_slotColumnsAboutToBeInserted(const m_newColumnCount = newColCount; } -void QConcatenateTablesProxyModelPrivate::_q_slotColumnsInserted(const QModelIndex &parent, int start, int end) +void QConcatenateTablesProxyModelPrivate::slotColumnsInserted(const QModelIndex &parent, int start, + int end) { Q_UNUSED(start); Q_UNUSED(end); @@ -590,7 +596,8 @@ void QConcatenateTablesProxyModelPrivate::_q_slotColumnsInserted(const QModelInd } } -void QConcatenateTablesProxyModelPrivate::_q_slotColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +void QConcatenateTablesProxyModelPrivate::slotColumnsAboutToBeRemoved(const QModelIndex &parent, + int start, int end) { Q_Q(QConcatenateTablesProxyModel); if (parent.isValid()) // flat model @@ -604,7 +611,8 @@ void QConcatenateTablesProxyModelPrivate::_q_slotColumnsAboutToBeRemoved(const Q m_newColumnCount = newColCount; } -void QConcatenateTablesProxyModelPrivate::_q_slotColumnsRemoved(const QModelIndex &parent, int start, int end) +void QConcatenateTablesProxyModelPrivate::slotColumnsRemoved(const QModelIndex &parent, int start, + int end) { Q_Q(QConcatenateTablesProxyModel); Q_UNUSED(start); @@ -617,7 +625,9 @@ void QConcatenateTablesProxyModelPrivate::_q_slotColumnsRemoved(const QModelInde } } -void QConcatenateTablesProxyModelPrivate::_q_slotDataChanged(const QModelIndex &from, const QModelIndex &to, const QList<int> &roles) +void QConcatenateTablesProxyModelPrivate::slotDataChanged(const QModelIndex &from, + const QModelIndex &to, + const QList<int> &roles) { Q_Q(QConcatenateTablesProxyModel); Q_ASSERT(from.isValid()); @@ -634,7 +644,8 @@ void QConcatenateTablesProxyModelPrivate::_q_slotDataChanged(const QModelIndex & emit q->dataChanged(myFrom, myTo, roles); } -void QConcatenateTablesProxyModelPrivate::_q_slotSourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint) +void QConcatenateTablesProxyModelPrivate::slotSourceLayoutAboutToBeChanged( + const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint) { Q_Q(QConcatenateTablesProxyModel); @@ -656,7 +667,8 @@ void QConcatenateTablesProxyModelPrivate::_q_slotSourceLayoutAboutToBeChanged(co } } -void QConcatenateTablesProxyModelPrivate::_q_slotSourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint) +void QConcatenateTablesProxyModelPrivate::slotSourceLayoutChanged( + const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint) { Q_Q(QConcatenateTablesProxyModel); if (!sourceParents.isEmpty() && !sourceParents.contains(QModelIndex())) @@ -673,20 +685,20 @@ void QConcatenateTablesProxyModelPrivate::_q_slotSourceLayoutChanged(const QList emit q->layoutChanged({}, hint); } -void QConcatenateTablesProxyModelPrivate::_q_slotModelAboutToBeReset() +void QConcatenateTablesProxyModelPrivate::slotModelAboutToBeReset() { Q_Q(QConcatenateTablesProxyModel); - Q_ASSERT(m_models.contains(const_cast<QAbstractItemModel *>(static_cast<const QAbstractItemModel *>(q->sender())))); + Q_ASSERT(containsSourceModel(static_cast<QAbstractItemModel *>(q->sender()))); q->beginResetModel(); // A reset might reduce both rowCount and columnCount, and we can't notify of both at the same time, // and notifying of one after the other leaves an intermediary invalid situation. // So the only safe choice is to forward it as a full reset. } -void QConcatenateTablesProxyModelPrivate::_q_slotModelReset() +void QConcatenateTablesProxyModelPrivate::slotModelReset() { Q_Q(QConcatenateTablesProxyModel); - Q_ASSERT(m_models.contains(const_cast<QAbstractItemModel *>(static_cast<const QAbstractItemModel *>(q->sender())))); + Q_ASSERT(containsSourceModel(static_cast<QAbstractItemModel *>(q->sender()))); m_columnCount = calculatedColumnCount(); m_rowCount = computeRowsPrior(nullptr); q->endResetModel(); @@ -697,10 +709,11 @@ int QConcatenateTablesProxyModelPrivate::calculatedColumnCount() const if (m_models.isEmpty()) return 0; - const auto it = std::min_element(m_models.begin(), m_models.end(), [](const QAbstractItemModel* model1, const QAbstractItemModel* model2) { - return model1->columnCount() < model2->columnCount(); - }); - return (*it)->columnCount(); + auto byColumnCount = [](const auto &a, const auto &b) { + return a.model->columnCount() < b.model->columnCount(); + }; + const auto it = std::min_element(m_models.begin(), m_models.end(), byColumnCount); + return it->model->columnCount(); } void QConcatenateTablesProxyModelPrivate::updateColumnCount() @@ -723,8 +736,8 @@ void QConcatenateTablesProxyModelPrivate::updateColumnCount() int QConcatenateTablesProxyModelPrivate::columnCountAfterChange(const QAbstractItemModel *model, int newCount) const { int newColumnCount = 0; - for (int i = 0; i < m_models.count(); ++i) { - const QAbstractItemModel *mod = m_models.at(i); + for (qsizetype i = 0; i < m_models.size(); ++i) { + const QAbstractItemModel *mod = m_models.at(i).model; const int colCount = mod == model ? newCount : mod->columnCount(); if (i == 0) newColumnCount = colCount; @@ -737,7 +750,7 @@ int QConcatenateTablesProxyModelPrivate::columnCountAfterChange(const QAbstractI int QConcatenateTablesProxyModelPrivate::computeRowsPrior(const QAbstractItemModel *sourceModel) const { int rowsPrior = 0; - for (const QAbstractItemModel *model : m_models) { + for (const auto &[model, _] : m_models) { if (model == sourceModel) break; rowsPrior += model->rowCount(); @@ -749,7 +762,7 @@ QConcatenateTablesProxyModelPrivate::SourceModelForRowResult QConcatenateTablesP { QConcatenateTablesProxyModelPrivate::SourceModelForRowResult result; int rowCount = 0; - for (QAbstractItemModel *model : m_models) { + for (const auto &[model, _] : m_models) { const int subRowCount = model->rowCount(); if (rowCount + subRowCount > row) { result.sourceModel = model; diff --git a/src/corelib/itemmodels/qconcatenatetablesproxymodel.h b/src/corelib/itemmodels/qconcatenatetablesproxymodel.h index a119bab098..9dbebd7b88 100644 --- a/src/corelib/itemmodels/qconcatenatetablesproxymodel.h +++ b/src/corelib/itemmodels/qconcatenatetablesproxymodel.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> -** 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 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QCONCATENATEROWSPROXYMODEL_H #define QCONCATENATEROWSPROXYMODEL_H @@ -82,21 +46,6 @@ public: private: Q_DECLARE_PRIVATE(QConcatenateTablesProxyModel) Q_DISABLE_COPY(QConcatenateTablesProxyModel) - - Q_PRIVATE_SLOT(d_func(), void _q_slotRowsAboutToBeInserted(const QModelIndex &, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_slotRowsInserted(const QModelIndex &, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_slotRowsAboutToBeRemoved(const QModelIndex &, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_slotRowsRemoved(const QModelIndex &, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_slotColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_slotColumnsInserted(const QModelIndex &parent, int, int)) - Q_PRIVATE_SLOT(d_func(), void _q_slotColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_slotColumnsRemoved(const QModelIndex &parent, int, int)) - Q_PRIVATE_SLOT(d_func(), - void _q_slotDataChanged(const QModelIndex &from, const QModelIndex &to, const QList<int> &roles)) - Q_PRIVATE_SLOT(d_func(), void _q_slotSourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint)) - Q_PRIVATE_SLOT(d_func(), void _q_slotSourceLayoutChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint)) - Q_PRIVATE_SLOT(d_func(), void _q_slotModelAboutToBeReset()) - Q_PRIVATE_SLOT(d_func(), void _q_slotModelReset()) }; QT_END_NAMESPACE diff --git a/src/corelib/itemmodels/qidentityproxymodel.cpp b/src/corelib/itemmodels/qidentityproxymodel.cpp index 6111cef993..89fa7e5c07 100644 --- a/src/corelib/itemmodels/qidentityproxymodel.cpp +++ b/src/corelib/itemmodels/qidentityproxymodel.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com> -** 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) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qidentityproxymodel.h" #include "qidentityproxymodel_p.h" @@ -180,7 +144,7 @@ QItemSelection QIdentityProxyModel::mapSelectionFromSource(const QItemSelection& QItemSelection::const_iterator it = selection.constBegin(); const QItemSelection::const_iterator end = selection.constEnd(); - proxySelection.reserve(selection.count()); + proxySelection.reserve(selection.size()); for ( ; it != end; ++it) { Q_ASSERT(it->model() == d->model); const QItemSelectionRange range(mapFromSource(it->topLeft()), mapFromSource(it->bottomRight())); @@ -203,7 +167,7 @@ QItemSelection QIdentityProxyModel::mapSelectionToSource(const QItemSelection& s QItemSelection::const_iterator it = selection.constBegin(); const QItemSelection::const_iterator end = selection.constEnd(); - sourceSelection.reserve(selection.count()); + sourceSelection.reserve(selection.size()); for ( ; it != end; ++it) { Q_ASSERT(it->model() == this); const QItemSelectionRange range(mapToSource(it->topLeft()), mapToSource(it->bottomRight())); @@ -239,7 +203,7 @@ QModelIndexList QIdentityProxyModel::match(const QModelIndex& start, int role, c QModelIndexList::const_iterator it = sourceList.constBegin(); const QModelIndexList::const_iterator end = sourceList.constEnd(); QModelIndexList proxyList; - proxyList.reserve(sourceList.count()); + proxyList.reserve(sourceList.size()); for ( ; it != end; ++it) proxyList.append(mapFromSource(*it)); return proxyList; @@ -326,97 +290,108 @@ void QIdentityProxyModel::setSourceModel(QAbstractItemModel* newSourceModel) { beginResetModel(); - if (sourceModel()) { - disconnect(sourceModel(), SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsAboutToBeInserted(QModelIndex,int,int))); - disconnect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsInserted(QModelIndex,int,int))); - disconnect(sourceModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsAboutToBeRemoved(QModelIndex,int,int))); - disconnect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsRemoved(QModelIndex,int,int))); - disconnect(sourceModel(), SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); - disconnect(sourceModel(), SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int))); - disconnect(sourceModel(), SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsAboutToBeInserted(QModelIndex,int,int))); - disconnect(sourceModel(), SIGNAL(columnsInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsInserted(QModelIndex,int,int))); - disconnect(sourceModel(), SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsAboutToBeRemoved(QModelIndex,int,int))); - disconnect(sourceModel(), SIGNAL(columnsRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsRemoved(QModelIndex,int,int))); - disconnect(sourceModel(), SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); - disconnect(sourceModel(), SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int))); - disconnect(sourceModel(), SIGNAL(modelAboutToBeReset()), - this, SLOT(_q_sourceModelAboutToBeReset())); - disconnect(sourceModel(), SIGNAL(modelReset()), - this, SLOT(_q_sourceModelReset())); - disconnect(sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)), - this, SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex,QList<int>))); - disconnect(sourceModel(), SIGNAL(headerDataChanged(Qt::Orientation,int,int)), - this, SLOT(_q_sourceHeaderDataChanged(Qt::Orientation,int,int))); - disconnect(sourceModel(), SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), - this, SLOT(_q_sourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint))); - disconnect(sourceModel(), SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), - this, SLOT(_q_sourceLayoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint))); - } + Q_D(QIdentityProxyModel); + + // Call QObject::disconnect() unconditionally, if there is an existing source + // model, it's disconnected, and if there isn't, then calling disconnect() on + // a default-constructed Connection does nothing + for (const auto &c : d->m_sourceModelConnections) + QObject::disconnect(c); QAbstractProxyModel::setSourceModel(newSourceModel); if (sourceModel()) { - connect(sourceModel(), SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - SLOT(_q_sourceRowsAboutToBeInserted(QModelIndex,int,int))); - connect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), - SLOT(_q_sourceRowsInserted(QModelIndex,int,int))); - connect(sourceModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - SLOT(_q_sourceRowsAboutToBeRemoved(QModelIndex,int,int))); - connect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), - SLOT(_q_sourceRowsRemoved(QModelIndex,int,int))); - connect(sourceModel(), SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - SLOT(_q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); - connect(sourceModel(), SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), - SLOT(_q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int))); - connect(sourceModel(), SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), - SLOT(_q_sourceColumnsAboutToBeInserted(QModelIndex,int,int))); - connect(sourceModel(), SIGNAL(columnsInserted(QModelIndex,int,int)), - SLOT(_q_sourceColumnsInserted(QModelIndex,int,int))); - connect(sourceModel(), SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - SLOT(_q_sourceColumnsAboutToBeRemoved(QModelIndex,int,int))); - connect(sourceModel(), SIGNAL(columnsRemoved(QModelIndex,int,int)), - SLOT(_q_sourceColumnsRemoved(QModelIndex,int,int))); - connect(sourceModel(), SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - SLOT(_q_sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); - connect(sourceModel(), SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), - SLOT(_q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int))); - connect(sourceModel(), SIGNAL(modelAboutToBeReset()), - SLOT(_q_sourceModelAboutToBeReset())); - connect(sourceModel(), SIGNAL(modelReset()), - SLOT(_q_sourceModelReset())); - connect(sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)), - SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex,QList<int>))); - connect(sourceModel(), SIGNAL(headerDataChanged(Qt::Orientation,int,int)), - SLOT(_q_sourceHeaderDataChanged(Qt::Orientation,int,int))); - connect(sourceModel(), SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), - SLOT(_q_sourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint))); - connect(sourceModel(), SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), - SLOT(_q_sourceLayoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint))); + auto *m = sourceModel(); + d->m_sourceModelConnections = { + QObjectPrivate::connect(m, &QAbstractItemModel::rowsAboutToBeInserted, d, + &QIdentityProxyModelPrivate::sourceRowsAboutToBeInserted), + QObjectPrivate::connect(m, &QAbstractItemModel::rowsInserted, d, + &QIdentityProxyModelPrivate::sourceRowsInserted), + QObjectPrivate::connect(m, &QAbstractItemModel::rowsAboutToBeRemoved, d, + &QIdentityProxyModelPrivate::sourceRowsAboutToBeRemoved), + QObjectPrivate::connect(m, &QAbstractItemModel::rowsRemoved, d, + &QIdentityProxyModelPrivate::sourceRowsRemoved), + QObjectPrivate::connect(m, &QAbstractItemModel::rowsAboutToBeMoved, d, + &QIdentityProxyModelPrivate::sourceRowsAboutToBeMoved), + QObjectPrivate::connect(m, &QAbstractItemModel::rowsMoved, d, + &QIdentityProxyModelPrivate::sourceRowsMoved), + QObjectPrivate::connect(m, &QAbstractItemModel::columnsAboutToBeInserted, d, + &QIdentityProxyModelPrivate::sourceColumnsAboutToBeInserted), + QObjectPrivate::connect(m, &QAbstractItemModel::columnsInserted, d, + &QIdentityProxyModelPrivate::sourceColumnsInserted), + QObjectPrivate::connect(m, &QAbstractItemModel::columnsAboutToBeRemoved, d, + &QIdentityProxyModelPrivate::sourceColumnsAboutToBeRemoved), + QObjectPrivate::connect(m, &QAbstractItemModel::columnsRemoved, d, + &QIdentityProxyModelPrivate::sourceColumnsRemoved), + QObjectPrivate::connect(m, &QAbstractItemModel::columnsAboutToBeMoved, d, + &QIdentityProxyModelPrivate::sourceColumnsAboutToBeMoved), + QObjectPrivate::connect(m, &QAbstractItemModel::columnsMoved, d, + &QIdentityProxyModelPrivate::sourceColumnsMoved), + QObjectPrivate::connect(m, &QAbstractItemModel::modelAboutToBeReset, d, + &QIdentityProxyModelPrivate::sourceModelAboutToBeReset), + QObjectPrivate::connect(m, &QAbstractItemModel::modelReset, d, + &QIdentityProxyModelPrivate::sourceModelReset), + QObjectPrivate::connect(m, &QAbstractItemModel::dataChanged, d, + &QIdentityProxyModelPrivate::sourceDataChanged), + QObjectPrivate::connect(m, &QAbstractItemModel::headerDataChanged, d, + &QIdentityProxyModelPrivate::sourceHeaderDataChanged), + }; + + if (d->m_handleLayoutChanges) { + d->m_sourceModelConnections.emplace_back( + QObjectPrivate::connect(m, &QAbstractItemModel::layoutAboutToBeChanged, d, + &QIdentityProxyModelPrivate::sourceLayoutAboutToBeChanged)); + d->m_sourceModelConnections.emplace_back( + QObjectPrivate::connect(m, &QAbstractItemModel::layoutChanged, d, + &QIdentityProxyModelPrivate::sourceLayoutChanged)); + } } endResetModel(); } -void QIdentityProxyModelPrivate::_q_sourceColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end) +/*! + \since 6.7 + + If \a b is \c true, this proxy model will handle the source model layout + changes (by connecting to \c QAbstractItemModel::layoutAboutToBeChanged + and \c QAbstractItemModel::layoutChanged singals). + + The default is for this proxy model to handle the source model layout + changes. + + In sub-classes of QIdentityProxyModel, it may be useful to set this to + \c false if you need to specially handle the source model layout changes. + + \note Calling this method will only have an effect after calling setSourceModel(). +*/ +void QIdentityProxyModel::setHandleSourceLayoutChanges(bool b) +{ + d_func()->m_handleLayoutChanges = b; +} + +/*! + \since 6.7 + + Returns \c true if this proxy model handles the source model layout + changes, otherwise returns \c false. +*/ +bool QIdentityProxyModel::isHandleSourceLayoutChanges() const +{ + return d_func()->m_handleLayoutChanges; +} + +void QIdentityProxyModelPrivate::sourceColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end) { Q_ASSERT(parent.isValid() ? parent.model() == model : true); Q_Q(QIdentityProxyModel); q->beginInsertColumns(q->mapFromSource(parent), start, end); } -void QIdentityProxyModelPrivate::_q_sourceColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest) +void QIdentityProxyModelPrivate::sourceColumnsAboutToBeMoved(const QModelIndex &sourceParent, + int sourceStart, int sourceEnd, + const QModelIndex &destParent, + int dest) { Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true); Q_ASSERT(destParent.isValid() ? destParent.model() == model : true); @@ -424,14 +399,14 @@ void QIdentityProxyModelPrivate::_q_sourceColumnsAboutToBeMoved(const QModelInde q->beginMoveColumns(q->mapFromSource(sourceParent), sourceStart, sourceEnd, q->mapFromSource(destParent), dest); } -void QIdentityProxyModelPrivate::_q_sourceColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +void QIdentityProxyModelPrivate::sourceColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { Q_ASSERT(parent.isValid() ? parent.model() == model : true); Q_Q(QIdentityProxyModel); q->beginRemoveColumns(q->mapFromSource(parent), start, end); } -void QIdentityProxyModelPrivate::_q_sourceColumnsInserted(const QModelIndex &parent, int start, int end) +void QIdentityProxyModelPrivate::sourceColumnsInserted(const QModelIndex &parent, int start, int end) { Q_ASSERT(parent.isValid() ? parent.model() == model : true); Q_Q(QIdentityProxyModel); @@ -441,7 +416,9 @@ void QIdentityProxyModelPrivate::_q_sourceColumnsInserted(const QModelIndex &par q->endInsertColumns(); } -void QIdentityProxyModelPrivate::_q_sourceColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest) +void QIdentityProxyModelPrivate::sourceColumnsMoved(const QModelIndex &sourceParent, + int sourceStart, int sourceEnd, + const QModelIndex &destParent, int dest) { Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true); Q_ASSERT(destParent.isValid() ? destParent.model() == model : true); @@ -454,7 +431,7 @@ void QIdentityProxyModelPrivate::_q_sourceColumnsMoved(const QModelIndex &source q->endMoveColumns(); } -void QIdentityProxyModelPrivate::_q_sourceColumnsRemoved(const QModelIndex &parent, int start, int end) +void QIdentityProxyModelPrivate::sourceColumnsRemoved(const QModelIndex &parent, int start, int end) { Q_ASSERT(parent.isValid() ? parent.model() == model : true); Q_Q(QIdentityProxyModel); @@ -464,7 +441,9 @@ void QIdentityProxyModelPrivate::_q_sourceColumnsRemoved(const QModelIndex &pare q->endRemoveColumns(); } -void QIdentityProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList<int> &roles) +void QIdentityProxyModelPrivate::sourceDataChanged(const QModelIndex &topLeft, + const QModelIndex &bottomRight, + const QList<int> &roles) { Q_ASSERT(topLeft.isValid() ? topLeft.model() == model : true); Q_ASSERT(bottomRight.isValid() ? bottomRight.model() == model : true); @@ -472,13 +451,15 @@ void QIdentityProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &topLeft emit q->dataChanged(q->mapFromSource(topLeft), q->mapFromSource(bottomRight), roles); } -void QIdentityProxyModelPrivate::_q_sourceHeaderDataChanged(Qt::Orientation orientation, int first, int last) +void QIdentityProxyModelPrivate::sourceHeaderDataChanged(Qt::Orientation orientation, int first, + int last) { Q_Q(QIdentityProxyModel); emit q->headerDataChanged(orientation, first, last); } -void QIdentityProxyModelPrivate::_q_sourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint) +void QIdentityProxyModelPrivate::sourceLayoutAboutToBeChanged( + const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint) { Q_Q(QIdentityProxyModel); @@ -506,7 +487,8 @@ void QIdentityProxyModelPrivate::_q_sourceLayoutAboutToBeChanged(const QList<QPe } } -void QIdentityProxyModelPrivate::_q_sourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint) +void QIdentityProxyModelPrivate::sourceLayoutChanged( + const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint) { Q_Q(QIdentityProxyModel); @@ -532,26 +514,29 @@ void QIdentityProxyModelPrivate::_q_sourceLayoutChanged(const QList<QPersistentM emit q->layoutChanged(parents, hint); } -void QIdentityProxyModelPrivate::_q_sourceModelAboutToBeReset() +void QIdentityProxyModelPrivate::sourceModelAboutToBeReset() { Q_Q(QIdentityProxyModel); q->beginResetModel(); } -void QIdentityProxyModelPrivate::_q_sourceModelReset() +void QIdentityProxyModelPrivate::sourceModelReset() { Q_Q(QIdentityProxyModel); q->endResetModel(); } -void QIdentityProxyModelPrivate::_q_sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end) +void QIdentityProxyModelPrivate::sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, + int end) { Q_ASSERT(parent.isValid() ? parent.model() == model : true); Q_Q(QIdentityProxyModel); q->beginInsertRows(q->mapFromSource(parent), start, end); } -void QIdentityProxyModelPrivate::_q_sourceRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest) +void QIdentityProxyModelPrivate::sourceRowsAboutToBeMoved(const QModelIndex &sourceParent, + int sourceStart, int sourceEnd, + const QModelIndex &destParent, int dest) { Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true); Q_ASSERT(destParent.isValid() ? destParent.model() == model : true); @@ -559,14 +544,15 @@ void QIdentityProxyModelPrivate::_q_sourceRowsAboutToBeMoved(const QModelIndex & q->beginMoveRows(q->mapFromSource(sourceParent), sourceStart, sourceEnd, q->mapFromSource(destParent), dest); } -void QIdentityProxyModelPrivate::_q_sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +void QIdentityProxyModelPrivate::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, + int end) { Q_ASSERT(parent.isValid() ? parent.model() == model : true); Q_Q(QIdentityProxyModel); q->beginRemoveRows(q->mapFromSource(parent), start, end); } -void QIdentityProxyModelPrivate::_q_sourceRowsInserted(const QModelIndex &parent, int start, int end) +void QIdentityProxyModelPrivate::sourceRowsInserted(const QModelIndex &parent, int start, int end) { Q_ASSERT(parent.isValid() ? parent.model() == model : true); Q_Q(QIdentityProxyModel); @@ -576,7 +562,9 @@ void QIdentityProxyModelPrivate::_q_sourceRowsInserted(const QModelIndex &parent q->endInsertRows(); } -void QIdentityProxyModelPrivate::_q_sourceRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest) +void QIdentityProxyModelPrivate::sourceRowsMoved(const QModelIndex &sourceParent, int sourceStart, + int sourceEnd, const QModelIndex &destParent, + int dest) { Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true); Q_ASSERT(destParent.isValid() ? destParent.model() == model : true); @@ -589,7 +577,7 @@ void QIdentityProxyModelPrivate::_q_sourceRowsMoved(const QModelIndex &sourcePar q->endMoveRows(); } -void QIdentityProxyModelPrivate::_q_sourceRowsRemoved(const QModelIndex &parent, int start, int end) +void QIdentityProxyModelPrivate::sourceRowsRemoved(const QModelIndex &parent, int start, int end) { Q_ASSERT(parent.isValid() ? parent.model() == model : true); Q_Q(QIdentityProxyModel); diff --git a/src/corelib/itemmodels/qidentityproxymodel.h b/src/corelib/itemmodels/qidentityproxymodel.h index ce2ac68f89..c8fc9d21b7 100644 --- a/src/corelib/itemmodels/qidentityproxymodel.h +++ b/src/corelib/itemmodels/qidentityproxymodel.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com> -** 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) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QIDENTITYPROXYMODEL_H @@ -80,34 +44,15 @@ public: bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override; bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationChild) override; + bool isHandleSourceLayoutChanges() const; + protected: QIdentityProxyModel(QIdentityProxyModelPrivate &dd, QObject* parent); + void setHandleSourceLayoutChanges(bool); private: Q_DECLARE_PRIVATE(QIdentityProxyModel) Q_DISABLE_COPY(QIdentityProxyModel) - - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeInserted(QModelIndex,int,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsInserted(QModelIndex,int,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeRemoved(QModelIndex,int,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsRemoved(QModelIndex,int,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int)) - - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeInserted(QModelIndex,int,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsInserted(QModelIndex,int,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeRemoved(QModelIndex,int,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsRemoved(QModelIndex,int,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int)) - - Q_PRIVATE_SLOT(d_func(), void _q_sourceDataChanged(QModelIndex, QModelIndex, QList<int>)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceHeaderDataChanged(Qt::Orientation orientation, int first, int last)) - - Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceModelAboutToBeReset()) - Q_PRIVATE_SLOT(d_func(), void _q_sourceModelReset()) }; QT_END_NAMESPACE diff --git a/src/corelib/itemmodels/qidentityproxymodel_p.h b/src/corelib/itemmodels/qidentityproxymodel_p.h index 7224f773cc..78e1f5316c 100644 --- a/src/corelib/itemmodels/qidentityproxymodel_p.h +++ b/src/corelib/itemmodels/qidentityproxymodel_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com> -** 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) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QIDENTITYPROXYMODEL_P_H #define QIDENTITYPROXYMODEL_P_H @@ -69,28 +33,38 @@ public: QList<QPersistentModelIndex> layoutChangePersistentIndexes; QModelIndexList proxyIndexes; - void _q_sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end); - void _q_sourceRowsInserted(const QModelIndex &parent, int start, int end); - void _q_sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); - void _q_sourceRowsRemoved(const QModelIndex &parent, int start, int end); - void _q_sourceRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest); - void _q_sourceRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest); + void sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end); + void sourceRowsInserted(const QModelIndex &parent, int start, int end); + void sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); + void sourceRowsRemoved(const QModelIndex &parent, int start, int end); + void sourceRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, + const QModelIndex &destParent, int dest); + void sourceRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, + const QModelIndex &destParent, int dest); - void _q_sourceColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end); - void _q_sourceColumnsInserted(const QModelIndex &parent, int start, int end); - void _q_sourceColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end); - void _q_sourceColumnsRemoved(const QModelIndex &parent, int start, int end); - void _q_sourceColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest); - void _q_sourceColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest); + void sourceColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end); + void sourceColumnsInserted(const QModelIndex &parent, int start, int end); + void sourceColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end); + void sourceColumnsRemoved(const QModelIndex &parent, int start, int end); + void sourceColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, + int sourceEnd, const QModelIndex &destParent, int dest); + void sourceColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, + const QModelIndex &destParent, int dest); - void _q_sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList<int> &roles); - void _q_sourceHeaderDataChanged(Qt::Orientation orientation, int first, int last); + void sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, + const QList<int> &roles); + void sourceHeaderDataChanged(Qt::Orientation orientation, int first, int last); - void _q_sourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint); - void _q_sourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint); - void _q_sourceModelAboutToBeReset(); - void _q_sourceModelReset(); + void sourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, + QAbstractItemModel::LayoutChangeHint hint); + void sourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, + QAbstractItemModel::LayoutChangeHint hint); + void sourceModelAboutToBeReset(); + void sourceModelReset(); +private: + bool m_handleLayoutChanges = true; + QVarLengthArray<QMetaObject::Connection, 18> m_sourceModelConnections; }; QT_END_NAMESPACE diff --git a/src/corelib/itemmodels/qitemselectionmodel.cpp b/src/corelib/itemmodels/qitemselectionmodel.cpp index 286a57eb3e..6df60aaf61 100644 --- a/src/corelib/itemmodels/qitemselectionmodel.cpp +++ b/src/corelib/itemmodels/qitemselectionmodel.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 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) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qitemselectionmodel.h" #include "qitemselectionmodel_p.h" @@ -43,6 +7,7 @@ #include <private/qitemselectionmodel_p.h> #include <private/qabstractitemmodel_p.h> #include <private/qduplicatetracker_p.h> +#include <private/qoffsetstringarray_p.h> #include <qdebug.h> #include <algorithm> @@ -62,6 +27,8 @@ QT_IMPL_METATYPE_EXTERN(QItemSelection) \ingroup model-view + \compares equality + A QItemSelectionRange contains information about a range of selected items in a model. A range of items is a contiguous array of model items, extending to cover a number of adjacent rows and @@ -251,17 +218,17 @@ QItemSelectionRange QItemSelectionRange::intersected(const QItemSelectionRange & } /*! - \fn bool QItemSelectionRange::operator==(const QItemSelectionRange &other) const + \fn bool QItemSelectionRange::operator==(const QItemSelectionRange &lhs, const QItemSelectionRange &rhs) - Returns \c true if the selection range is exactly the same as the \a other + Returns \c true if \a lhs selection range is exactly the same as the \a rhs range given; otherwise returns \c false. */ /*! - \fn bool QItemSelectionRange::operator!=(const QItemSelectionRange &other) const + \fn bool QItemSelectionRange::operator!=(const QItemSelectionRange &lhs, const QItemSelectionRange &rhs) - Returns \c true if the selection range differs from the \a other range given; + Returns \c true if \a lhs selection range differs from the \a rhs range given; otherwise returns \c false. */ @@ -273,7 +240,7 @@ QItemSelectionRange QItemSelectionRange::intersected(const QItemSelectionRange & */ -static void rowLengthsFromRange(const QItemSelectionRange &range, QList<QPair<QPersistentModelIndex, uint>> &result) +static void rowLengthsFromRange(const QItemSelectionRange &range, QList<std::pair<QPersistentModelIndex, uint>> &result) { if (range.isValid() && range.model()) { const QModelIndex topLeft = range.topLeft(); @@ -284,7 +251,7 @@ static void rowLengthsFromRange(const QItemSelectionRange &range, QList<QPair<QP // We don't need to keep track of ItemIsSelectable and ItemIsEnabled here. That is // required in indexesFromRange() because that method is called from public API // which requires the limitation. - result.push_back(qMakePair(QPersistentModelIndex(topLeft.sibling(row, column)), width)); + result.emplace_back(topLeft.sibling(row, column), width); } } } @@ -467,9 +434,9 @@ QModelIndexList QItemSelection::indexes() const return qSelectionIndexes<QModelIndexList>(*this); } -static QList<QPair<QPersistentModelIndex, uint>> qSelectionPersistentRowLengths(const QItemSelection &sel) +static QList<std::pair<QPersistentModelIndex, uint>> qSelectionPersistentRowLengths(const QItemSelection &sel) { - QList<QPair<QPersistentModelIndex, uint>> result; + QList<std::pair<QPersistentModelIndex, uint>> result; for (const QItemSelectionRange &range : sel) rowLengthsFromRange(range, result); return result; @@ -501,15 +468,15 @@ void QItemSelection::merge(const QItemSelection &other, QItemSelectionModel::Sel if (!range.isValid()) continue; newSelection.push_back(range); - for (int t = 0; t < count(); ++t) { + for (int t = 0; t < size(); ++t) { if (range.intersects(at(t))) intersections.append(at(t).intersected(range)); } } // Split the old (and new) ranges using the intersections - for (int i = 0; i < intersections.count(); ++i) { // for each intersection - for (int t = 0; t < count();) { // splitt each old range + for (int i = 0; i < intersections.size(); ++i) { // for each intersection + for (int t = 0; t < size();) { // splitt each old range if (at(t).intersects(intersections.at(i))) { split(at(t), intersections.at(i), this); removeAt(t); @@ -518,7 +485,7 @@ void QItemSelection::merge(const QItemSelection &other, QItemSelectionModel::Sel } } // only split newSelection if Toggle is specified - for (int n = 0; (command & QItemSelectionModel::Toggle) && n < newSelection.count();) { + for (int n = 0; (command & QItemSelectionModel::Toggle) && n < newSelection.size();) { if (newSelection.at(n).intersects(intersections.at(i))) { split(newSelection.at(n), intersections.at(i), &newSelection); newSelection.removeAt(n); @@ -585,57 +552,55 @@ void QItemSelection::split(const QItemSelectionRange &range, void QItemSelectionModelPrivate::initModel(QAbstractItemModel *m) { - struct Cx { - const char *signal; - const char *slot; - }; - static const Cx connections[] = { - { SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)) }, - { SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)) }, - { SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int)) }, - { SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), - SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int)) }, - { SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - SLOT(_q_layoutAboutToBeChanged()) }, - { SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - SLOT(_q_layoutAboutToBeChanged()) }, - { SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), - SLOT(_q_layoutChanged()) }, - { SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), - SLOT(_q_layoutChanged()) }, - { SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), - SLOT(_q_layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)) }, - { SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), - SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)) }, - { SIGNAL(modelReset()), - SLOT(reset()) }, - { SIGNAL(destroyed(QObject*)), - SLOT(_q_modelDestroyed()) }, - { nullptr, nullptr } - }; - - if (model == m) + Q_Q(QItemSelectionModel); + const QAbstractItemModel *oldModel = model.valueBypassingBindings(); + if (oldModel == m) return; - Q_Q(QItemSelectionModel); - if (model.value()) { - for (const Cx *cx = &connections[0]; cx->signal; cx++) - QObject::disconnect(model.value(), cx->signal, q, cx->slot); + if (oldModel) { q->reset(); + disconnectModel(); } // Caller has to call notify(), unless calling during construction (the common case). model.setValueBypassingBindings(m); - if (model.value()) { - for (const Cx *cx = &connections[0]; cx->signal; cx++) - QObject::connect(model.value(), cx->signal, q, cx->slot); + if (m) { + connections = std::array<QMetaObject::Connection, 12> { + QObjectPrivate::connect(m, &QAbstractItemModel::rowsAboutToBeRemoved, + this, &QItemSelectionModelPrivate::rowsAboutToBeRemoved), + QObjectPrivate::connect(m, &QAbstractItemModel::columnsAboutToBeRemoved, + this, &QItemSelectionModelPrivate::columnsAboutToBeRemoved), + QObjectPrivate::connect(m, &QAbstractItemModel::rowsAboutToBeInserted, + this, &QItemSelectionModelPrivate::rowsAboutToBeInserted), + QObjectPrivate::connect(m, &QAbstractItemModel::columnsAboutToBeInserted, + this, &QItemSelectionModelPrivate::columnsAboutToBeInserted), + QObjectPrivate::connect(m, &QAbstractItemModel::rowsAboutToBeMoved, + this, &QItemSelectionModelPrivate::triggerLayoutToBeChanged), + QObjectPrivate::connect(m, &QAbstractItemModel::columnsAboutToBeMoved, + this, &QItemSelectionModelPrivate::triggerLayoutToBeChanged), + QObjectPrivate::connect(m, &QAbstractItemModel::rowsMoved, + this, &QItemSelectionModelPrivate::triggerLayoutChanged), + QObjectPrivate::connect(m, &QAbstractItemModel::columnsMoved, + this, &QItemSelectionModelPrivate::triggerLayoutChanged), + QObjectPrivate::connect(m, &QAbstractItemModel::layoutAboutToBeChanged, + this, &QItemSelectionModelPrivate::layoutAboutToBeChanged), + QObjectPrivate::connect(m, &QAbstractItemModel::layoutChanged, + this, &QItemSelectionModelPrivate::layoutChanged), + QObject::connect(m, &QAbstractItemModel::modelReset, + q, &QItemSelectionModel::reset), + QObjectPrivate::connect(m, &QAbstractItemModel::destroyed, + this, &QItemSelectionModelPrivate::modelDestroyed) + }; } } +void QItemSelectionModelPrivate::disconnectModel() +{ + for (auto &connection : connections) + QObject::disconnect(connection); +} + /*! \internal @@ -653,7 +618,7 @@ QItemSelection QItemSelectionModelPrivate::expandSelection(const QItemSelection QItemSelection expanded; if (command & QItemSelectionModel::Rows) { - for (int i = 0; i < selection.count(); ++i) { + for (int i = 0; i < selection.size(); ++i) { QModelIndex parent = selection.at(i).parent(); int colCount = model->columnCount(parent); QModelIndex tl = model->index(selection.at(i).top(), 0, parent); @@ -663,7 +628,7 @@ QItemSelection QItemSelectionModelPrivate::expandSelection(const QItemSelection } } if (command & QItemSelectionModel::Columns) { - for (int i = 0; i < selection.count(); ++i) { + for (int i = 0; i < selection.size(); ++i) { QModelIndex parent = selection.at(i).parent(); int rowCount = model->rowCount(parent); QModelIndex tl = model->index(0, selection.at(i).left(), parent); @@ -678,7 +643,7 @@ QItemSelection QItemSelectionModelPrivate::expandSelection(const QItemSelection /*! \internal */ -void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &parent, +void QItemSelectionModelPrivate::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { Q_Q(QItemSelectionModel); @@ -761,7 +726,7 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare /*! \internal */ -void QItemSelectionModelPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &parent, +void QItemSelectionModelPrivate::columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { Q_Q(QItemSelectionModel); @@ -798,7 +763,7 @@ void QItemSelectionModelPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &p Split selection ranges if columns are about to be inserted in the middle. */ -void QItemSelectionModelPrivate::_q_columnsAboutToBeInserted(const QModelIndex &parent, +void QItemSelectionModelPrivate::columnsAboutToBeInserted(const QModelIndex &parent, int start, int end) { Q_UNUSED(end); @@ -828,7 +793,7 @@ void QItemSelectionModelPrivate::_q_columnsAboutToBeInserted(const QModelIndex & Split selection ranges if rows are about to be inserted in the middle. */ -void QItemSelectionModelPrivate::_q_rowsAboutToBeInserted(const QModelIndex &parent, +void QItemSelectionModelPrivate::rowsAboutToBeInserted(const QModelIndex &parent, int start, int end) { Q_Q(QItemSelectionModel); @@ -869,7 +834,8 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeInserted(const QModelIndex &par preparation for the layoutChanged() signal, where the indexes can be merged again. */ -void QItemSelectionModelPrivate::_q_layoutAboutToBeChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint hint) +void QItemSelectionModelPrivate::layoutAboutToBeChanged(const QList<QPersistentModelIndex> &, + QAbstractItemModel::LayoutChangeHint hint) { savedPersistentIndexes.clear(); savedPersistentCurrentIndexes.clear(); @@ -878,7 +844,7 @@ void QItemSelectionModelPrivate::_q_layoutAboutToBeChanged(const QList<QPersiste // optimization for when all indexes are selected // (only if there is lots of items (1000) because this is not entirely correct) - if (ranges.isEmpty() && currentSelection.count() == 1) { + if (ranges.isEmpty() && currentSelection.size() == 1) { QItemSelectionRange range = currentSelection.constFirst(); QModelIndex parent = range.parent(); tableRowCount = model->rowCount(parent); @@ -911,14 +877,14 @@ void QItemSelectionModelPrivate::_q_layoutAboutToBeChanged(const QList<QPersiste /*! \internal */ -static QItemSelection mergeRowLengths(const QList<QPair<QPersistentModelIndex, uint>> &rowLengths) +static QItemSelection mergeRowLengths(const QList<std::pair<QPersistentModelIndex, uint>> &rowLengths) { if (rowLengths.isEmpty()) return QItemSelection(); QItemSelection result; int i = 0; - while (i < rowLengths.count()) { + while (i < rowLengths.size()) { const QPersistentModelIndex &tl = rowLengths.at(i).first; if (!tl.isValid()) { ++i; @@ -926,7 +892,7 @@ static QItemSelection mergeRowLengths(const QList<QPair<QPersistentModelIndex, u } QPersistentModelIndex br = tl; const uint length = rowLengths.at(i).second; - while (++i < rowLengths.count()) { + while (++i < rowLengths.size()) { const QPersistentModelIndex &next = rowLengths.at(i).first; if (!next.isValid()) continue; @@ -956,7 +922,7 @@ static QItemSelection mergeIndexes(const QList<QPersistentModelIndex> &indexes) QItemSelection colSpans; // merge columns int i = 0; - while (i < indexes.count()) { + while (i < indexes.size()) { const QPersistentModelIndex &tl = indexes.at(i); if (!tl.isValid()) { ++i; @@ -966,7 +932,7 @@ static QItemSelection mergeIndexes(const QList<QPersistentModelIndex> &indexes) QModelIndex brParent = br.parent(); int brRow = br.row(); int brColumn = br.column(); - while (++i < indexes.count()) { + while (++i < indexes.size()) { const QPersistentModelIndex &next = indexes.at(i); if (!next.isValid()) continue; @@ -989,11 +955,11 @@ static QItemSelection mergeIndexes(const QList<QPersistentModelIndex> &indexes) // merge rows QItemSelection rowSpans; i = 0; - while (i < colSpans.count()) { + while (i < colSpans.size()) { QModelIndex tl = colSpans.at(i).topLeft(); QModelIndex br = colSpans.at(i).bottomRight(); QModelIndex prevTl = tl; - while (++i < colSpans.count()) { + while (++i < colSpans.size()) { QModelIndex nextTl = colSpans.at(i).topLeft(); QModelIndex nextBr = colSpans.at(i).bottomRight(); @@ -1016,7 +982,7 @@ static QItemSelection mergeIndexes(const QList<QPersistentModelIndex> &indexes) /*! \internal - Sort predicate function for QItemSelectionModelPrivate::_q_layoutChanged(), + Sort predicate function for QItemSelectionModelPrivate::layoutChanged(), sorting by parent first in addition to operator<(). This is to prevent fragmentation of the selection by grouping indexes with the same row, column of different parents next to each other, which may happen when a selection @@ -1034,7 +1000,7 @@ static bool qt_PersistentModelIndexLessThan(const QPersistentModelIndex &i1, con Merge the selected indexes into selection ranges again. */ -void QItemSelectionModelPrivate::_q_layoutChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint hint) +void QItemSelectionModelPrivate::layoutChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint hint) { // special case for when all indexes are selected if (tableSelected && tableColCount == model->columnCount(tableParent) @@ -1118,9 +1084,10 @@ void QItemSelectionModelPrivate::_q_layoutChanged(const QList<QPersistentModelIn We decide to break the new rule, imposed by bindable properties, and not break the old rule, because that may break existing code. */ -void QItemSelectionModelPrivate::_q_modelDestroyed() +void QItemSelectionModelPrivate::modelDestroyed() { model.setValueBypassingBindings(nullptr); + disconnectModel(); model.notify(); } @@ -1160,7 +1127,7 @@ void QItemSelectionModelPrivate::_q_modelDestroyed() \l{QItemSelectionModel::hasSelection()}{hasSelection}, and \l{QItemSelectionModel::currentIndex()}{currentIndex} are meta-object properties. - \sa {Model/View Programming}, QAbstractItemModel, {Chart Example} + \sa {Model/View Programming}, QAbstractItemModel */ /*! @@ -1329,7 +1296,7 @@ void QItemSelectionModel::select(const QItemSelection &selection, QItemSelection // If d->ranges is non-empty when the source model is reset the persistent indexes // it contains will be invalid. We can't clear them in a modelReset slot because that might already // be too late if another model observer is connected to the same modelReset slot and is invoked first - // it might call select() on this selection model before any such QItemSelectionModelPrivate::_q_modelReset() slot + // it might call select() on this selection model before any such QItemSelectionModelPrivate::modelReset() slot // is invoked, so it would not be cleared yet. We clear it invalid ranges in it here. d->ranges.removeIf(QtFunctionObjects::IsNotValid()); @@ -1402,7 +1369,7 @@ void QItemSelectionModel::reset() void QItemSelectionModel::clearSelection() { Q_D(QItemSelectionModel); - if (d->ranges.count() == 0 && d->currentSelection.count() == 0) + if (d->ranges.size() == 0 && d->currentSelection.size() == 0) return; select(QItemSelection(), Clear); @@ -1473,7 +1440,7 @@ bool QItemSelectionModel::isSelected(const QModelIndex &index) const } // check currentSelection - if (d->currentSelection.count()) { + if (d->currentSelection.size()) { if ((d->currentCommand & Deselect) && selected) selected = !d->currentSelection.contains(index); else if (d->currentCommand & Toggle) @@ -1508,8 +1475,8 @@ bool QItemSelectionModel::isRowSelected(int row, const QModelIndex &parent) cons return false; // return false if row exist in currentSelection (Deselect) - if (d->currentCommand & Deselect && d->currentSelection.count()) { - for (int i=0; i<d->currentSelection.count(); ++i) { + if (d->currentCommand & Deselect && d->currentSelection.size()) { + for (int i=0; i<d->currentSelection.size(); ++i) { if (d->currentSelection.at(i).parent() == parent && row >= d->currentSelection.at(i).top() && row <= d->currentSelection.at(i).bottom()) @@ -1518,11 +1485,11 @@ bool QItemSelectionModel::isRowSelected(int row, const QModelIndex &parent) cons } // return false if ranges in both currentSelection and ranges // intersect and have the same row contained - if (d->currentCommand & Toggle && d->currentSelection.count()) { - for (int i=0; i<d->currentSelection.count(); ++i) + if (d->currentCommand & Toggle && d->currentSelection.size()) { + for (int i=0; i<d->currentSelection.size(); ++i) if (d->currentSelection.at(i).top() <= row && d->currentSelection.at(i).bottom() >= row) - for (int j=0; j<d->ranges.count(); ++j) + for (int j=0; j<d->ranges.size(); ++j) if (d->ranges.at(j).top() <= row && d->ranges.at(j).bottom() >= row && d->currentSelection.at(i).intersected(d->ranges.at(j)).isValid()) return false; @@ -1537,7 +1504,7 @@ bool QItemSelectionModel::isRowSelected(int row, const QModelIndex &parent) cons // add ranges and currentSelection and check through them all QList<QItemSelectionRange>::const_iterator it; QList<QItemSelectionRange> joined = d->ranges; - if (d->currentSelection.count()) + if (d->currentSelection.size()) joined += d->currentSelection; for (int column = 0; column < colCount; ++column) { if (!isSelectable(row, column)) { @@ -1582,8 +1549,8 @@ bool QItemSelectionModel::isColumnSelected(int column, const QModelIndex &parent return false; // return false if column exist in currentSelection (Deselect) - if (d->currentCommand & Deselect && d->currentSelection.count()) { - for (int i = 0; i < d->currentSelection.count(); ++i) { + if (d->currentCommand & Deselect && d->currentSelection.size()) { + for (int i = 0; i < d->currentSelection.size(); ++i) { if (d->currentSelection.at(i).parent() == parent && column >= d->currentSelection.at(i).left() && column <= d->currentSelection.at(i).right()) @@ -1592,11 +1559,11 @@ bool QItemSelectionModel::isColumnSelected(int column, const QModelIndex &parent } // return false if ranges in both currentSelection and the selection model // intersect and have the same column contained - if (d->currentCommand & Toggle && d->currentSelection.count()) { - for (int i = 0; i < d->currentSelection.count(); ++i) { + if (d->currentCommand & Toggle && d->currentSelection.size()) { + for (int i = 0; i < d->currentSelection.size(); ++i) { if (d->currentSelection.at(i).left() <= column && d->currentSelection.at(i).right() >= column) { - for (int j = 0; j < d->ranges.count(); ++j) { + for (int j = 0; j < d->ranges.size(); ++j) { if (d->ranges.at(j).left() <= column && d->ranges.at(j).right() >= column && d->currentSelection.at(i).intersected(d->ranges.at(j)).isValid()) { return false; @@ -1615,7 +1582,7 @@ bool QItemSelectionModel::isColumnSelected(int column, const QModelIndex &parent // add ranges and currentSelection and check through them all QList<QItemSelectionRange>::const_iterator it; QList<QItemSelectionRange> joined = d->ranges; - if (d->currentSelection.count()) + if (d->currentSelection.size()) joined += d->currentSelection; for (int row = 0; row < rowCount; ++row) { if (!isSelectable(row, column)) { @@ -1656,7 +1623,7 @@ bool QItemSelectionModel::rowIntersectsSelection(int row, const QModelIndex &par QItemSelection sel = d->ranges; sel.merge(d->currentSelection, d->currentCommand); - for (const QItemSelectionRange &range : qAsConst(sel)) { + for (const QItemSelectionRange &range : std::as_const(sel)) { if (range.parent() != parent) return false; int top = range.top(); @@ -1691,7 +1658,7 @@ bool QItemSelectionModel::columnIntersectsSelection(int column, const QModelInde QItemSelection sel = d->ranges; sel.merge(d->currentSelection, d->currentCommand); - for (const QItemSelectionRange &range : qAsConst(sel)) { + for (const QItemSelectionRange &range : std::as_const(sel)) { if (range.parent() != parent) return false; int top = range.top(); @@ -1799,7 +1766,7 @@ QModelIndexList QItemSelectionModel::selectedRows(int column) const QDuplicateTracker<RowOrColumnDefinition> rowsSeen; const QItemSelection ranges = selection(); - for (int i = 0; i < ranges.count(); ++i) { + for (int i = 0; i < ranges.size(); ++i) { const QItemSelectionRange &range = ranges.at(i); QModelIndex parent = range.parent(); for (int row = range.top(); row <= range.bottom(); row++) { @@ -1828,7 +1795,7 @@ QModelIndexList QItemSelectionModel::selectedColumns(int row) const QDuplicateTracker<RowOrColumnDefinition> columnsSeen; const QItemSelection ranges = selection(); - for (int i = 0; i < ranges.count(); ++i) { + for (int i = 0; i < ranges.size(); ++i) { const QItemSelectionRange &range = ranges.at(i); QModelIndex parent = range.parent(); for (int column = range.left(); column <= range.right(); column++) { @@ -1921,9 +1888,8 @@ void QItemSelectionModel::setModel(QAbstractItemModel *model) { Q_D(QItemSelectionModel); d->model.removeBindingUnlessInWrapper(); - if (d->model == model) + if (d->model.valueBypassingBindings() == model) return; - d->initModel(model); d->model.notify(); } @@ -1951,9 +1917,9 @@ void QItemSelectionModel::emitSelectionChanged(const QItemSelection &newSelectio // remove equal ranges bool advance; - for (int o = 0; o < deselected.count(); ++o) { + for (int o = 0; o < deselected.size(); ++o) { advance = true; - for (int s = 0; s < selected.count() && o < deselected.count();) { + for (int s = 0; s < selected.size() && o < deselected.size();) { if (deselected.at(o) == selected.at(s)) { deselected.removeAt(o); selected.removeAt(s); @@ -1968,17 +1934,17 @@ void QItemSelectionModel::emitSelectionChanged(const QItemSelection &newSelectio // find intersections QItemSelection intersections; - for (int o = 0; o < deselected.count(); ++o) { - for (int s = 0; s < selected.count(); ++s) { + for (int o = 0; o < deselected.size(); ++o) { + for (int s = 0; s < selected.size(); ++s) { if (deselected.at(o).intersects(selected.at(s))) intersections.append(deselected.at(o).intersected(selected.at(s))); } } // compare remaining ranges with intersections and split them to find deselected and selected - for (int i = 0; i < intersections.count(); ++i) { + for (int i = 0; i < intersections.size(); ++i) { // split deselected - for (int o = 0; o < deselected.count();) { + for (int o = 0; o < deselected.size();) { if (deselected.at(o).intersects(intersections.at(i))) { QItemSelection::split(deselected.at(o), intersections.at(i), &deselected); deselected.removeAt(o); @@ -1987,7 +1953,7 @@ void QItemSelectionModel::emitSelectionChanged(const QItemSelection &newSelectio } } // split selected - for (int s = 0; s < selected.count();) { + for (int s = 0; s < selected.size();) { if (selected.at(s).intersects(intersections.at(i))) { QItemSelection::split(selected.at(s), intersections.at(i), &selected); selected.removeAt(s); diff --git a/src/corelib/itemmodels/qitemselectionmodel.h b/src/corelib/itemmodels/qitemselectionmodel.h index 423d6cc057..c4b8dadc97 100644 --- a/src/corelib/itemmodels/qitemselectionmodel.h +++ b/src/corelib/itemmodels/qitemselectionmodel.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2020 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) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QITEMSELECTIONMODEL_H #define QITEMSELECTIONMODEL_H @@ -93,12 +57,12 @@ public: bool intersects(const QItemSelectionRange &other) const; QItemSelectionRange intersected(const QItemSelectionRange &other) const; - +#if QT_CORE_REMOVED_SINCE(6, 8) inline bool operator==(const QItemSelectionRange &other) const - { return (tl == other.tl && br == other.br); } + { return comparesEqual(*this, other); } inline bool operator!=(const QItemSelectionRange &other) const - { return !operator==(other); } - + { return !operator==(other); } +#endif inline bool isValid() const { return (tl.isValid() && br.isValid() && tl.parent() == br.parent() @@ -110,6 +74,12 @@ public: QModelIndexList indexes() const; private: + friend bool comparesEqual(const QItemSelectionRange &lhs, + const QItemSelectionRange &rhs) noexcept + { + return (lhs.tl == rhs.tl && lhs.br == rhs.br); + } + Q_DECLARE_EQUALITY_COMPARABLE(QItemSelectionRange) QPersistentModelIndex tl, br; }; Q_DECLARE_TYPEINFO(QItemSelectionRange, Q_RELOCATABLE_TYPE); @@ -201,13 +171,6 @@ protected: private: Q_DISABLE_COPY(QItemSelectionModel) - Q_PRIVATE_SLOT(d_func(), void _q_columnsAboutToBeRemoved(const QModelIndex&, int, int)) - Q_PRIVATE_SLOT(d_func(), void _q_rowsAboutToBeRemoved(const QModelIndex&, int, int)) - Q_PRIVATE_SLOT(d_func(), void _q_columnsAboutToBeInserted(const QModelIndex&, int, int)) - Q_PRIVATE_SLOT(d_func(), void _q_rowsAboutToBeInserted(const QModelIndex&, int, int)) - Q_PRIVATE_SLOT(d_func(), void _q_layoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoHint)) - Q_PRIVATE_SLOT(d_func(), void _q_layoutChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoHint)) - Q_PRIVATE_SLOT(d_func(), void _q_modelDestroyed()) }; Q_DECLARE_OPERATORS_FOR_FLAGS(QItemSelectionModel::SelectionFlags) diff --git a/src/corelib/itemmodels/qitemselectionmodel_p.h b/src/corelib/itemmodels/qitemselectionmodel_p.h index b4da31431b..689cd26bd2 100644 --- a/src/corelib/itemmodels/qitemselectionmodel_p.h +++ b/src/corelib/itemmodels/qitemselectionmodel_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QITEMSELECTIONMODEL_P_H #define QITEMSELECTIONMODEL_P_H @@ -51,8 +15,10 @@ // We mean it. // +#include "qitemselectionmodel.h" #include "private/qobject_p.h" #include "private/qproperty_p.h" +#include <array> QT_REQUIRE_CONFIG(itemmodel); @@ -71,13 +37,23 @@ public: void initModel(QAbstractItemModel *model); - void _q_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); - void _q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end); - void _q_rowsAboutToBeInserted(const QModelIndex &parent, int start, int end); - void _q_columnsAboutToBeInserted(const QModelIndex &parent, int start, int end); - void _q_layoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); - void _q_layoutChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); - void _q_modelDestroyed(); + void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); + void columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end); + void rowsAboutToBeInserted(const QModelIndex &parent, int start, int end); + void columnsAboutToBeInserted(const QModelIndex &parent, int start, int end); + void layoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint); + void triggerLayoutToBeChanged() + { + layoutAboutToBeChanged(QList<QPersistentModelIndex>(), QAbstractItemModel::NoLayoutChangeHint); + } + + void layoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint); + void triggerLayoutChanged() + { + layoutChanged(QList<QPersistentModelIndex>(), QAbstractItemModel::NoLayoutChangeHint); + } + + void modelDestroyed(); inline void remove(QList<QItemSelectionRange> &r) { @@ -94,7 +70,8 @@ public: } void setModel(QAbstractItemModel *mod) { q_func()->setModel(mod); } - void modelChanged(QAbstractItemModel *mod) { q_func()->modelChanged(mod); } + void disconnectModel(); + void modelChanged(QAbstractItemModel *mod) { emit q_func()->modelChanged(mod); } Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QItemSelectionModelPrivate, QAbstractItemModel *, model, &QItemSelectionModelPrivate::setModel, &QItemSelectionModelPrivate::modelChanged, nullptr) @@ -105,12 +82,13 @@ public: QItemSelectionModel::SelectionFlags currentCommand; QList<QPersistentModelIndex> savedPersistentIndexes; QList<QPersistentModelIndex> savedPersistentCurrentIndexes; - QList<QPair<QPersistentModelIndex, uint>> savedPersistentRowLengths; - QList<QPair<QPersistentModelIndex, uint>> savedPersistentCurrentRowLengths; + QList<std::pair<QPersistentModelIndex, uint>> savedPersistentRowLengths; + QList<std::pair<QPersistentModelIndex, uint>> savedPersistentCurrentRowLengths; // optimization when all indexes are selected bool tableSelected; QPersistentModelIndex tableParent; int tableColCount, tableRowCount; + std::array<QMetaObject::Connection, 12> connections; }; QT_END_NAMESPACE diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp index 9ee438d699..a5284dbad4 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp +++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp @@ -1,48 +1,11 @@ -/**************************************************************************** -** -** 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. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qsortfilterproxymodel.h" #include "qitemselectionmodel.h" #include <qsize.h> #include <qdebug.h> #include <qdatetime.h> -#include <qpair.h> #include <qstringlist.h> #include <private/qabstractitemmodel_p.h> #include <private/qabstractproxymodel_p.h> @@ -52,7 +15,7 @@ QT_BEGIN_NAMESPACE -typedef QList<QPair<QModelIndex, QPersistentModelIndex>> QModelIndexPairList; +using QModelIndexPairList = QList<std::pair<QModelIndex, QPersistentModelIndex>>; struct QSortFilterProxyModelDataChanged { @@ -145,9 +108,9 @@ private: class QSortFilterProxyModelPrivate : public QAbstractProxyModelPrivate { +public: Q_DECLARE_PUBLIC(QSortFilterProxyModel) -public: enum class Direction { Rows = 1, Columns = 2, @@ -274,6 +237,8 @@ public: QModelIndexPairList saved_persistent_indexes; QList<QPersistentModelIndex> saved_layoutChange_parents; + std::array<QMetaObject::Connection, 18> sourceConnections; + QHash<QModelIndex, Mapping *>::const_iterator create_mapping( const QModelIndex &source_parent) const; QHash<QModelIndex, Mapping *>::const_iterator create_mapping_recursive( @@ -290,7 +255,7 @@ public: */ void set_filter_pattern(const QString &pattern) { - QRegularExpression re = filter_regularexpression.value(); + QRegularExpression re = filter_regularexpression.valueBypassingBindings(); const auto cs = re.patternOptions() & QRegularExpression::CaseInsensitiveOption; re.setPattern(pattern); re.setPatternOptions(cs); @@ -367,10 +332,10 @@ public: int find_source_sort_column() const; void sort_source_rows(QList<int> &source_rows, const QModelIndex &source_parent) const; - QList<QPair<int, QList<int>>> proxy_intervals_for_source_items_to_add( + QList<std::pair<int, QList<int>>> proxy_intervals_for_source_items_to_add( const QList<int> &proxy_to_source, const QList<int> &source_items, const QModelIndex &source_parent, Qt::Orientation orient) const; - QList<QPair<int, int>> proxy_intervals_for_source_items( + QList<std::pair<int, int>> proxy_intervals_for_source_items( const QList<int> &source_to_proxy, const QList<int> &source_items) const; void insert_source_items( QList<int> &source_to_proxy, QList<int> &proxy_to_source, @@ -486,7 +451,7 @@ bool QSortFilterProxyModelPrivate::recursiveChildAcceptsRow(int source_row, cons void QSortFilterProxyModelPrivate::remove_from_mapping(const QModelIndex &source_parent) { if (Mapping *m = source_index_mapping.take(source_parent)) { - for (const QModelIndex &mappedIdx : qAsConst(m->mapped_children)) + for (const QModelIndex &mappedIdx : std::as_const(m->mapped_children)) remove_from_mapping(mappedIdx); delete m; } @@ -723,8 +688,10 @@ void QSortFilterProxyModelPrivate::sort_source_rows( QSortFilterProxyModelGreaterThan gt(source_sort_column, source_parent, model, q); std::stable_sort(source_rows.begin(), source_rows.end(), gt); } - } else { // restore the source model order - std::stable_sort(source_rows.begin(), source_rows.end()); + } else if (sort_order == Qt::AscendingOrder) { + std::stable_sort(source_rows.begin(), source_rows.end(), std::less{}); + } else { + std::stable_sort(source_rows.begin(), source_rows.end(), std::greater{}); } } @@ -739,10 +706,10 @@ void QSortFilterProxyModelPrivate::sort_source_rows( The result is a vector of pairs, where each pair represents a (start, end) tuple, sorted in ascending order. */ -QList<QPair<int, int>> QSortFilterProxyModelPrivate::proxy_intervals_for_source_items( +QList<std::pair<int, int>> QSortFilterProxyModelPrivate::proxy_intervals_for_source_items( const QList<int> &source_to_proxy, const QList<int> &source_items) const { - QList<QPair<int, int>> proxy_intervals; + QList<std::pair<int, int>> proxy_intervals; if (source_items.isEmpty()) return proxy_intervals; @@ -759,19 +726,19 @@ QList<QPair<int, int>> QSortFilterProxyModelPrivate::proxy_intervals_for_source_ ++source_items_index; } // Add interval to result - proxy_intervals.append(QPair<int, int>(first_proxy_item, last_proxy_item)); + proxy_intervals.emplace_back(first_proxy_item, last_proxy_item); } std::stable_sort(proxy_intervals.begin(), proxy_intervals.end()); // Consolidate adjacent intervals for (int i = proxy_intervals.size()-1; i > 0; --i) { - QPair<int, int> &interval = proxy_intervals[i]; - QPair<int, int> &preceeding_interval = proxy_intervals[i - 1]; + std::pair<int, int> &interval = proxy_intervals[i]; + std::pair<int, int> &preceeding_interval = proxy_intervals[i - 1]; if (interval.first == preceeding_interval.second + 1) { preceeding_interval.second = interval.second; interval.first = interval.second = -1; } } - proxy_intervals.removeIf([](QPair<int, int> interval) { return interval.first < 0; }); + proxy_intervals.removeIf([](std::pair<int, int> interval) { return interval.first < 0; }); return proxy_intervals; } @@ -800,7 +767,7 @@ void QSortFilterProxyModelPrivate::remove_source_items( const auto end = proxy_intervals.rend(); for (auto it = proxy_intervals.rbegin(); it != end; ++it) { - const QPair<int, int> &interval = *it; + const std::pair<int, int> &interval = *it; const int proxy_start = interval.first; const int proxy_end = interval.second; remove_proxy_interval(source_to_proxy, proxy_to_source, proxy_start, proxy_end, @@ -854,22 +821,21 @@ void QSortFilterProxyModelPrivate::remove_proxy_interval( items), where items is a vector containing the (sorted) source items that should be inserted at that proxy model location. */ -QList<QPair<int, QList<int>>> QSortFilterProxyModelPrivate::proxy_intervals_for_source_items_to_add( +QList<std::pair<int, QList<int>>> QSortFilterProxyModelPrivate::proxy_intervals_for_source_items_to_add( const QList<int> &proxy_to_source, const QList<int> &source_items, const QModelIndex &source_parent, Qt::Orientation orient) const { Q_Q(const QSortFilterProxyModel); - QList<QPair<int, QList<int>>> proxy_intervals; + QList<std::pair<int, QList<int>>> proxy_intervals; if (source_items.isEmpty()) return proxy_intervals; int proxy_low = 0; int proxy_item = 0; int source_items_index = 0; - QList<int> source_items_in_interval; bool compare = (orient == Qt::Vertical && source_sort_column >= 0 && dynamic_sortfilter); while (source_items_index < source_items.size()) { - source_items_in_interval.clear(); + QList<int> source_items_in_interval; int first_new_source_item = source_items.at(source_items_index); source_items_in_interval.append(first_new_source_item); ++source_items_index; @@ -915,7 +881,7 @@ QList<QPair<int, QList<int>>> QSortFilterProxyModelPrivate::proxy_intervals_for_ } // Add interval to result - proxy_intervals.append(QPair<int, QList<int>>(proxy_item, source_items_in_interval)); + proxy_intervals.emplace_back(proxy_item, std::move(source_items_in_interval)); } return proxy_intervals; } @@ -943,7 +909,7 @@ void QSortFilterProxyModelPrivate::insert_source_items( const auto end = proxy_intervals.rend(); for (auto it = proxy_intervals.rbegin(); it != end; ++it) { - const QPair<int, QList<int>> &interval = *it; + const std::pair<int, QList<int>> &interval = *it; const int proxy_start = interval.first; const QList<int> &source_items = interval.second; const int proxy_end = proxy_start + source_items.size() - 1; @@ -995,12 +961,12 @@ void QSortFilterProxyModelPrivate::source_items_inserted( it = create_mapping(source_parent); Mapping *m = it.value(); QModelIndex proxy_parent = q->mapFromSource(source_parent); - if (m->source_rows.count() > 0) { - q->beginInsertRows(proxy_parent, 0, m->source_rows.count() - 1); + if (m->source_rows.size() > 0) { + q->beginInsertRows(proxy_parent, 0, m->source_rows.size() - 1); q->endInsertRows(); } - if (m->source_columns.count() > 0) { - q->beginInsertColumns(proxy_parent, 0, m->source_columns.count() - 1); + if (m->source_columns.size() > 0) { + q->beginInsertColumns(proxy_parent, 0, m->source_columns.size() - 1); q->endInsertColumns(); } return; @@ -1172,7 +1138,7 @@ void QSortFilterProxyModelPrivate::updateChildrenMapping(const QModelIndex &sour Qt::Orientation orient, int start, int end, int delta_item_count, bool remove) { // see if any mapped children should be (re)moved - QList<QPair<QModelIndex, Mapping *>> moved_source_index_mappings; + QList<std::pair<QModelIndex, Mapping *>> moved_source_index_mappings; auto it2 = parent_mapping->mapped_children.begin(); for ( ; it2 != parent_mapping->mapped_children.end();) { const QModelIndex source_child_index = *it2; @@ -1206,12 +1172,12 @@ void QSortFilterProxyModelPrivate::updateChildrenMapping(const QModelIndex &sour Mapping *cm = source_index_mapping.take(source_child_index); Q_ASSERT(cm); // we do not reinsert right away, because the new index might be identical with another, old index - moved_source_index_mappings.append(QPair<QModelIndex, Mapping*>(new_index, cm)); + moved_source_index_mappings.emplace_back(new_index, cm); } } // reinsert moved, mapped indexes - for (auto &pair : qAsConst(moved_source_index_mappings)) { + for (auto &pair : std::as_const(moved_source_index_mappings)) { pair.second->source_parent = pair.first; source_index_mapping.insert(pair.first, pair.second); } @@ -1226,7 +1192,7 @@ void QSortFilterProxyModelPrivate::proxy_item_range( { proxy_low = INT_MAX; proxy_high = INT_MIN; - for (int i = 0; i < source_items.count(); ++i) { + for (int i = 0; i < source_items.size(); ++i) { int proxy_item = source_to_proxy.at(source_items.at(i)); Q_ASSERT(proxy_item != -1); if (proxy_item < proxy_low) @@ -1259,11 +1225,11 @@ QModelIndexPairList QSortFilterProxyModelPrivate::store_persistent_indexes() con { Q_Q(const QSortFilterProxyModel); QModelIndexPairList source_indexes; - source_indexes.reserve(persistent.indexes.count()); - for (const QPersistentModelIndexData *data : qAsConst(persistent.indexes)) { + source_indexes.reserve(persistent.indexes.size()); + for (const QPersistentModelIndexData *data : std::as_const(persistent.indexes)) { const QModelIndex &proxy_index = data->index; QModelIndex source_index = q->mapToSource(proxy_index); - source_indexes.append(qMakePair(proxy_index, QPersistentModelIndex(source_index))); + source_indexes.emplace_back(proxy_index, source_index); } return source_indexes; } @@ -1279,7 +1245,7 @@ void QSortFilterProxyModelPrivate::update_persistent_indexes( { Q_Q(QSortFilterProxyModel); QModelIndexList from, to; - const int numSourceIndexes = source_indexes.count(); + const int numSourceIndexes = source_indexes.size(); from.reserve(numSourceIndexes); to.reserve(numSourceIndexes); for (const auto &indexPair : source_indexes) { @@ -1301,7 +1267,7 @@ void QSortFilterProxyModelPrivate::update_persistent_indexes( */ void QSortFilterProxyModelPrivate::filter_about_to_be_changed(const QModelIndex &source_parent) { - if (!filter_regularexpression.value().pattern().isEmpty() + if (!filter_regularexpression.valueBypassingBindings().pattern().isEmpty() && source_index_mapping.constFind(source_parent) == source_index_mapping.constEnd()) { create_mapping(source_parent); } @@ -1363,7 +1329,7 @@ QSet<int> QSortFilterProxyModelPrivate::handle_filter_changed( Q_Q(QSortFilterProxyModel); // Figure out which mapped items to remove QList<int> source_items_remove; - for (int i = 0; i < proxy_to_source.count(); ++i) { + for (int i = 0; i < proxy_to_source.size(); ++i) { const int source_item = proxy_to_source.at(i); if ((orient == Qt::Vertical) ? !filterAcceptsRowInternal(source_item, source_parent) @@ -1471,7 +1437,7 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc QList<int> source_rows_insert; QList<int> source_rows_change; QList<int> source_rows_resort; - int end = qMin(source_bottom_right.row(), m->proxy_rows.count() - 1); + int end = qMin(source_bottom_right.row(), m->proxy_rows.size() - 1); for (int source_row = source_top_left.row(); source_row <= end; ++source_row) { if (dynamic_sortfilter && !change_in_unmapped_parent) { if (m->proxy_rows.at(source_row) != -1) { @@ -2042,7 +2008,9 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsMoved( QSortFilterProxyModel::QSortFilterProxyModel(QObject *parent) : QAbstractProxyModel(*new QSortFilterProxyModelPrivate, parent) { - connect(this, SIGNAL(modelReset()), this, SLOT(_q_clearMapping())); + Q_D(QSortFilterProxyModel); + QObjectPrivate::connect(this, &QAbstractItemModel::modelReset, d, + &QSortFilterProxyModelPrivate::_q_clearMapping); } /*! @@ -2067,56 +2035,10 @@ void QSortFilterProxyModel::setSourceModel(QAbstractItemModel *sourceModel) beginResetModel(); - disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)), - this, SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex,QList<int>))); - - disconnect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), - this, SLOT(_q_sourceHeaderDataChanged(Qt::Orientation,int,int))); - - disconnect(d->model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsAboutToBeInserted(QModelIndex,int,int))); - - disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsInserted(QModelIndex,int,int))); - - disconnect(d->model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsAboutToBeInserted(QModelIndex,int,int))); - - disconnect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsInserted(QModelIndex,int,int))); - - disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsAboutToBeRemoved(QModelIndex,int,int))); - - disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsRemoved(QModelIndex,int,int))); - - disconnect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsAboutToBeRemoved(QModelIndex,int,int))); - - disconnect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsRemoved(QModelIndex,int,int))); - - disconnect(d->model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); - - disconnect(d->model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int))); - - disconnect(d->model, SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); - - disconnect(d->model, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int))); - - disconnect(d->model, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), - this, SLOT(_q_sourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint))); - - disconnect(d->model, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), - this, SLOT(_q_sourceLayoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint))); - - disconnect(d->model, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_sourceAboutToBeReset())); - disconnect(d->model, SIGNAL(modelReset()), this, SLOT(_q_sourceReset())); + if (d->model) { + for (const QMetaObject::Connection &connection : std::as_const(d->sourceConnections)) + disconnect(connection); + } // same as in _q_sourceReset() d->invalidatePersistentIndexes(); @@ -2124,57 +2046,61 @@ void QSortFilterProxyModel::setSourceModel(QAbstractItemModel *sourceModel) QAbstractProxyModel::setSourceModel(sourceModel); - connect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)), - this, SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex,QList<int>))); + d->sourceConnections = std::array<QMetaObject::Connection, 18>{ + QObjectPrivate::connect(d->model, &QAbstractItemModel::dataChanged, d, + &QSortFilterProxyModelPrivate::_q_sourceDataChanged), - connect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), - this, SLOT(_q_sourceHeaderDataChanged(Qt::Orientation,int,int))); + QObjectPrivate::connect(d->model, &QAbstractItemModel::headerDataChanged, d, + &QSortFilterProxyModelPrivate::_q_sourceHeaderDataChanged), - connect(d->model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsAboutToBeInserted(QModelIndex,int,int))); + QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsAboutToBeInserted, d, + &QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeInserted), - connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsInserted(QModelIndex,int,int))); + QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsInserted, d, + &QSortFilterProxyModelPrivate::_q_sourceRowsInserted), - connect(d->model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsAboutToBeInserted(QModelIndex,int,int))); + QObjectPrivate::connect(d->model, &QAbstractItemModel::columnsAboutToBeInserted, d, + &QSortFilterProxyModelPrivate::_q_sourceColumnsAboutToBeInserted), - connect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsInserted(QModelIndex,int,int))); + QObjectPrivate::connect(d->model, &QAbstractItemModel::columnsInserted, d, + &QSortFilterProxyModelPrivate::_q_sourceColumnsInserted), - connect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsAboutToBeRemoved(QModelIndex,int,int))); + QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsAboutToBeRemoved, d, + &QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeRemoved), - connect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsRemoved(QModelIndex,int,int))); + QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsRemoved, d, + &QSortFilterProxyModelPrivate::_q_sourceRowsRemoved), - connect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsAboutToBeRemoved(QModelIndex,int,int))); + QObjectPrivate::connect(d->model, &QAbstractItemModel::columnsAboutToBeRemoved, d, + &QSortFilterProxyModelPrivate::_q_sourceColumnsAboutToBeRemoved), - connect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsRemoved(QModelIndex,int,int))); + QObjectPrivate::connect(d->model, &QAbstractItemModel::columnsRemoved, d, + &QSortFilterProxyModelPrivate::_q_sourceColumnsRemoved), - connect(d->model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); + QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsAboutToBeMoved, d, + &QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeMoved), - connect(d->model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int))); + QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsMoved, d, + &QSortFilterProxyModelPrivate::_q_sourceRowsMoved), - connect(d->model, SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); + QObjectPrivate::connect(d->model, &QAbstractItemModel::columnsAboutToBeMoved, d, + &QSortFilterProxyModelPrivate::_q_sourceColumnsAboutToBeMoved), - connect(d->model, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int))); + QObjectPrivate::connect(d->model, &QAbstractItemModel::columnsMoved, d, + &QSortFilterProxyModelPrivate::_q_sourceColumnsMoved), - connect(d->model, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), - this, SLOT(_q_sourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint))); + QObjectPrivate::connect(d->model, &QAbstractItemModel::layoutAboutToBeChanged, d, + &QSortFilterProxyModelPrivate::_q_sourceLayoutAboutToBeChanged), - connect(d->model, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), - this, SLOT(_q_sourceLayoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint))); + QObjectPrivate::connect(d->model, &QAbstractItemModel::layoutChanged, d, + &QSortFilterProxyModelPrivate::_q_sourceLayoutChanged), - connect(d->model, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_sourceAboutToBeReset())); - connect(d->model, SIGNAL(modelReset()), this, SLOT(_q_sourceReset())); + QObjectPrivate::connect(d->model, &QAbstractItemModel::modelAboutToBeReset, d, + &QSortFilterProxyModelPrivate::_q_sourceAboutToBeReset), + QObjectPrivate::connect(d->model, &QAbstractItemModel::modelReset, d, + &QSortFilterProxyModelPrivate::_q_sourceReset) + }; endResetModel(); if (d->update_source_sort_column() && d->dynamic_sortfilter) d->sort(); @@ -2191,7 +2117,7 @@ QModelIndex QSortFilterProxyModel::index(int row, int column, const QModelIndex QModelIndex source_parent = mapToSource(parent); // parent is already mapped at this point IndexMap::const_iterator it = d->create_mapping(source_parent); // but make sure that the children are mapped - if (it.value()->source_rows.count() <= row || it.value()->source_columns.count() <= column) + if (it.value()->source_rows.size() <= row || it.value()->source_columns.size() <= column) return QModelIndex(); return d->create_index(row, column, it); @@ -2222,7 +2148,7 @@ QModelIndex QSortFilterProxyModel::sibling(int row, int column, const QModelInde return QModelIndex(); const IndexMap::const_iterator it = d->index_to_iterator(idx); - if (it.value()->source_rows.count() <= row || it.value()->source_columns.count() <= column) + if (it.value()->source_rows.size() <= row || it.value()->source_columns.size() <= column) return QModelIndex(); return d->create_index(row, column, it); @@ -2238,7 +2164,7 @@ int QSortFilterProxyModel::rowCount(const QModelIndex &parent) const if (parent.isValid() && !source_parent.isValid()) return 0; IndexMap::const_iterator it = d->create_mapping(source_parent); - return it.value()->source_rows.count(); + return it.value()->source_rows.size(); } /*! @@ -2251,7 +2177,7 @@ int QSortFilterProxyModel::columnCount(const QModelIndex &parent) const if (parent.isValid() && !source_parent.isValid()) return 0; IndexMap::const_iterator it = d->create_mapping(source_parent); - return it.value()->source_columns.count(); + return it.value()->source_columns.size(); } /*! @@ -2270,7 +2196,7 @@ bool QSortFilterProxyModel::hasChildren(const QModelIndex &parent) const return true; //we assume we might have children that can be fetched QSortFilterProxyModelPrivate::Mapping *m = d->create_mapping(source_parent).value(); - return m->source_rows.count() != 0 && m->source_columns.count() != 0; + return m->source_rows.size() != 0 && m->source_columns.size() != 0; } /*! @@ -2304,15 +2230,15 @@ QVariant QSortFilterProxyModel::headerData(int section, Qt::Orientation orientat { Q_D(const QSortFilterProxyModel); IndexMap::const_iterator it = d->create_mapping(QModelIndex()); - if (it.value()->source_rows.count() * it.value()->source_columns.count() > 0) + if (it.value()->source_rows.size() * it.value()->source_columns.size() > 0) return QAbstractProxyModel::headerData(section, orientation, role); int source_section; if (orientation == Qt::Vertical) { - if (section < 0 || section >= it.value()->source_rows.count()) + if (section < 0 || section >= it.value()->source_rows.size()) return QVariant(); source_section = it.value()->source_rows.at(section); } else { - if (section < 0 || section >= it.value()->source_columns.count()) + if (section < 0 || section >= it.value()->source_columns.size()) return QVariant(); source_section = it.value()->source_columns.at(section); } @@ -2327,15 +2253,15 @@ bool QSortFilterProxyModel::setHeaderData(int section, Qt::Orientation orientati { Q_D(QSortFilterProxyModel); IndexMap::const_iterator it = d->create_mapping(QModelIndex()); - if (it.value()->source_rows.count() * it.value()->source_columns.count() > 0) + if (it.value()->source_rows.size() * it.value()->source_columns.size() > 0) return QAbstractProxyModel::setHeaderData(section, orientation, value, role); int source_section; if (orientation == Qt::Vertical) { - if (section < 0 || section >= it.value()->source_rows.count()) + if (section < 0 || section >= it.value()->source_rows.size()) return false; source_section = it.value()->source_rows.at(section); } else { - if (section < 0 || section >= it.value()->source_columns.count()) + if (section < 0 || section >= it.value()->source_columns.size()) return false; source_section = it.value()->source_columns.at(section); } @@ -2349,7 +2275,7 @@ QMimeData *QSortFilterProxyModel::mimeData(const QModelIndexList &indexes) const { Q_D(const QSortFilterProxyModel); QModelIndexList source_indexes; - source_indexes.reserve(indexes.count()); + source_indexes.reserve(indexes.size()); for (const QModelIndex &idx : indexes) source_indexes << mapToSource(idx); return d->model->mimeData(source_indexes); @@ -2395,10 +2321,10 @@ bool QSortFilterProxyModel::insertRows(int row, int count, const QModelIndex &pa if (parent.isValid() && !source_parent.isValid()) return false; QSortFilterProxyModelPrivate::Mapping *m = d->create_mapping(source_parent).value(); - if (row > m->source_rows.count()) + if (row > m->source_rows.size()) return false; - int source_row = (row >= m->source_rows.count() - ? m->proxy_rows.count() + int source_row = (row >= m->source_rows.size() + ? m->proxy_rows.size() : m->source_rows.at(row)); return d->model->insertRows(source_row, count, source_parent); } @@ -2415,10 +2341,10 @@ bool QSortFilterProxyModel::insertColumns(int column, int count, const QModelInd if (parent.isValid() && !source_parent.isValid()) return false; QSortFilterProxyModelPrivate::Mapping *m = d->create_mapping(source_parent).value(); - if (column > m->source_columns.count()) + if (column > m->source_columns.size()) return false; - int source_column = (column >= m->source_columns.count() - ? m->proxy_columns.count() + int source_column = (column >= m->source_columns.size() + ? m->proxy_columns.size() : m->source_columns.at(column)); return d->model->insertColumns(source_column, count, source_parent); } @@ -2435,10 +2361,10 @@ bool QSortFilterProxyModel::removeRows(int row, int count, const QModelIndex &pa if (parent.isValid() && !source_parent.isValid()) return false; QSortFilterProxyModelPrivate::Mapping *m = d->create_mapping(source_parent).value(); - if (row + count > m->source_rows.count()) + if (row + count > m->source_rows.size()) return false; if ((count == 1) - || ((d->source_sort_column < 0) && (m->proxy_rows.count() == m->source_rows.count()))) { + || ((d->source_sort_column < 0) && (m->proxy_rows.size() == m->source_rows.size()))) { int source_row = m->source_rows.at(row); return d->model->removeRows(source_row, count, source_parent); } @@ -2450,7 +2376,7 @@ bool QSortFilterProxyModel::removeRows(int row, int count, const QModelIndex &pa rows.append(m->source_rows.at(i)); std::sort(rows.begin(), rows.end()); - int pos = rows.count() - 1; + int pos = rows.size() - 1; bool ok = true; while (pos >= 0) { const int source_end = rows.at(pos--); @@ -2477,9 +2403,9 @@ bool QSortFilterProxyModel::removeColumns(int column, int count, const QModelInd if (parent.isValid() && !source_parent.isValid()) return false; QSortFilterProxyModelPrivate::Mapping *m = d->create_mapping(source_parent).value(); - if (column + count > m->source_columns.count()) + if (column + count > m->source_columns.size()) return false; - if ((count == 1) || (m->proxy_columns.count() == m->source_columns.count())) { + if ((count == 1) || (m->proxy_columns.size() == m->source_columns.size())) { int source_column = m->source_columns.at(column); return d->model->removeColumns(source_column, count, source_parent); } @@ -2489,7 +2415,7 @@ bool QSortFilterProxyModel::removeColumns(int column, int count, const QModelInd for (int i = column; i < column + count; ++i) columns.append(m->source_columns.at(i)); - int pos = columns.count() - 1; + int pos = columns.size() - 1; bool ok = true; while (pos >= 0) { const int source_end = columns.at(pos--); @@ -2509,11 +2435,7 @@ bool QSortFilterProxyModel::removeColumns(int column, int count, const QModelInd */ void QSortFilterProxyModel::fetchMore(const QModelIndex &parent) { - Q_D(QSortFilterProxyModel); - QModelIndex source_parent; - if (d->indexValid(parent)) - source_parent = mapToSource(parent); - d->model->fetchMore(source_parent); + QAbstractProxyModel::fetchMore(parent); } /*! @@ -2521,11 +2443,7 @@ void QSortFilterProxyModel::fetchMore(const QModelIndex &parent) */ bool QSortFilterProxyModel::canFetchMore(const QModelIndex &parent) const { - Q_D(const QSortFilterProxyModel); - QModelIndex source_parent; - if (d->indexValid(parent)) - source_parent = mapToSource(parent); - return d->model->canFetchMore(source_parent); + return QAbstractProxyModel::canFetchMore(parent); } /*! @@ -2533,11 +2451,7 @@ bool QSortFilterProxyModel::canFetchMore(const QModelIndex &parent) const */ Qt::ItemFlags QSortFilterProxyModel::flags(const QModelIndex &index) const { - Q_D(const QSortFilterProxyModel); - QModelIndex source_index; - if (d->indexValid(index)) - source_index = mapToSource(index); - return d->model->flags(source_index); + return QAbstractProxyModel::flags(index); } /*! @@ -2578,7 +2492,10 @@ QSize QSortFilterProxyModel::span(const QModelIndex &index) const } /*! - \reimp + \reimp + Sorts the model by \a column in the given \a order. + If the sort \a column is less than zero, the model will be sorted by source model row + in the given \a order. */ void QSortFilterProxyModel::sort(int column, Qt::SortOrder order) { @@ -2593,9 +2510,12 @@ void QSortFilterProxyModel::sort(int column, Qt::SortOrder order) /*! \since 4.5 - \brief the column currently used for sorting + \return the column currently used for sorting + + This returns the most recently used sort column. The default value is -1, + which means that this proxy model does not sort. - This returns the most recently used sort column. + \sa sort() */ int QSortFilterProxyModel::sortColumn() const { @@ -2605,9 +2525,12 @@ int QSortFilterProxyModel::sortColumn() const /*! \since 4.5 - \brief the order currently used for sorting + \return the order currently used for sorting - This returns the most recently used sort order. + This returns the most recently used sort order. The default value is + Qt::AscendingOrder. + + \sa sort() */ Qt::SortOrder QSortFilterProxyModel::sortOrder() const { @@ -2650,11 +2573,12 @@ QBindable<QRegularExpression> QSortFilterProxyModel::bindableFilterRegularExpres void QSortFilterProxyModel::setFilterRegularExpression(const QRegularExpression ®ularExpression) { Q_D(QSortFilterProxyModel); - Qt::beginPropertyUpdateGroup(); - const bool regExpChanged = regularExpression != d->filter_regularexpression.value(); + const QScopedPropertyUpdateGroup guard; + const bool regExpChanged = + regularExpression != d->filter_regularexpression.valueBypassingBindings(); d->filter_regularexpression.removeBindingUnlessInWrapper(); d->filter_casesensitive.removeBindingUnlessInWrapper(); - const Qt::CaseSensitivity cs = filterCaseSensitivity(); + const Qt::CaseSensitivity cs = d->filter_casesensitive.valueBypassingBindings(); d->filter_about_to_be_changed(); const Qt::CaseSensitivity updatedCs = regularExpression.patternOptions() & QRegularExpression::CaseInsensitiveOption @@ -2669,7 +2593,6 @@ void QSortFilterProxyModel::setFilterRegularExpression(const QRegularExpression d->filter_regularexpression.notify(); if (cs != updatedCs) d->filter_casesensitive.notify(); - Qt::endPropertyUpdateGroup(); } /*! @@ -2696,7 +2619,7 @@ void QSortFilterProxyModel::setFilterKeyColumn(int column) Q_D(QSortFilterProxyModel); d->filter_column.removeBindingUnlessInWrapper(); d->filter_about_to_be_changed(); - const auto oldColumn = d->filter_column.value(); + const auto oldColumn = d->filter_column.valueBypassingBindings(); d->filter_column.setValueBypassingBindings(column); d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); if (oldColumn != column) @@ -2745,7 +2668,7 @@ void QSortFilterProxyModel::setFilterCaseSensitivity(Qt::CaseSensitivity cs) if (cs == d->filter_casesensitive) return; - Qt::beginPropertyUpdateGroup(); + const QScopedPropertyUpdateGroup guard; QRegularExpression::PatternOptions options = d->filter_regularexpression.value().patternOptions(); options.setFlag(QRegularExpression::CaseInsensitiveOption, cs == Qt::CaseInsensitive); @@ -2758,7 +2681,6 @@ void QSortFilterProxyModel::setFilterCaseSensitivity(Qt::CaseSensitivity cs) d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); d->filter_regularexpression.notify(); d->filter_casesensitive.notify(); - Qt::endPropertyUpdateGroup(); } QBindable<Qt::CaseSensitivity> QSortFilterProxyModel::bindableFilterCaseSensitivity() @@ -2937,6 +2859,8 @@ void QSortFilterProxyModel::setFilterFixedString(const QString &pattern) QComboBox. The default value is true. + + \sa sortColumn() */ bool QSortFilterProxyModel::dynamicSortFilter() const { @@ -2993,7 +2917,7 @@ void QSortFilterProxyModel::setSortRole(int role) { Q_D(QSortFilterProxyModel); d->sort_role.removeBindingUnlessInWrapper(); - if (d->sort_role == role) + if (d->sort_role.valueBypassingBindings() == role) return; d->sort_role.setValueBypassingBindings(role); d->sort(); @@ -3032,7 +2956,7 @@ void QSortFilterProxyModel::setFilterRole(int role) { Q_D(QSortFilterProxyModel); d->filter_role.removeBindingUnlessInWrapper(); - if (d->filter_role == role) + if (d->filter_role.valueBypassingBindings() == role) return; d->filter_about_to_be_changed(); d->filter_role.setValueBypassingBindings(role); diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.h b/src/corelib/itemmodels/qsortfilterproxymodel.h index b3c7b74453..9d5b2fac9f 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.h +++ b/src/corelib/itemmodels/qsortfilterproxymodel.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QSORTFILTERPROXYMODEL_H #define QSORTFILTERPROXYMODEL_H @@ -208,28 +172,6 @@ Q_SIGNALS: private: Q_DECLARE_PRIVATE(QSortFilterProxyModel) Q_DISABLE_COPY(QSortFilterProxyModel) - - Q_PRIVATE_SLOT(d_func(), - void _q_sourceDataChanged(const QModelIndex &source_top_left, const QModelIndex &source_bottom_right, - const QList<int> &roles)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceHeaderDataChanged(Qt::Orientation orientation, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceAboutToBeReset()) - Q_PRIVATE_SLOT(d_func(), void _q_sourceReset()) - Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeInserted(const QModelIndex &source_parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsInserted(const QModelIndex &source_parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsRemoved(const QModelIndex &source_parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeInserted(const QModelIndex &source_parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsInserted(const QModelIndex &source_parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsRemoved(const QModelIndex &source_parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int)) - Q_PRIVATE_SLOT(d_func(), void _q_clearMapping()) }; QT_END_NAMESPACE diff --git a/src/corelib/itemmodels/qstringlistmodel.cpp b/src/corelib/itemmodels/qstringlistmodel.cpp index 829d4cf3ed..dfbe72b289 100644 --- a/src/corelib/itemmodels/qstringlistmodel.cpp +++ b/src/corelib/itemmodels/qstringlistmodel.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only /* A simple model that uses a QStringList as its data source. @@ -44,6 +8,7 @@ #include "qstringlistmodel.h" #include <QtCore/qlist.h> +#include <QtCore/qmap.h> #include <algorithm> @@ -121,7 +86,7 @@ int QStringListModel::rowCount(const QModelIndex &parent) const if (parent.isValid()) return 0; - return lst.count(); + return lst.size(); } /*! @@ -129,7 +94,7 @@ int QStringListModel::rowCount(const QModelIndex &parent) const */ QModelIndex QStringListModel::sibling(int row, int column, const QModelIndex &idx) const { - if (!idx.isValid() || column != 0 || row >= lst.count() || row < 0) + if (!idx.isValid() || column != 0 || row >= lst.size() || row < 0) return QModelIndex(); return createIndex(row, 0); @@ -327,12 +292,12 @@ bool QStringListModel::moveRows(const QModelIndex &sourceParent, int sourceRow, return true; } -static bool ascendingLessThan(const QPair<QString, int> &s1, const QPair<QString, int> &s2) +static bool ascendingLessThan(const std::pair<QString, int> &s1, const std::pair<QString, int> &s2) { return s1.first < s2.first; } -static bool decendingLessThan(const QPair<QString, int> &s1, const QPair<QString, int> &s2) +static bool decendingLessThan(const std::pair<QString, int> &s1, const std::pair<QString, int> &s2) { return s1.first > s2.first; } @@ -344,11 +309,11 @@ void QStringListModel::sort(int, Qt::SortOrder order) { emit layoutAboutToBeChanged(QList<QPersistentModelIndex>(), VerticalSortHint); - QList<QPair<QString, int>> list; - const int lstCount = lst.count(); + QList<std::pair<QString, int>> list; + const int lstCount = lst.size(); list.reserve(lstCount); for (int i = 0; i < lstCount; ++i) - list.append(QPair<QString, int>(lst.at(i), i)); + list.emplace_back(lst.at(i), i); if (order == Qt::AscendingOrder) std::sort(list.begin(), list.end(), ascendingLessThan); @@ -364,7 +329,7 @@ void QStringListModel::sort(int, Qt::SortOrder order) QModelIndexList oldList = persistentIndexList(); QModelIndexList newList; - const int numOldIndexes = oldList.count(); + const int numOldIndexes = oldList.size(); newList.reserve(numOldIndexes); for (int i = 0; i < numOldIndexes; ++i) newList.append(index(forwarding.at(oldList.at(i).row()), 0)); diff --git a/src/corelib/itemmodels/qstringlistmodel.h b/src/corelib/itemmodels/qstringlistmodel.h index fb53c19f09..b93a9c7173 100644 --- a/src/corelib/itemmodels/qstringlistmodel.h +++ b/src/corelib/itemmodels/qstringlistmodel.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QSTRINGLISTMODEL_H #define QSTRINGLISTMODEL_H diff --git a/src/corelib/itemmodels/qtransposeproxymodel.cpp b/src/corelib/itemmodels/qtransposeproxymodel.cpp index 26b2628241..621b54782e 100644 --- a/src/corelib/itemmodels/qtransposeproxymodel.cpp +++ b/src/corelib/itemmodels/qtransposeproxymodel.cpp @@ -1,47 +1,12 @@ -/**************************************************************************** -** -** Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it> -** 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) 2018 Luca Beldi <v.ronin@yahoo.it> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qtransposeproxymodel.h" #include <private/qtransposeproxymodel_p.h> #include <QtCore/qlist.h> #include <QtCore/qmetaobject.h> #include <QtCore/qsize.h> +#include <QtCore/qmap.h> QT_BEGIN_NAMESPACE @@ -67,7 +32,7 @@ void QTransposeProxyModelPrivate::onLayoutChanged(const QList<QPersistentModelIn Q_ASSERT(layoutChangeProxyIndexes.size() == layoutChangePersistentIndexes.size()); QModelIndexList toList; toList.reserve(layoutChangePersistentIndexes.size()); - for (const QPersistentModelIndex &persistIdx : qAsConst(layoutChangePersistentIndexes)) + for (const QPersistentModelIndex &persistIdx : std::as_const(layoutChangePersistentIndexes)) toList << q->mapFromSource(persistIdx); q->changePersistentIndexList(layoutChangeProxyIndexes, toList); layoutChangeProxyIndexes.clear(); @@ -207,7 +172,7 @@ void QTransposeProxyModel::setSourceModel(QAbstractItemModel* newSourceModel) return; beginResetModel(); if (d->model) { - for (const QMetaObject::Connection& discIter : qAsConst(d->sourceConnections)) + for (const QMetaObject::Connection& discIter : std::as_const(d->sourceConnections)) disconnect(discIter); } d->sourceConnections.clear(); diff --git a/src/corelib/itemmodels/qtransposeproxymodel.h b/src/corelib/itemmodels/qtransposeproxymodel.h index 854a547fd4..67ce6f3bef 100644 --- a/src/corelib/itemmodels/qtransposeproxymodel.h +++ b/src/corelib/itemmodels/qtransposeproxymodel.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it> -** 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) 2018 Luca Beldi <v.ronin@yahoo.it> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTRANSPOSEPROXYMODEL_H #define QTRANSPOSEPROXYMODEL_H diff --git a/src/corelib/itemmodels/qtransposeproxymodel_p.h b/src/corelib/itemmodels/qtransposeproxymodel_p.h index 8cee3d2288..2e0c09b95b 100644 --- a/src/corelib/itemmodels/qtransposeproxymodel_p.h +++ b/src/corelib/itemmodels/qtransposeproxymodel_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it> -** 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) 2018 Luca Beldi <v.ronin@yahoo.it> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTRANSPOSEPROXYMODEL_P_H #define QTRANSPOSEPROXYMODEL_P_H |