From 6625c07d980f0761f64bde24d3b7f63cfc7e21d1 Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Mon, 15 Nov 2010 15:22:11 +0000
Subject: Sanitise the Roster widget on signout.

This will hopefully avoid crashes in the RosterDelegate due to
Qt believing that the RosterItems still exist and that it can read
them.

Unverified as I can't reproduce the crash on this machine, but
hopefully
Resolves: #678

diff --git a/Swift/Controllers/RosterController.cpp b/Swift/Controllers/RosterController.cpp
index ed311d9..038a883 100644
--- a/Swift/Controllers/RosterController.cpp
+++ b/Swift/Controllers/RosterController.cpp
@@ -72,6 +72,7 @@ RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, Avata
 RosterController::~RosterController() {
 	delete offlineFilter_;
 	delete expandiness_;
+	mainWindow_->setRosterModel(NULL);
 	if (mainWindow_->canDelete()) {
 		delete mainWindow_;
 	}
diff --git a/Swift/Controllers/UIInterfaces/MainWindow.h b/Swift/Controllers/UIInterfaces/MainWindow.h
index 3f37fc8..0d33466 100644
--- a/Swift/Controllers/UIInterfaces/MainWindow.h
+++ b/Swift/Controllers/UIInterfaces/MainWindow.h
@@ -29,6 +29,7 @@ namespace Swift {
 			virtual void setMyAvatarPath(const String& path) = 0;
 			virtual void setMyStatusText(const String& status) = 0;
 			virtual void setMyStatusType(StatusShow::Type type) = 0;
+			/** Must be able to cope with NULL to clear the roster */
 			virtual void setRosterModel(Roster* roster) = 0;
 			virtual void setConnecting() = 0;
 			
diff --git a/Swift/QtUI/Roster/RosterModel.cpp b/Swift/QtUI/Roster/RosterModel.cpp
index c2d4147..a6f40bb 100644
--- a/Swift/QtUI/Roster/RosterModel.cpp
+++ b/Swift/QtUI/Roster/RosterModel.cpp
@@ -30,15 +30,19 @@ RosterModel::~RosterModel() {
 
 void RosterModel::setRoster(Roster* roster) {
 	roster_ = roster;
-	if (!roster_) return;
-	roster->onChildrenChanged.connect(boost::bind(&RosterModel::handleChildrenChanged, this, _1));
-	roster->onDataChanged.connect(boost::bind(&RosterModel::handleDataChanged, this, _1));
+	if (roster_) {
+		roster->onChildrenChanged.connect(boost::bind(&RosterModel::handleChildrenChanged, this, _1));
+		roster->onDataChanged.connect(boost::bind(&RosterModel::handleDataChanged, this, _1));
+	}
 	reLayout();
 }
 
 void RosterModel::reLayout() {
 	//emit layoutChanged();
 	reset();
+	if (!roster_) {
+		return;
+	}
 	foreach (RosterItem* item, roster_->getRoot()->getDisplayedChildren()) {
 		GroupRosterItem* child = dynamic_cast<GroupRosterItem*>(item);
 		if (!child) continue;
@@ -161,6 +165,9 @@ QIcon RosterModel::getPresenceIcon(RosterItem* item) const {
 
 
 QModelIndex RosterModel::index(int row, int column, const QModelIndex& parent) const {
+	if (!roster_) {
+		return QModelIndex();
+	}
 	GroupRosterItem* parentItem;
 	if (!parent.isValid()) {
 		//top level
@@ -177,7 +184,7 @@ QModelIndex RosterModel::index(RosterItem* item) const {
 	/* 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 == NULL || (parent != roster_->getRoot() && !index(parent).isValid())) {
+	if (parent == NULL || roster_ == NULL || (parent != roster_->getRoot() && !index(parent).isValid())) {
 		return QModelIndex();
 	}
 	for (size_t i = 0; i < parent->getDisplayedChildren().size(); i++) {
@@ -189,7 +196,7 @@ QModelIndex RosterModel::index(RosterItem* item) const {
 }
 
 QModelIndex RosterModel::parent(const QModelIndex& child) const {
-	if (!child.isValid()) {
+	if (!roster_ || !child.isValid()) {
 		return QModelIndex();
 	}
 	
-- 
cgit v0.10.2-6-g49f6