From bddc29101cf46175ac198a08b14baf697fc0ba69 Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Mon, 23 Apr 2012 16:57:08 +0200 Subject: [PATCH] Introduce Group::aboutToMove() and moved() signals. Emit them instead of remove/add when groups are moved within a database. --- src/core/Database.h | 2 ++ src/core/Group.cpp | 46 ++++++++++++++++++--------- src/core/Group.h | 5 +++ src/gui/GroupModel.cpp | 23 ++++++++++++++ src/gui/GroupModel.h | 2 ++ tests/TestGroup.cpp | 68 ++++++++++++++++++++++++++++++++++++---- tests/TestGroupModel.cpp | 66 ++++++++++++++++++++++++++++++-------- tests/TestModified.cpp | 3 ++ tests/modeltest.cpp | 58 ++++++++++++++++++++++++++++++++-- tests/modeltest.h | 3 ++ 10 files changed, 239 insertions(+), 37 deletions(-) diff --git a/src/core/Database.h b/src/core/Database.h index ecbbc9c88..d7c905b11 100644 --- a/src/core/Database.h +++ b/src/core/Database.h @@ -95,6 +95,8 @@ Q_SIGNALS: void groupAdded(); void groupAboutToRemove(Group* group); void groupRemoved(); + void groupAboutToMove(Group* group, Group* toGroup, int index); + void groupMoved(); void modified(); private: diff --git a/src/core/Group.cpp b/src/core/Group.cpp index 7651bad86..064d73d6c 100644 --- a/src/core/Group.cpp +++ b/src/core/Group.cpp @@ -260,35 +260,47 @@ void Group::setParent(Group* parent, int index) // setting a new parent for root groups is not allowed Q_ASSERT(!m_db || (m_db->rootGroup() != this)); + bool moveWithinDatabase = (m_db && m_db == parent->m_db); + if (index == -1) { index = parent->children().size(); } - if (m_parent == parent && index == parent->children().indexOf(this)) { + if (m_parent == parent && parent->children().indexOf(this) == index) { return; } - cleanupParent(); - - m_parent = parent; - - if (m_db != parent->m_db) { - recCreateDelObjects(); - recSetDatabase(parent->m_db); + if (!moveWithinDatabase) { + cleanupParent(); + m_parent = parent; + if (parent->m_db) { + recCreateDelObjects(); + recSetDatabase(parent->m_db); + } + QObject::setParent(parent); + Q_EMIT aboutToAdd(this, index); + parent->m_children.insert(index, this); + } + else { + Q_EMIT aboutToMove(this, parent, index); + m_parent->m_children.removeAll(this); + m_parent = parent; + QObject::setParent(parent); + parent->m_children.insert(index, this); } - - QObject::setParent(parent); - - Q_EMIT aboutToAdd(this, index); - - parent->m_children.insert(index, this); if (m_updateTimeinfo) { m_timeInfo.setLocationChanged(QDateTime::currentDateTimeUtc()); } Q_EMIT modified(); - Q_EMIT added(); + + if (!moveWithinDatabase) { + Q_EMIT added(); + } + else { + Q_EMIT moved(); + } } void Group::setParent(Database* db) @@ -389,6 +401,8 @@ void Group::recSetDatabase(Database* db) disconnect(SIGNAL(removed()), m_db); disconnect(SIGNAL(aboutToAdd(Group*,int)), m_db); disconnect(SIGNAL(added()), m_db); + disconnect(SIGNAL(aboutToMove(Group*,Group*,int)), m_db); + disconnect(SIGNAL(moved()), m_db); disconnect(SIGNAL(modified()), m_db); } @@ -404,6 +418,8 @@ void Group::recSetDatabase(Database* db) connect(this, SIGNAL(removed()), db, SIGNAL(groupRemoved())); connect(this, SIGNAL(aboutToAdd(Group*,int)), db, SIGNAL(groupAboutToAdd(Group*,int))); connect(this, SIGNAL(added()), db, SIGNAL(groupAdded())); + connect(this, SIGNAL(aboutToMove(Group*,Group*,int)), db, SIGNAL(groupAboutToMove(Group*,Group*,int))); + connect(this, SIGNAL(moved()), db, SIGNAL(groupMoved())); connect(this, SIGNAL(modified()), db, SIGNAL(modified())); m_db = db; diff --git a/src/core/Group.h b/src/core/Group.h index 77290bc96..df217a8d3 100644 --- a/src/core/Group.h +++ b/src/core/Group.h @@ -85,6 +85,11 @@ Q_SIGNALS: void added(); void aboutToRemove(Group* group); void removed(); + /** + * Group moved within the database. + */ + void aboutToMove(Group* group, Group* toGroup, int index); + void moved(); void entryAboutToAdd(Entry* entry); void entryAdded(); diff --git a/src/gui/GroupModel.cpp b/src/gui/GroupModel.cpp index 2209d75f5..b8e878927 100644 --- a/src/gui/GroupModel.cpp +++ b/src/gui/GroupModel.cpp @@ -29,6 +29,8 @@ GroupModel::GroupModel(Database* db, QObject* parent) connect(db, SIGNAL(groupAdded()), SLOT(groupAdded())); connect(db, SIGNAL(groupAboutToRemove(Group*)), SLOT(groupAboutToRemove(Group*))); connect(db, SIGNAL(groupRemoved()), SLOT(groupRemoved())); + connect(db, SIGNAL(groupAboutToMove(Group*,Group*,int)), SLOT(groupAboutToMove(Group*,Group*,int))); + connect(db, SIGNAL(groupMoved()), SLOT(groupMoved())); } int GroupModel::rowCount(const QModelIndex& parent) const @@ -180,3 +182,24 @@ void GroupModel::groupAdded() { endInsertRows(); } + +void GroupModel::groupAboutToMove(Group* group, Group* toGroup, int pos) +{ + Q_ASSERT(group->parentGroup()); + + QModelIndex oldParentIndex = parent(group); + QModelIndex newParentIndex = index(toGroup); + int oldPos = group->parentGroup()->children().indexOf(group); + if (group->parentGroup() == toGroup && pos > oldPos) { + // beginMoveRows() has a bit different semantics than Group::setParent() and + // QList::move() when the new position is greater than the old + pos++; + } + + beginMoveRows(oldParentIndex, oldPos, oldPos, newParentIndex, pos); +} + +void GroupModel::groupMoved() +{ + endMoveRows(); +} diff --git a/src/gui/GroupModel.h b/src/gui/GroupModel.h index 677d81fd0..cf2eb72e4 100644 --- a/src/gui/GroupModel.h +++ b/src/gui/GroupModel.h @@ -48,6 +48,8 @@ private Q_SLOTS: void groupRemoved(); void groupAboutToAdd(Group* group, int index); void groupAdded(); + void groupAboutToMove(Group* group, Group* toGroup, int pos); + void groupMoved(); private: Group* m_root; diff --git a/tests/TestGroup.cpp b/tests/TestGroup.cpp index b41a5654e..c4b2fe751 100644 --- a/tests/TestGroup.cpp +++ b/tests/TestGroup.cpp @@ -99,26 +99,82 @@ void TestGroup::testParenting() void TestGroup::testSignals() { Database* db = new Database(); + Database* db2 = new Database(); QPointer root = db->rootGroup(); - Group* g1 = new Group(); - Group* g2 = new Group(); - g1->setParent(root); - g2->setParent(root); - QSignalSpy spyAboutToAdd(db, SIGNAL(groupAboutToAdd(Group*,int))); QSignalSpy spyAdded(db, SIGNAL(groupAdded())); QSignalSpy spyAboutToRemove(db, SIGNAL(groupAboutToRemove(Group*))); QSignalSpy spyRemoved(db, SIGNAL(groupRemoved())); + QSignalSpy spyAboutToMove(db, SIGNAL(groupAboutToMove(Group*,Group*,int))); + QSignalSpy spyMoved(db, SIGNAL(groupMoved())); - g2->setParent(root, 0); + QSignalSpy spyAboutToAdd2(db2, SIGNAL(groupAboutToAdd(Group*,int))); + QSignalSpy spyAdded2(db2, SIGNAL(groupAdded())); + QSignalSpy spyAboutToRemove2(db2, SIGNAL(groupAboutToRemove(Group*))); + QSignalSpy spyRemoved2(db2, SIGNAL(groupRemoved())); + QSignalSpy spyAboutToMove2(db2, SIGNAL(groupAboutToMove(Group*,Group*,int))); + QSignalSpy spyMoved2(db2, SIGNAL(groupMoved())); + Group* g1 = new Group(); + Group* g2 = new Group(); + + g1->setParent(root); QCOMPARE(spyAboutToAdd.count(), 1); QCOMPARE(spyAdded.count(), 1); + QCOMPARE(spyAboutToRemove.count(), 0); + QCOMPARE(spyRemoved.count(), 0); + QCOMPARE(spyAboutToMove.count(), 0); + QCOMPARE(spyMoved.count(), 0); + + g2->setParent(root); + QCOMPARE(spyAboutToAdd.count(), 2); + QCOMPARE(spyAdded.count(), 2); + QCOMPARE(spyAboutToRemove.count(), 0); + QCOMPARE(spyRemoved.count(), 0); + QCOMPARE(spyAboutToMove.count(), 0); + QCOMPARE(spyMoved.count(), 0); + + g2->setParent(root, 0); + QCOMPARE(spyAboutToAdd.count(), 2); + QCOMPARE(spyAdded.count(), 2); + QCOMPARE(spyAboutToRemove.count(), 0); + QCOMPARE(spyRemoved.count(), 0); + QCOMPARE(spyAboutToMove.count(), 1); + QCOMPARE(spyMoved.count(), 1); + + g1->setParent(g2); + QCOMPARE(spyAboutToAdd.count(), 2); + QCOMPARE(spyAdded.count(), 2); + QCOMPARE(spyAboutToRemove.count(), 0); + QCOMPARE(spyRemoved.count(), 0); + QCOMPARE(spyAboutToMove.count(), 2); + QCOMPARE(spyMoved.count(), 2); + + delete g1; + QCOMPARE(spyAboutToAdd.count(), 2); + QCOMPARE(spyAdded.count(), 2); QCOMPARE(spyAboutToRemove.count(), 1); QCOMPARE(spyRemoved.count(), 1); + QCOMPARE(spyAboutToMove.count(), 2); + QCOMPARE(spyMoved.count(), 2); + + g2->setParent(db2->rootGroup()); + QCOMPARE(spyAboutToAdd.count(), 2); + QCOMPARE(spyAdded.count(), 2); + QCOMPARE(spyAboutToRemove.count(), 2); + QCOMPARE(spyRemoved.count(), 2); + QCOMPARE(spyAboutToMove.count(), 2); + QCOMPARE(spyMoved.count(), 2); + QCOMPARE(spyAboutToAdd2.count(), 1); + QCOMPARE(spyAdded2.count(), 1); + QCOMPARE(spyAboutToRemove2.count(), 0); + QCOMPARE(spyRemoved2.count(), 0); + QCOMPARE(spyAboutToMove2.count(), 0); + QCOMPARE(spyMoved2.count(), 0); delete db; + delete db2; QVERIFY(root.isNull()); } diff --git a/tests/TestGroupModel.cpp b/tests/TestGroupModel.cpp index 82a6bff24..eea0f7f5a 100644 --- a/tests/TestGroupModel.cpp +++ b/tests/TestGroupModel.cpp @@ -61,11 +61,6 @@ void TestGroupModel::test() group121->setName("group121"); group121->setParent(group12); - Group* group2 = new Group(); - group1->setObjectName("group2"); - group2->setName("group2"); - group2->setParent(groupRoot); - GroupModel* model = new GroupModel(db, this); ModelTest* modelTest = new ModelTest(model, this); @@ -73,33 +68,78 @@ void TestGroupModel::test() QModelIndex indexRoot = model->index(0, 0); QModelIndex index1 = model->index(0, 0, indexRoot); QModelIndex index11 = model->index(0, 0, index1); - QModelIndex index12 = model->index(1, 0, index1); + QPersistentModelIndex index12 = model->index(1, 0, index1); QModelIndex index121 = model->index(0, 0, index12); - QModelIndex index2 = model->index(1, 0, indexRoot); QCOMPARE(model->data(indexRoot).toString(), QString("groupRoot")); QCOMPARE(model->data(index1).toString(), QString("group1")); QCOMPARE(model->data(index11).toString(), QString("group11")); QCOMPARE(model->data(index12).toString(), QString("group12")); QCOMPARE(model->data(index121).toString(), QString("group121")); - QCOMPARE(model->data(index2).toString(), QString("group2")); - QSignalSpy spy1(model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&))); + QSignalSpy spy1(model, SIGNAL(dataChanged(QModelIndex,QModelIndex))); group11->setName("test"); group121->setIcon(4); QCOMPARE(spy1.count(), 2); + QCOMPARE(model->data(index11).toString(), QString("test")); - QSignalSpy spyAboutToAdd(model, SIGNAL(rowsAboutToBeInserted(const QModelIndex&,int,int))); - QSignalSpy spyAdded(model, SIGNAL(rowsInserted(const QModelIndex&,int,int))); - QSignalSpy spyAboutToRemove(model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex&,int,int))); - QSignalSpy spyRemoved(model, SIGNAL(rowsRemoved(const QModelIndex&,int,int))); + QSignalSpy spyAboutToAdd(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int))); + QSignalSpy spyAdded(model, SIGNAL(rowsInserted(QModelIndex,int,int))); + QSignalSpy spyAboutToRemove(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int))); + QSignalSpy spyRemoved(model, SIGNAL(rowsRemoved(QModelIndex,int,int))); + QSignalSpy spyAboutToMove(model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); + QSignalSpy spyMoved(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int))); + + Group* group2 = new Group(); + group1->setObjectName("group2"); + group2->setName("group2"); + group2->setParent(groupRoot); + QModelIndex index2 = model->index(1, 0, indexRoot); + QCOMPARE(spyAboutToAdd.count(), 1); + QCOMPARE(spyAdded.count(), 1); + QCOMPARE(spyAboutToRemove.count(), 0); + QCOMPARE(spyRemoved.count(), 0); + QCOMPARE(spyAboutToMove.count(), 0); + QCOMPARE(spyMoved.count(), 0); + QCOMPARE(model->data(index2).toString(), QString("group2")); group12->setParent(group1, 0); + QCOMPARE(spyAboutToAdd.count(), 1); + QCOMPARE(spyAdded.count(), 1); + QCOMPARE(spyAboutToRemove.count(), 0); + QCOMPARE(spyRemoved.count(), 0); + QCOMPARE(spyAboutToMove.count(), 1); + QCOMPARE(spyMoved.count(), 1); + QCOMPARE(model->data(index12).toString(), QString("group12")); + group12->setParent(group1, 1); + QCOMPARE(spyAboutToAdd.count(), 1); + QCOMPARE(spyAdded.count(), 1); + QCOMPARE(spyAboutToRemove.count(), 0); + QCOMPARE(spyRemoved.count(), 0); + QCOMPARE(spyAboutToMove.count(), 2); + QCOMPARE(spyMoved.count(), 2); + QCOMPARE(model->data(index12).toString(), QString("group12")); + + group12->setParent(group2); + QCOMPARE(spyAboutToAdd.count(), 1); + QCOMPARE(spyAdded.count(), 1); + QCOMPARE(spyAboutToRemove.count(), 0); + QCOMPARE(spyRemoved.count(), 0); + QCOMPARE(spyAboutToMove.count(), 3); + QCOMPARE(spyMoved.count(), 3); + QVERIFY(index12.isValid()); + QCOMPARE(model->data(index12).toString(), QString("group12")); + QCOMPARE(model->data(index12.child(0, 0)).toString(), QString("group121")); + + delete group12; QCOMPARE(spyAboutToAdd.count(), 1); QCOMPARE(spyAdded.count(), 1); QCOMPARE(spyAboutToRemove.count(), 1); QCOMPARE(spyRemoved.count(), 1); + QCOMPARE(spyAboutToMove.count(), 3); + QCOMPARE(spyMoved.count(), 3); + QVERIFY(!index12.isValid()); // test removing a group that has children delete group1; diff --git a/tests/TestModified.cpp b/tests/TestModified.cpp index 6e144f7c3..65bb832a1 100644 --- a/tests/TestModified.cpp +++ b/tests/TestModified.cpp @@ -52,6 +52,9 @@ void TestModified::testSignals() g2->setParent(root); QCOMPARE(spyModified.count(), ++spyCount); + g2->setParent(root, 0); + QCOMPARE(spyModified.count(), ++spyCount); + Entry* entry1 = new Entry(); entry1->setGroup(g1); QCOMPARE(spyModified.count(), ++spyCount); diff --git a/tests/modeltest.cpp b/tests/modeltest.cpp index a55bb43a5..7b177367c 100644 --- a/tests/modeltest.cpp +++ b/tests/modeltest.cpp @@ -1,8 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ ** ** This file is part of the test suite of the Qt Toolkit. ** @@ -94,6 +93,12 @@ ModelTest::ModelTest ( QAbstractItemModel *_model, QObject *parent ) : QObject ( connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ), this, SLOT ( rowsRemoved ( const 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(); } @@ -559,3 +564,50 @@ void ModelTest::rowsRemoved ( const QModelIndex & parent, int start, int end ) QVERIFY( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) ); QVERIFY( c.next == model->data ( model->index ( start, 0, c.parent ) ) ); } + +void ModelTest::rowsAboutToBeMoved( const QModelIndex &srcParent, int start, int end, const QModelIndex &destParent, int destinationRow ) +{ + Changing cs; + cs.parent = srcParent; + cs.oldSize = model->rowCount ( srcParent ); + cs.last = model->data ( model->index ( start - 1, 0, srcParent ) ); + 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 ) +{ + 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 ) ); + + Q_ASSERT ( cs.last == model->data ( model->index ( start - 1, 0, srcParent ) ) ); + Q_ASSERT ( cs.next == model->data ( model->index ( start, 0, srcParent ) ) ); + } +} diff --git a/tests/modeltest.h b/tests/modeltest.h index e4ef478c5..46c3336e5 100644 --- a/tests/modeltest.h +++ b/tests/modeltest.h @@ -71,6 +71,9 @@ 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 rowsAboutToBeMoved ( const QModelIndex &srcParent, int start, int end, const QModelIndex &destParent, int destinationRow ); + void rowsMoved ( const QModelIndex &srcParent, int start, int end, const QModelIndex &destParent, int destinationRow ); + private: void checkChildren( const QModelIndex &parent, int currentDepth = 0 );