Branch 'kolab/integration/4.13.0' - korganizer/akonadicollectionview.cpp korganizer/views

Sandro Knauß knauss at kolabsys.com
Mon Oct 13 17:41:53 CEST 2014


 korganizer/akonadicollectionview.cpp                           |    2 
 korganizer/views/collectionview/controller.cpp                 |   46 
 korganizer/views/collectionview/controller.h                   |    2 
 korganizer/views/collectionview/reparentingmodel.cpp           |   41 
 korganizer/views/collectionview/reparentingmodel.h             |    1 
 korganizer/views/collectionview/tests/CMakeLists.txt           |    1 
 korganizer/views/collectionview/tests/modeltest.cpp            |  651 ++++++++++
 korganizer/views/collectionview/tests/modeltest.h              |   80 +
 korganizer/views/collectionview/tests/reparentingmodeltest.cpp |   77 +
 9 files changed, 860 insertions(+), 41 deletions(-)

New commits:
commit 4a8d069f7b32b4381202a05828c0573af0cfb2aa
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Mon Oct 13 17:38:33 2014 +0200

    Make it possible to update personnodes for the reparenting model
    
    * show subcols again
    * add tests to make sure that update works
    
    KOLAB: #3743

diff --git a/korganizer/akonadicollectionview.cpp b/korganizer/akonadicollectionview.cpp
index 0de456e..8b12286 100644
--- a/korganizer/akonadicollectionview.cpp
+++ b/korganizer/akonadicollectionview.cpp
@@ -351,7 +351,7 @@ class CollectionFilter : public QSortFilterProxyModel
         const Akonadi::Collection &col = sourceIndex.data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
         CollectionIdentificationAttribute *attr = col.attribute<CollectionIdentificationAttribute>();
         //We filter the user folders because we insert person nodes for user folders.
-        if ( (attr && attr->collectionNamespace().startsWith("user"))
+        if ( (attr && attr->collectionNamespace().startsWith("usertoplevel"))
                 || col.name().contains(QLatin1String("Other Users"))) {
             return false;
         }
diff --git a/korganizer/views/collectionview/controller.cpp b/korganizer/views/collectionview/controller.cpp
index 7c83a3c..d2b903f 100644
--- a/korganizer/views/collectionview/controller.cpp
+++ b/korganizer/views/collectionview/controller.cpp
@@ -110,7 +110,6 @@ bool CollectionNode::isDuplicateOf(const QModelIndex& sourceIndex)
     return (sourceIndex.data(Akonadi::EntityTreeModel::CollectionIdRole).value<Akonadi::Collection::Id>() == mCollection.id());
 }
 
-
 PersonNode::PersonNode(ReparentingModel& personModel, const Person& person, const QModelIndex &colIndex)
 :   Node(personModel),
     mPerson(person),
@@ -121,7 +120,6 @@ PersonNode::PersonNode(ReparentingModel& personModel, const Person& person, cons
 
 }
 
-
 PersonNode::~PersonNode()
 {
 
@@ -223,46 +221,48 @@ bool PersonNode::isDuplicateOf(const QModelIndex& sourceIndex)
     return (sourceIndex.data(PersonRole).value<Person>().uid == mPerson.uid);
 }
 
-void PersonNodeManager::checkSourceIndex(const QModelIndex &sourceIndex)
+Person PersonNodeManager::person(const QModelIndex &sourceIndex)
 {
+    Person person;
     const Akonadi::Collection col = sourceIndex.data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
-    // kDebug() << col.displayName() << col.enabled();
     if (col.isValid()) {
         CollectionIdentificationAttribute *attr = col.attribute<CollectionIdentificationAttribute>();
         if (attr && attr->collectionNamespace() == "usertoplevel") {
-            kDebug() << "Found user folder, creating person node " << col.displayName();
-            Person person;
             person.name = col.displayName();
             person.mail = QString::fromUtf8(attr->mail());
             person.ou = QString::fromUtf8(attr->ou());
             person.uid = col.name();
             person.rootCollection = col.id();
-
-            model.addNode(ReparentingModel::Node::Ptr(new PersonNode(model, person, sourceIndex)));
         }
     }
+    return person;
 }
 
-void PersonNodeManager::checkSourceIndexRemoval(const QModelIndex &sourceIndex)
+void PersonNodeManager::checkSourceIndex(const QModelIndex &sourceIndex)
 {
-    const Akonadi::Collection col = sourceIndex.data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
-    // kDebug() << col.displayName() << col.enabled();
-    if (col.isValid()) {
-        CollectionIdentificationAttribute *attr = col.attribute<CollectionIdentificationAttribute>();
-        if (attr && attr->collectionNamespace() == "usertoplevel") {
-            kDebug() << "Found user folder, removing person node " << col.displayName();
-            Person person;
-            person.name = col.displayName();
-            person.mail = QString::fromUtf8(attr->mail());
-            person.ou = QString::fromUtf8(attr->ou());
-            person.uid = col.name();
-            person.rootCollection = col.id();
-            model.removeNode(PersonNode(model, person, sourceIndex));
-        }
+    const Person &p = person(sourceIndex);
+    if (p.rootCollection > -1) {
+        model.addNode(ReparentingModel::Node::Ptr(new PersonNode(model, p, sourceIndex)));
+    }
+}
+
+void PersonNodeManager::updateSourceIndex(const QModelIndex &sourceIndex)
+{
+    const Person &p = person(sourceIndex);
+    if (p.rootCollection > -1) {
+        model.updateNode(ReparentingModel::Node::Ptr(new PersonNode(model, p, sourceIndex)));
     }
 }
 
 
+void PersonNodeManager::checkSourceIndexRemoval(const QModelIndex &sourceIndex)
+{
+    const Person &p = person(sourceIndex);
+    if (p.rootCollection > -1) {
+        model.removeNode(PersonNode(model, p, sourceIndex));
+    }
+}
+
 CollectionSearchJob::CollectionSearchJob(const QString& searchString, QObject* parent)
     : KJob(parent),
     mSearchString(searchString)
diff --git a/korganizer/views/collectionview/controller.h b/korganizer/views/collectionview/controller.h
index 0f404a0..c7ea03b 100644
--- a/korganizer/views/collectionview/controller.h
+++ b/korganizer/views/collectionview/controller.h
@@ -133,8 +133,10 @@ class PersonNodeManager : public ReparentingModel::NodeManager
 public:
     PersonNodeManager(ReparentingModel &personModel) : ReparentingModel::NodeManager(personModel){};
 private:
+    Person person(const QModelIndex &sourceIndex);
     void checkSourceIndex(const QModelIndex &sourceIndex);
     void checkSourceIndexRemoval(const QModelIndex &sourceIndex);
+    void updateSourceIndex(const QModelIndex &sourceIndex);
 };
 
 class CollectionSearchJob : public KJob
diff --git a/korganizer/views/collectionview/reparentingmodel.cpp b/korganizer/views/collectionview/reparentingmodel.cpp
index 824f31c..5ef1c89 100644
--- a/korganizer/views/collectionview/reparentingmodel.cpp
+++ b/korganizer/views/collectionview/reparentingmodel.cpp
@@ -279,7 +279,13 @@ void ReparentingModel::updateNode(const ReparentingModel::Node::Ptr &node)
     Q_FOREACH(const ReparentingModel::Node::Ptr &existing, mProxyNodes) {
         if (*existing == *node) {
             node->parent = existing->parent;
+            node->children = existing->children;
+            Q_FOREACH(ReparentingModel::Node::Ptr child, existing->children) {
+                child->parent = node.data();
+            }
+            node->sourceIndex = existing->sourceIndex;
             int r = row(existing.data());
+            mProxyNodes.replace(mProxyNodes.indexOf(existing), node);
             existing->parent->children.replace(r, node);
             const QModelIndex i = index(node.data());
             Q_ASSERT(i.row() == r);
@@ -468,7 +474,7 @@ void ReparentingModel::onSourceRowsInserted(QModelIndex parent, int start, int e
             Q_ASSERT(validateNode(parentNode));
         }
         Q_ASSERT(parentNode);
-        
+
         //Remove any duplicates that we are going to replace
         removeDuplicates(sourceIndex);
 
@@ -588,9 +594,8 @@ void ReparentingModel::onSourceLayoutChanged()
 void ReparentingModel::onSourceDataChanged(QModelIndex begin, QModelIndex end)
 {
     for (int row = begin.row(); row <= end.row(); row++) {
-        mNodeManager->checkSourceIndex(sourceModel()->index(row, begin.column(), begin.parent()));
+        mNodeManager->updateSourceIndex(sourceModel()->index(row, begin.column(), begin.parent()));
     }
-    emit dataChanged(mapFromSource(begin), mapFromSource(end));
 }
 
 void ReparentingModel::onSourceModelAboutToBeReset()
@@ -614,6 +619,9 @@ ReparentingModel::Node *ReparentingModel::extractNode(const QModelIndex &index)
 
 QModelIndex ReparentingModel::index(int row, int column, const QModelIndex& parent) const
 {
+    if (row < 0 || column != 0) {
+        return QModelIndex();
+    }
     // kDebug() << parent << row;
     const Node *parentNode;
     if (parent.isValid()) {
@@ -623,7 +631,7 @@ QModelIndex ReparentingModel::index(int row, int column, const QModelIndex& pare
     }
     //At least QAbstractItemView expects that we deal with this properly (see rowsAboutToBeRemoved "find the next visible and enabled item")
     //Also QAbstractItemModel::match does all kinds of weird shit including passing row=-1
-    if (parentNode->children.size() <= row || row < 0) {
+    if (parentNode->children.size() <= row) {
         return QModelIndex();
     }
     Node *node = parentNode->children.at(row).data();
@@ -709,15 +717,14 @@ void ReparentingModel::reparentSourceNodes(const Node::Ptr &proxyNode)
     //Reparent source nodes according to the provided rules
     Q_FOREACH(Node *n, mSourceNodes) {
         if (proxyNode->adopts(n->sourceIndex)) {
-            const int oldRow = n->sourceIndex.row();
-            beginRemoveRows(index(n->parent), oldRow, oldRow);
-            //We lie about the row being removed already, but the view can deal with that better than if we call endRemoveRows after beginInsertRows
-            endRemoveRows();
-
+            //kDebug() << "reparenting" << n->data(Qt::DisplayRole).toString() << "from" << n->parent->data(Qt::DisplayRole).toString()
+            //         << "to" << proxyNode->data(Qt::DisplayRole).toString();
+            const int oldRow = row(n);
             const int newRow = proxyNode->children.size();
-            beginInsertRows(index(proxyNode.data()), newRow, newRow);
+            beginMoveRows(index(n->parent), oldRow, oldRow,
+                          index(proxyNode.data()), newRow);
             proxyNode->reparent(n);
-            endInsertRows();
+            endMoveRows();
             Q_ASSERT(validateNode(n));
         }
     }
@@ -745,7 +752,9 @@ void ReparentingModel::rebuildAll()
 
 QVariant ReparentingModel::data(const QModelIndex& proxyIndex, int role) const
 {
-    Q_ASSERT(proxyIndex.isValid());
+    if (!proxyIndex.isValid()) {
+        return QVariant();
+    }
     const Node *node = extractNode(proxyIndex);
     if (node->isSourceNode()) {
         return sourceModel()->data(mapToSource(proxyIndex), role);
@@ -755,6 +764,9 @@ QVariant ReparentingModel::data(const QModelIndex& proxyIndex, int role) const
 
 bool ReparentingModel::setData(const QModelIndex& index, const QVariant& value, int role)
 {
+    if (!index.isValid()) {
+        return false;
+    }
     Q_ASSERT(index.isValid());
     if (!sourceModel()) {
         return false;
@@ -831,6 +843,11 @@ int ReparentingModel::rowCount(const QModelIndex& parent) const
     if (!parent.isValid()) {
         return mRootNode.children.size();
     }
+
+    if (parent.column() != 0) {
+        return 0;
+    }
+
     Node *node = extractNode(parent);
     return node->children.size();
 }
diff --git a/korganizer/views/collectionview/reparentingmodel.h b/korganizer/views/collectionview/reparentingmodel.h
index 4f88c84..ff66a4b 100644
--- a/korganizer/views/collectionview/reparentingmodel.h
+++ b/korganizer/views/collectionview/reparentingmodel.h
@@ -79,6 +79,7 @@ public:
         //Allows the implementation to create proxy nodes as necessary
         virtual void checkSourceIndex(const QModelIndex &/* sourceIndex */){};
         virtual void checkSourceIndexRemoval(const QModelIndex &/* sourceIndex */){};
+        virtual void updateSourceIndex(const QModelIndex & sourceIndex ){checkSourceIndex(sourceIndex);};
     };
 
 public:
diff --git a/korganizer/views/collectionview/tests/CMakeLists.txt b/korganizer/views/collectionview/tests/CMakeLists.txt
index 1053df8..ddfa073 100644
--- a/korganizer/views/collectionview/tests/CMakeLists.txt
+++ b/korganizer/views/collectionview/tests/CMakeLists.txt
@@ -5,6 +5,7 @@ include_directories(
 set(reparentingmodeltest_SRCS
     reparentingmodeltest.cpp
     ../reparentingmodel.cpp
+    modeltest.cpp
 )
 
 kde4_add_unit_test(reparentingmodeltest NOGUI ${reparentingmodeltest_SRCS})
diff --git a/korganizer/views/collectionview/tests/modeltest.cpp b/korganizer/views/collectionview/tests/modeltest.cpp
new file mode 100644
index 0000000..25022d2
--- /dev/null
+++ b/korganizer/views/collectionview/tests/modeltest.cpp
@@ -0,0 +1,651 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 Trolltech ASA. All rights reserved.
+**
+** This file is part of the Qt Concurrent project on Trolltech Labs.
+**
+** This file may be used under the terms of the GNU General Public
+** License version 2.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of
+** this file.  Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+** http://www.trolltech.com/products/qt/opensource.html
+**
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://www.trolltech.com/products/qt/licensing.html or contact the
+** sales department at sales at trolltech.com.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+//krazy:excludeall=style
+
+#include "modeltest.h"
+
+#include <QtGui>
+
+Q_DECLARE_METATYPE ( QModelIndex )
+
+/*!
+    Connect to all of the models signals.  Whenever anything happens recheck everything.
+*/
+ModelTest::ModelTest ( QAbstractItemModel *_model, QObject *parent ) : QObject ( parent ), model ( _model ), fetchingMore ( false )
+{
+    Q_ASSERT ( model );
+
+    connect ( model, SIGNAL (columnsAboutToBeInserted(QModelIndex,int,int)),
+              this, SLOT (runAllTests()) );
+    connect ( model, SIGNAL (columnsAboutToBeRemoved(QModelIndex,int,int)),
+              this, SLOT (runAllTests()) );
+    connect ( model, SIGNAL (columnsInserted(QModelIndex,int,int)),
+              this, SLOT (runAllTests()) );
+    connect ( model, SIGNAL (columnsRemoved(QModelIndex,int,int)),
+              this, SLOT (runAllTests()) );
+    connect ( model, SIGNAL (dataChanged(QModelIndex,QModelIndex)),
+              this, SLOT (runAllTests()) );
+    connect ( model, SIGNAL (headerDataChanged(Qt::Orientation,int,int)),
+              this, SLOT (runAllTests()) );
+    connect ( model, SIGNAL (layoutAboutToBeChanged()), this, SLOT (runAllTests()) );
+    connect ( model, SIGNAL (layoutChanged()), this, SLOT (runAllTests()) );
+    connect ( model, SIGNAL (modelReset()), this, SLOT (runAllTests()) );
+    connect ( model, SIGNAL (modelAboutToBeReset()), this, SLOT (modelAboutToBeReset()) );
+    connect ( model, SIGNAL (modelReset()), this, SLOT (modelReset()) );
+    connect ( model, SIGNAL (rowsAboutToBeInserted(QModelIndex,int,int)),
+              this, SLOT (runAllTests()) );
+    connect ( model, SIGNAL (rowsAboutToBeRemoved(QModelIndex,int,int)),
+              this, SLOT (runAllTests()) );
+    connect ( model, SIGNAL (rowsInserted(QModelIndex,int,int)),
+              this, SLOT (runAllTests()) );
+    connect ( model, SIGNAL (rowsRemoved(QModelIndex,int,int)),
+              this, SLOT (runAllTests()) );
+
+    // Special checks for inserting/removing
+    connect ( model, SIGNAL (layoutAboutToBeChanged()),
+              this, SLOT (layoutAboutToBeChanged()) );
+    connect ( model, SIGNAL (layoutChanged()),
+              this, SLOT (layoutChanged()) );
+
+    connect ( model, SIGNAL (rowsAboutToBeInserted(QModelIndex,int,int)),
+              this, SLOT (rowsAboutToBeInserted(QModelIndex,int,int)) );
+    connect ( model, SIGNAL (rowsAboutToBeRemoved(QModelIndex,int,int)),
+              this, SLOT (rowsAboutToBeRemoved(QModelIndex,int,int)) );
+    connect ( model, SIGNAL (rowsInserted(QModelIndex,int,int)),
+              this, SLOT (rowsInserted(QModelIndex,int,int)) );
+    connect ( model, SIGNAL (rowsRemoved(QModelIndex,int,int)),
+              this, SLOT (rowsRemoved(QModelIndex,int,int)) );
+
+    connect ( model, SIGNAL (rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
+              this, SLOT (rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)) );
+    connect ( model, SIGNAL (rowsMoved(QModelIndex,int,int,QModelIndex,int)),
+              this, SLOT (rowsMoved(QModelIndex,int,int,QModelIndex,int)) );
+
+    runAllTests();
+}
+
+void ModelTest::runAllTests()
+{
+
+    qDebug() << "runAllTests";
+    if ( fetchingMore )
+        return;
+    nonDestructiveBasicTest();
+    rowCount();
+    columnCount();
+    hasIndex();
+    index();
+    parent();
+    data();
+}
+
+/*!
+    nonDestructiveBasicTest tries to call a number of the basic functions (not all)
+    to make sure the model doesn't outright segfault, testing the functions that makes sense.
+*/
+void ModelTest::nonDestructiveBasicTest()
+{
+    Q_ASSERT ( model->buddy ( QModelIndex() ) == QModelIndex() );
+//     model->canFetchMore ( QModelIndex() );
+    Q_ASSERT ( model->columnCount ( QModelIndex() ) >= 0 );
+    Q_ASSERT ( model->data ( QModelIndex() ) == QVariant() );
+//     fetchingMore = true;
+//     model->fetchMore ( QModelIndex() );
+//     fetchingMore = false;
+    Qt::ItemFlags flags = model->flags ( QModelIndex() );
+    Q_ASSERT ( flags == Qt::ItemIsDropEnabled || flags == 0 );
+    Q_UNUSED( flags );
+    model->hasChildren ( QModelIndex() );
+    model->hasIndex ( 0, 0 );
+    model->headerData ( 0, Qt::Horizontal );
+    model->index ( 0, 0 );
+    model->itemData ( QModelIndex() );
+    QVariant cache;
+    model->match ( QModelIndex(), -1, cache );
+    model->mimeTypes();
+    Q_ASSERT ( model->parent ( QModelIndex() ) == QModelIndex() );
+    Q_ASSERT ( model->rowCount() >= 0 );
+    QVariant variant;
+    model->setData ( QModelIndex(), variant, -1 );
+    model->setHeaderData ( -1, Qt::Horizontal, QVariant() );
+    model->setHeaderData ( 999999, Qt::Horizontal, QVariant() );
+    QMap<int, QVariant> roles;
+    model->sibling ( 0, 0, QModelIndex() );
+    model->span ( QModelIndex() );
+    model->supportedDropActions();
+}
+
+/*!
+    Tests model's implementation of QAbstractItemModel::rowCount() and hasChildren()
+
+    Models that are dynamically populated are not as fully tested here.
+ */
+void ModelTest::rowCount()
+{
+//     qDebug() << "rc";
+    // check top row
+    QModelIndex topIndex = model->index ( 0, 0, QModelIndex() );
+    int rows = model->rowCount ( topIndex );
+    Q_ASSERT ( rows >= 0 );
+    if ( rows > 0 )
+        Q_ASSERT ( model->hasChildren ( topIndex ) == true );
+
+    QModelIndex secondLevelIndex = model->index ( 0, 0, topIndex );
+    if ( secondLevelIndex.isValid() ) { // not the top level
+        // check a row count where parent is valid
+        rows = model->rowCount ( secondLevelIndex );
+        Q_ASSERT ( rows >= 0 );
+        if ( rows > 0 )
+            Q_ASSERT ( model->hasChildren ( secondLevelIndex ) == true );
+    }
+
+    // The models rowCount() is tested more extensively in checkChildren(),
+    // but this catches the big mistakes
+}
+
+/*!
+    Tests model's implementation of QAbstractItemModel::columnCount() and hasChildren()
+ */
+void ModelTest::columnCount()
+{
+    // check top row
+    QModelIndex topIndex = model->index ( 0, 0, QModelIndex() );
+    Q_ASSERT ( model->columnCount ( topIndex ) >= 0 );
+
+    // check a column count where parent is valid
+    QModelIndex childIndex = model->index ( 0, 0, topIndex );
+    if ( childIndex.isValid() )
+        Q_ASSERT ( model->columnCount ( childIndex ) >= 0 );
+
+    // columnCount() is tested more extensively in checkChildren(),
+    // but this catches the big mistakes
+}
+
+/*!
+    Tests model's implementation of QAbstractItemModel::hasIndex()
+ */
+void ModelTest::hasIndex()
+{
+//     qDebug() << "hi";
+    // Make sure that invalid values returns an invalid index
+    Q_ASSERT ( model->hasIndex ( -2, -2 ) == false );
+    Q_ASSERT ( model->hasIndex ( -2, 0 ) == false );
+    Q_ASSERT ( model->hasIndex ( 0, -2 ) == false );
+
+    int rows = model->rowCount();
+    int columns = model->columnCount();
+
+    // check out of bounds
+    Q_ASSERT ( model->hasIndex ( rows, columns ) == false );
+    Q_ASSERT ( model->hasIndex ( rows + 1, columns + 1 ) == false );
+
+    Q_UNUSED( columns );
+
+    if ( rows > 0 )
+        Q_ASSERT ( model->hasIndex ( 0, 0 ) == true );
+
+    // hasIndex() is tested more extensively in checkChildren(),
+    // but this catches the big mistakes
+}
+
+/*!
+    Tests model's implementation of QAbstractItemModel::index()
+ */
+void ModelTest::index()
+{
+//     qDebug() << "i";
+    // Make sure that invalid values returns an invalid index
+    Q_ASSERT ( model->index ( -2, -2 ) == QModelIndex() );
+    Q_ASSERT ( model->index ( -2, 0 ) == QModelIndex() );
+    Q_ASSERT ( model->index ( 0, -2 ) == QModelIndex() );
+
+    int rows = model->rowCount();
+    int columns = model->columnCount();
+
+    if ( rows == 0 )
+        return;
+
+    // Catch off by one errors
+    Q_ASSERT ( model->index ( rows, columns ) == QModelIndex() );
+    Q_ASSERT ( model->index ( 0, 0 ).isValid() == true );
+
+    Q_UNUSED( columns );
+
+    // Make sure that the same index is *always* returned
+    QModelIndex a = model->index ( 0, 0 );
+    QModelIndex b = model->index ( 0, 0 );
+    Q_ASSERT ( a == b );
+
+    // index() is tested more extensively in checkChildren(),
+    // but this catches the big mistakes
+}
+
+/*!
+    Tests model's implementation of QAbstractItemModel::parent()
+ */
+void ModelTest::parent()
+{
+//     qDebug() << "p";
+    // Make sure the model wont crash and will return an invalid QModelIndex
+    // when asked for the parent of an invalid index.
+    Q_ASSERT ( model->parent ( QModelIndex() ) == QModelIndex() );
+
+    if ( model->rowCount() == 0 )
+        return;
+
+    // Column 0                | Column 1    |
+    // QModelIndex()           |             |
+    //    \- topIndex          | topIndex1   |
+    //         \- childIndex   | childIndex1 |
+
+    // Common error test #1, make sure that a top level index has a parent
+    // that is a invalid QModelIndex.
+    QModelIndex topIndex = model->index ( 0, 0, QModelIndex() );
+    Q_ASSERT ( model->parent ( topIndex ) == QModelIndex() );
+
+    // Common error test #2, make sure that a second level index has a parent
+    // that is the first level index.
+    if ( model->rowCount ( topIndex ) > 0 ) {
+        QModelIndex childIndex = model->index ( 0, 0, topIndex );
+        Q_ASSERT ( model->parent ( childIndex ) == topIndex );
+    }
+
+    // Common error test #3, the second column should NOT have the same children
+    // as the first column in a row.
+    // Usually the second column shouldn't have children.
+    QModelIndex topIndex1 = model->index ( 0, 1, QModelIndex() );
+    if ( model->rowCount ( topIndex1 ) > 0 ) {
+        QModelIndex childIndex = model->index ( 0, 0, topIndex );
+        QModelIndex childIndex1 = model->index ( 0, 0, topIndex1 );
+        Q_ASSERT ( childIndex != childIndex1 );
+    }
+
+    // Full test, walk n levels deep through the model making sure that all
+    // parent's children correctly specify their parent.
+    checkChildren ( QModelIndex() );
+}
+
+/*!
+    Called from the parent() test.
+
+    A model that returns an index of parent X should also return X when asking
+    for the parent of the index.
+
+    This recursive function does pretty extensive testing on the whole model in an
+    effort to catch edge cases.
+
+    This function assumes that rowCount(), columnCount() and index() already work.
+    If they have a bug it will point it out, but the above tests should have already
+    found the basic bugs because it is easier to figure out the problem in
+    those tests then this one.
+ */
+void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth )
+{
+    // First just try walking back up the tree.
+    QModelIndex p = parent;
+    while ( p.isValid() )
+        p = p.parent();
+
+    // For models that are dynamically populated
+//     if ( model->canFetchMore ( parent ) ) {
+//         fetchingMore = true;
+//         model->fetchMore ( parent );
+//         fetchingMore = false;
+//     }
+
+    int rows = model->rowCount ( parent );
+    int columns = model->columnCount ( parent );
+
+    //qDebug() << "checkChildren" << "parent=" << model->data ( parent ).value<QString>()
+    //<< "current count of parent=" << rows << "columns=" << columns;
+    QString indent= QLatin1String("");
+    for (int i=0; i<currentDepth; i++) {
+        indent += QLatin1String("    ");
+    }
+    qDebug() << QString(indent+QLatin1String("+")).toUtf8() << model->data ( parent ).value<QString>();
+
+    if ( rows > 0 )
+    {
+
+      Q_ASSERT(parent.column() <= 0);
+        Q_ASSERT ( model->hasChildren ( parent ) );
+    }
+
+    // Some further testing against rows(), columns(), and hasChildren()
+    Q_ASSERT ( rows >= 0 );
+    Q_ASSERT ( columns >= 0 );
+    if ( rows > 0 )
+        Q_ASSERT ( model->hasChildren ( parent ) == true );
+
+    //qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows
+    //         << "columns:" << columns << "parent column:" << parent.column();
+
+    Q_ASSERT ( model->hasIndex ( rows, 0, parent ) == false );
+    Q_ASSERT ( model->index(rows, 0, parent).isValid() == false );
+    for ( int r = 0; r < rows; ++r ) {
+//         if ( model->canFetchMore ( parent ) ) {
+//             fetchingMore = true;
+//             model->fetchMore ( parent );
+//             fetchingMore = false;
+//         }
+        Q_ASSERT ( model->hasIndex ( r, columns, parent ) == false );
+        Q_ASSERT ( model->index(r, columns, parent).isValid() == false );
+        for ( int c = 0; c < columns; ++c ) {
+            Q_ASSERT ( model->hasIndex ( r, c, parent ) == true );
+            QModelIndex index = model->index ( r, c, parent );
+            // rowCount() and columnCount() said that it existed...
+            Q_ASSERT ( index.isValid() == true );
+
+            // index() should always return the same index when called twice in a row
+            QModelIndex modifiedIndex = model->index ( r, c, parent );
+            Q_ASSERT ( index == modifiedIndex );
+
+            // Make sure we get the same index if we request it twice in a row
+            QModelIndex a = model->index ( r, c, parent );
+            QModelIndex b = model->index ( r, c, parent );
+            Q_ASSERT ( a == b );
+
+            // Some basic checking on the index that is returned
+            Q_ASSERT ( index.model() == model );
+            Q_ASSERT ( index.row() == r );
+            Q_ASSERT ( index.column() == c );
+            // While you can technically return a QVariant usually this is a sign
+            // of an bug in data()  Disable if this really is ok in your model.
+            //qDebug() << index << index.data() << index.parent();
+            Q_ASSERT ( model->data ( index, Qt::DisplayRole ).isValid() == true );
+
+            // If the next test fails here is some somewhat useful debug you play with.
+            /*
+            if (model->parent(index) != parent) {
+                qDebug() << r << c << currentDepth << model->data(index).toString()
+                         << model->data(parent).toString();
+                qDebug() << index << parent << model->parent(index);
+                // And a view that you can even use to show the model.
+                //QTreeView view;
+                //view.setModel(model);
+                //view.show();
+            }*/
+
+            // Check that we can get back our real parent.
+            Q_ASSERT ( model->parent ( index ) == parent );
+
+            // recursively go down the children
+            if ( model->hasChildren ( index ) && currentDepth < 10 ) {
+                //qDebug() << r << c << "has children" << model->rowCount(index);
+                checkChildren ( index, currentDepth+1 );
+                //qDebug() << "----";
+            }/* else { if (currentDepth >= 10) qDebug() << "checked 10 deep"; };*/
+            else {  qDebug() << QString(indent+QLatin1String("    |---")).toUtf8() << model->data ( index ).value<QString>(); }
+
+            // make sure that after testing the children that the index doesn't change.
+            QModelIndex newerIndex = model->index ( r, c, parent );
+            Q_ASSERT ( index == newerIndex );
+        }
+    }
+}
+
+/*!
+    Tests model's implementation of QAbstractItemModel::data()
+ */
+void ModelTest::data()
+{
+    // Invalid index should return an invalid qvariant
+    Q_ASSERT ( !model->data ( QModelIndex() ).isValid() );
+
+    if ( model->rowCount() == 0 )
+        return;
+
+    // A valid index should have a valid QVariant data
+    Q_ASSERT ( model->index ( 0, 0 ).isValid() );
+
+    // shouldn't be able to set data on an invalid index
+    Q_ASSERT ( model->setData ( QModelIndex(), QLatin1String ( "foo" ), Qt::DisplayRole ) == false );
+
+    // General Purpose roles that should return a QString
+    QVariant variant = model->data ( model->index ( 0, 0 ), Qt::ToolTipRole );
+    if ( variant.isValid() ) {
+        Q_ASSERT ( qVariantCanConvert<QString> ( variant ) );
+    }
+    variant = model->data ( model->index ( 0, 0 ), Qt::StatusTipRole );
+    if ( variant.isValid() ) {
+        Q_ASSERT ( qVariantCanConvert<QString> ( variant ) );
+    }
+    variant = model->data ( model->index ( 0, 0 ), Qt::WhatsThisRole );
+    if ( variant.isValid() ) {
+        Q_ASSERT ( qVariantCanConvert<QString> ( variant ) );
+    }
+
+    // General Purpose roles that should return a QSize
+    variant = model->data ( model->index ( 0, 0 ), Qt::SizeHintRole );
+    if ( variant.isValid() ) {
+        Q_ASSERT ( qVariantCanConvert<QSize> ( variant ) );
+    }
+
+    // General Purpose roles that should return a QFont
+    QVariant fontVariant = model->data ( model->index ( 0, 0 ), Qt::FontRole );
+    if ( fontVariant.isValid() ) {
+        Q_ASSERT ( qVariantCanConvert<QFont> ( fontVariant ) );
+    }
+
+    // Check that the alignment is one we know about
+    QVariant textAlignmentVariant = model->data ( model->index ( 0, 0 ), Qt::TextAlignmentRole );
+    if ( textAlignmentVariant.isValid() ) {
+        int alignment = textAlignmentVariant.toInt();
+        Q_ASSERT ( alignment == ( alignment & ( Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask ) ) );
+        Q_UNUSED( alignment );
+    }
+
+    // General Purpose roles that should return a QColor
+    QVariant colorVariant = model->data ( model->index ( 0, 0 ), Qt::BackgroundColorRole );
+    if ( colorVariant.isValid() ) {
+        Q_ASSERT ( qVariantCanConvert<QColor> ( colorVariant ) );
+    }
+
+    colorVariant = model->data ( model->index ( 0, 0 ), Qt::TextColorRole );
+    if ( colorVariant.isValid() ) {
+        Q_ASSERT ( qVariantCanConvert<QColor> ( colorVariant ) );
+    }
+
+    // Check that the "check state" is one we know about.
+    QVariant checkStateVariant = model->data ( model->index ( 0, 0 ), Qt::CheckStateRole );
+    if ( checkStateVariant.isValid() ) {
+        int state = checkStateVariant.toInt();
+        Q_ASSERT ( state == Qt::Unchecked ||
+                   state == Qt::PartiallyChecked ||
+                   state == Qt::Checked );
+        Q_UNUSED( state );
+    }
+}
+
+/*!
+    Store what is about to be inserted to make sure it actually happens
+
+    \sa rowsInserted()
+ */
+void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int end )
+{
+//     Q_UNUSED(end);
+    qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).value<QString>()
+    << "current count of parent=" << model->rowCount ( parent ); // << "display of last=" << model->data( model->index(start-1, 0, parent) );
+//     qDebug() << model->index(start-1, 0, parent) << model->data( model->index(start-1, 0, parent) );
+    Changing c;
+    c.parent = parent;
+    c.oldSize = model->rowCount ( parent );
+    c.last = model->data ( model->index ( start - 1, 0, parent ) );
+    c.next = model->data ( model->index ( start, 0, parent ) );
+    insert.push ( c );
+}
+
+/*!
+    Confirm that what was said was going to happen actually did
+
+    \sa rowsAboutToBeInserted()
+ */
+void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end )
+{
+    Changing c = insert.pop();
+    Q_ASSERT ( c.parent == parent );
+    qDebug() << "rowsInserted"  << "start=" << start << "end=" << end << "oldsize=" << c.oldSize
+    << "parent=" << model->data ( parent ).value<QString>() << "current rowcount=" << model->rowCount ( parent );
+
+    for (int ii=start; ii <= end; ii++)
+    {
+      qDebug() << "itemWasInserted:" << model->data ( model->index ( ii, 0, parent ));
+    }
+
+    Q_ASSERT ( c.oldSize + ( end - start + 1 ) == model->rowCount ( parent ) );
+    Q_ASSERT ( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) );
+    /*
+    if (c.next != model->data(model->index(end + 1, 0, c.parent))) {
+        qDebug() << start << end;
+        for (int i=0; i < model->rowCount(); ++i)
+            qDebug() << model->index(i, 0).data().toString();
+        qDebug() << c.next << model->data(model->index(end + 1, 0, c.parent));
+    }
+    */
+    Q_ASSERT ( c.next == model->data ( model->index ( end + 1, 0, c.parent ) ) );
+}
+
+
+void ModelTest::modelAboutToBeReset()
+{
+  qDebug() << "@@@@@@@@@@@" << "modelAboutToBeReset";
+}
+
+void ModelTest::modelReset()
+{
+  qDebug() << "@@@@@@@@@@@" << "modelReset";
+}
+
+void ModelTest::layoutAboutToBeChanged()
+{
+    for ( int i = 0; i < qBound ( 0, model->rowCount(), 100 ); ++i )
+        changing.append ( QPersistentModelIndex ( model->index ( i, 0 ) ) );
+}
+
+void ModelTest::layoutChanged()
+{
+    for ( int i = 0; i < changing.count(); ++i ) {
+        QPersistentModelIndex p = changing[i];
+        Q_ASSERT ( p == model->index ( p.row(), p.column(), p.parent() ) );
+    }
+    changing.clear();
+}
+
+void ModelTest::rowsAboutToBeMoved(const QModelIndex &srcParent, int start, int end, const QModelIndex &destParent, int destinationRow )
+{
+  qDebug() << "rowsAboutToBeMoved" << srcParent << start << end << destParent << destinationRow;
+  Changing cs;
+  cs.parent = srcParent;
+  cs.oldSize = model->rowCount ( srcParent );
+  cs.last = model->data ( model->index ( start - 1, 0, srcParent ) );
+  qDebug() << start << model->data ( model->index (start , 0, srcParent)).toString();
+  cs.next = model->data ( model->index ( end + 1, 0, srcParent ) );
+  remove.push ( cs );
+  Changing cd;  
+  cd.parent = destParent;
+  cd.oldSize = model->rowCount ( destParent );
+  cd.last = model->data ( model->index ( destinationRow - 1, 0, destParent ) );
+  cd.next = model->data ( model->index ( destinationRow, 0, destParent ) );
+  insert.push ( cd );
+}
+
+void ModelTest::rowsMoved(const QModelIndex &srcParent, int start, int end, const QModelIndex &destParent, int destinationRow )
+{
+  qDebug() << "rowsMoved" << srcParent << start << end << destParent << destinationRow;
+
+  Changing cd = insert.pop();
+  Q_ASSERT ( cd.parent == destParent );
+  if (srcParent == destParent)
+  {
+    Q_ASSERT ( cd.oldSize == model->rowCount ( destParent ) );
+
+    // TODO: Find out what I can assert here about last and next.
+//     Q_ASSERT ( cd.last == model->data ( model->index ( destinationRow - 1, 0, cd.parent ) ) );
+//     Q_ASSERT ( cd.next == model->data ( model->index ( destinationRow + (end - start + 1), 0, cd.parent ) ) );
+
+
+  }
+  else
+  {
+    Q_ASSERT ( cd.oldSize + ( end - start + 1 ) == model->rowCount ( destParent ) );
+
+    Q_ASSERT ( cd.last == model->data ( model->index ( destinationRow - 1, 0, cd.parent ) ) );
+    Q_ASSERT ( cd.next == model->data ( model->index ( destinationRow + (end - start + 1), 0, cd.parent ) ) );
+  }
+  Changing cs = remove.pop();
+
+  Q_ASSERT ( cs.parent == srcParent );
+  if (srcParent == destParent)
+  {
+    Q_ASSERT ( cs.oldSize == model->rowCount ( srcParent ) );
+  }
+  else
+  {
+    Q_ASSERT ( cs.oldSize - ( end - start + 1 ) == model->rowCount ( srcParent ) );
+    qDebug() << start - 1 << model->data ( model->index ( start - 1, 0, srcParent ) ).toString() << cs.last.toString();  
+    qDebug() << start << model->data ( model->index ( start , 0, srcParent ) ).toString() << cs.next.toString();  
+    Q_ASSERT ( cs.last == model->data ( model->index ( start - 1, 0, srcParent ) ) );
+    qDebug() << cs.next << model->data ( model->index ( start, 0, srcParent ) );
+    Q_ASSERT ( cs.next == model->data ( model->index ( start, 0, srcParent ) ) );
+  }
+
+}
+
+/*!
+    Store what is about to be inserted to make sure it actually happens
+
+    \sa rowsRemoved()
+ */
+void ModelTest::rowsAboutToBeRemoved ( const QModelIndex &parent, int start, int end )
+{
+qDebug() << "ratbr" << parent << start << end;
+    for (int ii=start; ii <= end; ii++)
+    {
+      qDebug() << "itemwillbe removed:" << model->data ( model->index ( ii, 0, parent ));
+    }
+
+
+    Changing c;
+    c.parent = parent;
+    c.oldSize = model->rowCount ( parent );
+    c.last = model->data ( model->index ( start - 1, 0, parent ) );
+    c.next = model->data ( model->index ( end + 1, 0, parent ) );
+    remove.push ( c );
+}
+
+/*!
+    Confirm that what was said was going to happen actually did
+
+    \sa rowsAboutToBeRemoved()
+ */
+void ModelTest::rowsRemoved ( const QModelIndex & parent, int start, int end )
+{
+  qDebug() << "rr" << parent << start << end;
+    Changing c = remove.pop();
+    Q_ASSERT ( c.parent == parent );
+    Q_ASSERT ( c.oldSize - ( end - start + 1 ) == model->rowCount ( parent ) );
+    Q_ASSERT ( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) );
+    Q_ASSERT ( c.next == model->data ( model->index ( start, 0, c.parent ) ) );
+}
+
diff --git a/korganizer/views/collectionview/tests/modeltest.h b/korganizer/views/collectionview/tests/modeltest.h
new file mode 100644
index 0000000..0ed70be
--- /dev/null
+++ b/korganizer/views/collectionview/tests/modeltest.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 Trolltech ASA. All rights reserved.
+**
+** This file is part of the Qt Concurrent project on Trolltech Labs.
+**
+** This file may be used under the terms of the GNU General Public
+** License version 2.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of
+** this file.  Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+** http://www.trolltech.com/products/qt/opensource.html
+**
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://www.trolltech.com/products/qt/licensing.html or contact the
+** sales department at sales at trolltech.com.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+//krazy:excludeall=style
+
+#ifndef MODELTEST_H
+#define MODELTEST_H
+
+#include <QtCore/QObject>
+#include <QtCore/QAbstractItemModel>
+#include <QtCore/QStack>
+
+class ModelTest : public QObject
+{
+  Q_OBJECT
+
+public:
+  explicit ModelTest( QAbstractItemModel *model, QObject *parent = 0 );
+
+private Q_SLOTS:
+  void nonDestructiveBasicTest();
+  void rowCount();
+  void columnCount();
+  void hasIndex();
+  void index();
+  void parent();
+  void data();
+
+protected Q_SLOTS:
+  void runAllTests();
+  void layoutAboutToBeChanged();
+  void layoutChanged();
+  void modelAboutToBeReset();
+  void modelReset();
+  void rowsAboutToBeInserted( const QModelIndex &parent, int start, int end );
+  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 rowsAboutToBeMoved ( const QModelIndex &, int, int, const QModelIndex &, int);
+  void rowsMoved ( const QModelIndex &, int, int, const QModelIndex &, int );
+
+private:
+  void checkChildren( const QModelIndex &parent, int currentDepth = 0 );
+
+  QAbstractItemModel *model;
+
+  struct Changing {
+    QModelIndex parent;
+    int oldSize;
+    QVariant last;
+    QVariant next;
+  };
+  QStack<Changing> insert;
+  QStack<Changing> remove;
+
+  bool fetchingMore;
+
+  QList<QPersistentModelIndex> changing;
+};
+
+#endif
diff --git a/korganizer/views/collectionview/tests/reparentingmodeltest.cpp b/korganizer/views/collectionview/tests/reparentingmodeltest.cpp
index f7ddd70..6fb5526 100644
--- a/korganizer/views/collectionview/tests/reparentingmodeltest.cpp
+++ b/korganizer/views/collectionview/tests/reparentingmodeltest.cpp
@@ -33,7 +33,9 @@ public:
     DummyNode(ReparentingModel &personModel, const QString &name, const QString &data=QString())
     : ReparentingModel::Node(personModel),
     mName(name),
-    mData(data)
+    mData(data),
+    mUid(name),
+    mParent(QLatin1String("orphan"))
     {}
 
     virtual ~DummyNode(){};
@@ -41,15 +43,21 @@ public:
     virtual bool operator==(const Node &node) const {
         const DummyNode *dummyNode = dynamic_cast<const DummyNode*>(&node);
         if (dummyNode) {
-            return (dummyNode->mName == mName);
+            return (dummyNode->mUid == mUid);
         }
         return false;
     }
 
+    QString mUid;
+    QString mParent;
 private:
     virtual QVariant data(int role) const {
         if (role == Qt::DisplayRole) {
-            return mName;
+            if (mName != mUid) {
+                return QString(mUid+QLatin1Char('-')+mName);
+            } else {
+                return mName;
+            }
         } else if (role == Qt::UserRole) {
             return mData;
         }
@@ -61,11 +69,11 @@ private:
         return false;
     }
     virtual bool isDuplicateOf(const QModelIndex& sourceIndex) {
-        return (sourceIndex.data().toString() == mName);
+        return (sourceIndex.data().toString() == mUid);
     }
 
     virtual bool adopts(const QModelIndex& sourceIndex) {
-        return sourceIndex.data().toString().contains(QLatin1String("orphan"));
+        return sourceIndex.data().toString().contains(mParent);
     }
 
     QString mName;
@@ -148,6 +156,7 @@ private Q_SLOTS:
     void testNestedDeduplicateProxyNodeFirst();
     void testUpdateNode();
     void testReparent();
+    void testReparentSubcollections();
     void testReparentResetWithoutCrash();
     void testAddReparentedSourceItem();
     void testRemoveReparentedSourceItem();
@@ -413,6 +422,63 @@ void ReparentingModelTest::testReparent()
     QCOMPARE(reparentingModel.rowCount(getIndex("proxy1", reparentingModel)), 1);
 }
 
+void ReparentingModelTest::testReparentSubcollections()
+{
+    QStandardItemModel sourceModel;
+    ReparentingModel reparentingModel;  
+    reparentingModel.setSourceModel(&sourceModel);
+
+    /* Source structure
+     -- + 
+        -- + orphan
+           -- + col1
+              -- sub1
+              -- sub2
+           -- col2
+    */
+    sourceModel.appendRow(new QStandardItem(QLatin1String("orphan")));
+    sourceModel.item(0,0)->appendRow(new QStandardItem(QLatin1String("col1")));
+    sourceModel.item(0,0)->child(0,0)->appendRow(new QStandardItem(QLatin1String("sub1")));
+    sourceModel.item(0,0)->child(0,0)->appendRow(new QStandardItem(QLatin1String("sub2")));
+    sourceModel.item(0,0)->appendRow(new QStandardItem(QLatin1String("col2")));
+    
+    DummyNode *node = new DummyNode(reparentingModel, QLatin1String("col1"));
+    node->mUid = QLatin1String("uid");
+    node->mParent = QLatin1String("col");
+    
+    /* new srutcure:
+     -- + 
+        -- orphan
+        -- + uid-col1
+           -- + col1
+              -- sub1
+              -- sub2
+           -- col2
+    */
+    reparentingModel.addNode(ReparentingModel::Node::Ptr(node));
+
+    QTest::qWait(0);
+
+    QCOMPARE(reparentingModel.rowCount(QModelIndex()), 2);
+    QVERIFY(getIndex("col1", reparentingModel).isValid());
+    QCOMPARE(getIndex("col1", reparentingModel).parent(), getIndex("uid-col1", reparentingModel));
+    QCOMPARE(reparentingModel.rowCount(getIndex("col1", reparentingModel)), 2);
+    QCOMPARE(reparentingModel.rowCount(getIndex("uid-col1", reparentingModel)), 2);
+
+    node = new DummyNode(reparentingModel, QLatin1String("xxx"));
+    node->mUid = QLatin1String("uid");
+    node->mParent = QLatin1String("col");
+
+    // same structure but new data
+    reparentingModel.updateNode(ReparentingModel::Node::Ptr(node));
+
+    QTest::qWait(0);
+
+    QCOMPARE(getIndex("col1", reparentingModel).parent(), getIndex("uid-xxx", reparentingModel));
+    QCOMPARE(reparentingModel.rowCount(getIndex("col1", reparentingModel)), 2);
+    QCOMPARE(reparentingModel.rowCount(getIndex("uid-xxx", reparentingModel)), 2);
+}
+
 /*
  * This test ensures we properly deal with reparented source nodes if the model is reset.
  * This is important since source nodes are removed during the model reset while the proxy nodes (to which the source nodes have been reparented) remain.
@@ -677,3 +743,4 @@ void ReparentingModelTest::testRemoveNodeByNodeManagerWithDataChanged()
 QTEST_MAIN(ReparentingModelTest)
 
 #include "reparentingmodeltest.moc"
+    
\ No newline at end of file





More information about the commits mailing list