changeset 21583:21cbdaf265f6

This fixes the problem where all accounts are disabled due to connection errors, which leaves you with no enabled accounts, and therefore the buddy list flips into "Welcome to Pidgin!" mode, thereby hiding all the connection error mini dialogs. I'm amazed I haven't heard any noise about this problem. I attempted to fix up PidginScrollBook, and got part way there, but gtk_container_get_children now doesn't return any kids. I suspect this is due to the child widgets we care about already being children of the notebook. I don't know nearly enough gtk to be sure if this is good or not. There are still some buglets in how/when the buddy list notebook page is selected, and I have a feeling some of the gtkblist.c changes could be improved, but I believe this is more usable than before. This took far too much time. References #3989
author Stu Tomlinson <stu@nosnilmot.com>
date Sun, 18 Nov 2007 21:03:29 +0000
parents b00659aa0acf
children 055e1abac7cf 8fcd795f627e
files pidgin/gtkblist.c pidgin/gtkscrollbook.c pidgin/gtkscrollbook.h
diffstat 3 files changed, 100 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/pidgin/gtkblist.c	Sun Nov 18 17:34:39 2007 +0000
+++ b/pidgin/gtkblist.c	Sun Nov 18 21:03:29 2007 +0000
@@ -4226,18 +4226,44 @@
 		pidgin_blist_sort_method_set(val);
 }
 
-static void account_modified(PurpleAccount *account, PidginBuddyList *gtkblist)
-{
+static gboolean pidgin_blist_select_notebook_page_cb(gpointer user_data)
+{
+	PidginBuddyList *gtkblist = (PidginBuddyList *)user_data;
+	int errors = 0;
 	GList *list;
-	if (!gtkblist)
-		return;
-
-	if ((list = purple_accounts_get_all_active()) != NULL) {
+	PidginBuddyListPrivate *priv;
+
+	priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist);
+
+	/* this is far too ugly thanks to me not wanting to fix #3989 properly right now */
+	if (priv->error_scrollbook != NULL) {
+#if GTK_CHECK_VERSION(2,2,0)
+		errors = gtk_notebook_get_n_pages(GTK_NOTEBOOK(priv->error_scrollbook->notebook));
+#else
+		errors = g_list_length(GTK_NOTEBOOK(priv->error_scrollbook->notebook)->children);
+#endif
+	}
+	if ((list = purple_accounts_get_all_active()) != NULL || errors ||
+	    (list = gtk_container_get_children(GTK_CONTAINER(priv->error_scrollbook)))) {
 		gtk_notebook_set_current_page(GTK_NOTEBOOK(gtkblist->notebook), 1);
 		g_list_free(list);
 	} else
 		gtk_notebook_set_current_page(GTK_NOTEBOOK(gtkblist->notebook), 0);
 
+	return FALSE;
+}
+
+static void pidgin_blist_select_notebook_page(PidginBuddyList *gtkblist)
+{
+	purple_timeout_add(0, pidgin_blist_select_notebook_page_cb, gtkblist);
+}
+
+static void account_modified(PurpleAccount *account, PidginBuddyList *gtkblist)
+{
+	if (!gtkblist)
+		return;
+
+	pidgin_blist_select_notebook_page(gtkblist);
 	update_menu_bar(gtkblist);
 }
 
@@ -4248,7 +4274,7 @@
 	if (!gtkblist)
 		return;
 
-	update_menu_bar(gtkblist);
+	account_modified(account, gtkblist);
 }
 
 static gboolean
@@ -4429,8 +4455,10 @@
                                PurpleAccount *account)
 {
 	GtkWidget *widget = find_child_widget_by_account(container, account);
-	if(widget)
+	if(widget) {
+		gtk_container_remove(container, widget);
 		gtk_widget_destroy(widget);
+	}
 }
 
 /* Generic error buttons */
@@ -4438,12 +4466,14 @@
 static void
 generic_error_modify_cb(PurpleAccount *account)
 {
+	purple_account_clear_current_error(account);
 	pidgin_account_dialog_show(PIDGIN_MODIFY_ACCOUNT_DIALOG, account);
 }
 
 static void
 generic_error_enable_cb(PurpleAccount *account)
 {
+	purple_account_clear_current_error(account);
 	purple_account_set_enabled(account, purple_core_get_ui(), TRUE);
 }
 
@@ -4530,7 +4560,7 @@
 {
 	PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist);
 	remove_child_widget_by_account(
-		GTK_CONTAINER(priv->error_scrollbook->notebook), account);
+		GTK_CONTAINER(priv->error_scrollbook), account);
 }
 
 
@@ -4712,6 +4742,7 @@
 	else
 		pidgin_blist_update_account_error_state(account, NULL);
 
+	pidgin_blist_select_notebook_page(gtkblist);
 	/* Don't bother updating the error if it hasn't changed.  This stops
 	 * URGENT being repeatedly set for network errors whenever they try to
 	 * reconnect.
@@ -4902,7 +4933,6 @@
 	GtkWidget *sw;
 	GtkWidget *sep;
 	GtkWidget *label;
-	GList *accounts;
 	char *pretty, *tmp;
 	GtkAccelGroup *accel_group;
 	GtkTreeSelection *selection;
@@ -4993,10 +5023,7 @@
 	gtkblist->vbox = gtk_vbox_new(FALSE, 0);
 	gtk_notebook_append_page(GTK_NOTEBOOK(gtkblist->notebook), gtkblist->vbox, NULL);
 	gtk_widget_show_all(gtkblist->notebook);
-	if ((accounts = purple_accounts_get_all_active())) {
-		g_list_free(accounts);
-		gtk_notebook_set_current_page(GTK_NOTEBOOK(gtkblist->notebook), 1);
-	}
+	pidgin_blist_select_notebook_page(gtkblist);
 
 	ebox = gtk_event_box_new();
 	gtk_box_pack_start(GTK_BOX(gtkblist->vbox), ebox, FALSE, FALSE, 0);
--- a/pidgin/gtkscrollbook.c	Sun Nov 18 17:34:39 2007 +0000
+++ b/pidgin/gtkscrollbook.c	Sun Nov 18 21:03:29 2007 +0000
@@ -146,21 +146,74 @@
 static void
 pidgin_scroll_book_add(GtkContainer *container, GtkWidget *widget)
 {
+	GList *children;
+	PidginScrollBook *scroll_book;
+
+	g_return_if_fail(GTK_IS_WIDGET (widget));
+	g_return_if_fail (widget->parent == NULL);
+
+	scroll_book = PIDGIN_SCROLL_BOOK(container);
+	children = scroll_book->children;
+	children = g_list_append(children, widget);
 	gtk_widget_show(widget);
 	gtk_notebook_append_page(GTK_NOTEBOOK(PIDGIN_SCROLL_BOOK(container)->notebook), widget, NULL);
 	page_count_change_cb(PIDGIN_SCROLL_BOOK(container));
 }
 
 static void
+pidgin_scroll_book_remove(GtkContainer *container, GtkWidget *widget)
+{
+	int page;
+	GList *children;
+	GtkWidget *child;
+	PidginScrollBook *scroll_book;
+	g_return_if_fail(GTK_IS_WIDGET(widget));
+
+	scroll_book = PIDGIN_SCROLL_BOOK(container);
+	children = scroll_book->children;
+
+	while (children) {
+		child = children->data;
+		if (child == widget) {
+			gtk_widget_unparent (widget);
+			children = g_list_remove_link (scroll_book->children, children);
+			g_list_free(children);
+			break;
+		}
+	}
+
+	page = gtk_notebook_page_num(GTK_NOTEBOOK(PIDGIN_SCROLL_BOOK(container)->notebook), widget);
+	if (page >= 0) {
+		gtk_notebook_remove_page(GTK_NOTEBOOK(PIDGIN_SCROLL_BOOK(container)->notebook), page);
+	}
+}
+
+static void
 pidgin_scroll_book_forall(GtkContainer *container,
 			   gboolean include_internals,
 			   GtkCallback callback,
 			   gpointer callback_data)
 {
-	PidginScrollBook *scroll_book = PIDGIN_SCROLL_BOOK(container);
-	if (include_internals)
+	GList *children;
+	PidginScrollBook *scroll_book;
+
+	g_return_if_fail(GTK_IS_CONTAINER(container));
+
+	scroll_book = PIDGIN_SCROLL_BOOK(container);
+
+	if (include_internals) {
 		(*callback)(scroll_book->hbox, callback_data);
-	(*callback)(scroll_book->notebook, callback_data);
+		(*callback)(scroll_book->notebook, callback_data);
+	}
+
+	children = scroll_book->children;
+
+	while (children) {
+		GtkWidget *child;
+		child = children->data;
+		children = children->next;
+		(*callback)(child, callback_data);
+	}
 }
 
 static void
@@ -169,6 +222,7 @@
 	GtkContainerClass *container_class = (GtkContainerClass*)klass;
 
 	container_class->add = pidgin_scroll_book_add;
+	container_class->remove = pidgin_scroll_book_remove;
 	container_class->forall = pidgin_scroll_book_forall;	
 	
 }
--- a/pidgin/gtkscrollbook.h	Sun Nov 18 17:34:39 2007 +0000
+++ b/pidgin/gtkscrollbook.h	Sun Nov 18 21:03:29 2007 +0000
@@ -29,10 +29,6 @@
 
 #include <gtk/gtk.h>
 
-#if !GTK_CHECK_VERSION(2,4,0)
-#include "pidgincombobox.h"
-#endif
-
 G_BEGIN_DECLS
 
 #define PIDGIN_TYPE_SCROLL_BOOK             (pidgin_scroll_book_get_type ())
@@ -54,9 +50,9 @@
 	GtkWidget *label;
 	GtkWidget *left_arrow;
 	GtkWidget *right_arrow;
+	GList *children;
 	
 	/* Padding for future expansion */
-	void (*_gtk_reserved0) (void);
 	void (*_gtk_reserved1) (void);
 	void (*_gtk_reserved2) (void);
 	void (*_gtk_reserved3) (void);
@@ -66,7 +62,7 @@
 
 struct _PidginScrollBookClass
 {
-	GtkComboBoxClass parent_class;
+	GtkContainerClass parent_class;
 
 	/* Padding for future expansion */
 	void (*_gtk_reserved0) (void);