# HG changeset patch # User Sean Egan # Date 1126507603 0 # Node ID 1116993aadd2e5772050dfa55722d8305dc91f7e # Parent a26eb48d19530fd85df81579b70b20daccd805d4 [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 diff -r a26eb48d1953 -r 1116993aadd2 src/gtkconn.c --- 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(_("%s has been disconnected.\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 * diff -r a26eb48d1953 -r 1116993aadd2 src/gtkstatusbox.c --- 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); }