[Ktutorial-commits] SF.net SVN: ktutorial:[112] trunk/ktutorial/ktutorial-editor
Status: Alpha
Brought to you by:
danxuliu
From: <dan...@us...> - 2010-03-06 17:11:33
|
Revision: 112 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=112&view=rev Author: danxuliu Date: 2010-03-06 17:11:26 +0000 (Sat, 06 Mar 2010) Log Message: ----------- Emit signals when the structure or data of a TreeItem is modified, so the TreeModel can watch those signals and notify its views to be updated. Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/view/TextTreeItem.cpp trunk/ktutorial/ktutorial-editor/src/view/TreeItem.cpp trunk/ktutorial/ktutorial-editor/src/view/TreeItem.h trunk/ktutorial/ktutorial-editor/tests/unit/view/TextTreeItemTest.cpp trunk/ktutorial/ktutorial-editor/tests/unit/view/TreeItemTest.cpp Modified: trunk/ktutorial/ktutorial-editor/src/view/TextTreeItem.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/TextTreeItem.cpp 2010-03-05 23:48:40 UTC (rev 111) +++ trunk/ktutorial/ktutorial-editor/src/view/TextTreeItem.cpp 2010-03-06 17:11:26 UTC (rev 112) @@ -27,4 +27,6 @@ void TextTreeItem::setText(const QString& text) { mText = text; + + emit dataChanged(this); } Modified: trunk/ktutorial/ktutorial-editor/src/view/TreeItem.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/TreeItem.cpp 2010-03-05 23:48:40 UTC (rev 111) +++ trunk/ktutorial/ktutorial-editor/src/view/TreeItem.cpp 2010-03-06 17:11:26 UTC (rev 112) @@ -38,21 +38,33 @@ Q_ASSERT(!mChildren.contains(child)); Q_ASSERT(child->parent() == this); + emit childAboutToBeInserted(child, mChildren.count()); + mChildren.append(child); + + emit childInserted(child); } void TreeItem::insertChild(TreeItem* child, int index) { Q_ASSERT(!mChildren.contains(child)); Q_ASSERT(child->parent() == this); + emit childAboutToBeInserted(child, index); + mChildren.insert(index, child); + + emit childInserted(child); } void TreeItem::removeChild(TreeItem* child) { Q_ASSERT(mChildren.contains(child)); Q_ASSERT(child->parent() == this); + emit childAboutToBeRemoved(child); + mChildren.removeAt(mChildren.indexOf(child)); + + emit childRemoved(child); } TreeItem* TreeItem::parent() { Modified: trunk/ktutorial/ktutorial-editor/src/view/TreeItem.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/TreeItem.h 2010-03-05 23:48:40 UTC (rev 111) +++ trunk/ktutorial/ktutorial-editor/src/view/TreeItem.h 2010-03-06 17:11:26 UTC (rev 112) @@ -34,13 +34,19 @@ * the name of the person and two child TreeItems, one that contains the age and * one that contains the profession. * + * The structure of a tree can be modified after being added to a TreeModel. + * Changes in the layout (adding or removing child items) or the data are + * notified to the TreeModel, which notifies the views to be updated as needed. + * * TreeItem is an abstract class. Subclasses must implement its text() method, * that provides the data for that item to the TreeModel when DisplayRole is - * used. + * used. They also have to emit dataChanged(TreeItem*) signal when the data to + * be shown is modified. * * @see TreeModel */ -class TreeItem { +class TreeItem: public QObject { +Q_OBJECT public: /** @@ -116,6 +122,52 @@ */ int childIndex() const; +Q_SIGNALS: + + /** + * Emitted just before a child is inserted or appended. + * It is used to notify the TreeModel in order to update the views. + * + * @param child The child to be added. + * @param index The position to insert it (if the item is appended, the + * index is equal to the child count). + */ + void childAboutToBeInserted(TreeItem* child, int index); + + /** + * Emitted after a child is inserted or appended. + * It is used to notify the TreeModel in order to update the views. + * + * @param child The child added. + */ + void childInserted(TreeItem* child); + + /** + * Emitted just before a child is removed. + * It is used to notify the TreeModel in order to update the views. + * + * @param child The child to be removed. + */ + void childAboutToBeRemoved(TreeItem* child); + + /** + * Emitted after a child is removed. + * It is used to notify the TreeModel in order to update the views. + * + * @param child The child removed. + */ + void childRemoved(TreeItem* child); + + /** + * Emitted when the data to be used by the TreeModel changes. + * It is used to notify the TreeModel in order to update the views. + * + * It must be emitted by subclasses as needed. + * + * @param item This TreeItem. + */ + void dataChanged(TreeItem* item); + private: /** Modified: trunk/ktutorial/ktutorial-editor/tests/unit/view/TextTreeItemTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/view/TextTreeItemTest.cpp 2010-03-05 23:48:40 UTC (rev 111) +++ trunk/ktutorial/ktutorial-editor/tests/unit/view/TextTreeItemTest.cpp 2010-03-06 17:11:26 UTC (rev 112) @@ -39,11 +39,23 @@ QCOMPARE(treeItem.parent(), &parent); } +//TreeItem* must be declared as a metatype to be used in qvariant_cast +Q_DECLARE_METATYPE(TreeItem*); + void TextTreeItemTest::testSetText() { TextTreeItem item; + + //TreeItem* must be registered in order to be used with QSignalSpy + int treeItemStarType = qRegisterMetaType<TreeItem*>("TreeItem*"); + QSignalSpy dataChangedSpy(&item, SIGNAL(dataChanged(TreeItem*))); + item.setText("Hello world"); QCOMPARE(item.text(), QString("Hello world")); + QCOMPARE(dataChangedSpy.count(), 1); + QVariant argument = dataChangedSpy.at(0).at(0); + QCOMPARE(argument.userType(), treeItemStarType); + QCOMPARE(qvariant_cast<TreeItem*>(argument), &item); } QTEST_MAIN(TextTreeItemTest) Modified: trunk/ktutorial/ktutorial-editor/tests/unit/view/TreeItemTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/view/TreeItemTest.cpp 2010-03-05 23:48:40 UTC (rev 111) +++ trunk/ktutorial/ktutorial-editor/tests/unit/view/TreeItemTest.cpp 2010-03-06 17:11:26 UTC (rev 112) @@ -25,6 +25,8 @@ private slots: + void initTestCase(); + void testConstructor(); void testAppendChild(); @@ -36,6 +38,15 @@ void testRemoveChild(); void testRemoveChildSeveralChildren(); +private: + + int mTreeItemStarType; + + void assertAboutToBeInsertedSignal(const QSignalSpy& spy, int index, + TreeItem* item, int itemIndex) const; + + void assertSignal(const QSignalSpy& spy, int index, TreeItem* item) const; + }; class StubTreeItem: public TreeItem { @@ -52,6 +63,11 @@ }; +void TreeItemTest::initTestCase() { + //TreeItem* must be registered in order to be used with QSignalSpy + mTreeItemStarType = qRegisterMetaType<TreeItem*>("TreeItem*"); +} + void TreeItemTest::testConstructor() { StubTreeItem parent; StubTreeItem treeItem(&parent); @@ -60,16 +76,32 @@ QCOMPARE(treeItem.parent(), &parent); } +//TreeItem* must be declared as a metatype to be used in qvariant_cast +Q_DECLARE_METATYPE(TreeItem*); + void TreeItemTest::testAppendChild() { StubTreeItem treeItem; TreeItem* child = new StubTreeItem(&treeItem); + QSignalSpy aboutToBeInsertedSpy(&treeItem, + SIGNAL(childAboutToBeInserted(TreeItem*, int))); + QSignalSpy insertedSpy(&treeItem, SIGNAL(childInserted(TreeItem*))); + treeItem.appendChild(child); QCOMPARE(treeItem.childCount(), 1); QCOMPARE(treeItem.child(0), child); QCOMPARE(child->childIndex(), 0); QCOMPARE(child->parent(), &treeItem); + + //The proper way to check this would be asserting not only that the signals + //were emitted, but that when they were emitted the item wasn't and was + //already added (depending on the signal). However, that is too much effort + //for little gain. + QCOMPARE(aboutToBeInsertedSpy.count(), 1); + assertAboutToBeInsertedSignal(aboutToBeInsertedSpy, 0, child, 0); + QCOMPARE(insertedSpy.count(), 1); + assertSignal(insertedSpy, 0, child); } void TreeItemTest::testAppendChildSeveralChildren() { @@ -78,6 +110,10 @@ TreeItem* child2 = new StubTreeItem(&treeItem); TreeItem* child3 = new StubTreeItem(&treeItem); + QSignalSpy aboutToBeInsertedSpy(&treeItem, + SIGNAL(childAboutToBeInserted(TreeItem*, int))); + QSignalSpy insertedSpy(&treeItem, SIGNAL(childInserted(TreeItem*))); + treeItem.appendChild(child1); treeItem.appendChild(child2); treeItem.appendChild(child3); @@ -92,18 +128,36 @@ QCOMPARE(child2->parent(), &treeItem); QCOMPARE(child3->childIndex(), 2); QCOMPARE(child3->parent(), &treeItem); + + QCOMPARE(aboutToBeInsertedSpy.count(), 3); + assertAboutToBeInsertedSignal(aboutToBeInsertedSpy, 0, child1, 0); + assertAboutToBeInsertedSignal(aboutToBeInsertedSpy, 1, child2, 1); + assertAboutToBeInsertedSignal(aboutToBeInsertedSpy, 2, child3, 2); + QCOMPARE(insertedSpy.count(), 3); + assertSignal(insertedSpy, 0, child1); + assertSignal(insertedSpy, 1, child2); + assertSignal(insertedSpy, 2, child3); } void TreeItemTest::testInsertChild() { StubTreeItem treeItem; TreeItem* child = new StubTreeItem(&treeItem); + QSignalSpy aboutToBeInsertedSpy(&treeItem, + SIGNAL(childAboutToBeInserted(TreeItem*, int))); + QSignalSpy insertedSpy(&treeItem, SIGNAL(childInserted(TreeItem*))); + treeItem.insertChild(child, 0); QCOMPARE(treeItem.childCount(), 1); QCOMPARE(treeItem.child(0), child); QCOMPARE(child->childIndex(), 0); QCOMPARE(child->parent(), &treeItem); + + QCOMPARE(aboutToBeInsertedSpy.count(), 1); + assertAboutToBeInsertedSignal(aboutToBeInsertedSpy, 0, child, 0); + QCOMPARE(insertedSpy.count(), 1); + assertSignal(insertedSpy, 0, child); } void TreeItemTest::testInsertChildSeveralChildren() { @@ -113,6 +167,10 @@ TreeItem* child3 = new StubTreeItem(&treeItem); TreeItem* child4 = new StubTreeItem(&treeItem); + QSignalSpy aboutToBeInsertedSpy(&treeItem, + SIGNAL(childAboutToBeInserted(TreeItem*, int))); + QSignalSpy insertedSpy(&treeItem, SIGNAL(childInserted(TreeItem*))); + treeItem.insertChild(child2, 0); treeItem.insertChild(child1, 0); treeItem.insertChild(child4, 2); @@ -131,6 +189,17 @@ QCOMPARE(child3->parent(), &treeItem); QCOMPARE(child4->childIndex(), 3); QCOMPARE(child4->parent(), &treeItem); + + QCOMPARE(aboutToBeInsertedSpy.count(), 4); + assertAboutToBeInsertedSignal(aboutToBeInsertedSpy, 0, child2, 0); + assertAboutToBeInsertedSignal(aboutToBeInsertedSpy, 1, child1, 0); + assertAboutToBeInsertedSignal(aboutToBeInsertedSpy, 2, child4, 2); + assertAboutToBeInsertedSignal(aboutToBeInsertedSpy, 3, child3, 2); + QCOMPARE(insertedSpy.count(), 4); + assertSignal(insertedSpy, 0, child2); + assertSignal(insertedSpy, 1, child1); + assertSignal(insertedSpy, 2, child4); + assertSignal(insertedSpy, 3, child3); } void TreeItemTest::testRemoveChild() { @@ -139,12 +208,21 @@ //stack StubTreeItem child(&treeItem); + QSignalSpy aboutToBeRemovedSpy(&treeItem, + SIGNAL(childAboutToBeRemoved(TreeItem*))); + QSignalSpy removedSpy(&treeItem, SIGNAL(childRemoved(TreeItem*))); + treeItem.appendChild(&child); treeItem.removeChild(&child); QCOMPARE(treeItem.childCount(), 0); QCOMPARE(child.childIndex(), -1); QCOMPARE(child.parent(), &treeItem); + + QCOMPARE(aboutToBeRemovedSpy.count(), 1); + assertSignal(aboutToBeRemovedSpy, 0, &child); + QCOMPARE(removedSpy.count(), 1); + assertSignal(removedSpy, 0, &child); } void TreeItemTest::testRemoveChildSeveralChildren() { @@ -155,6 +233,10 @@ StubTreeItem child2(&treeItem); StubTreeItem child3(&treeItem); + QSignalSpy aboutToBeRemovedSpy(&treeItem, + SIGNAL(childAboutToBeRemoved(TreeItem*))); + QSignalSpy removedSpy(&treeItem, SIGNAL(childRemoved(TreeItem*))); + treeItem.appendChild(&child1); treeItem.appendChild(&child2); treeItem.appendChild(&child3); @@ -171,6 +253,11 @@ QCOMPARE(child3.childIndex(), 1); QCOMPARE(child3.parent(), &treeItem); + QCOMPARE(aboutToBeRemovedSpy.count(), 1); + assertSignal(aboutToBeRemovedSpy, 0, &child2); + QCOMPARE(removedSpy.count(), 1); + assertSignal(removedSpy, 0, &child2); + treeItem.removeChild(&child1); treeItem.removeChild(&child3); @@ -181,8 +268,40 @@ QCOMPARE(child2.parent(), &treeItem); QCOMPARE(child3.childIndex(), -1); QCOMPARE(child3.parent(), &treeItem); + + QCOMPARE(aboutToBeRemovedSpy.count(), 3); + assertSignal(aboutToBeRemovedSpy, 1, &child1); + assertSignal(aboutToBeRemovedSpy, 2, &child3); + QCOMPARE(removedSpy.count(), 3); + assertSignal(removedSpy, 1, &child1); + assertSignal(removedSpy, 2, &child3); } +/////////////////////////////////// Helpers //////////////////////////////////// + +void TreeItemTest::assertAboutToBeInsertedSignal(const QSignalSpy& spy, + int index, TreeItem* item, + int itemIndex) const { + QCOMPARE(spy.at(index).count(), 2); + + QVariant argument = spy.at(index).at(0); + QCOMPARE(argument.userType(), mTreeItemStarType); + QCOMPARE(qvariant_cast<TreeItem*>(argument), item); + + argument = spy.at(index).at(1); + QCOMPARE(argument.type(), QVariant::Int); + QCOMPARE(argument.toInt(), itemIndex); +} + +void TreeItemTest::assertSignal(const QSignalSpy& spy, int index, + TreeItem* item) const { + QCOMPARE(spy.at(index).count(), 1); + + QVariant argument = spy.at(index).at(0); + QCOMPARE(argument.userType(), mTreeItemStarType); + QCOMPARE(qvariant_cast<TreeItem*>(argument), item); +} + QTEST_MAIN(TreeItemTest) #include "TreeItemTest.moc" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |