diff options
Diffstat (limited to 'src/corelib/itemmodels')
-rw-r--r-- | src/corelib/itemmodels/qabstractitemmodel.cpp | 43 | ||||
-rw-r--r-- | src/corelib/itemmodels/qabstractitemmodel.h | 18 | ||||
-rw-r--r-- | src/corelib/itemmodels/qabstractproxymodel.cpp | 93 | ||||
-rw-r--r-- | src/corelib/itemmodels/qabstractproxymodel_p.h | 10 | ||||
-rw-r--r-- | src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp | 178 | ||||
-rw-r--r-- | src/corelib/itemmodels/qconcatenatetablesproxymodel.h | 15 | ||||
-rw-r--r-- | src/corelib/itemmodels/qidentityproxymodel.cpp | 208 | ||||
-rw-r--r-- | src/corelib/itemmodels/qidentityproxymodel.h | 25 | ||||
-rw-r--r-- | src/corelib/itemmodels/qidentityproxymodel_p.h | 52 | ||||
-rw-r--r-- | src/corelib/itemmodels/qitemselectionmodel.cpp | 118 | ||||
-rw-r--r-- | src/corelib/itemmodels/qitemselectionmodel.h | 21 | ||||
-rw-r--r-- | src/corelib/itemmodels/qitemselectionmodel_p.h | 34 | ||||
-rw-r--r-- | src/corelib/itemmodels/qsortfilterproxymodel.cpp | 211 | ||||
-rw-r--r-- | src/corelib/itemmodels/qsortfilterproxymodel.h | 22 | ||||
-rw-r--r-- | src/corelib/itemmodels/qstringlistmodel.cpp | 8 |
15 files changed, 548 insertions, 508 deletions
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp index ecac010edb..cd29f2fcc2 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.cpp +++ b/src/corelib/itemmodels/qabstractitemmodel.cpp @@ -19,6 +19,8 @@ #include <qdatetime.h> #include <qloggingcategory.h> +#include <functional> + #include <limits.h> QT_BEGIN_NAMESPACE @@ -210,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. @@ -380,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; @@ -397,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); } /*! @@ -475,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; @@ -489,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; @@ -684,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(); } @@ -1497,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} */ /*! @@ -1739,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. @@ -2538,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 @@ -3726,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 */ /*! @@ -3880,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 */ /*! @@ -4158,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 e56412241a..8f22f14989 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.h +++ b/src/corelib/itemmodels/qabstractitemmodel.h @@ -178,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(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; @@ -499,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/qabstractproxymodel.cpp b/src/corelib/itemmodels/qabstractproxymodel.cpp index 023587e39a..abdeefb4da 100644 --- a/src/corelib/itemmodels/qabstractproxymodel.cpp +++ b/src/corelib/itemmodels/qabstractproxymodel.cpp @@ -55,6 +55,41 @@ 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()) @@ -66,25 +101,16 @@ void QAbstractProxyModelPrivate::_q_sourceModelRowsInserted(const QModelIndex &p { if (parent.isValid()) return; - if (sourceHadZeroRows) { - Q_Q(QAbstractProxyModel); - const int columnCount = q->columnCount(); - if (columnCount > 0) - emit q->headerDataChanged(Qt::Horizontal, 0, columnCount - 1); - } + if (sourceHadZeroRows) + scheduleHeaderUpdate(Qt::Horizontal); } - void QAbstractProxyModelPrivate::_q_sourceModelRowsRemoved(const QModelIndex &parent, int, int) { if (parent.isValid()) return; - if (model->rowCount() == 0) { - Q_Q(QAbstractProxyModel); - const int columnCount = q->columnCount(); - if (columnCount > 0) - emit q->headerDataChanged(Qt::Horizontal, 0, columnCount - 1); - } + if (model->rowCount() == 0) + scheduleHeaderUpdate(Qt::Horizontal); } void QAbstractProxyModelPrivate::_q_sourceModelColumnsAboutToBeInserted(const QModelIndex &parent, int, int) @@ -98,24 +124,16 @@ void QAbstractProxyModelPrivate::_q_sourceModelColumnsInserted(const QModelIndex { if (parent.isValid()) return; - if (sourceHadZeroColumns) { - Q_Q(QAbstractProxyModel); - const int rowCount = q->rowCount(); - if (rowCount > 0) - emit q->headerDataChanged(Qt::Vertical, 0, rowCount - 1); - } + if (sourceHadZeroColumns) + scheduleHeaderUpdate(Qt::Vertical); } void QAbstractProxyModelPrivate::_q_sourceModelColumnsRemoved(const QModelIndex &parent, int, int) { if (parent.isValid()) return; - if (model->columnCount() == 0) { - Q_Q(QAbstractProxyModel); - const int rowCount = q->rowCount(); - if (rowCount > 0) - emit q->headerDataChanged(Qt::Vertical, 0, rowCount - 1); - } + if (model->columnCount() == 0) + scheduleHeaderUpdate(Qt::Vertical); } /*! @@ -159,31 +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; 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)) } + { 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 != d->model) { - if (d->model) { + if (sourceModel != currentModel) { + if (currentModel) { for (const auto &c : connectionTable) - disconnect(d->model, c.signalName, this, c.slotName); + disconnect(currentModel, c.signalName, this, c.slotName); } if (sourceModel) { d->model.setValueBypassingBindings(sourceModel); for (const auto &c : connectionTable) - connect(d->model, c.signalName, this, c.slotName); + connect(sourceModel, c.signalName, this, c.slotName); } else { d->model.setValueBypassingBindings(QAbstractItemModelPrivate::staticEmptyModel()); } diff --git a/src/corelib/itemmodels/qabstractproxymodel_p.h b/src/corelib/itemmodels/qabstractproxymodel_p.h index 678ec4804f..d33666d00b 100644 --- a/src/corelib/itemmodels/qabstractproxymodel_p.h +++ b/src/corelib/itemmodels/qabstractproxymodel_p.h @@ -16,6 +16,7 @@ // // +#include "qabstractproxymodel.h" #include "private/qabstractitemmodel_p.h" #include "private/qproperty_p.h" @@ -30,7 +31,9 @@ public: QAbstractProxyModelPrivate() : QAbstractItemModelPrivate(), sourceHadZeroRows(false), - sourceHadZeroColumns(false) + sourceHadZeroColumns(false), + updateVerticalHeader(false), + updateHorizontalHeader(false) {} void setModelForwarder(QAbstractItemModel *sourceModel) { @@ -57,8 +60,13 @@ public: 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 44cf28b47a..3a49d37cff 100644 --- a/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp +++ b/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp @@ -26,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; @@ -116,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(); @@ -208,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); @@ -226,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); @@ -292,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(); } /*! @@ -334,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 @@ -420,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; } /*! @@ -434,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(); @@ -472,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(); @@ -488,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 @@ -498,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 @@ -507,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 @@ -517,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 @@ -526,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 @@ -542,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); @@ -555,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 @@ -569,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); @@ -582,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()); @@ -599,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); @@ -621,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())) @@ -638,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(); @@ -662,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() @@ -688,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.size(); ++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; @@ -702,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(); @@ -714,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 3d924fb18b..9dbebd7b88 100644 --- a/src/corelib/itemmodels/qconcatenatetablesproxymodel.h +++ b/src/corelib/itemmodels/qconcatenatetablesproxymodel.h @@ -46,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 cc0730d769..89fa7e5c07 100644 --- a/src/corelib/itemmodels/qidentityproxymodel.cpp +++ b/src/corelib/itemmodels/qidentityproxymodel.cpp @@ -290,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); @@ -388,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); @@ -405,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); @@ -418,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); @@ -428,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); @@ -436,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); @@ -470,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); @@ -496,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); @@ -523,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); @@ -540,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); @@ -553,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 42b87d30a2..c8fc9d21b7 100644 --- a/src/corelib/itemmodels/qidentityproxymodel.h +++ b/src/corelib/itemmodels/qidentityproxymodel.h @@ -44,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 0aa0624ab0..78e1f5316c 100644 --- a/src/corelib/itemmodels/qidentityproxymodel_p.h +++ b/src/corelib/itemmodels/qidentityproxymodel_p.h @@ -33,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 _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 _q_sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList<int> &roles); - void _q_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 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 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 sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, + const QList<int> &roles); + void sourceHeaderDataChanged(Qt::Orientation orientation, int first, int last); + + 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 0f3cbadca5..6df60aaf61 100644 --- a/src/corelib/itemmodels/qitemselectionmodel.cpp +++ b/src/corelib/itemmodels/qitemselectionmodel.cpp @@ -27,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 @@ -216,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. */ @@ -238,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(); @@ -249,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); } } } @@ -432,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; @@ -550,52 +552,55 @@ void QItemSelection::split(const QItemSelectionRange &range, void QItemSelectionModelPrivate::initModel(QAbstractItemModel *m) { - static constexpr auto connections = qOffsetStringArray( - QT_STRINGIFY_SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - QT_STRINGIFY_SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)), - QT_STRINGIFY_SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - QT_STRINGIFY_SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)), - QT_STRINGIFY_SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - QT_STRINGIFY_SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int)), - QT_STRINGIFY_SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), - QT_STRINGIFY_SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int)), - QT_STRINGIFY_SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - QT_STRINGIFY_SLOT(_q_layoutAboutToBeChanged()), - QT_STRINGIFY_SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - QT_STRINGIFY_SLOT(_q_layoutAboutToBeChanged()), - QT_STRINGIFY_SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), - QT_STRINGIFY_SLOT(_q_layoutChanged()), - QT_STRINGIFY_SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), - QT_STRINGIFY_SLOT(_q_layoutChanged()), - QT_STRINGIFY_SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), - QT_STRINGIFY_SLOT(_q_layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), - QT_STRINGIFY_SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), - QT_STRINGIFY_SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), - QT_STRINGIFY_SIGNAL(modelReset()), - QT_STRINGIFY_SLOT(reset()), - QT_STRINGIFY_SIGNAL(destroyed(QObject*)), - QT_STRINGIFY_SLOT(_q_modelDestroyed()) - ); - - if (model == m) + Q_Q(QItemSelectionModel); + const QAbstractItemModel *oldModel = model.valueBypassingBindings(); + if (oldModel == m) return; - Q_Q(QItemSelectionModel); - if (model.value()) { - for (int i = 0; i < connections.count(); i += 2) - QObject::disconnect(model.value(), connections.at(i), q, connections.at(i + 1)); + if (oldModel) { q->reset(); + disconnectModel(); } // Caller has to call notify(), unless calling during construction (the common case). model.setValueBypassingBindings(m); - if (model.value()) { - for (int i = 0; i < connections.count(); i += 2) - QObject::connect(model.value(), connections.at(i), q, connections.at(i + 1)); + 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 @@ -638,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); @@ -721,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); @@ -758,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); @@ -788,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); @@ -829,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(); @@ -871,7 +877,7 @@ 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(); @@ -976,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 @@ -994,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) @@ -1078,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(); } @@ -1120,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 */ /*! @@ -1289,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()); @@ -1881,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(); } diff --git a/src/corelib/itemmodels/qitemselectionmodel.h b/src/corelib/itemmodels/qitemselectionmodel.h index 4237e7f74f..c4b8dadc97 100644 --- a/src/corelib/itemmodels/qitemselectionmodel.h +++ b/src/corelib/itemmodels/qitemselectionmodel.h @@ -57,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() @@ -74,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); @@ -165,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 f63526e8ae..689cd26bd2 100644 --- a/src/corelib/itemmodels/qitemselectionmodel_p.h +++ b/src/corelib/itemmodels/qitemselectionmodel_p.h @@ -15,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); @@ -35,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) { @@ -58,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) @@ -69,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 d067edea05..a9ead2e1eb 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp +++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp @@ -6,7 +6,6 @@ #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> @@ -16,7 +15,7 @@ QT_BEGIN_NAMESPACE -typedef QList<QPair<QModelIndex, QPersistentModelIndex>> QModelIndexPairList; +using QModelIndexPairList = QList<std::pair<QModelIndex, QPersistentModelIndex>>; struct QSortFilterProxyModelDataChanged { @@ -109,9 +108,9 @@ private: class QSortFilterProxyModelPrivate : public QAbstractProxyModelPrivate { +public: Q_DECLARE_PUBLIC(QSortFilterProxyModel) -public: enum class Direction { Rows = 1, Columns = 2, @@ -238,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( @@ -254,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); @@ -331,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, @@ -703,10 +704,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; @@ -723,19 +724,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; } @@ -764,7 +765,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, @@ -818,22 +819,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; @@ -879,7 +879,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; } @@ -907,7 +907,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; @@ -1136,7 +1136,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; @@ -1170,7 +1170,7 @@ 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); } } @@ -1227,7 +1227,7 @@ QModelIndexPairList QSortFilterProxyModelPrivate::store_persistent_indexes() con 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; } @@ -1265,7 +1265,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); } @@ -2006,7 +2006,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); } /*! @@ -2031,56 +2033,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(); @@ -2088,57 +2044,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(); @@ -2473,11 +2433,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); } /*! @@ -2485,11 +2441,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); } /*! @@ -2497,11 +2449,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); } /*! @@ -2620,11 +2568,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 @@ -2639,7 +2588,6 @@ void QSortFilterProxyModel::setFilterRegularExpression(const QRegularExpression d->filter_regularexpression.notify(); if (cs != updatedCs) d->filter_casesensitive.notify(); - Qt::endPropertyUpdateGroup(); } /*! @@ -2666,7 +2614,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) @@ -2715,7 +2663,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); @@ -2728,7 +2676,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() @@ -2965,7 +2912,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(); @@ -3004,7 +2951,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 bbd829d731..9d5b2fac9f 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.h +++ b/src/corelib/itemmodels/qsortfilterproxymodel.h @@ -172,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 002f500263..dfbe72b289 100644 --- a/src/corelib/itemmodels/qstringlistmodel.cpp +++ b/src/corelib/itemmodels/qstringlistmodel.cpp @@ -292,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; } @@ -309,11 +309,11 @@ void QStringListModel::sort(int, Qt::SortOrder order) { emit layoutAboutToBeChanged(QList<QPersistentModelIndex>(), VerticalSortHint); - QList<QPair<QString, int>> list; + 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); |