pidgin/pidgin

Parents d8e0a25a57ac
Children 45fef383cf60
Remove the account error scrollbook from the blist as notifications have replaced it.

Also clear account errors when we attempt a new connection which made clearing
the errors after the account has connected redundant.

Testing Done:
Caused the same account to get disconnected between pidgin 2 and 3 to verify notifications were working as expected.

Bugs closed: PIDGIN-17640

Reviewed at https://reviews.imfreedom.org/r/1521/
--- a/libpurple/account.c Tue Jul 05 02:03:30 2022 -0500
+++ b/libpurple/account.c Wed Jul 06 05:47:52 2022 -0500
@@ -1112,6 +1112,8 @@
g_return_if_fail(PURPLE_IS_ACCOUNT(account));
+ purple_account_clear_current_error(account);
+
username = purple_account_get_username(account);
if (!purple_account_get_enabled(account)) {
--- a/libpurple/accounts.c Tue Jul 05 02:03:30 2022 -0500
+++ b/libpurple/accounts.c Wed Jul 06 05:47:52 2022 -0500
@@ -637,7 +637,6 @@
gpointer unused)
{
PurpleAccount *account = purple_connection_get_account(gc);
- purple_account_clear_current_error(account);
purple_signal_emit(purple_accounts_get_handle(), "account-signed-on",
account);
--- a/pidgin/gtkblist.c Tue Jul 05 02:03:30 2022 -0500
+++ b/pidgin/gtkblist.c Wed Jul 06 05:47:52 2022 -0500
@@ -97,16 +97,6 @@
/* GBoxed reference count */
int box_count;
- /* Used to hold error minidialogs. Gets packed
- * inside PidginBuddyList.error_buttons
- */
- PidginScrollBook *error_scrollbook;
-
- /* Pointer to the mini-dialog about having signed on elsewhere, if one
- * is showing; %NULL otherwise.
- */
- PidginMiniDialog *signed_on_elsewhere;
-
guint select_notebook_page_timeout;
@@ -3097,453 +3087,6 @@
pidgin_blist_sort_method_set(val);
}
-/***********************************/
-/* Connection error handling stuff */
-/***********************************/
-
-#define OBJECT_DATA_KEY_ACCOUNT "account"
-#define DO_NOT_CLEAR_ERROR "do-not-clear-error"
-
-static gboolean
-find_account_widget(GObject *widget,
- PurpleAccount *account)
-{
- if (g_object_get_data(widget, OBJECT_DATA_KEY_ACCOUNT) == account)
- return 0; /* found */
- else
- return 1;
-}
-
-static void
-pack_protocol_icon_start(GtkWidget *box,
- PurpleAccount *account)
-{
- GdkPixbuf *pixbuf;
- GtkWidget *image;
-
- pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL);
- if (pixbuf != NULL) {
- image = gtk_image_new_from_pixbuf(pixbuf);
- g_object_unref(pixbuf);
-
- gtk_box_pack_start(GTK_BOX(box), image, FALSE, FALSE, 0);
- }
-}
-
-static void
-add_error_dialog(PidginBuddyList *gtkblist,
- GtkWidget *dialog)
-{
- PidginBuddyListPrivate *priv =
- pidgin_buddy_list_get_instance_private(gtkblist);
- gtk_container_add(GTK_CONTAINER(priv->error_scrollbook), dialog);
-}
-
-static GtkWidget *
-find_child_widget_by_account(GtkContainer *container,
- PurpleAccount *account)
-{
- GList *l = NULL;
- GList *children = NULL;
- GtkWidget *ret = NULL;
- /* XXX: Workaround for the currently incomplete implementation of PidginScrollBook */
- if(PIDGIN_IS_SCROLL_BOOK(container)) {
- PidginScrollBook *scroll_book = PIDGIN_SCROLL_BOOK(container);
- GtkWidget *notebook = pidgin_scroll_book_get_notebook(scroll_book);
- container = GTK_CONTAINER(notebook);
- }
- children = gtk_container_get_children(container);
- l = g_list_find_custom(children, account, (GCompareFunc) find_account_widget);
- if (l)
- ret = GTK_WIDGET(l->data);
- g_list_free(children);
- return ret;
-}
-
-static void
-remove_child_widget_by_account(GtkContainer *container,
- PurpleAccount *account)
-{
- GtkWidget *widget = find_child_widget_by_account(container, account);
- if(widget) {
- /* Since we are destroying the widget in response to a change in
- * error, we should not clear the error.
- */
- g_object_set_data(G_OBJECT(widget), DO_NOT_CLEAR_ERROR,
- GINT_TO_POINTER(TRUE));
- gtk_widget_destroy(widget);
- }
-}
-
-/* Generic error buttons */
-
-static void
-generic_account_connect_cb(G_GNUC_UNUSED PidginMiniDialog *mini_dialog,
- G_GNUC_UNUSED GtkButton *button,
- gpointer user_data)
-{
- PurpleAccount *account = user_data;
- purple_account_connect(account);
-}
-
-static void
-generic_error_modify_cb(G_GNUC_UNUSED PidginMiniDialog *mini_dialog,
- G_GNUC_UNUSED GtkButton *button,
- gpointer user_data)
-{
- PurpleAccount *account = user_data;
- purple_account_clear_current_error(account);
- pidgin_account_dialog_show(PIDGIN_MODIFY_ACCOUNT_DIALOG, account);
-}
-
-static void
-generic_error_enable_cb(G_GNUC_UNUSED PidginMiniDialog *mini_dialog,
- G_GNUC_UNUSED GtkButton *button,
- gpointer user_data)
-{
- PurpleAccount *account = user_data;
- purple_account_clear_current_error(account);
- purple_account_set_enabled(account, TRUE);
-}
-
-static void
-generic_error_destroy_cb(GtkWidget *dialog,
- PurpleAccount *account)
-{
- /* If the error dialog is being destroyed in response to the
- * account-error-changed signal, we don't want to clear the current
- * error.
- */
- if (g_object_get_data(G_OBJECT(dialog), DO_NOT_CLEAR_ERROR) == NULL)
- purple_account_clear_current_error(account);
-}
-
-#define SSL_FAQ_URI "https://developer.pidgin.im/wiki/FAQssl"
-
-static void
-ssl_faq_clicked_cb(PidginMiniDialog *mini_dialog,
- GtkButton *button,
- gpointer ignored)
-{
- purple_notify_uri(NULL, SSL_FAQ_URI);
-}
-
-static void
-add_generic_error_dialog(PurpleAccount *account,
- const PurpleConnectionErrorInfo *err)
-{
- GtkWidget *mini_dialog;
- const char *username = purple_account_get_username(account);
- gboolean enabled = purple_account_get_enabled(account);
- char *primary;
-
- if (enabled)
- primary = g_strdup_printf(_("%s disconnected"), username);
- else
- primary = g_strdup_printf(_("%s disabled"), username);
-
- mini_dialog = pidgin_mini_dialog_new_with_buttons(
- primary, err->description, "dialog-error", account,
- enabled ? _("Reconnect") : _("Re-enable"),
- enabled ? generic_account_connect_cb : generic_error_enable_cb,
- _("Modify Account"), generic_error_modify_cb,
- NULL);
-
- g_free(primary);
-
- g_object_set_data(G_OBJECT(mini_dialog), OBJECT_DATA_KEY_ACCOUNT,
- account);
-
- if(err->type == PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT)
- pidgin_mini_dialog_add_non_closing_button(PIDGIN_MINI_DIALOG(mini_dialog),
- _("SSL FAQs"), ssl_faq_clicked_cb, NULL);
-
- g_signal_connect_after(mini_dialog, "destroy",
- (GCallback)generic_error_destroy_cb,
- account);
-
- add_error_dialog(gtkblist, mini_dialog);
-}
-
-static void
-remove_generic_error_dialog(PurpleAccount *account)
-{
- PidginBuddyListPrivate *priv =
- pidgin_buddy_list_get_instance_private(gtkblist);
- remove_child_widget_by_account(
- GTK_CONTAINER(priv->error_scrollbook), account);
-}
-
-
-static void
-update_generic_error_message(PurpleAccount *account,
- const char *description)
-{
- PidginBuddyListPrivate *priv =
- pidgin_buddy_list_get_instance_private(gtkblist);
- GtkWidget *mini_dialog = find_child_widget_by_account(
- GTK_CONTAINER(priv->error_scrollbook), account);
- pidgin_mini_dialog_set_description(PIDGIN_MINI_DIALOG(mini_dialog),
- description);
-}
-
-
-/* Notifications about accounts which were disconnected with
- * PURPLE_CONNECTION_ERROR_NAME_IN_USE
- */
-
-typedef void (*AccountFunction)(PurpleAccount *);
-
-static void
-elsewhere_foreach_account(PidginMiniDialog *mini_dialog,
- AccountFunction f)
-{
- PurpleAccount *account;
- GList *labels = gtk_container_get_children(
- GTK_CONTAINER(mini_dialog->contents));
- GList *l;
-
- for (l = labels; l; l = l->next) {
- account = g_object_get_data(G_OBJECT(l->data), OBJECT_DATA_KEY_ACCOUNT);
- if (account)
- f(account);
- else
- purple_debug_warning("gtkblist", "mini_dialog's child "
- "didn't have an account stored in it!");
- }
- g_list_free(labels);
-}
-
-static void
-enable_account(PurpleAccount *account)
-{
- purple_account_set_enabled(account, TRUE);
-}
-
-static void
-reconnect_elsewhere_accounts(PidginMiniDialog *mini_dialog,
- GtkButton *button,
- gpointer unused)
-{
- elsewhere_foreach_account(mini_dialog, enable_account);
-}
-
-static void
-clear_elsewhere_errors(PidginMiniDialog *mini_dialog,
- gpointer unused)
-{
- elsewhere_foreach_account(mini_dialog, purple_account_clear_current_error);
-}
-
-static void
-ensure_signed_on_elsewhere_minidialog(PidginBuddyList *gtkblist)
-{
- PidginBuddyListPrivate *priv =
- pidgin_buddy_list_get_instance_private(gtkblist);
- PidginMiniDialog *mini_dialog;
-
- if(priv->signed_on_elsewhere)
- return;
-
- mini_dialog = priv->signed_on_elsewhere =
- pidgin_mini_dialog_new(_("Welcome back!"), NULL, "pidgin-disconnect");
-
- pidgin_mini_dialog_add_button(mini_dialog, _("Re-enable"),
- reconnect_elsewhere_accounts, NULL);
-
- /* Make dismissing the dialog clear the errors. The "destroy" signal
- * does not appear to fire at quit, which is fortunate!
- */
- g_signal_connect(G_OBJECT(mini_dialog), "destroy",
- (GCallback) clear_elsewhere_errors, NULL);
-
- add_error_dialog(gtkblist, GTK_WIDGET(mini_dialog));
-
- /* Set priv->signed_on_elsewhere to NULL when the dialog is destroyed */
- g_signal_connect(G_OBJECT(mini_dialog), "destroy",
- (GCallback) gtk_widget_destroyed, &(priv->signed_on_elsewhere));
-}
-
-static void
-update_signed_on_elsewhere_minidialog_title(void)
-{
- PidginBuddyListPrivate *priv =
- pidgin_buddy_list_get_instance_private(gtkblist);
- PidginMiniDialog *mini_dialog = priv->signed_on_elsewhere;
- guint accounts;
- char *title;
-
- if (mini_dialog == NULL)
- return;
-
- accounts = pidgin_mini_dialog_get_num_children(mini_dialog);
- if (accounts == 0) {
- gtk_widget_destroy(GTK_WIDGET(mini_dialog));
- return;
- }
-
- title = g_strdup_printf(
- ngettext("%d account was disabled because you signed on from another location:",
- "%d accounts were disabled because you signed on from another location:",
- accounts),
- accounts);
- pidgin_mini_dialog_set_description(mini_dialog, title);
- g_free(title);
-}
-
-static GtkWidget *
-create_account_label(PurpleAccount *account)
-{
- GtkWidget *hbox, *label;
- const char *username = purple_account_get_username(account);
- char *markup;
- char *description;
-
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
- g_object_set_data(G_OBJECT(hbox), OBJECT_DATA_KEY_ACCOUNT, account);
-
- pack_protocol_icon_start(hbox, account);
-
- label = gtk_label_new(NULL);
- markup = g_strdup_printf("<span size=\"smaller\">%s</span>", username);
- gtk_label_set_markup(GTK_LABEL(label), markup);
- g_free(markup);
- gtk_label_set_xalign(GTK_LABEL(label), 0);
- gtk_label_set_yalign(GTK_LABEL(label), 0);
- g_object_set(G_OBJECT(label), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
- description = purple_account_get_current_error(account)->description;
- if (description != NULL && *description != '\0')
- gtk_widget_set_tooltip_text(label, description);
- gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
-
- return hbox;
-}
-
-static void
-add_to_signed_on_elsewhere(PurpleAccount *account)
-{
- PidginBuddyListPrivate *priv =
- pidgin_buddy_list_get_instance_private(gtkblist);
- PidginMiniDialog *mini_dialog;
- GtkWidget *account_label;
-
- ensure_signed_on_elsewhere_minidialog(gtkblist);
- mini_dialog = priv->signed_on_elsewhere;
-
- if(find_child_widget_by_account(GTK_CONTAINER(mini_dialog->contents), account))
- return;
-
- account_label = create_account_label(account);
- gtk_box_pack_start(mini_dialog->contents, account_label, FALSE, FALSE, 0);
- gtk_widget_show_all(account_label);
-
- update_signed_on_elsewhere_minidialog_title();
-}
-
-static void
-remove_from_signed_on_elsewhere(PurpleAccount *account)
-{
- PidginBuddyListPrivate *priv =
- pidgin_buddy_list_get_instance_private(gtkblist);
- PidginMiniDialog *mini_dialog = priv->signed_on_elsewhere;
- if(mini_dialog == NULL)
- return;
-
- remove_child_widget_by_account(GTK_CONTAINER(mini_dialog->contents), account);
-
- update_signed_on_elsewhere_minidialog_title();
-}
-
-
-static void
-update_signed_on_elsewhere_tooltip(PurpleAccount *account,
- const char *description)
-{
- PidginBuddyListPrivate *priv =
- pidgin_buddy_list_get_instance_private(gtkblist);
- GtkContainer *c = GTK_CONTAINER(priv->signed_on_elsewhere->contents);
- GtkWidget *label = find_child_widget_by_account(c, account);
- gtk_widget_set_tooltip_text(label, description);
-}
-
-
-/* Call appropriate error notification code based on error types */
-static void
-update_account_error_state(PurpleAccount *account,
- const PurpleConnectionErrorInfo *old,
- const PurpleConnectionErrorInfo *new,
- PidginBuddyList *gtkblist)
-{
- gboolean descriptions_differ;
- const char *desc;
-
- if (old == NULL && new == NULL)
- return;
-
- if (old != NULL && new == NULL) {
- if(old->type == PURPLE_CONNECTION_ERROR_NAME_IN_USE)
- remove_from_signed_on_elsewhere(account);
- else
- remove_generic_error_dialog(account);
- return;
- }
-
- if (old == NULL && new != NULL) {
- if(new->type == PURPLE_CONNECTION_ERROR_NAME_IN_USE)
- add_to_signed_on_elsewhere(account);
- else
- add_generic_error_dialog(account, new);
- return;
- }
-
- /* else, new and old are both non-NULL */
-
- descriptions_differ = !purple_strequal(old->description, new->description);
- desc = new->description;
-
- switch (new->type) {
- case PURPLE_CONNECTION_ERROR_NAME_IN_USE:
- if (old->type == PURPLE_CONNECTION_ERROR_NAME_IN_USE
- && descriptions_differ) {
- update_signed_on_elsewhere_tooltip(account, desc);
- } else {
- remove_generic_error_dialog(account);
- add_to_signed_on_elsewhere(account);
- }
- break;
- default:
- if (old->type == PURPLE_CONNECTION_ERROR_NAME_IN_USE) {
- remove_from_signed_on_elsewhere(account);
- add_generic_error_dialog(account, new);
- } else if (descriptions_differ) {
- update_generic_error_message(account, desc);
- }
- break;
- }
-}
-
-/* In case accounts are loaded before the blist (which they currently are),
- * let's call update_account_error_state ourselves on every account's current
- * state when the blist starts.
- */
-static void
-show_initial_account_errors(PidginBuddyList *gtkblist)
-{
- PurpleAccountManager *manager = NULL;
- GList *l = NULL;
- PurpleAccount *account;
- const PurpleConnectionErrorInfo *err;
-
- manager = purple_account_manager_get_default();
- l = purple_account_manager_get_all(manager);
- for(; l; l = l->next) {
- account = l->data;
- err = purple_account_get_current_error(account);
-
- update_account_error_state(account, NULL, err, gtkblist);
- }
-}
-
/* This assumes there are not things like groupless buddies or multi-leveled groups.
* I'm sure other things in this code assumes that also.
*/
@@ -3733,7 +3276,6 @@
static void pidgin_blist_show(PurpleBuddyList *list)
{
- PidginBuddyListPrivate *priv;
GSimpleActionGroup *action_group = NULL;
void *handle;
GtkTreeViewColumn *column;
@@ -3747,7 +3289,6 @@
}
gtkblist = PIDGIN_BUDDY_LIST(list);
- priv = pidgin_buddy_list_get_instance_private(gtkblist);
gtkblist->window = pidgin_contact_list_window_new();
g_signal_connect(G_OBJECT(gtkblist->window), "focus-in-event",
@@ -3840,10 +3381,6 @@
gtkblist->scrollbook = pidgin_scroll_book_new();
gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->scrollbook, FALSE, FALSE, 0);
- priv->error_scrollbook = PIDGIN_SCROLL_BOOK(pidgin_scroll_book_new());
- gtk_box_pack_start(GTK_BOX(gtkblist->vbox),
- GTK_WIDGET(priv->error_scrollbook), FALSE, FALSE, 0);
-
/* Update some dynamic things */
pidgin_blist_update_sort_methods();
@@ -3863,11 +3400,6 @@
/* Setup some purple signal handlers. */
- handle = purple_accounts_get_handle();
- purple_signal_connect(handle, "account-error-changed", gtkblist,
- G_CALLBACK(update_account_error_state),
- gtkblist);
-
handle = purple_conversations_get_handle();
purple_signal_connect(handle, "conversation-updated", gtkblist,
G_CALLBACK(conversation_updated_cb),
@@ -3882,8 +3414,6 @@
G_CALLBACK(conversation_created_cb),
gtkblist);
- show_initial_account_errors(gtkblist);
-
/* emit our created signal */
handle = pidgin_blist_get_handle();
purple_signal_emit(handle, "gtkblist-created", list);