[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.
|