From 2cf77cc6154d4e902514dd7e9a13ee86c0d2c99b Mon Sep 17 00:00:00 2001
From: Olivier Goffart <ogoffart@trolltech.com>
Date: Tue, 2 Feb 2010 13:46:09 +0100
Subject: QSortFilterProxyModel: Fix dynamic sorting when severals rows are
 added.

We need to update the sorting column in clear_mapping.
But the problem is that updating the source column create a mapping
(because it uses mapToSource). So we need to clear that wrong mapping again

In _q_sourceLayoutChanged there was an uneeded special case.
The case where the source_sort_column might change was never triggered
because of that. So now that the special case has been removed, we need
to do as in clear_mapping.

The test cover the change in clear_mapping and in _q_sourceLayoutChanged

The problem was shown in the Kopete: https://bugs.kde.org/show_bug.cgi?id=199850

Reviewed-by: Thierry
Task-number: QTBUG-7537
(cherry picked from commit 7b96944a02991e404cdab61e24182b90f5849120)
---
 src/gui/itemviews/qsortfilterproxymodel.cpp        | 16 +++--
 .../tst_qsortfilterproxymodel.cpp                  | 69 ++++++++++++++++++++++
 2 files changed, 79 insertions(+), 6 deletions(-)

diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp
index 359d801..20cb79f 100644
--- a/src/gui/itemviews/qsortfilterproxymodel.cpp
+++ b/src/gui/itemviews/qsortfilterproxymodel.cpp
@@ -270,6 +270,11 @@ void QSortFilterProxyModelPrivate::clear_mapping()
 
     qDeleteAll(source_index_mapping);
     source_index_mapping.clear();
+    if (dynamic_sortfilter && update_source_sort_column()) {
+        //update_source_sort_column might have created wrong mapping so we have to clear it again
+        qDeleteAll(source_index_mapping);
+        source_index_mapping.clear();
+    }
 
     // update the persistent indexes
     update_persistent_indexes(source_indexes);
@@ -1208,11 +1213,6 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutAboutToBeChanged()
 void QSortFilterProxyModelPrivate::_q_sourceLayoutChanged()
 {
     Q_Q(QSortFilterProxyModel);
-    if (saved_persistent_indexes.isEmpty()) {
-        clear_mapping();
-        emit q->layoutChanged();
-        return;
-    }
 
     qDeleteAll(source_index_mapping);
     source_index_mapping.clear();
@@ -1220,7 +1220,11 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutChanged()
     update_persistent_indexes(saved_persistent_indexes);
     saved_persistent_indexes.clear();
 
-    update_source_sort_column();
+    if (dynamic_sortfilter && update_source_sort_column()) {
+        //update_source_sort_column might have created wrong mapping so we have to clear it again
+        qDeleteAll(source_index_mapping);
+        source_index_mapping.clear();
+    }
 
     emit q->layoutChanged();
 }
diff --git a/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
index 8a8ff83..7c5160f 100644
--- a/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
+++ b/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
@@ -136,6 +136,7 @@ private slots:
     void task252507_mapFromToSource();
     void task255652_removeRowsRecursive();
     void taskQTBUG_6205_doubleProxySelectionSetSourceModel();
+    void taskQTBUG_7537_appearsAndSort();
 
 protected:
     void buildHierarchy(const QStringList &data, QAbstractItemModel *model);
@@ -2852,5 +2853,73 @@ void tst_QSortFilterProxyModel::taskQTBUG_6205_doubleProxySelectionSetSourceMode
     QVERIFY(ism.selection().isEmpty());
 }
 
+void tst_QSortFilterProxyModel::taskQTBUG_7537_appearsAndSort()
+{
+    class PModel : public QSortFilterProxyModel
+    {
+        public:
+            PModel() : mVisible(false) {};
+        protected:
+            bool filterAcceptsRow(int, const QModelIndex &) const
+            {
+                return mVisible;
+            }
+
+        public:
+            void updateXX()
+            {
+                mVisible = true;
+                invalidate();
+            }
+        private:
+            bool mVisible;
+    } proxyModel;
+
+
+    QStringListModel sourceModel;
+    QStringList list;
+    list << "b" << "a" << "c";
+    sourceModel.setStringList(list);
+
+    proxyModel.setSourceModel(&sourceModel);
+    proxyModel.setDynamicSortFilter(true);
+    proxyModel.sort(0, Qt::AscendingOrder);
+
+    QApplication::processEvents();
+    QCOMPARE(sourceModel.rowCount(), 3);
+    QCOMPARE(proxyModel.rowCount(), 0); //all rows are hidden at first;
+
+    QSignalSpy spyAbout1(&proxyModel, SIGNAL(layoutAboutToBeChanged()));
+    QSignalSpy spyChanged1(&proxyModel, SIGNAL(layoutChanged()));
+
+    //introducing secondProxyModel to test the layoutChange when many items appears at once
+    QSortFilterProxyModel secondProxyModel;
+    secondProxyModel.setSourceModel(&proxyModel);
+    secondProxyModel.setDynamicSortFilter(true);
+    secondProxyModel.sort(0, Qt::DescendingOrder);
+    QCOMPARE(secondProxyModel.rowCount(), 0); //all rows are hidden at first;
+    QSignalSpy spyAbout2(&secondProxyModel, SIGNAL(layoutAboutToBeChanged()));
+    QSignalSpy spyChanged2(&secondProxyModel, SIGNAL(layoutChanged()));
+
+    proxyModel.updateXX();
+    QApplication::processEvents();
+    //now rows should be visible, and sorted
+    QCOMPARE(proxyModel.rowCount(), 3);
+    QCOMPARE(proxyModel.data(proxyModel.index(0,0), Qt::DisplayRole).toString(), QString::fromLatin1("a"));
+    QCOMPARE(proxyModel.data(proxyModel.index(1,0), Qt::DisplayRole).toString(), QString::fromLatin1("b"));
+    QCOMPARE(proxyModel.data(proxyModel.index(2,0), Qt::DisplayRole).toString(), QString::fromLatin1("c"));
+
+    //now rows should be visible, and sorted
+    QCOMPARE(secondProxyModel.rowCount(), 3);
+    QCOMPARE(secondProxyModel.data(secondProxyModel.index(0,0), Qt::DisplayRole).toString(), QString::fromLatin1("c"));
+    QCOMPARE(secondProxyModel.data(secondProxyModel.index(1,0), Qt::DisplayRole).toString(), QString::fromLatin1("b"));
+    QCOMPARE(secondProxyModel.data(secondProxyModel.index(2,0), Qt::DisplayRole).toString(), QString::fromLatin1("a"));
+
+    QCOMPARE(spyAbout1.count(), 1);
+    QCOMPARE(spyChanged1.count(), 1);
+    QCOMPARE(spyAbout2.count(), 1);
+    QCOMPARE(spyChanged2.count(), 1);
+}
+
 QTEST_MAIN(tst_QSortFilterProxyModel)
 #include "tst_qsortfilterproxymodel.moc"
-- 
cgit v0.12