# HG changeset patch
# Node ID 977592d81ffd
# Parent  4fd76e8dedf8
diff --git a/pidgin/pidginconversationwindow.c b/pidgin/pidginconversationwindow.c
--- a/pidgin/pidginconversationwindow.c
+++ b/pidgin/pidginconversationwindow.c
@@ -20,6 +20,8 @@
  * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
+#include <glib/gi18n-lib.h>
+
 #include "pidginconversationwindow.h"
 
 #include "gtkconv.h"
@@ -45,6 +47,8 @@
 	GtkTreeStore *model;
 
 	GtkWidget *stack;
+
+	GtkTreePath *conversation_path;
 };
 
 G_DEFINE_TYPE(PidginConversationWindow, pidgin_conversation_window,
@@ -83,27 +87,6 @@
 }
 
 static gboolean
-pidgin_conversation_window_foreach_destroy(GtkTreeModel *model,
-                                           GtkTreePath *path,
-                                           GtkTreeIter *iter,
-                                           gpointer data)
-{
-	PurpleConversation *conversation = NULL;
-
-	gtk_tree_model_get(model, iter,
-	                   PIDGIN_CONVERSATION_WINDOW_COLUMN_OBJECT, &conversation,
-	                   -1);
-
-	if(conversation != NULL) {
-		pidgin_conversation_detach(conversation);
-
-		gtk_list_store_remove(GTK_LIST_STORE(model), iter);
-	}
-
-	return FALSE;
-}
-
-static gboolean
 pidgin_conversation_window_key_pressed_cb(GtkEventControllerKey *controller,
                                           guint keyval,
                                           G_GNUC_UNUSED guint keycode,
@@ -152,8 +135,32 @@
 	PidginConversationWindow *window = PIDGIN_CONVERSATION_WINDOW(obj);
 
 	if(GTK_IS_TREE_MODEL(window->model)) {
-		gtk_tree_model_foreach(GTK_TREE_MODEL(window->model),
-		                       pidgin_conversation_window_foreach_destroy, window);
+		GtkTreeModel *model = GTK_TREE_MODEL(window->model);
+		GtkTreeIter parent, iter;
+
+		gtk_tree_model_get_iter(model, &parent, window->conversation_path);
+		if(gtk_tree_model_iter_children(model, &iter, &parent)) {
+			gboolean valid = FALSE;
+
+			/* gtk_tree_store_remove moves the iter to the next item at the
+			 * same level, so we abuse that to do our iteration.
+			 */
+			do {
+				PurpleConversation *conversation = NULL;
+
+				gtk_tree_model_get(model, &iter,
+				                   PIDGIN_CONVERSATION_WINDOW_COLUMN_OBJECT, &conversation,
+				                   -1);
+
+				if(PURPLE_IS_CONVERSATION(conversation)) {
+					pidgin_conversation_detach(conversation);
+
+					valid = gtk_tree_store_remove(window->model, &iter);
+				}
+			} while(valid);
+		}
+
+		g_clear_pointer(&window->conversation_path, gtk_tree_path_free);
 	}
 
 	G_OBJECT_CLASS(pidgin_conversation_window_parent_class)->dispose(obj);
@@ -165,6 +172,7 @@
 	GtkWidget *menubar = NULL;
 	GMenuModel *model = NULL;
 	GtkEventController *key = NULL;
+	GtkTreeIter iter;
 
 	gtk_widget_init_template(GTK_WIDGET(window));
 
@@ -189,6 +197,14 @@
 	                 window);
 	g_object_set_data_full(G_OBJECT(window), "key-press-controller", key,
 	                       g_object_unref);
+
+	/* Add our toplevels to the tree store. */
+	gtk_tree_store_append(window->model, &iter, NULL);
+	gtk_tree_store_set(window->model, &iter,
+	                   PIDGIN_CONVERSATION_WINDOW_COLUMN_MARKUP, _("Conversations"),
+	                   -1);
+	window->conversation_path = gtk_tree_model_get_path(GTK_TREE_MODEL(window->model),
+	                                                    &iter);
 }
 
 static void
@@ -255,12 +271,26 @@
                                PurpleConversation *conversation)
 {
 	PidginConversation *gtkconv = NULL;
-	GtkTreeIter iter;
+	GtkTreeIter parent, iter;
+	GtkTreeModel *model = NULL;
 	const gchar *markup = NULL;
+	gboolean expand = FALSE;
 
 	g_return_if_fail(PIDGIN_IS_CONVERSATION_WINDOW(window));
 	g_return_if_fail(PURPLE_IS_CONVERSATION(conversation));
 
+	model = GTK_TREE_MODEL(window->model);
+	if(!gtk_tree_model_get_iter(model, &parent, window->conversation_path)) {
+		/* If we can't find the conversation_path we have to bail. */
+		g_warning("couldn't get an iterator to conversation_path");
+
+		return;
+	}
+
+	if(!gtk_tree_model_iter_has_child(model, &parent)) {
+		expand = TRUE;
+	}
+
 	markup = purple_conversation_get_name(conversation);
 
 	gtkconv = PIDGIN_CONVERSATION(conversation);
@@ -280,12 +310,19 @@
 		}
 	}
 
-	gtk_tree_store_prepend(window->model, &iter, NULL);
+	gtk_tree_store_prepend(window->model, &iter, &parent);
 	gtk_tree_store_set(window->model, &iter,
 	                   PIDGIN_CONVERSATION_WINDOW_COLUMN_OBJECT, conversation,
 	                   PIDGIN_CONVERSATION_WINDOW_COLUMN_MARKUP, markup,
 	                   -1);
 
+	/* If we just added the first child, expand the parent. */
+	if(expand) {
+		gtk_tree_view_expand_row(GTK_TREE_VIEW(window->view),
+		                         window->conversation_path, FALSE);
+	}
+
+
 	if(!gtk_widget_is_visible(GTK_WIDGET(window))) {
 		gtk_widget_show_all(GTK_WIDGET(window));
 	}
@@ -295,19 +332,27 @@
 pidgin_conversation_window_remove(PidginConversationWindow *window,
                                   PurpleConversation *conversation)
 {
-	GtkTreeIter iter;
+	GtkTreeIter parent, iter;
+	GtkTreeModel *model = NULL;
 	GObject *obj = NULL;
 
 	g_return_if_fail(PIDGIN_IS_CONVERSATION_WINDOW(window));
 	g_return_if_fail(PURPLE_IS_CONVERSATION(conversation));
 
-	if(!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(window->model), &iter)) {
-		/* The tree is empty. */
+	model = GTK_TREE_MODEL(window->model);
+
+	if(!gtk_tree_model_get_iter(model, &parent, window->conversation_path)) {
+		/* The path is somehow invalid, so bail... */
+		return;
+	}
+
+	if(!gtk_tree_model_iter_children(model, &iter, &parent)) {
+		/* The conversations iter has no children. */
 		return;
 	}
 
 	do {
-		gtk_tree_model_get(GTK_TREE_MODEL(window->model), &iter,
+		gtk_tree_model_get(model, &iter,
 		                   PIDGIN_CONVERSATION_WINDOW_COLUMN_OBJECT, &obj,
 		                   -1);
 
@@ -320,7 +365,7 @@
 		}
 
 		g_clear_object(&obj);
-	} while(gtk_tree_model_iter_next(GTK_TREE_MODEL(window->model), &iter));
+	} while(gtk_tree_model_iter_next(model, &iter));
 }
 
 guint
