--- a/pidgin/pidginconversationwindow.c Mon Jan 24 20:16:44 2022 -0600
+++ b/pidgin/pidginconversationwindow.c Mon Jan 24 20:29:28 2022 -0600
@@ -20,6 +20,8 @@
* along with this program; if not, see <https://www.gnu.org/licenses/>.
+#include <glib/gi18n-lib.h> #include "pidginconversationwindow.h"
@@ -45,6 +47,8 @@
+ GtkTreePath *conversation_path; G_DEFINE_TYPE(PidginConversationWindow, pidgin_conversation_window,
@@ -83,27 +87,6 @@
-pidgin_conversation_window_foreach_destroy(GtkTreeModel *model,
- PurpleConversation *conversation = NULL;
- gtk_tree_model_get(model, iter,
- PIDGIN_CONVERSATION_WINDOW_COLUMN_OBJECT, &conversation,
- if(conversation != NULL) {
- pidgin_conversation_detach(conversation);
- gtk_list_store_remove(GTK_LIST_STORE(model), iter);
pidgin_conversation_window_key_pressed_cb(GtkEventControllerKey *controller,
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. + PurpleConversation *conversation = NULL; + gtk_tree_model_get(model, &iter, + PIDGIN_CONVERSATION_WINDOW_COLUMN_OBJECT, &conversation, + if(PURPLE_IS_CONVERSATION(conversation)) { + pidgin_conversation_detach(conversation); + valid = gtk_tree_store_remove(window->model, &iter); + g_clear_pointer(&window->conversation_path, gtk_tree_path_free); G_OBJECT_CLASS(pidgin_conversation_window_parent_class)->dispose(obj);
@@ -162,6 +169,7 @@
pidgin_conversation_window_init(PidginConversationWindow *window) {
GtkEventController *key = NULL;
gtk_widget_init_template(GTK_WIDGET(window));
@@ -175,6 +183,14 @@
g_object_set_data_full(G_OBJECT(window), "key-press-controller", key,
+ /* 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"), + window->conversation_path = gtk_tree_model_get_path(GTK_TREE_MODEL(window->model), @@ -241,12 +257,26 @@
PurpleConversation *conversation)
PidginConversation *gtkconv = NULL;
+ 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"); + if(!gtk_tree_model_iter_has_child(model, &parent)) { markup = purple_conversation_get_name(conversation);
gtkconv = PIDGIN_CONVERSATION(conversation);
@@ -266,12 +296,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,
+ /* If we just added the first child, expand the parent. */ + 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));
@@ -281,19 +318,27 @@
pidgin_conversation_window_remove(PidginConversationWindow *window,
PurpleConversation *conversation)
+ GtkTreeIter parent, iter; + GtkTreeModel *model = 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... */ + if(!gtk_tree_model_iter_children(model, &iter, &parent)) { + /* The conversations iter has no children. */ - gtk_tree_model_get(GTK_TREE_MODEL(window->model), &iter,
+ gtk_tree_model_get(model, &iter, PIDGIN_CONVERSATION_WINDOW_COLUMN_OBJECT, &obj,
@@ -306,7 +351,7 @@
- } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(window->model), &iter));
+ } while(gtk_tree_model_iter_next(model, &iter));