changeset 11523:1116993aadd2

[gaim-migrate @ 13771] Incorporated Autorecon's code into the core. Removed the Disconnected window Shows connection errors in status box. This works _ok_ when signed on with a single account, but won't currently Handle multiple accounts at all. I wanted to get this in before going to bed tonight, so I can work on it later, though. Feel free to help. committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Mon, 12 Sep 2005 06:46:43 +0000
parents a26eb48d1953
children 4fd0c3a663b8
files src/gtkconn.c src/gtkstatusbox.c
diffstat 2 files changed, 77 insertions(+), 378 deletions(-) [+]
line wrap: on
line diff
--- a/src/gtkconn.c	Mon Sep 12 06:04:27 2005 +0000
+++ b/src/gtkconn.c	Mon Sep 12 06:46:43 2005 +0000
@@ -38,6 +38,17 @@
 #include "gtkdialogs.h"
 #include "gtkutils.h"
 
+#define INITIAL_RECON_DELAY 8000
+#define MAX_RECON_DELAY 2048000
+
+typedef struct {
+	int delay;
+	guint timeout;
+} GaimAutoRecon;
+
+static GHashTable *hash = NULL;
+static GSList *accountReconnecting = NULL;
+
 static void gaim_gtk_connection_connect_progress(GaimConnection *gc,
 		const char *text, size_t step, size_t step_count)
 {
@@ -52,10 +63,18 @@
 static void gaim_gtk_connection_connected(GaimConnection *gc)
 {
 	GaimGtkBuddyList *gtkblist = gaim_gtk_blist_get_default_gtk_blist();
+	GaimAccount *account = NULL;
 	if (!gtkblist)
 		return;
 	gtk_gaim_status_box_set_connecting(GTK_GAIM_STATUS_BOX(gtkblist->statusbox),
 					   (gaim_connections_get_connecting() != NULL));
+	account = gaim_connection_get_account(gc);
+	g_hash_table_remove(hash, account);
+	if (accountReconnecting == NULL)
+		return;
+	accountReconnecting = g_slist_remove(accountReconnecting, account);
+	if (accountReconnecting == NULL)
+		gtk_gaim_status_box_set_error(GTK_GAIM_STATUS_BOX(gtkblist->statusbox), NULL);
 	gaim_gtk_blist_update_protocol_actions();
 }
 
@@ -79,411 +98,89 @@
 {
 }
 
-/*
- * The next couple of functions deal with the disconnected dialog
- */
-struct disconnect_window {
-	GtkWidget *window;
-	GtkWidget *treeview;
-	GtkWidget *sw;
-	GtkWidget *label;
-	GtkWidget *reconnect_btn;
-	GtkWidget *reconnectall_btn;
-};
-static struct disconnect_window *disconnect_window = NULL;
-
-static void disconnect_connection_change_cb(GaimConnection *gc, void *data);
 
-/*
- * Destroy the dialog and remove the signals associated with it.
- */
-static void disconnect_window_hide()
+static void
+free_auto_recon(gpointer data)
 {
-	gaim_signal_disconnect(gaim_connections_get_handle(), "signed-on",
-			disconnect_window, GAIM_CALLBACK(disconnect_connection_change_cb));
+	GaimAutoRecon *info = data;
 
-	gaim_signal_disconnect(gaim_connections_get_handle(), "signed-off",
-			disconnect_window, GAIM_CALLBACK(disconnect_connection_change_cb));
+	if (info->timeout != 0)
+		g_source_remove(info->timeout);
 
-	gtk_widget_destroy(disconnect_window->window);
-	g_free(disconnect_window);
-	disconnect_window = NULL;
+	g_free(info);
 }
 
-/*
- * Make sure the Reconnect and Reconnect All buttons are correctly 
- * shown or hidden.  Also make sure the label on the Reconnect 
- * button is correctly set to either Reconnect or Remove.  If there 
- * is more than one account then make sure the GtkTreeView is shown.  
- * If there are no accounts disconnected then hide the dialog.
- */
-static void disconnect_window_update_buttons()
+static gboolean
+do_signon(gpointer data)
 {
-	GtkTreeIter iter;
-	GtkTreeSelection *sel;
-	GtkTreeModel *model;
-	char *label_text;
-	GaimAccount *account = NULL;
-
-	if (disconnect_window == NULL)
-		return;
+	GaimAccount *account = data;
+	GaimAutoRecon *info;
 
-	model = gtk_tree_view_get_model(GTK_TREE_VIEW(disconnect_window->treeview));
-
-	if (model == NULL)
-		return;
-
-	if (!gtk_tree_model_get_iter_first(model, &iter)) {
-		/* No more accounts being shown.  Caloo calay! */
-		disconnect_window_hide();
-		return;
-	}
+	gaim_debug(GAIM_DEBUG_INFO, "autorecon", "do_signon called\n");
+	g_return_val_if_fail(account != NULL, FALSE);
+	info = g_hash_table_lookup(hash, account);
 
-	/*
-	 * If we have more than one disconnected account then show the
-	 * GtkTreeView and the "Reconnect All" button
-	 */
-	if (gtk_tree_model_iter_next(model, &iter)) {
-		gtk_widget_show_all(disconnect_window->sw);
-		gtk_widget_show(disconnect_window->reconnectall_btn);
-	} else {
-		gtk_widget_hide_all(disconnect_window->sw);
-		gtk_widget_hide(disconnect_window->reconnectall_btn);
-	}
+	if (g_list_index(gaim_accounts_get_all(), account) < 0)
+		return FALSE;
+
+	if (info)
+		info->timeout = 0;
 
-	/*
-	 * Make sure one of the accounts is selected.
-	 */
-	sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(disconnect_window->treeview));
-	if (!gtk_tree_selection_get_selected(sel, &model, &iter)) {
-		gtk_tree_model_get_iter_first(model, &iter);
-		gtk_tree_selection_select_iter(sel, &iter);
-	}
+	gaim_debug(GAIM_DEBUG_INFO, "autorecon", "calling gaim_account_connect\n");
+	gaim_account_connect(account);
+	gaim_debug(GAIM_DEBUG_INFO, "autorecon", "done calling gaim_account_connect\n");
 
-	/*
-	 * Update the Reconnect/Remove button appropriately and set the
-	 * label in the dialog to what it should be.  If there is only
-	 * one account in the tree model, and that account is connected,
-	 * then we don't show the remove button.
-	 */
-	gtk_tree_model_get(model, &iter, 3, &label_text, 4, &account, -1);
-	gtk_button_set_label(GTK_BUTTON(disconnect_window->reconnect_btn),
-		gaim_account_is_disconnected(account) ? _("Reconnect") : _("_Remove"));
-	gtk_label_set_markup(GTK_LABEL(disconnect_window->label), label_text);
-	gtk_dialog_set_response_sensitive(GTK_DIALOG(disconnect_window->window), GTK_RESPONSE_ACCEPT, TRUE);
-	gtk_tree_model_get_iter_first(model, &iter);
-	if (gaim_account_is_disconnected(account) || gtk_tree_model_iter_next(model, &iter))
-		gtk_widget_show(disconnect_window->reconnect_btn);
-	else
-		gtk_widget_hide(disconnect_window->reconnect_btn);
-	g_free(label_text);
+	return FALSE;
 }
 
-static void disconnect_response_cb(GtkDialog *dialog, gint id, GtkWidget *widget)
+static void gaim_gtk_connection_report_disconnect(GaimConnection *gc, const char *text)
 {
-	GtkTreeIter iter;
-	GtkTreeSelection *sel = NULL;
-	GtkTreeModel *model = NULL;
+	GaimGtkBuddyList *list = gaim_gtk_blist_get_default_gtk_blist();
 	GaimAccount *account = NULL;
-
-	switch (id) {
-	case GTK_RESPONSE_APPLY: /* Reconnect All */
-		model = gtk_tree_view_get_model(GTK_TREE_VIEW(disconnect_window->treeview));
-		if (gtk_tree_model_get_iter_first(model, &iter)) {
-			/* tree rows to be deleted */
-			GList *l_del = NULL, *l_del_iter = NULL;
-			/* accounts to be connected */
-			GList *l_accts = NULL, *l_accts_iter = NULL;
-			do {
-				GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
-				GtkTreeRowReference* del_row = gtk_tree_row_reference_new(model, path);
-				l_del = g_list_append(l_del, del_row);
-				gtk_tree_path_free(path);
-
-				gtk_tree_model_get(model, &iter, 4, &account, -1);
-				if (gaim_account_is_disconnected(account) && g_list_find(l_accts, account) == NULL)
-					l_accts = g_list_append(l_accts, account);
-			} while (gtk_tree_model_iter_next(model, &iter));
+	GaimAutoRecon *info;
+	GSList* listAccount;
 
-			/* remove all rows */
-			/* We could just do the following, but we only want to remove accounts 
-			 * that are going to be reconnected, not accounts that have already 
-			 * been reconnected.
-			 */
-			/* gtk_list_store_clear(GTK_LIST_STORE(model)); */
-			l_del_iter = l_del;
-			while (l_del_iter != NULL) {
-				GtkTreeRowReference* del_row = l_del_iter->data;
-				GtkTreePath *path = gtk_tree_row_reference_get_path(del_row);
-				if (gtk_tree_model_get_iter(model, &iter, path))
-					gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
-				gtk_tree_path_free(path);
-				gtk_tree_row_reference_free(del_row);
-				l_del_iter = l_del_iter->next;
-			}
-			g_list_free(l_del);
-
-			/* reconnect disconnected accounts */
-			l_accts_iter = l_accts;
-			while (l_accts_iter != NULL) {
-				account = l_accts_iter->data;
-				gaim_account_connect(account);
-				l_accts_iter = l_accts_iter->next;
-			}
-			g_list_free(l_accts);
-
-		}
-
-		disconnect_window_update_buttons();
+	gtk_gaim_status_box_set_error(GTK_GAIM_STATUS_BOX(list->statusbox), text);
+	if (hash == NULL) {
+	       	hash = g_hash_table_new_full(g_int_hash, g_int_equal, NULL,
+	       	free_auto_recon);
+	}
+	account = gaim_connection_get_account(gc);
+	info = g_hash_table_lookup(hash, account);
+	if (accountReconnecting)
+		listAccount = g_slist_find(accountReconnecting, account);
+	else
+		listAccount = NULL;
 
-		break;
-
-	case GTK_RESPONSE_ACCEPT: /* Reconnect Selected */
-		model = gtk_tree_view_get_model(GTK_TREE_VIEW(disconnect_window->treeview));
-
-		/*
-		 * If we have more than one account disconnection displayed, then 
-		 * the scroll window is visible and we should use the selected 
-		 * account to reconnect.
-		 */
-		if (GTK_WIDGET_VISIBLE(disconnect_window->sw)) {
-			sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(disconnect_window->treeview));
-			if (!gtk_tree_selection_get_selected(sel, &model, &iter))
-				return;
+	if (!gc->wants_to_die) {
+		if (info == NULL) {
+			info = g_new0(GaimAutoRecon, 1);
+			g_hash_table_insert(hash, account, info);
+			info->delay = INITIAL_RECON_DELAY;
 		} else {
-			/* There is only one account disconnection, so reconnect to it. */
-			if (!gtk_tree_model_get_iter_first(model, &iter))
-				return;
+			info->delay = MIN(2 * info->delay, MAX_RECON_DELAY);
+			if (info->timeout != 0)
+				g_source_remove(info->timeout);
 		}
+		info->timeout = g_timeout_add(info->delay, do_signon, account);
 
-		/* remove all disconnections of the account to be reconnected */
-		gtk_tree_model_get(model, &iter, 4, &account, -1);
-		if (gtk_tree_model_get_iter_first(model, &iter)) {
-			GList *l_del = NULL, *l_del_iter = NULL;
-			GaimAccount *account2 = NULL;
-			do {
-				gtk_tree_model_get(model, &iter, 4, &account2, -1);
-				if (account2 == account) {
-					GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
-					GtkTreeRowReference* del_row = gtk_tree_row_reference_new(model, path);
-					l_del = g_list_append(l_del, del_row);
-					gtk_tree_path_free(path);
-				}
-			} while (gtk_tree_model_iter_next(model, &iter));
+		if (!listAccount)
+			accountReconnecting = g_slist_prepend(accountReconnecting, account);
+	} else if (info != NULL) {
+		g_hash_table_remove(hash, account);
 
-			l_del_iter = l_del;
-			while (l_del_iter != NULL) {
-				GtkTreeRowReference* del_row = l_del_iter->data;
-				GtkTreePath *path = gtk_tree_row_reference_get_path(del_row);
-				if (gtk_tree_model_get_iter(model, &iter, path))
-					gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
-				gtk_tree_path_free(path);
-				gtk_tree_row_reference_free(del_row);
-				l_del_iter = l_del_iter->next;
-			}
-			g_list_free(l_del);
-		}
-
-		gaim_account_connect(account);
-		disconnect_window_update_buttons();
-
-		break;
-
-	case GTK_RESPONSE_DELETE_EVENT:
-	case GTK_RESPONSE_CLOSE:
-		disconnect_window_hide();
-		break;
-
+		if (listAccount)
+			accountReconnecting = g_slist_delete_link(accountReconnecting, listAccount);
 	}
 }
 
-/*
- * Called whenever a different account is selected in the GtkListWhatever.
- */
-static void disconnect_tree_cb(GtkTreeSelection *sel, GtkTreeModel *model)
-{
-	disconnect_window_update_buttons();
-}
-
-/*
- * Update the icon next to the account in the disconnect dialog, and 
- * gray the Reconnect All button if there is only 1 disconnected account.
- */
-static void disconnect_connection_change_cb(GaimConnection *gc, void *data) {
-	GaimAccount *account = gaim_connection_get_account(gc);
-	GtkTreeIter iter;
-	GtkTreeModel *model;
-	GdkPixbuf *icon;
-	GdkPixbuf *scale;
-	GList *l_disc_accts = NULL;
-
-	if (disconnect_window == NULL)
-		return;
-
-	model = gtk_tree_view_get_model(GTK_TREE_VIEW(disconnect_window->treeview));
-	icon = gaim_gtk_create_prpl_icon(account);
-	scale = gdk_pixbuf_scale_simple(icon, 16, 16, GDK_INTERP_BILINEAR);
-
-	/* Mark all disconnections w/ the account type disconnected /w grey icon */
-	if (gaim_account_is_disconnected(account))
-		gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.0, FALSE);
-
-	gtk_tree_model_get_iter_first(model, &iter);
-	do {
-		GaimAccount *account2 = NULL;
-		/* Gray out the icon if this row is for this account */
-		gtk_tree_model_get(model, &iter, 4, &account2, -1);
-		if (account2 == account)
-			gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, scale, -1);
-
-		/* Add  */
-		if (gaim_account_is_disconnected(account2)
-				&& g_list_find(l_disc_accts, account2) == NULL)
-			l_disc_accts = g_list_append(l_disc_accts, account2);
-	} while (gtk_tree_model_iter_next(model, &iter));
-
-	gtk_dialog_set_response_sensitive(
-		GTK_DIALOG(disconnect_window->window),
-		GTK_RESPONSE_APPLY,
-		g_list_length(l_disc_accts) > 1);
-	g_list_free(l_disc_accts);
-
-	if (icon != NULL)
-		g_object_unref(G_OBJECT(icon));
-	if (scale  != NULL)
-		g_object_unref(G_OBJECT(scale));
-
-	disconnect_window_update_buttons();
-}
-
-static void
-gaim_gtk_connection_report_disconnect(GaimConnection *gc, const char *text)
-{
-	char *label_text = NULL;
-	GtkTreeIter new_iter;
-	GtkListStore *list_store;
-	GtkTreeViewColumn *col;
-	GtkTreeSelection *sel = NULL;
-
-	label_text = g_strdup_printf(_("<span weight=\"bold\" size=\"larger\">%s has been disconnected.</span>\n\n%s\n%s"),
-				     gaim_account_get_username(gaim_connection_get_account(gc)), gaim_date_full(),
-				     text ? text : _("Reason Unknown."));
-
-	/* Build the window if it isn't there yet */
-	if (!disconnect_window) {
-		GtkWidget *hbox, *vbox, *img;
-		GtkCellRenderer *rend, *rend2;
-
-		disconnect_window = g_new0(struct disconnect_window, 1);
-		disconnect_window->window = gtk_dialog_new_with_buttons(_("Disconnected"), NULL, GTK_DIALOG_NO_SEPARATOR, NULL);
-		g_signal_connect(G_OBJECT(disconnect_window->window), "response", G_CALLBACK(disconnect_response_cb), disconnect_window);
-
-		gtk_container_set_border_width(GTK_CONTAINER(disconnect_window->window), GAIM_HIG_BOX_SPACE);
-		gtk_window_set_resizable(GTK_WINDOW(disconnect_window->window), FALSE);
-		gtk_dialog_set_has_separator(GTK_DIALOG(disconnect_window->window), FALSE);
-		gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(disconnect_window->window)->vbox), GAIM_HIG_BORDER);
-		gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(disconnect_window->window)->vbox), GAIM_HIG_BOX_SPACE);
-
-		hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER);
-		gtk_container_add(GTK_CONTAINER(GTK_DIALOG(disconnect_window->window)->vbox), hbox);
-		img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG);
-		gtk_misc_set_alignment(GTK_MISC(img), 0, 0);
-		gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0);
-
-		vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER);
-		gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
-
-		disconnect_window->label = gtk_label_new(label_text);
-
-		gtk_label_set_line_wrap(GTK_LABEL(disconnect_window->label), TRUE);
-		gtk_misc_set_alignment(GTK_MISC(disconnect_window->label), 0, 0);
-		gtk_box_pack_start(GTK_BOX(vbox), disconnect_window->label, FALSE, FALSE, 0);
-
-		disconnect_window->reconnect_btn = gtk_dialog_add_button(
-			GTK_DIALOG(disconnect_window->window),
-			_("_Reconnect"),
-			GTK_RESPONSE_ACCEPT);
-
-		disconnect_window->reconnectall_btn = gtk_dialog_add_button(
-			GTK_DIALOG(disconnect_window->window),
-			_("Reconnect _All"),
-			GTK_RESPONSE_APPLY);
-
-		gtk_dialog_add_button(
-			GTK_DIALOG(disconnect_window->window),
-			GTK_STOCK_CLOSE,
-			GTK_RESPONSE_CLOSE);
-
-		gtk_widget_show_all(disconnect_window->window);
-
-		/* Tree View */
-		disconnect_window->sw = gtk_scrolled_window_new(NULL,NULL);
-		gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(disconnect_window->sw), GTK_SHADOW_IN);
-		gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(disconnect_window->sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
-		gtk_box_pack_start(GTK_BOX(vbox), disconnect_window->sw, TRUE, TRUE, 0);
-
-		list_store = gtk_list_store_new(5, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
-		disconnect_window->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store));
-
-		rend = gtk_cell_renderer_pixbuf_new();
-		rend2 = gtk_cell_renderer_text_new();
-		col = gtk_tree_view_column_new();
-		gtk_tree_view_column_set_title(col, _("Account"));
-		gtk_tree_view_column_pack_start(col, rend, FALSE);
-		gtk_tree_view_column_pack_start(col, rend2, FALSE);
-		gtk_tree_view_column_set_attributes(col, rend, "pixbuf", 0, NULL);
-		gtk_tree_view_column_set_attributes(col, rend2, "text", 1, NULL);
-		gtk_tree_view_append_column (GTK_TREE_VIEW(disconnect_window->treeview), col);
-
-		rend = gtk_cell_renderer_text_new();
-		col = gtk_tree_view_column_new_with_attributes (_("Time"),
-								rend, "text", 2, NULL);
-		gtk_tree_view_append_column (GTK_TREE_VIEW(disconnect_window->treeview), col);
-
-		g_object_unref(G_OBJECT(list_store));
-		gtk_container_add(GTK_CONTAINER(disconnect_window->sw), disconnect_window->treeview);
-
-		sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (disconnect_window->treeview));
-		gtk_widget_set_size_request(disconnect_window->treeview, -1, 96);
-		g_signal_connect (G_OBJECT (sel), "changed",
-				  G_CALLBACK (disconnect_tree_cb), list_store);
-
-		gaim_signal_connect(gaim_connections_get_handle(), "signed-on",
-				disconnect_window, GAIM_CALLBACK(disconnect_connection_change_cb), NULL);
-
-		gaim_signal_connect(gaim_connections_get_handle(), "signed-off",
-				disconnect_window, GAIM_CALLBACK(disconnect_connection_change_cb), NULL);
-	} else
-		list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(disconnect_window->treeview)));
-
-	/* Add this account to our list of disconnected accounts */
-	gtk_list_store_append(list_store, &new_iter);
-	gtk_list_store_set(list_store, &new_iter,
-			   0, NULL,
-			   1, gaim_account_get_username(gaim_connection_get_account(gc)),
-			   2, gaim_date_full(),
-			   3, label_text,
-			   4, gaim_connection_get_account(gc), -1);
-
-	/* Make sure the newly disconnected account is selected */
-	sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(disconnect_window->treeview));
-	gtk_tree_selection_select_iter(sel, &new_iter);
-
-	disconnect_window_update_buttons();
-
-	g_free(label_text);
-}
-/*
- * End of disconnected dialog
- */
-
 static GaimConnectionUiOps conn_ui_ops =
 {
 	gaim_gtk_connection_connect_progress,
 	gaim_gtk_connection_connected,
 	gaim_gtk_connection_disconnected,
 	gaim_gtk_connection_notice,
-	gaim_gtk_connection_report_disconnect
+	gaim_gtk_connection_report_disconnect,
 };
 
 GaimConnectionUiOps *
--- a/src/gtkstatusbox.c	Mon Sep 12 06:04:27 2005 +0000
+++ b/src/gtkstatusbox.c	Mon Sep 12 06:46:43 2005 +0000
@@ -190,12 +190,12 @@
 		text = g_strdup_printf("%s", title);
 	}
 
-	if (status_box->error)
+	if (status_box->connecting)
+		pixbuf = status_box->connecting_pixbufs[status_box->connecting_index];
+	else if (status_box->error)
 		pixbuf = status_box->error_pixbuf;
 	else if (status_box->typing)
 		pixbuf = status_box->typing_pixbufs[status_box->typing_index];
-	else if (status_box->connecting)
-		pixbuf = status_box->connecting_pixbufs[status_box->connecting_index];
 	else
 		pixbuf = status_box->pixbuf;
 
@@ -421,6 +421,8 @@
 void
 gtk_gaim_status_box_set_error(GtkGaimStatusBox *status_box, const gchar *error)
 {
+	if (status_box->error)
+		g_free(status_box->error);
 	status_box->error = g_strdup(error);
 	gtk_gaim_status_box_refresh(status_box);
 }