Hello community,

here is the log from the commit of package kitemmodels for openSUSE:Factory 
checked in at 2016-03-16 10:30:12
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kitemmodels (Old)
 and      /work/SRC/openSUSE:Factory/.kitemmodels.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kitemmodels"

Changes:
--------
--- /work/SRC/openSUSE:Factory/kitemmodels/kitemmodels.changes  2016-02-24 
18:55:49.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.kitemmodels.new/kitemmodels.changes     
2016-03-16 10:30:13.000000000 +0100
@@ -1,0 +2,18 @@
+Sun Mar  6 09:59:36 UTC 2016 - hrvoje.sen...@gmail.com
+
+- Update to 5.20.0 (boo#970856)
+  * KLinkItemSelectionModel: Add new default constructor
+  * KLinkItemSelectionModel: Make the linked selection
+    model settable
+  * KLinkItemSelectionModel: Handle changes to the
+    selectionModel model
+  * KLinkItemSelectionModel: Don't store model locally
+  * KSelectionProxyModel: Fix iteration bug
+  * Reset KSelectionProxyModel state when needed
+  * Add a property indicating whether the models form a
+    connected chain
+  * KModelIndexProxyMapper: Simplify logic of connected check
+  * For more details please see:
+    https://www.kde.org/announcements/kde-frameworks-5.20.0.php
+
+-------------------------------------------------------------------

Old:
----
  kitemmodels-5.19.0.tar.xz

New:
----
  kitemmodels-5.20.0.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kitemmodels.spec ++++++
--- /var/tmp/diff_new_pack.4xarMF/_old  2016-03-16 10:30:14.000000000 +0100
+++ /var/tmp/diff_new_pack.4xarMF/_new  2016-03-16 10:30:14.000000000 +0100
@@ -17,9 +17,9 @@
 
 
 %define lname   libKF5ItemModels5
-%define _tar_path 5.19
+%define _tar_path 5.20
 Name:           kitemmodels
-Version:        5.19.0
+Version:        5.20.0
 Release:        0
 BuildRequires:  cmake >= 2.8.12
 BuildRequires:  extra-cmake-modules >= %{_tar_path}

++++++ kitemmodels-5.19.0.tar.xz -> kitemmodels-5.20.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitemmodels-5.19.0/CMakeLists.txt 
new/kitemmodels-5.20.0/CMakeLists.txt
--- old/kitemmodels-5.19.0/CMakeLists.txt       2016-02-06 10:38:41.000000000 
+0100
+++ new/kitemmodels-5.20.0/CMakeLists.txt       2016-03-04 23:18:50.000000000 
+0100
@@ -3,7 +3,7 @@
 project(KItemModels)
 
 include(FeatureSummary)
-find_package(ECM 5.19.0  NO_MODULE)
+find_package(ECM 5.20.0  NO_MODULE)
 set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake 
Modules." URL 
"https://projects.kde.org/projects/kdesupport/extra-cmake-modules";)
 feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND 
FATAL_ON_MISSING_REQUIRED_PACKAGES)
 
@@ -23,7 +23,7 @@
 include(ECMSetupVersion)
 include(ECMGenerateHeaders)
 
-set(KF5_VERSION "5.19.0") # handled by release scripts
+set(KF5_VERSION "5.20.0") # handled by release scripts
 
 ecm_setup_version(${KF5_VERSION} VARIABLE_PREFIX KITEMMODELS
                         VERSION_HEADER 
"${CMAKE_CURRENT_BINARY_DIR}/kitemmodels_version.h"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitemmodels-5.19.0/autotests/CMakeLists.txt 
new/kitemmodels-5.20.0/autotests/CMakeLists.txt
--- old/kitemmodels-5.19.0/autotests/CMakeLists.txt     2016-02-06 
10:38:41.000000000 +0100
+++ new/kitemmodels-5.20.0/autotests/CMakeLists.txt     2016-03-04 
23:18:50.000000000 +0100
@@ -21,6 +21,7 @@
   klinkitemselectionmodeltest.cpp
   testmodelqueuedconnections.cpp
   kselectionproxymodeltest.cpp
+  kmodelindexproxymappertest.cpp
   krecursivefilterproxymodeltest.cpp
   krearrangecolumnsproxymodeltest.cpp
   LINK_LIBRARIES KF5::ItemModels Qt5::Test Qt5::Widgets proxymodeltestsuite
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kitemmodels-5.19.0/autotests/klinkitemselectionmodeltest.cpp 
new/kitemmodels-5.20.0/autotests/klinkitemselectionmodeltest.cpp
--- old/kitemmodels-5.19.0/autotests/klinkitemselectionmodeltest.cpp    
2016-02-06 10:38:41.000000000 +0100
+++ new/kitemmodels-5.20.0/autotests/klinkitemselectionmodeltest.cpp    
2016-03-04 23:18:50.000000000 +0100
@@ -23,6 +23,7 @@
 
 #include <QItemSelectionModel>
 #include <QSortFilterProxyModel>
+#include <QIdentityProxyModel>
 #include <QStandardItem>
 #include <QStandardItemModel>
 
@@ -105,5 +106,166 @@
     QCOMPARE(mainIndex, m_mainModel->index(m_mainModel->rowCount() - 1, 0));
 }
 
+void KLinkItemSelectionModelTest::testChangeModel()
+{
+#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
+    QVERIFY(m_mainSelectionModel->selection().isEmpty());
+
+    {
+    auto idx = m_mainModel->index(6, 0);
+    m_mainSelectionModel->select(idx, QItemSelectionModel::Select);
+    }
+
+    QVERIFY(!m_mainSelectionModel->selection().isEmpty());
+    QVERIFY(!m_subSelectionModel->selection().isEmpty());
+    QCOMPARE(m_mainSelectionModel->selection().indexes().first().row(), 6);
+    QCOMPARE(m_subSelectionModel->selection().indexes().first().row(), 1);
+
+    QIdentityProxyModel newIntermediateProxy;
+
+    newIntermediateProxy.setSourceModel(m_mainModel);
+
+    // Change the model of the KLinkItemSelectionModel
+    m_subSelectionModel->setModel(&newIntermediateProxy);
+
+    QVERIFY(m_mainSelectionModel->selection().isEmpty());
+    QVERIFY(m_subSelectionModel->selection().isEmpty());
+#endif
+}
+
+void KLinkItemSelectionModelTest::testChangeModelOfExternal()
+{
+#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
+    QVERIFY(m_mainSelectionModel->selection().isEmpty());
+
+    {
+    auto idx = m_mainModel->index(6, 0);
+    m_mainSelectionModel->select(idx, QItemSelectionModel::Select);
+    }
+
+    QVERIFY(!m_mainSelectionModel->selection().isEmpty());
+    QVERIFY(!m_subSelectionModel->selection().isEmpty());
+    QCOMPARE(m_mainSelectionModel->selection().indexes().first().row(), 6);
+    QCOMPARE(m_subSelectionModel->selection().indexes().first().row(), 1);
+
+    QIdentityProxyModel newIntermediateProxy;
+
+    newIntermediateProxy.setSourceModel(m_mainModel);
+
+    // Change the model of the external QISM
+    m_mainSelectionModel->setModel(&newIntermediateProxy);
+
+    QVERIFY(m_mainSelectionModel->selection().isEmpty());
+    QVERIFY(m_subSelectionModel->selection().isEmpty());
+#endif
+}
+
+void KLinkItemSelectionModelTest::testChangeLinkedSelectionModel()
+{
+    QVERIFY(m_mainSelectionModel->selection().isEmpty());
+
+    {
+    auto idx = m_mainModel->index(6, 0);
+    m_mainSelectionModel->select(idx, QItemSelectionModel::Select);
+    }
+
+    QVERIFY(!m_mainSelectionModel->selection().isEmpty());
+    QVERIFY(!m_subSelectionModel->selection().isEmpty());
+    QCOMPARE(m_mainSelectionModel->selection().indexes().first().row(), 6);
+    QCOMPARE(m_subSelectionModel->selection().indexes().first().row(), 1);
+
+    QItemSelectionModel replacementSelectionModel(m_mainModel, 0);
+    {
+    auto idx = m_mainModel->index(7, 0);
+    replacementSelectionModel.select(idx, QItemSelectionModel::Select);
+    }
+
+    
m_subSelectionModel->setLinkedItemSelectionModel(&replacementSelectionModel);
+
+    QVERIFY(!replacementSelectionModel.selection().isEmpty());
+    QVERIFY(!m_subSelectionModel->selection().isEmpty());
+    QCOMPARE(replacementSelectionModel.selection().indexes().first().row(), 7);
+    QCOMPARE(m_subSelectionModel->selection().indexes().first().row(), 2);
+}
+
+void KLinkItemSelectionModelTest::testAdditionalLink()
+{
+#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
+    {
+    auto idx = m_mainModel->index(6, 0);
+    m_mainSelectionModel->select(idx, QItemSelectionModel::Select);
+    }
+
+    QVERIFY(!m_mainSelectionModel->selection().isEmpty());
+    QVERIFY(!m_subSelectionModel->selection().isEmpty());
+    QCOMPARE(m_mainSelectionModel->selection().indexes().first().row(), 6);
+    QCOMPARE(m_subSelectionModel->selection().indexes().first().row(), 1);
+
+    {
+    QSortFilterProxyModel additionalProxy;
+    additionalProxy.setFilterRegExp(QRegExp(QStringLiteral("^[3-9]")));
+    additionalProxy.setSourceModel(m_mainModel);
+
+    KLinkItemSelectionModel additionalLink;
+    additionalLink.setModel(&additionalProxy);
+    additionalLink.setLinkedItemSelectionModel(m_mainSelectionModel);
+    QVERIFY(!additionalLink.selection().isEmpty());
+    QCOMPARE(additionalLink.selection().indexes().first().row(), 3);
+
+    auto idx = additionalProxy.index(4, 0);
+    QVERIFY(idx.isValid());
+    additionalLink.select(idx, QItemSelectionModel::ClearAndSelect);
+
+    QVERIFY(!additionalLink.selection().isEmpty());
+    QCOMPARE(additionalLink.selection().indexes().first().row(), 4);
+
+    QVERIFY(!m_mainSelectionModel->selection().isEmpty());
+    QVERIFY(!m_subSelectionModel->selection().isEmpty());
+    QCOMPARE(m_mainSelectionModel->selection().indexes().first().row(), 7);
+    QCOMPARE(m_subSelectionModel->selection().indexes().first().row(), 2);
+    }
+
+    QVERIFY(!m_mainSelectionModel->selection().isEmpty());
+    QVERIFY(!m_subSelectionModel->selection().isEmpty());
+    QCOMPARE(m_mainSelectionModel->selection().indexes().first().row(), 7);
+    QCOMPARE(m_subSelectionModel->selection().indexes().first().row(), 2);
+#endif
+}
+
+void KLinkItemSelectionModelTest::testClearSelection()
+{
+    QVERIFY(m_mainSelectionModel->selection().isEmpty());
+
+    {
+    auto idx = m_mainModel->index(6, 0);
+    m_mainSelectionModel->select(idx, QItemSelectionModel::Select);
+    }
+
+    QVERIFY(!m_mainSelectionModel->selection().isEmpty());
+    QVERIFY(!m_subSelectionModel->selection().isEmpty());
+    QCOMPARE(m_mainSelectionModel->selection().indexes().first().row(), 6);
+    QCOMPARE(m_subSelectionModel->selection().indexes().first().row(), 1);
+
+    m_subSelectionModel->clear();
+
+    QVERIFY(m_mainSelectionModel->selection().isEmpty());
+    QVERIFY(m_subSelectionModel->selection().isEmpty());
+
+    {
+    auto idx = m_mainModel->index(6, 0);
+    m_mainSelectionModel->select(idx, QItemSelectionModel::Select);
+    }
+
+    QVERIFY(!m_mainSelectionModel->selection().isEmpty());
+    QVERIFY(!m_subSelectionModel->selection().isEmpty());
+    QCOMPARE(m_mainSelectionModel->selection().indexes().first().row(), 6);
+    QCOMPARE(m_subSelectionModel->selection().indexes().first().row(), 1);
+
+    m_mainSelectionModel->clear();
+
+    QVERIFY(m_mainSelectionModel->selection().isEmpty());
+    QVERIFY(m_subSelectionModel->selection().isEmpty());
+}
+
 QTEST_MAIN(KLinkItemSelectionModelTest)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kitemmodels-5.19.0/autotests/klinkitemselectionmodeltest.h 
new/kitemmodels-5.20.0/autotests/klinkitemselectionmodeltest.h
--- old/kitemmodels-5.19.0/autotests/klinkitemselectionmodeltest.h      
2016-02-06 10:38:41.000000000 +0100
+++ new/kitemmodels-5.20.0/autotests/klinkitemselectionmodeltest.h      
2016-03-04 23:18:50.000000000 +0100
@@ -37,6 +37,11 @@
     void testToggle();
     void testMainSetCurrent();
     void testSubSetCurrent();
+    void testChangeModel();
+    void testChangeModelOfExternal();
+    void testChangeLinkedSelectionModel();
+    void testAdditionalLink();
+    void testClearSelection();
 
 private:
     QStandardItemModel *m_mainModel;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kitemmodels-5.19.0/autotests/kmodelindexproxymappertest.cpp 
new/kitemmodels-5.20.0/autotests/kmodelindexproxymappertest.cpp
--- old/kitemmodels-5.19.0/autotests/kmodelindexproxymappertest.cpp     
1970-01-01 01:00:00.000000000 +0100
+++ new/kitemmodels-5.20.0/autotests/kmodelindexproxymappertest.cpp     
2016-03-04 23:18:50.000000000 +0100
@@ -0,0 +1,208 @@
+/*
+    Copyright (c) 2016 Ableton AG <i...@ableton.com>
+        Author Stephen Kelly <stephen.ke...@ableton.com>
+
+    This library is free software; you can redistribute it and/or modify it
+    under the terms of the GNU Library General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or (at your
+    option) any later version.
+
+    This library is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+    License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to the
+    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+*/
+
+#include <QSignalSpy>
+#include <QTest>
+#include <QStringListModel>
+#include <QIdentityProxyModel>
+#include <QItemSelection>
+
+#include "kmodelindexproxymapper.h"
+
+class ModelIndexProxyMapperTest : public QObject
+{
+    Q_OBJECT
+private Q_SLOTS:
+
+    void init();
+
+    void testIndexMapping();
+    void testSelectionMapping();
+    void selfConnection();
+    void connectedChangedSimple();
+    void connectedChangedComplex();
+    void crossWires();
+    void isConnected();
+
+private:
+    QStringListModel baseModel;
+
+    QIdentityProxyModel proxy_common1;
+
+    QIdentityProxyModel proxy_left1;
+    QIdentityProxyModel proxy_left2;
+    QIdentityProxyModel proxy_left3;
+
+    QIdentityProxyModel proxy_right1;
+    QIdentityProxyModel proxy_right2;
+    QIdentityProxyModel proxy_right3;
+    QIdentityProxyModel proxy_right4;
+};
+
+void ModelIndexProxyMapperTest::init()
+{
+    baseModel.setStringList({"Monday", "Tuesday", "Wednesday"});
+
+    proxy_common1.setSourceModel(&baseModel);
+
+    proxy_left1.setSourceModel(&proxy_common1);
+    proxy_left2.setSourceModel(&proxy_left1);
+    proxy_left3.setSourceModel(&proxy_left2);
+
+    proxy_right1.setSourceModel(&proxy_common1);
+    proxy_right2.setSourceModel(&proxy_right1);
+    proxy_right3.setSourceModel(&proxy_right2);
+    proxy_right4.setSourceModel(&proxy_right3);
+}
+
+void ModelIndexProxyMapperTest::testIndexMapping()
+{
+    KModelIndexProxyMapper mapper(&proxy_left3, &proxy_right4);
+
+    auto leftIdx = proxy_left3.index(0, 0);
+    auto rightIdx = proxy_right4.index(0, 0);
+
+    QVERIFY(leftIdx.isValid());
+    QVERIFY(rightIdx.isValid());
+
+    QCOMPARE(mapper.mapLeftToRight(leftIdx), rightIdx);
+    QCOMPARE(mapper.mapRightToLeft(rightIdx), leftIdx);
+}
+
+void ModelIndexProxyMapperTest::testSelectionMapping()
+{
+    KModelIndexProxyMapper mapper(&proxy_left3, &proxy_right4);
+
+    auto leftIdx = proxy_left3.index(0, 0);
+    auto rightIdx = proxy_right4.index(0, 0);
+
+    auto leftSel = QItemSelection(leftIdx, leftIdx);
+    auto rightSel = QItemSelection(rightIdx, rightIdx);
+
+    QCOMPARE(leftSel.indexes().size(), 1);
+    QCOMPARE(rightSel.indexes().size(), 1);
+
+    QVERIFY(leftSel.indexes().first().isValid());
+    QVERIFY(rightSel.indexes().first().isValid());
+
+    QCOMPARE(mapper.mapSelectionLeftToRight(leftSel), rightSel);
+    QCOMPARE(mapper.mapSelectionRightToLeft(rightSel), leftSel);
+}
+
+void ModelIndexProxyMapperTest::selfConnection()
+{
+    KModelIndexProxyMapper mapper(&baseModel, &baseModel);
+    QVERIFY(mapper.isConnected());
+
+    auto idx = baseModel.index(0, 0);
+    QVERIFY(idx.isValid());
+
+    QCOMPARE(mapper.mapLeftToRight(idx), idx);
+}
+
+void ModelIndexProxyMapperTest::connectedChangedSimple()
+{
+    QIdentityProxyModel proxy1;
+    Q_SET_OBJECT_NAME(proxy1);
+
+    KModelIndexProxyMapper mapper(&proxy1, &baseModel);
+
+    QSignalSpy spy(&mapper, SIGNAL(isConnectedChanged()));
+
+    QVERIFY(!mapper.isConnected());
+    proxy1.setSourceModel(&baseModel);
+
+    QVERIFY(mapper.isConnected());
+    QCOMPARE(spy.count(), 1);
+}
+
+void ModelIndexProxyMapperTest::connectedChangedComplex()
+{
+    KModelIndexProxyMapper mapper(&proxy_left3, &proxy_right4);
+
+    QSignalSpy spy(&mapper, SIGNAL(isConnectedChanged()));
+
+    QVERIFY(mapper.isConnected());
+
+    proxy_right2.setSourceModel(Q_NULLPTR);
+
+    QVERIFY(!mapper.isConnected());
+    QCOMPARE(spy.count(), 1);
+
+    proxy_right2.setSourceModel(&proxy_right1);
+
+    QVERIFY(mapper.isConnected());
+    QCOMPARE(spy.count(), 2);
+
+    auto leftIdx = proxy_left3.index(0, 0);
+    QVERIFY(leftIdx.isValid());
+    auto rightIdx = mapper.mapLeftToRight(leftIdx);
+    QVERIFY(rightIdx.isValid());
+    QCOMPARE(mapper.mapRightToLeft(rightIdx), leftIdx);
+
+    QIdentityProxyModel replacement_right1;
+    replacement_right1.setSourceModel(&proxy_right1);
+    proxy_right2.setSourceModel(&replacement_right1);
+
+    QVERIFY(mapper.isConnected());
+    QCOMPARE(spy.count(), 2);
+}
+
+void ModelIndexProxyMapperTest::crossWires()
+{
+    KModelIndexProxyMapper mapper(&proxy_left3, &proxy_right4);
+
+    QSignalSpy spy(&mapper, SIGNAL(isConnectedChanged()));
+
+    QVERIFY(mapper.isConnected());
+
+    proxy_left3.setSourceModel(&proxy_right3);
+
+    QVERIFY(mapper.isConnected());
+    QCOMPARE(spy.count(), 0);
+
+    {
+    auto leftIdx = proxy_left3.index(0, 0);
+    auto rightIdx = proxy_right4.index(0, 0);
+    QCOMPARE(mapper.mapLeftToRight(leftIdx), rightIdx);
+    }
+
+    proxy_right4.setSourceModel(&proxy_left2);
+
+    QVERIFY(mapper.isConnected());
+    QCOMPARE(spy.count(), 0);
+
+    {
+    auto leftIdx = proxy_left3.index(0, 0);
+    auto rightIdx = proxy_right4.index(0, 0);
+    QCOMPARE(mapper.mapLeftToRight(leftIdx), rightIdx);
+    }
+}
+
+void ModelIndexProxyMapperTest::isConnected()
+{
+    KModelIndexProxyMapper mapper1(&proxy_left1, &baseModel);
+    QVERIFY(mapper1.isConnected());
+    KModelIndexProxyMapper mapper2(&baseModel, &proxy_left1);
+    QVERIFY(mapper2.isConnected());
+}
+
+QTEST_MAIN(ModelIndexProxyMapperTest)
+#include "kmodelindexproxymappertest.moc"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kitemmodels-5.19.0/autotests/kselectionproxymodeltest.cpp 
new/kitemmodels-5.20.0/autotests/kselectionproxymodeltest.cpp
--- old/kitemmodels-5.19.0/autotests/kselectionproxymodeltest.cpp       
2016-02-06 10:38:41.000000000 +0100
+++ new/kitemmodels-5.20.0/autotests/kselectionproxymodeltest.cpp       
2016-03-04 23:18:50.000000000 +0100
@@ -1,6 +1,8 @@
 /*
     Copyright (c) 2015 Stephen Kelly <steve...@gmail.com>
     Copyright (c) 2015 David Faure <fa...@kde.org>
+    Copyright (c) 2016 Ableton AG <i...@ableton.com>
+        Author Stephen Kelly <stephen.ke...@ableton.com>
 
     This library is free software; you can redistribute it and/or modify it
     under the terms of the GNU Library General Public License as published by
@@ -45,6 +47,7 @@
 private Q_SLOTS:
   void columnCountShouldBeStable();
   void selectOnSourceReset();
+  void selectionMapping();
 
 #if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
   void selectionModelModelChange();
@@ -134,7 +137,13 @@
     QStringLiteral("Tomorrow")
   });
 
+  QSignalSpy resetSpy(&proxy, &QAbstractItemModel::modelReset);
+
   selectionModel.setModel(&strings2);
+
+  QCOMPARE(resetSpy.size(), 1);
+  QCOMPARE(proxy.rowCount(), 0);
+
   proxy.setSourceModel(&strings2);
   selectionModel.select(strings2.index(0, 0), QItemSelectionModel::Select);
 
@@ -162,6 +171,25 @@
 }
 #endif
 
+void KSelectionProxyModelTest::selectionMapping()
+{
+    QStringListModel strings(days);
+    QItemSelectionModel selectionModel(&strings);
+    KSelectionProxyModel proxy(&selectionModel);
+    proxy.setFilterBehavior(KSelectionProxyModel::SubTrees);
+    proxy.setSourceModel(&strings);
+    auto idx1 = strings.index(0, 0);
+    auto idx2 = strings.index(2, 0);
+    QItemSelection sourceSel;
+    sourceSel << QItemSelectionRange(idx1, idx2);
+    selectionModel.select(sourceSel, QItemSelectionModel::Select);
+
+    QItemSelection proxySel;
+    proxySel << QItemSelectionRange(proxy.index(0, 0), proxy.index(2, 0));
+
+    QCOMPARE(proxy.mapSelectionToSource(proxySel), sourceSel);
+}
+
 QTEST_MAIN(KSelectionProxyModelTest)
 
 #include "kselectionproxymodeltest.moc"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitemmodels-5.19.0/src/klinkitemselectionmodel.cpp 
new/kitemmodels-5.20.0/src/klinkitemselectionmodel.cpp
--- old/kitemmodels-5.19.0/src/klinkitemselectionmodel.cpp      2016-02-06 
10:38:41.000000000 +0100
+++ new/kitemmodels-5.20.0/src/klinkitemselectionmodel.cpp      2016-03-04 
23:18:50.000000000 +0100
@@ -2,6 +2,8 @@
     Copyright (C) 2010 Klarälvdalens Datakonsult AB,
         a KDAB Group company, i...@kdab.net,
         author Stephen Kelly <step...@kdab.com>
+    Copyright (c) 2016 Ableton AG <i...@ableton.com>
+        Author Stephen Kelly <stephen.ke...@ableton.com>
 
     This library is free software; you can redistribute it and/or modify it
     under the terms of the GNU Library General Public License as published by
@@ -29,14 +31,20 @@
 class KLinkItemSelectionModelPrivate
 {
 public:
-    KLinkItemSelectionModelPrivate(KLinkItemSelectionModel 
*proxySelectionModel, QAbstractItemModel *model,
-                                   QItemSelectionModel 
*linkedItemSelectionModel)
+    KLinkItemSelectionModelPrivate(KLinkItemSelectionModel 
*proxySelectionModel)
         : q_ptr(proxySelectionModel),
-          m_model(model),
-          m_linkedItemSelectionModel(linkedItemSelectionModel),
+          m_linkedItemSelectionModel(Q_NULLPTR),
           m_ignoreCurrentChanged(false),
-          m_indexMapper(new KModelIndexProxyMapper(model, 
linkedItemSelectionModel->model(), proxySelectionModel))
+          m_indexMapper(Q_NULLPTR)
     {
+        QObject::connect(q_ptr, &QItemSelectionModel::currentChanged, q_ptr,
+            [this](const QModelIndex& idx) { slotCurrentChanged(idx); } );
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
+        QObject::connect(q_ptr, &QItemSelectionModel::modelChanged, q_ptr, 
[this] {
+            reinitializeIndexMapper();
+        });
+#endif
     }
 
     Q_DECLARE_PUBLIC(KLinkItemSelectionModel)
@@ -53,23 +61,43 @@
         return true;
     }
 
+    void reinitializeIndexMapper()
+    {
+        delete m_indexMapper;
+        m_indexMapper = Q_NULLPTR;
+        if (!q_ptr->model()
+                || !m_linkedItemSelectionModel
+                || !m_linkedItemSelectionModel->model()) {
+            return;
+        }
+        m_indexMapper = new KModelIndexProxyMapper(
+            q_ptr->model(),
+            m_linkedItemSelectionModel->model(),
+            q_ptr);
+        const QItemSelection mappedSelection = 
m_indexMapper->mapSelectionRightToLeft(m_linkedItemSelectionModel->selection());
+        q_ptr->QItemSelectionModel::select(mappedSelection, 
QItemSelectionModel::ClearAndSelect);
+    }
+
     void sourceSelectionChanged(const QItemSelection &selected, const 
QItemSelection &deselected);
     void sourceCurrentChanged(const QModelIndex &current);
     void slotCurrentChanged(const QModelIndex &current);
 
-    QAbstractItemModel *const m_model;
-    QItemSelectionModel *const m_linkedItemSelectionModel;
+    QItemSelectionModel *m_linkedItemSelectionModel;
     bool m_ignoreCurrentChanged;
-    KModelIndexProxyMapper *const m_indexMapper;
+    KModelIndexProxyMapper * m_indexMapper;
 };
 
 KLinkItemSelectionModel::KLinkItemSelectionModel(QAbstractItemModel *model, 
QItemSelectionModel *proxySelector, QObject *parent)
     : QItemSelectionModel(model, parent),
-      d_ptr(new KLinkItemSelectionModelPrivate(this, model, proxySelector))
+      d_ptr(new KLinkItemSelectionModelPrivate(this))
+{
+    setLinkedItemSelectionModel(proxySelector);
+}
+
+KLinkItemSelectionModel::KLinkItemSelectionModel(QObject *parent)
+    : QItemSelectionModel(Q_NULLPTR, parent),
+      d_ptr(new KLinkItemSelectionModelPrivate(this))
 {
-    connect(proxySelector, 
SIGNAL(selectionChanged(QItemSelection,QItemSelection)), 
SLOT(sourceSelectionChanged(QItemSelection,QItemSelection)));
-    connect(proxySelector, SIGNAL(currentChanged(QModelIndex,QModelIndex)), 
SLOT(sourceCurrentChanged(QModelIndex)));
-    connect(this, SIGNAL(currentChanged(QModelIndex,QModelIndex)), 
SLOT(slotCurrentChanged(QModelIndex)));
 }
 
 KLinkItemSelectionModel::~KLinkItemSelectionModel()
@@ -77,6 +105,38 @@
     delete d_ptr;
 }
 
+QItemSelectionModel *KLinkItemSelectionModel::linkedItemSelectionModel() const
+{
+    Q_D(const KLinkItemSelectionModel);
+    return d->m_linkedItemSelectionModel;
+}
+
+void KLinkItemSelectionModel::setLinkedItemSelectionModel(QItemSelectionModel 
*selectionModel)
+{
+    Q_D(KLinkItemSelectionModel);
+    if (d->m_linkedItemSelectionModel != selectionModel) {
+
+        if (d->m_linkedItemSelectionModel) {
+            disconnect(d->m_linkedItemSelectionModel);
+        }
+
+        d->m_linkedItemSelectionModel = selectionModel;
+
+        if (d->m_linkedItemSelectionModel) {
+            connect(d->m_linkedItemSelectionModel, 
SIGNAL(selectionChanged(QItemSelection,QItemSelection)), 
SLOT(sourceSelectionChanged(QItemSelection,QItemSelection)));
+            connect(d->m_linkedItemSelectionModel, 
SIGNAL(currentChanged(QModelIndex,QModelIndex)), 
SLOT(sourceCurrentChanged(QModelIndex)));
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
+            connect(d->m_linkedItemSelectionModel, 
&QItemSelectionModel::modelChanged, this, [this] {
+                d_ptr->reinitializeIndexMapper();
+            });
+#endif
+        }
+        d->reinitializeIndexMapper();
+        Q_EMIT linkedItemSelectionModelChanged();
+    }
+}
+
 void KLinkItemSelectionModel::select(const QModelIndex &index, 
QItemSelectionModel::SelectionFlags command)
 {
     Q_D(KLinkItemSelectionModel);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitemmodels-5.19.0/src/klinkitemselectionmodel.h 
new/kitemmodels-5.20.0/src/klinkitemselectionmodel.h
--- old/kitemmodels-5.19.0/src/klinkitemselectionmodel.h        2016-02-06 
10:38:41.000000000 +0100
+++ new/kitemmodels-5.20.0/src/klinkitemselectionmodel.h        2016-03-04 
23:18:50.000000000 +0100
@@ -2,6 +2,8 @@
     Copyright (C) 2010 Klarälvdalens Datakonsult AB,
         a KDAB Group company, i...@kdab.net,
         author Stephen Kelly <step...@kdab.com>
+    Copyright (c) 2016 Ableton AG <i...@ableton.com>
+        Author Stephen Kelly <stephen.ke...@ableton.com>
 
     This library is free software; you can redistribute it and/or modify it
     under the terms of the GNU Library General Public License as published by
@@ -95,15 +97,27 @@
 class KITEMMODELS_EXPORT KLinkItemSelectionModel : public QItemSelectionModel
 {
     Q_OBJECT
+    Q_PROPERTY(QItemSelectionModel *linkedItemSelectionModel READ 
linkedItemSelectionModel
+        WRITE setLinkedItemSelectionModel NOTIFY 
linkedItemSelectionModelChanged)
 public:
     /**
       Constructor.
     */
     KLinkItemSelectionModel(QAbstractItemModel *targetModel, 
QItemSelectionModel *linkedItemSelectionModel, QObject *parent = 0);
+
+    explicit KLinkItemSelectionModel(QObject *parent = Q_NULLPTR);
+
     ~KLinkItemSelectionModel();
+
+    QItemSelectionModel *linkedItemSelectionModel() const;
+    void setLinkedItemSelectionModel(QItemSelectionModel *selectionModel);
+
     void select(const QModelIndex &index, QItemSelectionModel::SelectionFlags 
command) Q_DECL_OVERRIDE;
     void select(const QItemSelection &selection, 
QItemSelectionModel::SelectionFlags command) Q_DECL_OVERRIDE;
 
+Q_SIGNALS:
+    void linkedItemSelectionModelChanged();
+
 protected:
     KLinkItemSelectionModelPrivate *const d_ptr;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitemmodels-5.19.0/src/kmodelindexproxymapper.cpp 
new/kitemmodels-5.20.0/src/kmodelindexproxymapper.cpp
--- old/kitemmodels-5.19.0/src/kmodelindexproxymapper.cpp       2016-02-06 
10:38:41.000000000 +0100
+++ new/kitemmodels-5.20.0/src/kmodelindexproxymapper.cpp       2016-03-04 
23:18:50.000000000 +0100
@@ -2,6 +2,8 @@
     Copyright (C) 2010 Klarälvdalens Datakonsult AB,
         a KDAB Group company, i...@kdab.net,
         author Stephen Kelly <step...@kdab.com>
+    Copyright (c) 2016 Ableton AG <i...@ableton.com>
+        Author Stephen Kelly <stephen.ke...@ableton.com>
 
     This library is free software; you can redistribute it and/or modify it
     under the terms of the GNU Library General Public License as published by
@@ -30,13 +32,14 @@
 class KModelIndexProxyMapperPrivate
 {
     KModelIndexProxyMapperPrivate(const QAbstractItemModel *leftModel, const 
QAbstractItemModel *rightModel, KModelIndexProxyMapper *qq)
-        : q_ptr(qq), m_leftModel(leftModel), m_rightModel(rightModel)
+        : q_ptr(qq), m_leftModel(leftModel), m_rightModel(rightModel), 
mConnected(false)
     {
         createProxyChain();
     }
 
     void createProxyChain();
-    bool assertValid();
+    void checkConnected();
+    void setConnected(bool connected);
 
     bool assertSelectionValid(const QItemSelection &selection) const
     {
@@ -57,6 +60,8 @@
 
     QPointer<const QAbstractItemModel> m_leftModel;
     QPointer<const QAbstractItemModel> m_rightModel;
+
+    bool mConnected;
 };
 
 /*
@@ -97,25 +102,28 @@
 
 void KModelIndexProxyMapperPrivate::createProxyChain()
 {
-    QPointer<const QAbstractItemModel> targetModel = m_rightModel;
-
-    if (!targetModel) {
-        return;
+    Q_FOREACH (auto p, m_proxyChainUp) {
+        p->disconnect(q_ptr);
     }
-
-    if (m_leftModel == targetModel) {
-        return;
+    Q_FOREACH (auto p, m_proxyChainDown) {
+        p->disconnect(q_ptr);
     }
+    m_proxyChainUp.clear();
+    m_proxyChainDown.clear();
+    QPointer<const QAbstractItemModel> targetModel = m_rightModel;
 
     QList<QPointer<const QAbstractProxyModel> > proxyChainDown;
     QPointer<const QAbstractProxyModel> selectionTargetProxyModel = 
qobject_cast<const QAbstractProxyModel *>(targetModel);
     while (selectionTargetProxyModel) {
         proxyChainDown.prepend(selectionTargetProxyModel);
+        QObject::connect(selectionTargetProxyModel.data(), 
&QAbstractProxyModel::sourceModelChanged, q_ptr,
+            [this]{ createProxyChain(); });
 
         selectionTargetProxyModel = qobject_cast<const QAbstractProxyModel 
*>(selectionTargetProxyModel->sourceModel());
 
         if (selectionTargetProxyModel == m_leftModel) {
             m_proxyChainDown = proxyChainDown;
+            checkConnected();
             return;
         }
     }
@@ -125,6 +133,8 @@
 
     while (sourceProxyModel) {
         m_proxyChainUp.append(sourceProxyModel);
+        QObject::connect(sourceProxyModel.data(), 
&QAbstractProxyModel::sourceModelChanged, q_ptr,
+            [this]{ createProxyChain(); });
 
         sourceProxyModel = qobject_cast<const QAbstractProxyModel 
*>(sourceProxyModel->sourceModel());
 
@@ -132,25 +142,28 @@
 
         if (targetIndex != -1) {
             m_proxyChainDown = proxyChainDown.mid(targetIndex + 1, 
proxyChainDown.size());
+            checkConnected();
             return;
         }
     }
     m_proxyChainDown = proxyChainDown;
-    Q_ASSERT(assertValid());
+    checkConnected();
+}
+
+void KModelIndexProxyMapperPrivate::checkConnected()
+{
+    auto konamiRight = m_proxyChainUp.isEmpty() ? m_leftModel : 
m_proxyChainUp.last()->sourceModel();
+    auto konamiLeft = m_proxyChainDown.isEmpty() ? m_rightModel : 
m_proxyChainDown.first()->sourceModel();
+    setConnected(konamiLeft && (konamiLeft == konamiRight));
 }
 
-bool KModelIndexProxyMapperPrivate::assertValid()
+void KModelIndexProxyMapperPrivate::setConnected(bool connected)
 {
-    if (m_proxyChainDown.isEmpty()) {
-        Q_ASSERT(!m_proxyChainUp.isEmpty());
-        Q_ASSERT(m_proxyChainUp.last()->sourceModel() == m_rightModel);
-    } else if (m_proxyChainUp.isEmpty()) {
-        Q_ASSERT(!m_proxyChainDown.isEmpty());
-        Q_ASSERT(m_proxyChainDown.first()->sourceModel() == m_leftModel);
-    } else {
-        Q_ASSERT(m_proxyChainDown.first()->sourceModel() == 
m_proxyChainUp.last()->sourceModel());
+    if (mConnected != connected) {
+        Q_Q(KModelIndexProxyMapper);
+        mConnected = connected;
+        Q_EMIT q->isConnectedChanged();
     }
-    return true;
 }
 
 KModelIndexProxyMapper::KModelIndexProxyMapper(const QAbstractItemModel 
*leftModel, const QAbstractItemModel *rightModel, QObject *parent)
@@ -210,7 +223,7 @@
 {
     Q_D(const KModelIndexProxyMapper);
 
-    if (selection.isEmpty()) {
+    if (selection.isEmpty() || !d->mConnected) {
         return QItemSelection();
     }
 
@@ -228,7 +241,10 @@
         if (!proxy) {
             return QItemSelection();
         }
+
+        Q_ASSERT(seekSelection.isEmpty() || seekSelection.first().model() == 
proxy);
         seekSelection = proxy->mapSelectionToSource(seekSelection);
+        Q_ASSERT(seekSelection.isEmpty() || seekSelection.first().model() == 
proxy->sourceModel());
 
 #ifdef RANGE_FIX_HACK
         seekSelection = removeInvalidRanges(seekSelection);
@@ -243,7 +259,9 @@
         if (!proxy) {
             return QItemSelection();
         }
+        Q_ASSERT(seekSelection.isEmpty() || seekSelection.first().model() == 
proxy->sourceModel());
         seekSelection = proxy->mapSelectionFromSource(seekSelection);
+        Q_ASSERT(seekSelection.isEmpty() || seekSelection.first().model() == 
proxy);
 
 #ifdef RANGE_FIX_HACK
         seekSelection = removeInvalidRanges(seekSelection);
@@ -259,7 +277,7 @@
 {
     Q_D(const KModelIndexProxyMapper);
 
-    if (selection.isEmpty()) {
+    if (selection.isEmpty() || !d->mConnected) {
         return QItemSelection();
     }
 
@@ -306,3 +324,8 @@
     return seekSelection;
 }
 
+bool KModelIndexProxyMapper::isConnected() const
+{
+    Q_D(const KModelIndexProxyMapper);
+    return d->mConnected;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitemmodels-5.19.0/src/kmodelindexproxymapper.h 
new/kitemmodels-5.20.0/src/kmodelindexproxymapper.h
--- old/kitemmodels-5.19.0/src/kmodelindexproxymapper.h 2016-02-06 
10:38:41.000000000 +0100
+++ new/kitemmodels-5.20.0/src/kmodelindexproxymapper.h 2016-03-04 
23:18:50.000000000 +0100
@@ -2,6 +2,8 @@
     Copyright (C) 2010 Klarälvdalens Datakonsult AB,
         a KDAB Group company, i...@kdab.net,
         author Stephen Kelly <step...@kdab.com>
+    Copyright (c) 2016 Ableton AG <i...@ableton.com>
+        Author Stephen Kelly <stephen.ke...@ableton.com>
 
     This library is free software; you can redistribute it and/or modify it
     under the terms of the GNU Library General Public License as published by
@@ -73,12 +75,22 @@
  *   Proxy 2   Proxy 4
  * @endverbatim
  *
+ * The isConnected property indicates whether there is a
+ * path from the left side to the right side.
+ *
  * @author Stephen Kelly <steve...@gmail.com>
  *
  */
 class KITEMMODELS_EXPORT KModelIndexProxyMapper : public QObject
 {
     Q_OBJECT
+
+    /**
+     * Indicates whether there is a chain that can be followed from leftModel 
to rightModel.
+     *
+     * This value can change if the sourceModel of an intermediate proxy is 
changed.
+     */
+    Q_PROPERTY(bool isConnected READ isConnected NOTIFY isConnectedChanged)
 public:
     /**
      * Constructor
@@ -107,6 +119,11 @@
      */
     QItemSelection mapSelectionRightToLeft(const QItemSelection &selection) 
const;
 
+    bool isConnected() const;
+
+Q_SIGNALS:
+    void isConnectedChanged();
+
 private:
     //@cond PRIVATE
     Q_DECLARE_PRIVATE(KModelIndexProxyMapper)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitemmodels-5.19.0/src/kselectionproxymodel.cpp 
new/kitemmodels-5.20.0/src/kselectionproxymodel.cpp
--- old/kitemmodels-5.19.0/src/kselectionproxymodel.cpp 2016-02-06 
10:38:41.000000000 +0100
+++ new/kitemmodels-5.20.0/src/kselectionproxymodel.cpp 2016-03-04 
23:18:50.000000000 +0100
@@ -1,5 +1,7 @@
 /*
     Copyright (c) 2009 Stephen Kelly <steve...@gmail.com>
+    Copyright (c) 2016 Ableton AG <i...@ableton.com>
+        Author Stephen Kelly <stephen.ke...@ableton.com>
 
     This library is free software; you can redistribute it and/or modify it
     under the terms of the GNU Library General Public License as published by
@@ -2466,6 +2468,7 @@
                     SLOT(selectionChanged(QItemSelection,QItemSelection)));
 
             auto handleSelectionModelModel = [ &, d] {
+                beginResetModel();
                 if (d->selectionModelModelAboutToBeResetConnection)
                 {
                     disconnect(d->selectionModelModelAboutToBeResetConnection);
@@ -2482,7 +2485,11 @@
                     d->selectionModelModelResetConnection = connect(
                         d->m_selectionModel->model(),
                         SIGNAL(modelReset()), this, SLOT(sourceModelReset()));
+                    d->m_rootIndexList.clear();
+                    delete d->m_indexMapper;
+                    d->m_indexMapper = new 
KModelIndexProxyMapper(sourceModel(), d->m_selectionModel->model(), this);
                 }
+                endResetModel();
             };
 #if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
             connect(d->m_selectionModel.data(), 
&QItemSelectionModel::modelChanged,
@@ -2651,7 +2658,7 @@
                 const QModelIndex sourceIdx = mapToSource(idx);
                 Q_ASSERT(sourceIdx.isValid());
                 topSelection.append(QItemSelectionRange(sourceTopLeft, 
sourceIdx));
-                for (int i = it->top() + 1; i < it->bottom(); ++it) {
+                for (int i = it->top() + 1; i <= it->bottom(); ++i) {
                     const QModelIndex left = mapToSource(createIndex(i, 0));
                     const QModelIndex right = mapToSource(createIndex(i, 
it->right()));
                     Q_ASSERT(left.isValid());


Reply via email to