From da64a5079249ec04e4d3d6df2cc87ee69f66b977 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 8 Aug 2012 14:56:14 +0200 Subject: [PATCH] Only emit headerDataChanged for valid proxy intervals. Modeltest asserts before the patch, and passes afterward. Task-number: QTBUG-26515 Change-Id: I08a89cd5c9c59613badcddbd056a3d0b8fbbca13 Reviewed-by: Marc Mutz Reviewed-by: Stephen Kelly --- src/corelib/itemmodels/qsortfilterproxymodel.cpp | 42 ++++++++++++++++++---- .../tst_qsortfilterproxymodel.cpp | 35 ++++++++++++++++++ tests/auto/other/modeltest/modeltest.cpp | 29 ++++++++++++++- tests/auto/other/modeltest/modeltest.h | 2 ++ 4 files changed, 100 insertions(+), 8 deletions(-) diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp index fb84dce..7863dc6 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp +++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp @@ -1226,15 +1226,43 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc void QSortFilterProxyModelPrivate::_q_sourceHeaderDataChanged(Qt::Orientation orientation, int start, int end) { + Q_ASSERT(start <= end); + Q_Q(QSortFilterProxyModel); Mapping *m = create_mapping(QModelIndex()).value(); - int proxy_start = (orientation == Qt::Vertical - ? m->proxy_rows.at(start) - : m->proxy_columns.at(start)); - int proxy_end = (orientation == Qt::Vertical - ? m->proxy_rows.at(end) - : m->proxy_columns.at(end)); - emit q->headerDataChanged(orientation, proxy_start, proxy_end); + + const QVector &source_to_proxy = (orientation == Qt::Vertical) ? m->proxy_rows : m->proxy_columns; + + QVector proxy_positions; + proxy_positions.reserve(end - start + 1); + { + Q_ASSERT(source_to_proxy.size() > end); + QVector::const_iterator it = source_to_proxy.constBegin() + start; + const QVector::const_iterator endIt = source_to_proxy.constBegin() + end + 1; + for ( ; it != endIt; ++it) { + if (*it != -1) + proxy_positions.push_back(*it); + } + } + + qSort(proxy_positions); + + int last_index = 0; + const int numItems = proxy_positions.size(); + while (last_index < numItems) { + const int proxyStart = proxy_positions.at(last_index); + int proxyEnd = proxyStart; + ++last_index; + for (int i = last_index; i < numItems; ++i) { + if (proxy_positions.at(i) == proxyEnd + 1) { + ++last_index; + ++proxyEnd; + } else { + break; + } + } + emit q->headerDataChanged(orientation, proxyStart, proxyEnd); + } } void QSortFilterProxyModelPrivate::_q_sourceAboutToBeReset() diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp index 3770abb..444d26c 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp @@ -140,6 +140,7 @@ private slots: void testMultipleProxiesWithSelection(); void mapSelectionFromSource(); void filteredColumns(); + void headerDataChanged(); void testParentLayoutChanged(); void moveSourceRows(); @@ -3155,6 +3156,40 @@ void tst_QSortFilterProxyModel::filteredColumns() insertCommand->doCommand(); } +class ChangableHeaderData : public QStringListModel +{ + Q_OBJECT +public: + explicit ChangableHeaderData(QObject *parent = 0) + : QStringListModel(parent) + { + + } + + void emitHeaderDataChanged() + { + headerDataChanged(Qt::Vertical, 0, rowCount() - 1); + } +}; + + +void tst_QSortFilterProxyModel::headerDataChanged() +{ + ChangableHeaderData *model = new ChangableHeaderData(this); + + QStringList numbers; + for (int i = 0; i < 10; ++i) + numbers.append(QString::number(i)); + model->setStringList(numbers); + + QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this); + proxy->setSourceModel(model); + + new ModelTest(proxy, this); + + model->emitHeaderDataChanged(); +} + void tst_QSortFilterProxyModel::resetInvalidate_data() { QTest::addColumn("test"); diff --git a/tests/auto/other/modeltest/modeltest.cpp b/tests/auto/other/modeltest/modeltest.cpp index 98f6600..c204a74 100644 --- a/tests/auto/other/modeltest/modeltest.cpp +++ b/tests/auto/other/modeltest/modeltest.cpp @@ -80,7 +80,7 @@ ModelTest::ModelTest ( QAbstractItemModel *_model, QObject *parent ) : QObject ( connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ), this, SLOT ( runAllTests() ) ); - // Special checks for inserting/removing + // Special checks for changes connect ( model, SIGNAL ( layoutAboutToBeChanged() ), this, SLOT ( layoutAboutToBeChanged() ) ); connect ( model, SIGNAL ( layoutChanged() ), @@ -94,6 +94,10 @@ ModelTest::ModelTest ( QAbstractItemModel *_model, QObject *parent ) : QObject ( this, SLOT ( rowsInserted ( const QModelIndex &, int, int ) ) ); connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ), this, SLOT ( rowsRemoved ( const QModelIndex &, int, int ) ) ); + connect ( model, SIGNAL ( dataChanged ( const QModelIndex &, const QModelIndex & ) ), + this, SLOT ( dataChanged ( const QModelIndex &, const QModelIndex & ) ) ); + connect ( model, SIGNAL ( headerDataChanged ( Qt::Orientation, int, int ) ), + this, SLOT ( headerDataChanged ( Qt::Orientation, int, int ) ) ); runAllTests(); } @@ -561,4 +565,27 @@ void ModelTest::rowsRemoved ( const QModelIndex & parent, int start, int end ) QVERIFY( c.next == model->data ( model->index ( start, 0, c.parent ) ) ); } +void ModelTest::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) +{ + QVERIFY(topLeft.isValid()); + QVERIFY(bottomRight.isValid()); + QModelIndex commonParent = bottomRight.parent(); + QVERIFY(topLeft.parent() == commonParent); + QVERIFY(topLeft.row() <= bottomRight.row()); + QVERIFY(topLeft.column() <= bottomRight.column()); + int rowCount = model->rowCount(commonParent); + int columnCount = model->columnCount(commonParent); + QVERIFY(bottomRight.row() < rowCount); + QVERIFY(bottomRight.column() < columnCount); +} + +void ModelTest::headerDataChanged(Qt::Orientation orientation, int start, int end) +{ + QVERIFY(start >= 0); + QVERIFY(end >= 0); + QVERIFY(start <= end); + int itemCount = orientation == Qt::Vertical ? model->rowCount() : model->columnCount(); + QVERIFY(start < itemCount); + QVERIFY(end < itemCount); +} diff --git a/tests/auto/other/modeltest/modeltest.h b/tests/auto/other/modeltest/modeltest.h index 1b254a4..9c828db 100644 --- a/tests/auto/other/modeltest/modeltest.h +++ b/tests/auto/other/modeltest/modeltest.h @@ -71,6 +71,8 @@ protected Q_SLOTS: void rowsInserted( const QModelIndex & parent, int start, int end ); void rowsAboutToBeRemoved( const QModelIndex &parent, int start, int end ); void rowsRemoved( const QModelIndex & parent, int start, int end ); + void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + void headerDataChanged(Qt::Orientation orientation, int start, int end); private: void checkChildren( const QModelIndex &parent, int currentDepth = 0 ); -- 2.7.4