comparison pidgin/gtkblist.c @ 21410:4ccc4ad0a8b0

Use PidginMiniDialog to display signed in elsewhere errors in the blist.
author Will Thompson <will.thompson@collabora.co.uk>
date Mon, 05 Nov 2007 01:19:51 +0000
parents c1c7e28223f8
children b089fd1ad059
comparison
equal deleted inserted replaced
21409:62a116ddc6e5 21410:4ccc4ad0a8b0
56 #include "gtkprivacy.h" 56 #include "gtkprivacy.h"
57 #include "gtkroomlist.h" 57 #include "gtkroomlist.h"
58 #include "gtkstatusbox.h" 58 #include "gtkstatusbox.h"
59 #include "gtkscrollbook.h" 59 #include "gtkscrollbook.h"
60 #include "gtkutils.h" 60 #include "gtkutils.h"
61 #include "pidgin/minidialog.h"
61 62
62 #include <gdk/gdkkeysyms.h> 63 #include <gdk/gdkkeysyms.h>
63 #include <gtk/gtk.h> 64 #include <gtk/gtk.h>
64 #include <gdk/gdk.h> 65 #include <gdk/gdk.h>
65 66
112 /** PidginScrollBook used to hold error minidialogs. Gets packed 113 /** PidginScrollBook used to hold error minidialogs. Gets packed
113 * inside PidginBuddyList.error_buttons 114 * inside PidginBuddyList.error_buttons
114 */ 115 */
115 GtkWidget *error_scrollbook; 116 GtkWidget *error_scrollbook;
116 117
117 /** List of #PurpleAccount that were disconnected with
118 * #PURPLE_CONNECTION_ERROR_NAME_IN_USE that have not been dealt with
119 * by the user.
120 */
121 GList *accounts_signed_on_elsewhere;
122 /** Pointer to the mini-dialog about having signed on elsewhere, if one 118 /** Pointer to the mini-dialog about having signed on elsewhere, if one
123 * is showing; @c NULL otherwise. 119 * is showing; @c NULL otherwise.
124 */ 120 */
125 GtkWidget *signed_on_elsewhere_minidialog; 121 PidginMiniDialog *signed_on_elsewhere;
126 GtkLabel *signed_on_elsewhere_minidialog_title;
127 GtkVBox *signed_on_elsewhere_minidialog_accounts;
128 } PidginBuddyListPrivate; 122 } PidginBuddyListPrivate;
129 123
130 #define PIDGIN_BUDDY_LIST_GET_PRIVATE(list) \ 124 #define PIDGIN_BUDDY_LIST_GET_PRIVATE(list) \
131 ((PidginBuddyListPrivate *)((list)->priv)) 125 ((PidginBuddyListPrivate *)((list)->priv))
132 126
4365 4359
4366 if (!GTK_WIDGET_HAS_FOCUS(gtkblist->window)) 4360 if (!GTK_WIDGET_HAS_FOCUS(gtkblist->window))
4367 pidgin_set_urgent(GTK_WINDOW(gtkblist->window), TRUE); 4361 pidgin_set_urgent(GTK_WINDOW(gtkblist->window), TRUE);
4368 } 4362 }
4369 4363
4364 static GtkWidget *
4365 find_child_widget_by_account(GtkContainer *container,
4366 PurpleAccount *account)
4367 {
4368 GList *l = NULL;
4369 GList *children = gtk_container_get_children(container);
4370 GtkWidget *ret = NULL;
4371 l = g_list_find_custom(children, account, (GCompareFunc) find_account_widget);
4372 if (l)
4373 ret = GTK_WIDGET(l->data);
4374 g_list_free(children);
4375 return ret;
4376 }
4377
4370 static void 4378 static void
4371 remove_child_widget_by_account(GtkContainer *container, 4379 remove_child_widget_by_account(GtkContainer *container,
4372 PurpleAccount *account) 4380 PurpleAccount *account)
4373 { 4381 {
4374 GList *l = NULL; 4382 GtkWidget *widget = find_child_widget_by_account(container, account);
4375 GList *children = gtk_container_get_children(container); 4383 if(widget)
4376 l = g_list_find_custom(children, account, (GCompareFunc) find_account_widget); 4384 gtk_widget_destroy(widget);
4377 if (l) { /* it may have already been removed by being acted on */
4378 gtk_widget_destroy(GTK_WIDGET(l->data));
4379 }
4380 g_list_free(children);
4381 } 4385 }
4382 4386
4383 /* Generic error buttons */ 4387 /* Generic error buttons */
4384 4388
4385 static void 4389 static void
4451 4455
4452 /* Notifications about accounts which were disconnected with 4456 /* Notifications about accounts which were disconnected with
4453 * PURPLE_CONNECTION_ERROR_NAME_IN_USE 4457 * PURPLE_CONNECTION_ERROR_NAME_IN_USE
4454 */ 4458 */
4455 4459
4460 typedef void (*AccountFunction)(PurpleAccount *);
4461
4456 static void 4462 static void
4457 destroy_signed_on_elsewhere_minidialog(PidginBuddyListPrivate *priv) 4463 elsewhere_foreach_account(PidginMiniDialog *mini_dialog,
4458 { 4464 AccountFunction f)
4459 if(priv->signed_on_elsewhere_minidialog == NULL) 4465 {
4466 PurpleAccount *account;
4467 GList *labels = gtk_container_get_children(
4468 GTK_CONTAINER(mini_dialog->contents));
4469 GList *l;
4470
4471 for (l = labels; l; l = l->next) {
4472 account = g_object_get_data(G_OBJECT(l->data), OBJECT_DATA_KEY_ACCOUNT);
4473 if (account)
4474 f(account);
4475 else
4476 purple_debug_warning("gtkblist", "mini_dialog's child "
4477 "didn't have an account stored in it!");
4478 }
4479 g_list_free(labels);
4480 }
4481
4482 static void
4483 enable_account(PurpleAccount *account)
4484 {
4485 purple_account_set_enabled(account, purple_core_get_ui(), TRUE);
4486 }
4487
4488 static void
4489 reconnect_elsewhere_accounts(PidginMiniDialog *mini_dialog,
4490 GtkButton *button,
4491 gpointer unused)
4492 {
4493 elsewhere_foreach_account(mini_dialog, enable_account);
4494 }
4495
4496 static void
4497 ignore_elsewhere_accounts(PidginMiniDialog *mini_dialog,
4498 GtkButton *button,
4499 gpointer unused)
4500 {
4501 elsewhere_foreach_account(mini_dialog, purple_account_clear_current_error);
4502 }
4503
4504 static void
4505 ensure_signed_on_elsewhere_minidialog(PidginBuddyList *gtkblist)
4506 {
4507 PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist);
4508 PidginMiniDialog *mini_dialog;
4509
4510 if(priv->signed_on_elsewhere)
4460 return; 4511 return;
4461 4512
4462 gtk_widget_destroy(priv->signed_on_elsewhere_minidialog); 4513 mini_dialog = priv->signed_on_elsewhere =
4463 priv->signed_on_elsewhere_minidialog = NULL; 4514 pidgin_mini_dialog_new(NULL, NULL, PIDGIN_STOCK_DISCONNECT);
4464 priv->signed_on_elsewhere_minidialog_accounts = NULL; 4515
4465 priv->signed_on_elsewhere_minidialog_title = NULL; 4516 pidgin_mini_dialog_add_button(mini_dialog, _("Re-enable"),
4466 } 4517 reconnect_elsewhere_accounts, NULL);
4467 4518
4468 static void 4519 pidgin_mini_dialog_add_button(mini_dialog, _("Ignore"),
4469 reconnect_elsewhere_accounts(PidginBuddyList *gtkblist) 4520 ignore_elsewhere_accounts, NULL);
4470 { 4521
4471 PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist); 4522 add_error_dialog(gtkblist, GTK_WIDGET(mini_dialog));
4472 GList *l; 4523
4473 PurpleAccount *account; 4524 /* Set priv->signed_on_elsewhere to NULL when it is destroyed */
4474 for (l = priv->accounts_signed_on_elsewhere; l; l = l->next) { 4525 g_signal_connect(G_OBJECT(mini_dialog), "destroy",
4475 account = l->data; 4526 (GCallback) gtk_widget_destroyed, &(priv->signed_on_elsewhere));
4476 purple_account_set_enabled(account, purple_core_get_ui(), TRUE);
4477 }
4478 g_list_free(priv->accounts_signed_on_elsewhere);
4479 priv->accounts_signed_on_elsewhere = NULL;
4480
4481 destroy_signed_on_elsewhere_minidialog(priv);
4482 }
4483
4484 static void
4485 ignore_elsewhere_accounts(PidginBuddyList *gtkblist)
4486 {
4487 PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist);
4488 GList *accounts_elsewhere, *l;
4489
4490 /* priv->accounts_signed_on_elsewhere gets changed in
4491 * update_account_error_state, which is called when
4492 * purple_account_clear_current_error emits account-error-changed. So
4493 * let's take a copy.
4494 *
4495 * (Or maybe we could just use while(priv->accounts_elsewhere) and rely
4496 * on it being ultimately reduced to NULL? But that sounds fragile.)
4497 */
4498 accounts_elsewhere = g_list_copy(priv->accounts_signed_on_elsewhere);
4499
4500 for (l = accounts_elsewhere; l != NULL; l = l->next)
4501 {
4502 PurpleAccount *account = l->data;
4503 purple_account_clear_current_error(account);
4504 }
4505
4506 g_list_free(accounts_elsewhere);
4507
4508 destroy_signed_on_elsewhere_minidialog(priv);
4509 }
4510
4511 static GtkWidget *
4512 make_elsewhere_minidialog_button(const char *text,
4513 GCallback callback)
4514 {
4515 GtkWidget *button = gtk_button_new();
4516 GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
4517 GtkWidget *label = gtk_label_new(NULL);
4518 char *button_text =
4519 g_strdup_printf("<span size=\"smaller\">%s</span>", text);
4520
4521 gtk_container_set_border_width(GTK_CONTAINER(hbox), 0);
4522
4523 g_signal_connect_swapped(G_OBJECT(button), "clicked", callback,
4524 gtkblist);
4525 gtk_container_add(GTK_CONTAINER(button), hbox);
4526
4527 gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), button_text);
4528 g_free(button_text);
4529
4530 gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
4531 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
4532
4533 return button;
4534 }
4535
4536 static void
4537 create_signed_on_elsewhere_minidialog(PidginBuddyList *gtkblist)
4538 {
4539 PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist);
4540 GtkWidget *dialog, *vbox, *hbox, *label, *img, *button;
4541
4542 if(priv->signed_on_elsewhere_minidialog)
4543 return;
4544
4545 dialog = gtk_vbox_new(FALSE, 0);
4546 gtk_container_set_border_width(GTK_CONTAINER(dialog), PIDGIN_HIG_BOX_SPACE);
4547 priv->signed_on_elsewhere_minidialog = dialog;
4548
4549 /* HBox to hold error icon and title */
4550 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4551
4552 img = gtk_image_new_from_stock(PIDGIN_STOCK_DISCONNECT,
4553 gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL));
4554 gtk_misc_set_alignment(GTK_MISC(img), 0, 0);
4555 if (img)
4556 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0);
4557
4558 label = gtk_label_new(NULL);
4559 priv->signed_on_elsewhere_minidialog_title = GTK_LABEL(label);
4560 gtk_widget_set_size_request(label,
4561 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width")-25, -1);
4562 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
4563 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
4564 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
4565 gtk_box_pack_start(GTK_BOX(dialog), hbox, FALSE, FALSE, 0);
4566
4567 /* VBox to hold "[prplicon] account@server.com" widgets */
4568 vbox = gtk_vbox_new(FALSE, 0);
4569 priv->signed_on_elsewhere_minidialog_accounts = GTK_VBOX(vbox);
4570 gtk_box_pack_start(GTK_BOX(dialog), vbox, FALSE, FALSE, 0);
4571
4572 /* HBox to hold buttons */
4573 hbox = gtk_hbox_new(FALSE, 0);
4574
4575 button = make_elsewhere_minidialog_button(_("Re-enable"),
4576 (GCallback) reconnect_elsewhere_accounts);
4577 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
4578
4579 button = make_elsewhere_minidialog_button(_("Ignore"),
4580 (GCallback) ignore_elsewhere_accounts);
4581 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
4582
4583 gtk_box_pack_start(GTK_BOX(dialog), hbox, FALSE, FALSE, 0);
4584 add_error_dialog(gtkblist, dialog);
4585 } 4527 }
4586 4528
4587 static void 4529 static void
4588 update_signed_on_elsewhere_minidialog_title(void) 4530 update_signed_on_elsewhere_minidialog_title(void)
4589 { 4531 {
4590 PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist); 4532 PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist);
4591 guint length; 4533 PidginMiniDialog *mini_dialog = priv->signed_on_elsewhere;
4592 char *title, *title_markup; 4534 guint accounts;
4593 4535 char *title;
4594 length = g_list_length(priv->accounts_signed_on_elsewhere); 4536
4595 if (length == 0) 4537 if (mini_dialog == NULL)
4596 {
4597 destroy_signed_on_elsewhere_minidialog(priv);
4598 return; 4538 return;
4599 } 4539
4600 4540 accounts = pidgin_mini_dialog_get_num_children(mini_dialog);
4601 create_signed_on_elsewhere_minidialog(gtkblist);
4602 4541
4603 title = g_strdup_printf( 4542 title = g_strdup_printf(
4604 ngettext("%d account was disabled because you signed on from another location.", 4543 ngettext("%d account was disabled because you signed on from another location.",
4605 "%d accounts were disabled because you signed on from another location.", 4544 "%d accounts were disabled because you signed on from another location.",
4606 length), 4545 accounts),
4607 length); 4546 accounts);
4608 title_markup = g_strdup_printf("<span weight=\"bold\" size=\"smaller\">%s</span>", title); 4547 pidgin_mini_dialog_set_title(mini_dialog, title);
4609
4610 gtk_label_set_markup(priv->signed_on_elsewhere_minidialog_title, title_markup);
4611
4612 g_free(title_markup);
4613 g_free(title); 4548 g_free(title);
4614
4615 gtk_widget_show_all(priv->signed_on_elsewhere_minidialog);
4616 } 4549 }
4617 4550
4618 static GtkWidget * 4551 static GtkWidget *
4619 create_account_label(PurpleAccount *account) 4552 create_account_label(PurpleAccount *account)
4620 { 4553 {
4650 4583
4651 static void 4584 static void
4652 add_to_signed_on_elsewhere(PurpleAccount *account) 4585 add_to_signed_on_elsewhere(PurpleAccount *account)
4653 { 4586 {
4654 PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist); 4587 PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist);
4588 PidginMiniDialog *mini_dialog;
4655 GtkWidget *account_label; 4589 GtkWidget *account_label;
4656 if(g_list_find(priv->accounts_signed_on_elsewhere, account) != NULL) 4590
4591 ensure_signed_on_elsewhere_minidialog(gtkblist);
4592 mini_dialog = priv->signed_on_elsewhere;
4593
4594 if(find_child_widget_by_account(GTK_CONTAINER(mini_dialog->contents), account))
4657 return; 4595 return;
4658 4596
4659 priv->accounts_signed_on_elsewhere = 4597 account_label = create_account_label(account);
4660 g_list_prepend(priv->accounts_signed_on_elsewhere, account); 4598 gtk_box_pack_start(mini_dialog->contents, account_label, FALSE, FALSE, 0);
4599 gtk_widget_show_all(account_label);
4661 4600
4662 update_signed_on_elsewhere_minidialog_title(); 4601 update_signed_on_elsewhere_minidialog_title();
4663
4664 account_label = create_account_label(account);
4665 gtk_box_pack_start(GTK_BOX(priv->signed_on_elsewhere_minidialog_accounts),
4666 account_label, FALSE, FALSE, 0);
4667 gtk_widget_show_all(account_label);
4668 4602
4669 if (!GTK_WIDGET_HAS_FOCUS(gtkblist->window)) 4603 if (!GTK_WIDGET_HAS_FOCUS(gtkblist->window))
4670 pidgin_set_urgent(GTK_WINDOW(gtkblist->window), TRUE); 4604 pidgin_set_urgent(GTK_WINDOW(gtkblist->window), TRUE);
4671 } 4605 }
4672 4606
4673 static void 4607 static void
4674 remove_from_signed_on_elsewhere(PurpleAccount *account) 4608 remove_from_signed_on_elsewhere(PurpleAccount *account)
4675 { 4609 {
4676 PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist); 4610 PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist);
4677 if(g_list_find(priv->accounts_signed_on_elsewhere, account) == NULL) 4611 PidginMiniDialog *mini_dialog = priv->signed_on_elsewhere;
4612 if(mini_dialog == NULL)
4678 return; 4613 return;
4679 4614
4680 priv->accounts_signed_on_elsewhere = 4615 remove_child_widget_by_account(GTK_CONTAINER(mini_dialog->contents), account);
4681 g_list_remove(priv->accounts_signed_on_elsewhere, account);
4682
4683 if(priv->signed_on_elsewhere_minidialog_accounts)
4684 remove_child_widget_by_account(GTK_CONTAINER(
4685 priv->signed_on_elsewhere_minidialog_accounts),
4686 account);
4687 4616
4688 update_signed_on_elsewhere_minidialog_title(); 4617 update_signed_on_elsewhere_minidialog_title();
4689 } 4618 }
4690 4619
4691 4620