From e497af7cd28d2cf58d81ed8fd351b5d5ccfa56a4 Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Wed, 26 May 2010 17:29:44 +0100
Subject: Don't let roster groups open and close on their own.

Resolves: #368

diff --git a/Swift/QtUI/Roster/QtTreeWidget.cpp b/Swift/QtUI/Roster/QtTreeWidget.cpp
index 997c1f6..6ace3df 100644
--- a/Swift/QtUI/Roster/QtTreeWidget.cpp
+++ b/Swift/QtUI/Roster/QtTreeWidget.cpp
@@ -100,32 +100,16 @@ void QtTreeWidget::handleCollapsed(const QModelIndex& index) {
 }
 
 void QtTreeWidget::handleModelItemExpanded(const QModelIndex& index, bool shouldExpand) {
-	if (this->isExpanded(index) == shouldExpand) {
+	if (!index.isValid()) {
 		return;
 	}
-	//setExpanded(index, shouldExpand);
-	if (shouldExpand) {
-		expand(index);
-		emit expanded(index);
-	} else {
-		collapse(index);
-		emit collapsed(index);
+	bool alreadyRight = this->isExpanded(index) == shouldExpand;
+	if (alreadyRight) {
+		return;
 	}
+	setExpanded(index, shouldExpand);
 }
 
-// void QtTreeWidget::handleDataChanged(const QModelIndex& topLeft, const QModelIndex& /*bottomRight*/) {
-// 	//in our model, this is only thrown with topLeft == bottomRight
-// 	if (!topLeft.isValid()) {
-// 		return;
-// 	}
-// 	QtTreeWidgetItem* qtItem = static_cast<QtTreeWidgetItem*>(topLeft.internalPointer());
-// 	if (qtItem) {
-// 		setExpanded(topLeft, qtItem->isExpanded());
-// 		//qDebug() << "Item changed, passing expanded state to view: " << qtItem->isExpanded() << " giving an expanded state of " << isExpanded(topLeft);
-// 	}
-
-// }
-
 void QtTreeWidget::drawBranches(QPainter*, const QRect&, const QModelIndex&) const {
 }
 
diff --git a/Swift/QtUI/Roster/RosterModel.cpp b/Swift/QtUI/Roster/RosterModel.cpp
index 12cedda..e5a938e 100644
--- a/Swift/QtUI/Roster/RosterModel.cpp
+++ b/Swift/QtUI/Roster/RosterModel.cpp
@@ -33,31 +33,26 @@ void RosterModel::setRoster(Roster* roster) {
 	if (!roster_) return;
 	roster->onChildrenChanged.connect(boost::bind(&RosterModel::handleChildrenChanged, this, _1));
 	roster->onDataChanged.connect(boost::bind(&RosterModel::handleDataChanged, this, _1));
-	roster->onGroupAdded.connect(boost::bind(&RosterModel::handleGroupAdded, this, _1));
-	emit layoutChanged();
-}
-
-void RosterModel::handleGroupAdded(GroupRosterItem* group) {
-	emit itemExpanded(index(group), group->isExpanded());
+	reLayout();
 }
 
-void RosterModel::handleChildrenChanged(GroupRosterItem* group) {
-	foreach (RosterItem* item, group->getDisplayedChildren()) {
+void RosterModel::reLayout() {
+	emit layoutChanged();
+	foreach (RosterItem* item, roster_->getRoot()->getDisplayedChildren()) {
 		GroupRosterItem* child = dynamic_cast<GroupRosterItem*>(item);
 		if (!child) continue;
 		emit itemExpanded(index(child), child->isExpanded());
 	}
-	emit layoutChanged();
+}
+
+void RosterModel::handleChildrenChanged(GroupRosterItem* /*group*/) {
+	reLayout();
 }							  
 
 void RosterModel::handleDataChanged(RosterItem* item) {
 	Q_ASSERT(item);
 	QModelIndex modelIndex = index(item);
 	if (modelIndex.isValid()) {
-		GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item);
-		if (group) {
-			emit itemExpanded(modelIndex, group->isExpanded());
-		}
 		emit dataChanged(modelIndex, modelIndex);
 	}
 }
@@ -167,6 +162,12 @@ QModelIndex RosterModel::index(int row, int column, const QModelIndex& parent) c
 
 QModelIndex RosterModel::index(RosterItem* item) const {
 	GroupRosterItem* parent = item->getParent();
+	/* Recursive check that it's ok to create such an item 
+		Assuming there are more contacts in a group than groups in a 
+		group, this could save a decent chunk of search time at startup.*/
+	if (parent != roster_->getRoot() && !index(parent).isValid()) {
+		return QModelIndex();
+	}
 	for (size_t i = 0; i < parent->getDisplayedChildren().size(); i++) {
 		if (parent->getDisplayedChildren()[i] == item) {
 			return createIndex(i, 0, item);
diff --git a/Swift/QtUI/Roster/RosterModel.h b/Swift/QtUI/Roster/RosterModel.h
index 10aeccd..4d9e03c 100644
--- a/Swift/QtUI/Roster/RosterModel.h
+++ b/Swift/QtUI/Roster/RosterModel.h
@@ -39,7 +39,6 @@ namespace Swift {
 		private:
 			void handleDataChanged(RosterItem* item);
 			void handleChildrenChanged(GroupRosterItem* item);
-			void handleGroupAdded(GroupRosterItem* group);
 			RosterItem* getItem(const QModelIndex& index) const;
 			QColor intToColor(int color) const;
 			QColor getTextColor(RosterItem* item) const;
@@ -49,6 +48,7 @@ namespace Swift {
 			QString getStatusText(RosterItem* item) const;
 			QIcon getPresenceIcon(RosterItem* item) const;
 			int getChildCount(RosterItem* item) const;
+			void reLayout();
 			Roster* roster_;
 			QtTreeWidget* view_;
 	};
diff --git a/Swiften/Roster/GroupRosterItem.cpp b/Swiften/Roster/GroupRosterItem.cpp
index 7ce57d2..e5490e2 100644
--- a/Swiften/Roster/GroupRosterItem.cpp
+++ b/Swiften/Roster/GroupRosterItem.cpp
@@ -24,6 +24,12 @@ bool GroupRosterItem::isExpanded() const {
 	return expanded_;
 }
 
+/**
+	This has no effect, and is only used by the UI.
+	If reTransmit is specified, dataChanged will be emitted on a change -
+	This may be undesireable if called from the UI, so you can use reTransmit=false
+	to avoid a loop in this case.
+ */
 void GroupRosterItem::setExpanded(bool expanded) {
 	expanded_ = expanded;
 }
@@ -33,7 +39,6 @@ const std::vector<RosterItem*>& GroupRosterItem::getChildren() const {
 }
 
 const std::vector<RosterItem*>& GroupRosterItem::getDisplayedChildren() const {
-//	std::cout << "Fetching displayed children for " << getDisplayName() << " and found " << displayedChildren_.size() << std::endl;
 	return displayedChildren_;
 }
 
@@ -110,7 +115,6 @@ bool GroupRosterItem::itemLessThan(const RosterItem* left, const RosterItem* rig
 		if (rightContact) {
 			return true;
 		}
-//		std::cout << "Comparing groups " << left->getSortableDisplayName() << " and " << right->getSortableDisplayName() << std::endl;
 		return left->getSortableDisplayName() < right->getSortableDisplayName();
 	}
 }
@@ -131,8 +135,8 @@ void GroupRosterItem::setDisplayed(RosterItem* item, bool displayed) {
 	} else {
 		displayedChildren_.erase(std::remove(displayedChildren_.begin(), displayedChildren_.end(), item), displayedChildren_.end());
 	}
-	onDataChanged();
 	onChildrenChanged();
+	onDataChanged();
 }
 
 void GroupRosterItem::handleDataChanged(RosterItem* /*item*/) {
@@ -158,8 +162,8 @@ void GroupRosterItem::handleChildrenChanged(GroupRosterItem* group) {
 		displayedChildren_.erase(std::remove(displayedChildren_.begin(), displayedChildren_.end(), group), displayedChildren_.end());
 	}
 	if (oldSize != getDisplayedChildren().size()) {
-		onDataChanged();
 		onChildrenChanged();
+		onDataChanged();
 	}
 }
 
diff --git a/Swiften/Roster/Roster.cpp b/Swiften/Roster/Roster.cpp
index caf2b5e..a83ea89 100644
--- a/Swiften/Roster/Roster.cpp
+++ b/Swiften/Roster/Roster.cpp
@@ -23,6 +23,7 @@ namespace Swift {
 
 Roster::Roster() {
 	root_ = new GroupRosterItem("Dummy-Root", NULL);
+	root_->onChildrenChanged.connect(boost::bind(&Roster::handleChildrenChanged, this, root_));
 }
 
 Roster::~Roster() {
@@ -52,7 +53,6 @@ GroupRosterItem* Roster::getGroup(const String& groupName) {
 	}
 	GroupRosterItem* group = new GroupRosterItem(groupName, root_);
 	root_->addChild(group);
-//	std::cout << "Added " << groupName << " to root" << std::endl;
 	group->onChildrenChanged.connect(boost::bind(&Roster::handleChildrenChanged, this, group));
 	group->onDataChanged.connect(boost::bind(&Roster::handleDataChanged, this, group));
 	return group;
@@ -155,9 +155,7 @@ void Roster::filterContact(ContactRosterItem* contact, GroupRosterItem* group) {
 	}
 	group->setDisplayed(contact, filters_.size() == 0 || !hide);
 	int newDisplayedSize = group->getDisplayedChildren().size();
-//	std::cout << ", new size = " << newDisplayedSize << std::endl;
 	if (oldDisplayedSize == 0 && newDisplayedSize > 0) {
-//		std::cout << "Newly created" << std::endl;
 		onGroupAdded(group);
 	}
 }
-- 
cgit v0.10.2-6-g49f6