Mercurial > pidgin.yaz
comparison pidgin/gtkblist.c @ 21420:1ce05db42eb3
propagate from branch 'im.pidgin.pidgin' (head 18b9b46acf72ed063fad2e2779a5202fd6d8126b)
to branch 'im.pidgin.cpw.resiak.disconnectreason' (head 9ef6f213c70686d6e6f62c382a626a749bf4bf6c)
author | Will Thompson <will.thompson@collabora.co.uk> |
---|---|
date | Sun, 11 Nov 2007 14:19:55 +0000 |
parents | 0bad71ee1465 38cc722159ff |
children | 3f87c15d8438 |
comparison
equal
deleted
inserted
replaced
21319:85fbadb8b8fd | 21420:1ce05db42eb3 |
---|---|
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 |
105 GtkSizeGroup *sg; | 106 GtkSizeGroup *sg; |
106 | 107 |
107 GList *entries; | 108 GList *entries; |
108 } PidginJoinChatData; | 109 } PidginJoinChatData; |
109 | 110 |
111 typedef struct | |
112 { | |
113 /** PidginScrollBook used to hold error minidialogs. Gets packed | |
114 * inside PidginBuddyList.error_buttons | |
115 */ | |
116 GtkWidget *error_scrollbook; | |
117 | |
118 /** Pointer to the mini-dialog about having signed on elsewhere, if one | |
119 * is showing; @c NULL otherwise. | |
120 */ | |
121 PidginMiniDialog *signed_on_elsewhere; | |
122 } PidginBuddyListPrivate; | |
123 | |
124 #define PIDGIN_BUDDY_LIST_GET_PRIVATE(list) \ | |
125 ((PidginBuddyListPrivate *)((list)->priv)) | |
110 | 126 |
111 static GtkWidget *accountmenu = NULL; | 127 static GtkWidget *accountmenu = NULL; |
112 | 128 |
113 static guint visibility_manager_count = 0; | 129 static guint visibility_manager_count = 0; |
114 static GdkVisibilityState gtk_blist_visibility = GDK_VISIBILITY_UNOBSCURED; | 130 static GdkVisibilityState gtk_blist_visibility = GDK_VISIBILITY_UNOBSCURED; |
4123 **********************************************************************************/ | 4139 **********************************************************************************/ |
4124 | 4140 |
4125 static void pidgin_blist_new_list(PurpleBuddyList *blist) | 4141 static void pidgin_blist_new_list(PurpleBuddyList *blist) |
4126 { | 4142 { |
4127 PidginBuddyList *gtkblist; | 4143 PidginBuddyList *gtkblist; |
4144 PidginBuddyListPrivate *priv; | |
4128 | 4145 |
4129 gtkblist = g_new0(PidginBuddyList, 1); | 4146 gtkblist = g_new0(PidginBuddyList, 1); |
4130 gtkblist->connection_errors = g_hash_table_new_full(g_direct_hash, | 4147 gtkblist->connection_errors = g_hash_table_new_full(g_direct_hash, |
4131 g_direct_equal, NULL, g_free); | 4148 g_direct_equal, NULL, g_free); |
4149 gtkblist->priv = priv = g_new0(PidginBuddyListPrivate, 1); | |
4150 | |
4132 blist->ui_data = gtkblist; | 4151 blist->ui_data = gtkblist; |
4133 } | 4152 } |
4134 | 4153 |
4135 static void pidgin_blist_new_node(PurpleBlistNode *node) | 4154 static void pidgin_blist_new_node(PurpleBlistNode *node) |
4136 { | 4155 { |
4282 #endif | 4301 #endif |
4283 0, 0, | 4302 0, 0, |
4284 widget->allocation.width - 2 - HEADLINE_CLOSE_SIZE, 2, | 4303 widget->allocation.width - 2 - HEADLINE_CLOSE_SIZE, 2, |
4285 HEADLINE_CLOSE_SIZE, HEADLINE_CLOSE_SIZE, | 4304 HEADLINE_CLOSE_SIZE, HEADLINE_CLOSE_SIZE, |
4286 GDK_RGB_DITHER_NONE, 0, 0); | 4305 GDK_RGB_DITHER_NONE, 0, 0); |
4306 #if 0 | |
4307 /* The presence of one opening paren in each branch of | |
4308 * GTK_CHECK_VERSION confuses vim's bracket matching for the | |
4309 * rest of the file. | |
4310 */ | |
4311 ) | |
4312 #endif | |
4287 gtk_paint_focus(widget->style, widget->window, GTK_STATE_PRELIGHT, | 4313 gtk_paint_focus(widget->style, widget->window, GTK_STATE_PRELIGHT, |
4288 NULL, widget, NULL, | 4314 NULL, widget, NULL, |
4289 widget->allocation.width - HEADLINE_CLOSE_SIZE - 3, 1, | 4315 widget->allocation.width - HEADLINE_CLOSE_SIZE - 3, 1, |
4290 HEADLINE_CLOSE_SIZE + 2, HEADLINE_CLOSE_SIZE + 2); | 4316 HEADLINE_CLOSE_SIZE + 2, HEADLINE_CLOSE_SIZE + 2); |
4291 } | 4317 } |
4352 | 4378 |
4353 /***********************************/ | 4379 /***********************************/ |
4354 /* Connection error handling stuff */ | 4380 /* Connection error handling stuff */ |
4355 /***********************************/ | 4381 /***********************************/ |
4356 | 4382 |
4383 #define OBJECT_DATA_KEY_ACCOUNT "account" | |
4384 | |
4385 static gboolean | |
4386 find_account_widget(GObject *widget, | |
4387 PurpleAccount *account) | |
4388 { | |
4389 if (g_object_get_data(widget, OBJECT_DATA_KEY_ACCOUNT) == account) | |
4390 return 0; /* found */ | |
4391 else | |
4392 return 1; | |
4393 } | |
4394 | |
4357 static void | 4395 static void |
4358 ce_modify_account_cb(PurpleAccount *account) | 4396 pack_prpl_icon_start(GtkWidget *box, |
4397 PurpleAccount *account) | |
4398 { | |
4399 GdkPixbuf *pixbuf; | |
4400 GtkWidget *image; | |
4401 | |
4402 pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); | |
4403 if (pixbuf != NULL) { | |
4404 image = gtk_image_new_from_pixbuf(pixbuf); | |
4405 g_object_unref(pixbuf); | |
4406 | |
4407 gtk_box_pack_start(GTK_BOX(box), image, FALSE, FALSE, 0); | |
4408 } | |
4409 } | |
4410 | |
4411 static void | |
4412 add_error_dialog(PidginBuddyList *gtkblist, | |
4413 GtkWidget *dialog) | |
4414 { | |
4415 PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist); | |
4416 gtk_container_add(GTK_CONTAINER(priv->error_scrollbook), dialog); | |
4417 | |
4418 if (!GTK_WIDGET_HAS_FOCUS(gtkblist->window)) | |
4419 pidgin_set_urgent(GTK_WINDOW(gtkblist->window), TRUE); | |
4420 } | |
4421 | |
4422 static GtkWidget * | |
4423 find_child_widget_by_account(GtkContainer *container, | |
4424 PurpleAccount *account) | |
4425 { | |
4426 GList *l = NULL; | |
4427 GList *children = gtk_container_get_children(container); | |
4428 GtkWidget *ret = NULL; | |
4429 l = g_list_find_custom(children, account, (GCompareFunc) find_account_widget); | |
4430 if (l) | |
4431 ret = GTK_WIDGET(l->data); | |
4432 g_list_free(children); | |
4433 return ret; | |
4434 } | |
4435 | |
4436 static void | |
4437 remove_child_widget_by_account(GtkContainer *container, | |
4438 PurpleAccount *account) | |
4439 { | |
4440 GtkWidget *widget = find_child_widget_by_account(container, account); | |
4441 if(widget) | |
4442 gtk_widget_destroy(widget); | |
4443 } | |
4444 | |
4445 /* Generic error buttons */ | |
4446 | |
4447 static void | |
4448 generic_error_modify_cb(PurpleAccount *account) | |
4359 { | 4449 { |
4360 pidgin_account_dialog_show(PIDGIN_MODIFY_ACCOUNT_DIALOG, account); | 4450 pidgin_account_dialog_show(PIDGIN_MODIFY_ACCOUNT_DIALOG, account); |
4361 } | 4451 } |
4362 | 4452 |
4363 static void | 4453 static void |
4364 ce_enable_account_cb(PurpleAccount *account) | 4454 generic_error_enable_cb(PurpleAccount *account) |
4365 { | 4455 { |
4366 purple_account_set_enabled(account, purple_core_get_ui(), TRUE); | 4456 purple_account_set_enabled(account, purple_core_get_ui(), TRUE); |
4367 } | 4457 } |
4368 | 4458 |
4369 static void | 4459 static void |
4370 connection_error_button_clicked_cb(GtkButton *widget, gpointer user_data) | 4460 generic_error_ignore_cb(PurpleAccount *account) |
4461 { | |
4462 purple_account_clear_current_error(account); | |
4463 } | |
4464 | |
4465 static void | |
4466 generic_error_destroy_cb(GtkObject *dialog, | |
4467 PurpleAccount *account) | |
4468 { | |
4469 g_hash_table_remove(gtkblist->connection_errors, account); | |
4470 } | |
4471 | |
4472 static void | |
4473 add_generic_error_dialog(PurpleAccount *account, | |
4474 const PurpleConnectionErrorInfo *err) | |
4475 { | |
4476 GtkWidget *mini_dialog; | |
4477 const char *username = purple_account_get_username(account); | |
4478 gboolean enabled = | |
4479 purple_account_get_enabled(account, purple_core_get_ui()); | |
4480 char *primary; | |
4481 | |
4482 if (enabled) | |
4483 primary = g_strdup_printf(_("%s disconnected"), username); | |
4484 else | |
4485 primary = g_strdup_printf(_("%s disabled"), username); | |
4486 | |
4487 mini_dialog = pidgin_make_mini_dialog(NULL, PIDGIN_STOCK_DISCONNECT, | |
4488 primary, err->description, account, | |
4489 (enabled ? _("Reconnect") : _("Re-enable")), | |
4490 (enabled ? PURPLE_CALLBACK(purple_account_connect) | |
4491 : PURPLE_CALLBACK(generic_error_enable_cb)), | |
4492 _("Modify Account"), PURPLE_CALLBACK(generic_error_modify_cb), | |
4493 _("Ignore"), PURPLE_CALLBACK(generic_error_ignore_cb), | |
4494 NULL); | |
4495 | |
4496 g_free(primary); | |
4497 | |
4498 g_object_set_data(G_OBJECT(mini_dialog), OBJECT_DATA_KEY_ACCOUNT, | |
4499 account); | |
4500 | |
4501 g_signal_connect_after(mini_dialog, "destroy", | |
4502 (GCallback)generic_error_destroy_cb, | |
4503 account); | |
4504 | |
4505 add_error_dialog(gtkblist, mini_dialog); | |
4506 } | |
4507 | |
4508 static void | |
4509 remove_generic_error_dialog(PurpleAccount *account) | |
4510 { | |
4511 PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist); | |
4512 remove_child_widget_by_account(GTK_CONTAINER(priv->error_scrollbook), | |
4513 account); | |
4514 } | |
4515 | |
4516 | |
4517 /* Notifications about accounts which were disconnected with | |
4518 * PURPLE_CONNECTION_ERROR_NAME_IN_USE | |
4519 */ | |
4520 | |
4521 typedef void (*AccountFunction)(PurpleAccount *); | |
4522 | |
4523 static void | |
4524 elsewhere_foreach_account(PidginMiniDialog *mini_dialog, | |
4525 AccountFunction f) | |
4371 { | 4526 { |
4372 PurpleAccount *account; | 4527 PurpleAccount *account; |
4373 char *primary; | 4528 GList *labels = gtk_container_get_children( |
4374 const char *text; | 4529 GTK_CONTAINER(mini_dialog->contents)); |
4375 gboolean enabled; | 4530 GList *l; |
4376 GList *list; | 4531 |
4377 | 4532 for (l = labels; l; l = l->next) { |
4378 account = user_data; | 4533 account = g_object_get_data(G_OBJECT(l->data), OBJECT_DATA_KEY_ACCOUNT); |
4379 primary = g_strdup_printf(_("%s disconnected"), | 4534 if (account) |
4380 purple_account_get_username(account)); | 4535 f(account); |
4381 text = g_hash_table_lookup(gtkblist->connection_errors, account); | 4536 else |
4382 | 4537 purple_debug_warning("gtkblist", "mini_dialog's child " |
4383 enabled = purple_account_get_enabled(account, purple_core_get_ui()); | 4538 "didn't have an account stored in it!"); |
4384 purple_request_action_with_hint(account, _("Connection Error"), primary, text, 2, | 4539 } |
4385 account, NULL, NULL, | 4540 g_list_free(labels); |
4386 PURPLE_REQUEST_UI_HINT_ACCOUNT, account, 3, | 4541 } |
4387 _("OK"), NULL, | 4542 |
4388 _("Modify Account"), PURPLE_CALLBACK(ce_modify_account_cb), | |
4389 enabled ? _("Connect") : _("Re-enable Account"), | |
4390 enabled ? PURPLE_CALLBACK(purple_account_connect) : | |
4391 PURPLE_CALLBACK(ce_enable_account_cb)); | |
4392 g_free(primary); | |
4393 gtk_widget_destroy(GTK_WIDGET(widget)); | |
4394 g_hash_table_remove(gtkblist->connection_errors, account); | |
4395 if ((list = gtk_container_get_children(GTK_CONTAINER(gtkblist->error_buttons))) == NULL) { | |
4396 gtk_widget_hide(gtkblist->error_buttons); | |
4397 } else { | |
4398 g_list_free(list); | |
4399 } | |
4400 } | |
4401 | |
4402 /* Add some buttons that show connection errors */ | |
4403 static void | 4543 static void |
4404 create_connection_error_buttons(gpointer key, gpointer value, | 4544 enable_account(PurpleAccount *account) |
4405 gpointer user_data) | 4545 { |
4406 { | 4546 purple_account_set_enabled(account, purple_core_get_ui(), TRUE); |
4407 PurpleAccount *account; | 4547 } |
4408 gchar *escaped, *text; | 4548 |
4409 GtkWidget *button, *label, *image, *hbox; | 4549 static void |
4410 GdkPixbuf *pixbuf; | 4550 reconnect_elsewhere_accounts(PidginMiniDialog *mini_dialog, |
4411 | 4551 GtkButton *button, |
4412 account = key; | 4552 gpointer unused) |
4413 escaped = g_markup_escape_text((const gchar *)value, -1); | 4553 { |
4414 text = g_strdup_printf(_("<span color=\"red\">%s disconnected: %s</span>"), | 4554 elsewhere_foreach_account(mini_dialog, enable_account); |
4415 purple_account_get_username(account), | 4555 } |
4416 escaped); | 4556 |
4417 g_free(escaped); | 4557 static void |
4558 ignore_elsewhere_accounts(PidginMiniDialog *mini_dialog, | |
4559 GtkButton *button, | |
4560 gpointer unused) | |
4561 { | |
4562 elsewhere_foreach_account(mini_dialog, purple_account_clear_current_error); | |
4563 } | |
4564 | |
4565 static void | |
4566 ensure_signed_on_elsewhere_minidialog(PidginBuddyList *gtkblist) | |
4567 { | |
4568 PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist); | |
4569 PidginMiniDialog *mini_dialog; | |
4570 | |
4571 if(priv->signed_on_elsewhere) | |
4572 return; | |
4573 | |
4574 mini_dialog = priv->signed_on_elsewhere = | |
4575 pidgin_mini_dialog_new(NULL, NULL, PIDGIN_STOCK_DISCONNECT); | |
4576 | |
4577 pidgin_mini_dialog_add_button(mini_dialog, _("Re-enable"), | |
4578 reconnect_elsewhere_accounts, NULL); | |
4579 | |
4580 pidgin_mini_dialog_add_button(mini_dialog, _("Ignore"), | |
4581 ignore_elsewhere_accounts, NULL); | |
4582 | |
4583 add_error_dialog(gtkblist, GTK_WIDGET(mini_dialog)); | |
4584 | |
4585 /* Set priv->signed_on_elsewhere to NULL when the dialog is destroyed */ | |
4586 g_signal_connect(G_OBJECT(mini_dialog), "destroy", | |
4587 (GCallback) gtk_widget_destroyed, &(priv->signed_on_elsewhere)); | |
4588 } | |
4589 | |
4590 static void | |
4591 update_signed_on_elsewhere_minidialog_title(void) | |
4592 { | |
4593 PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist); | |
4594 PidginMiniDialog *mini_dialog = priv->signed_on_elsewhere; | |
4595 guint accounts; | |
4596 char *title; | |
4597 | |
4598 if (mini_dialog == NULL) | |
4599 return; | |
4600 | |
4601 accounts = pidgin_mini_dialog_get_num_children(mini_dialog); | |
4602 | |
4603 title = g_strdup_printf( | |
4604 ngettext("%d account was disabled because you signed on from another location.", | |
4605 "%d accounts were disabled because you signed on from another location.", | |
4606 accounts), | |
4607 accounts); | |
4608 pidgin_mini_dialog_set_title(mini_dialog, title); | |
4609 g_free(title); | |
4610 } | |
4611 | |
4612 static GtkWidget * | |
4613 create_account_label(PurpleAccount *account) | |
4614 { | |
4615 GtkWidget *hbox, *label; | |
4616 const char *username = purple_account_get_username(account); | |
4617 char *markup; | |
4418 | 4618 |
4419 hbox = gtk_hbox_new(FALSE, 6); | 4619 hbox = gtk_hbox_new(FALSE, 6); |
4420 | 4620 g_object_set_data(G_OBJECT(hbox), OBJECT_DATA_KEY_ACCOUNT, account); |
4421 /* Create the icon */ | 4621 |
4422 if (purple_account_get_status_type_with_primitive(account, | 4622 pack_prpl_icon_start(hbox, account); |
4423 PURPLE_STATUS_OFFLINE) != NULL) { | 4623 |
4424 pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); | 4624 label = gtk_label_new(NULL); |
4425 if (pixbuf != NULL) { | 4625 markup = g_strdup_printf("<span size=\"smaller\">%s</span>", username); |
4426 image = gtk_image_new_from_pixbuf(pixbuf); | 4626 gtk_label_set_markup(GTK_LABEL(label), markup); |
4427 g_object_unref(pixbuf); | 4627 g_free(markup); |
4428 | 4628 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); |
4429 gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); | |
4430 } | |
4431 } | |
4432 | |
4433 /* Create the text */ | |
4434 label = gtk_label_new(""); | |
4435 gtk_label_set_markup(GTK_LABEL(label), text); | |
4436 g_free(text); | |
4437 #if GTK_CHECK_VERSION(2,6,0) | 4629 #if GTK_CHECK_VERSION(2,6,0) |
4438 g_object_set(label, "ellipsize", PANGO_ELLIPSIZE_END, NULL); | 4630 g_object_set(G_OBJECT(label), "ellipsize", PANGO_ELLIPSIZE_END, NULL); |
4631 #endif | |
4632 #if GTK_CHECK_VERSION(2,12,0) | |
4633 { /* avoid unused variable warnings on pre-2.12 Gtk */ | |
4634 char *description = | |
4635 purple_account_get_current_error(account)->description; | |
4636 if (description != NULL && *description != '\0') | |
4637 gtk_widget_set_tooltip_text(label, description); | |
4638 } | |
4439 #endif | 4639 #endif |
4440 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); | 4640 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); |
4441 | 4641 |
4442 /* Create the actual button and put the icon and text on it */ | 4642 return hbox; |
4443 button = gtk_button_new(); | 4643 } |
4444 gtk_container_add(GTK_CONTAINER(button), hbox); | 4644 |
4445 g_signal_connect(G_OBJECT(button), "clicked", | 4645 static void |
4446 G_CALLBACK(connection_error_button_clicked_cb), | 4646 add_to_signed_on_elsewhere(PurpleAccount *account) |
4447 account); | 4647 { |
4448 gtk_widget_show_all(button); | 4648 PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist); |
4449 gtk_box_pack_end(GTK_BOX(gtkblist->error_buttons), button, | 4649 PidginMiniDialog *mini_dialog; |
4450 FALSE, FALSE, 0); | 4650 GtkWidget *account_label; |
4451 gtk_widget_show_all(gtkblist->error_buttons); | 4651 |
4652 ensure_signed_on_elsewhere_minidialog(gtkblist); | |
4653 mini_dialog = priv->signed_on_elsewhere; | |
4654 | |
4655 if(find_child_widget_by_account(GTK_CONTAINER(mini_dialog->contents), account)) | |
4656 return; | |
4657 | |
4658 account_label = create_account_label(account); | |
4659 gtk_box_pack_start(mini_dialog->contents, account_label, FALSE, FALSE, 0); | |
4660 gtk_widget_show_all(account_label); | |
4661 | |
4662 update_signed_on_elsewhere_minidialog_title(); | |
4663 | |
4664 if (!GTK_WIDGET_HAS_FOCUS(gtkblist->window)) | |
4665 pidgin_set_urgent(GTK_WINDOW(gtkblist->window), TRUE); | |
4666 } | |
4667 | |
4668 static void | |
4669 remove_from_signed_on_elsewhere(PurpleAccount *account) | |
4670 { | |
4671 PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist); | |
4672 PidginMiniDialog *mini_dialog = priv->signed_on_elsewhere; | |
4673 if(mini_dialog == NULL) | |
4674 return; | |
4675 | |
4676 remove_child_widget_by_account(GTK_CONTAINER(mini_dialog->contents), account); | |
4677 | |
4678 update_signed_on_elsewhere_minidialog_title(); | |
4679 } | |
4680 | |
4681 | |
4682 /* Call appropriate error notification code based on error types */ | |
4683 static void | |
4684 update_account_error_state(PurpleAccount *account, | |
4685 const PurpleConnectionErrorInfo *old, | |
4686 const PurpleConnectionErrorInfo *new, | |
4687 PidginBuddyList *gtkblist) | |
4688 { | |
4689 /* For backwards compatibility: */ | |
4690 if (new) | |
4691 pidgin_blist_update_account_error_state(account, new->description); | |
4692 else | |
4693 pidgin_blist_update_account_error_state(account, NULL); | |
4694 | |
4695 if (old) { | |
4696 if(old->type == PURPLE_CONNECTION_ERROR_NAME_IN_USE) | |
4697 remove_from_signed_on_elsewhere(account); | |
4698 else | |
4699 remove_generic_error_dialog(account); | |
4700 } | |
4701 | |
4702 if (new) { | |
4703 if(new->type == PURPLE_CONNECTION_ERROR_NAME_IN_USE) | |
4704 add_to_signed_on_elsewhere(account); | |
4705 else | |
4706 add_generic_error_dialog(account, new); | |
4707 } | |
4708 } | |
4709 | |
4710 /* In case accounts are loaded before the blist (which they currently are), | |
4711 * let's call update_account_error_state ourselves on every account's current | |
4712 * state when the blist starts. | |
4713 */ | |
4714 static void | |
4715 show_initial_account_errors(PidginBuddyList *gtkblist) | |
4716 { | |
4717 GList *l = purple_accounts_get_all(); | |
4718 PurpleAccount *account; | |
4719 const PurpleConnectionErrorInfo *err; | |
4720 | |
4721 for (; l; l = l->next) | |
4722 { | |
4723 account = l->data; | |
4724 err = purple_account_get_current_error(account); | |
4725 | |
4726 update_account_error_state(account, NULL, err, gtkblist); | |
4727 } | |
4452 } | 4728 } |
4453 | 4729 |
4454 void | 4730 void |
4455 pidgin_blist_update_account_error_state(PurpleAccount *account, const char *text) | 4731 pidgin_blist_update_account_error_state(PurpleAccount *account, const char *text) |
4456 { | 4732 { |
4457 GList *l; | 4733 /* connection_errors isn't actually used anywhere; it's just kept in |
4458 | 4734 * sync with reality in case a plugin uses it. |
4735 */ | |
4459 if (text == NULL) | 4736 if (text == NULL) |
4460 g_hash_table_remove(gtkblist->connection_errors, account); | 4737 g_hash_table_remove(gtkblist->connection_errors, account); |
4461 else | 4738 else |
4462 g_hash_table_insert(gtkblist->connection_errors, account, g_strdup(text)); | 4739 g_hash_table_insert(gtkblist->connection_errors, account, g_strdup(text)); |
4463 | |
4464 /* Remove the old error buttons */ | |
4465 for (l = gtk_container_get_children(GTK_CONTAINER(gtkblist->error_buttons)); | |
4466 l != NULL; | |
4467 l = g_list_delete_link(l, l)) | |
4468 { | |
4469 gtk_widget_destroy(GTK_WIDGET(l->data)); | |
4470 } | |
4471 | |
4472 /* Add new error buttons */ | |
4473 g_hash_table_foreach(gtkblist->connection_errors, | |
4474 create_connection_error_buttons, NULL); | |
4475 } | 4740 } |
4476 | 4741 |
4477 static gboolean | 4742 static gboolean |
4478 paint_headline_hbox (GtkWidget *widget, | 4743 paint_headline_hbox (GtkWidget *widget, |
4479 GdkEventExpose *event, | 4744 GdkEventExpose *event, |
4596 } | 4861 } |
4597 #endif | 4862 #endif |
4598 | 4863 |
4599 static void pidgin_blist_show(PurpleBuddyList *list) | 4864 static void pidgin_blist_show(PurpleBuddyList *list) |
4600 { | 4865 { |
4866 PidginBuddyListPrivate *priv; | |
4601 void *handle; | 4867 void *handle; |
4602 GtkCellRenderer *rend; | 4868 GtkCellRenderer *rend; |
4603 GtkTreeViewColumn *column; | 4869 GtkTreeViewColumn *column; |
4604 GtkWidget *menu; | 4870 GtkWidget *menu; |
4605 GtkWidget *ebox; | 4871 GtkWidget *ebox; |
4622 purple_blist_set_visible(purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/list_visible")); | 4888 purple_blist_set_visible(purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/list_visible")); |
4623 return; | 4889 return; |
4624 } | 4890 } |
4625 | 4891 |
4626 gtkblist = PIDGIN_BLIST(list); | 4892 gtkblist = PIDGIN_BLIST(list); |
4893 priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist); | |
4627 | 4894 |
4628 gtkblist->empty_avatar = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 32, 32); | 4895 gtkblist->empty_avatar = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 32, 32); |
4629 gdk_pixbuf_fill(gtkblist->empty_avatar, 0x00000000); | 4896 gdk_pixbuf_fill(gtkblist->empty_avatar, 0x00000000); |
4630 | 4897 |
4631 gtkblist->window = pidgin_create_window(_("Buddy List"), 0, "buddy_list", TRUE); | 4898 gtkblist->window = pidgin_create_window(_("Buddy List"), 0, "buddy_list", TRUE); |
4924 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), sep, FALSE, FALSE, 0); | 5191 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), sep, FALSE, FALSE, 0); |
4925 | 5192 |
4926 gtkblist->scrollbook = pidgin_scroll_book_new(); | 5193 gtkblist->scrollbook = pidgin_scroll_book_new(); |
4927 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->scrollbook, FALSE, FALSE, 0); | 5194 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->scrollbook, FALSE, FALSE, 0); |
4928 | 5195 |
4929 /* Create an empty vbox used for showing connection errors */ | 5196 /* Create an vbox which holds the scrollbook which is actually used to |
5197 * display connection errors. The vbox needs to still exist for | |
5198 * backwards compatibility. | |
5199 */ | |
4930 gtkblist->error_buttons = gtk_vbox_new(FALSE, 0); | 5200 gtkblist->error_buttons = gtk_vbox_new(FALSE, 0); |
4931 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->error_buttons, FALSE, FALSE, 0); | 5201 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->error_buttons, FALSE, FALSE, 0); |
4932 gtk_container_set_border_width(GTK_CONTAINER(gtkblist->error_buttons), 3); | 5202 gtk_container_set_border_width(GTK_CONTAINER(gtkblist->error_buttons), 0); |
4933 | 5203 |
5204 priv->error_scrollbook = pidgin_scroll_book_new(); | |
5205 gtk_box_pack_start(GTK_BOX(gtkblist->error_buttons), | |
5206 priv->error_scrollbook, FALSE, FALSE, 0); | |
5207 | |
5208 | |
4934 /* Add the statusbox */ | 5209 /* Add the statusbox */ |
4935 gtkblist->statusbox = pidgin_status_box_new(); | 5210 gtkblist->statusbox = pidgin_status_box_new(); |
4936 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->statusbox, FALSE, TRUE, 0); | 5211 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->statusbox, FALSE, TRUE, 0); |
4937 gtk_widget_set_name(gtkblist->statusbox, "pidgin_blist_statusbox"); | 5212 gtk_widget_set_name(gtkblist->statusbox, "pidgin_blist_statusbox"); |
4938 gtk_container_set_border_width(GTK_CONTAINER(gtkblist->statusbox), 3); | 5213 gtk_container_set_border_width(GTK_CONTAINER(gtkblist->statusbox), 3); |
4999 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/sound/mute", | 5274 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/sound/mute", |
5000 pidgin_blist_mute_pref_cb, NULL); | 5275 pidgin_blist_mute_pref_cb, NULL); |
5001 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/sound/method", | 5276 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/sound/method", |
5002 pidgin_blist_sound_method_pref_cb, NULL); | 5277 pidgin_blist_sound_method_pref_cb, NULL); |
5003 | 5278 |
5279 | |
5004 /* Setup some purple signal handlers. */ | 5280 /* Setup some purple signal handlers. */ |
5005 purple_signal_connect(purple_accounts_get_handle(), "account-enabled", | 5281 |
5006 gtkblist, PURPLE_CALLBACK(account_modified), gtkblist); | 5282 handle = purple_accounts_get_handle(); |
5007 purple_signal_connect(purple_accounts_get_handle(), "account-disabled", | 5283 purple_signal_connect(handle, "account-enabled", gtkblist, |
5008 gtkblist, PURPLE_CALLBACK(account_modified), gtkblist); | 5284 PURPLE_CALLBACK(account_modified), gtkblist); |
5009 purple_signal_connect(purple_accounts_get_handle(), "account-removed", | 5285 purple_signal_connect(handle, "account-disabled", gtkblist, |
5010 gtkblist, PURPLE_CALLBACK(account_modified), gtkblist); | 5286 PURPLE_CALLBACK(account_modified), gtkblist); |
5011 purple_signal_connect(purple_accounts_get_handle(), "account-status-changed", | 5287 purple_signal_connect(handle, "account-removed", gtkblist, |
5012 gtkblist, PURPLE_CALLBACK(account_status_changed), gtkblist); | 5288 PURPLE_CALLBACK(account_modified), gtkblist); |
5013 | 5289 purple_signal_connect(handle, "account-status-changed", gtkblist, |
5014 purple_signal_connect(pidgin_account_get_handle(), "account-modified", | 5290 PURPLE_CALLBACK(account_status_changed), |
5015 gtkblist, PURPLE_CALLBACK(account_modified), gtkblist); | 5291 gtkblist); |
5016 | 5292 purple_signal_connect(handle, "account-error-changed", gtkblist, |
5017 purple_signal_connect(purple_connections_get_handle(), "signed-on", | 5293 PURPLE_CALLBACK(update_account_error_state), |
5018 gtkblist, PURPLE_CALLBACK(sign_on_off_cb), list); | 5294 gtkblist); |
5019 purple_signal_connect(purple_connections_get_handle(), "signed-off", | 5295 |
5020 gtkblist, PURPLE_CALLBACK(sign_on_off_cb), list); | 5296 handle = pidgin_account_get_handle(); |
5021 | 5297 purple_signal_connect(handle, "account-modified", gtkblist, |
5022 purple_signal_connect(purple_plugins_get_handle(), "plugin-load", | 5298 PURPLE_CALLBACK(account_modified), gtkblist); |
5023 gtkblist, PURPLE_CALLBACK(plugin_changed_cb), NULL); | 5299 |
5024 purple_signal_connect(purple_plugins_get_handle(), "plugin-unload", | 5300 handle = purple_connections_get_handle(); |
5025 gtkblist, PURPLE_CALLBACK(plugin_changed_cb), NULL); | 5301 purple_signal_connect(handle, "signed-on", gtkblist, |
5026 | 5302 PURPLE_CALLBACK(sign_on_off_cb), list); |
5027 purple_signal_connect(purple_conversations_get_handle(), "conversation-updated", | 5303 purple_signal_connect(handle, "signed-off", gtkblist, |
5028 gtkblist, PURPLE_CALLBACK(conversation_updated_cb), | 5304 PURPLE_CALLBACK(sign_on_off_cb), list); |
5029 gtkblist); | 5305 |
5030 purple_signal_connect(purple_conversations_get_handle(), "deleting-conversation", | 5306 handle = purple_plugins_get_handle(); |
5031 gtkblist, PURPLE_CALLBACK(conversation_deleting_cb), | 5307 purple_signal_connect(handle, "plugin-load", gtkblist, |
5032 gtkblist); | 5308 PURPLE_CALLBACK(plugin_changed_cb), NULL); |
5033 purple_signal_connect(purple_conversations_get_handle(), "conversation-created", | 5309 purple_signal_connect(handle, "plugin-unload", gtkblist, |
5034 gtkblist, PURPLE_CALLBACK(conversation_created_cb), | 5310 PURPLE_CALLBACK(plugin_changed_cb), NULL); |
5035 gtkblist); | 5311 |
5312 handle = purple_conversations_get_handle(); | |
5313 purple_signal_connect(handle, "conversation-updated", gtkblist, | |
5314 PURPLE_CALLBACK(conversation_updated_cb), | |
5315 gtkblist); | |
5316 purple_signal_connect(handle, "deleting-conversation", gtkblist, | |
5317 PURPLE_CALLBACK(conversation_deleting_cb), | |
5318 gtkblist); | |
5319 purple_signal_connect(handle, "conversation-created", gtkblist, | |
5320 PURPLE_CALLBACK(conversation_created_cb), | |
5321 gtkblist); | |
5036 | 5322 |
5037 gtk_widget_hide(gtkblist->headline_hbox); | 5323 gtk_widget_hide(gtkblist->headline_hbox); |
5038 gtk_widget_hide(gtkblist->error_buttons); | 5324 |
5325 show_initial_account_errors(gtkblist); | |
5039 | 5326 |
5040 /* emit our created signal */ | 5327 /* emit our created signal */ |
5328 handle = pidgin_blist_get_handle(); | |
5041 purple_signal_emit(handle, "gtkblist-created", list); | 5329 purple_signal_emit(handle, "gtkblist-created", list); |
5042 } | 5330 } |
5043 | 5331 |
5044 static void redo_buddy_list(PurpleBuddyList *list, gboolean remove, gboolean rerender) | 5332 static void redo_buddy_list(PurpleBuddyList *list, gboolean remove, gboolean rerender) |
5045 { | 5333 { |
5658 } | 5946 } |
5659 | 5947 |
5660 | 5948 |
5661 static void pidgin_blist_destroy(PurpleBuddyList *list) | 5949 static void pidgin_blist_destroy(PurpleBuddyList *list) |
5662 { | 5950 { |
5951 PidginBuddyListPrivate *priv; | |
5952 | |
5663 if (!gtkblist) | 5953 if (!gtkblist) |
5664 return; | 5954 return; |
5665 | 5955 |
5666 purple_signals_disconnect_by_handle(gtkblist); | 5956 purple_signals_disconnect_by_handle(gtkblist); |
5667 | 5957 |
5690 | 5980 |
5691 gdk_cursor_unref(gtkblist->hand_cursor); | 5981 gdk_cursor_unref(gtkblist->hand_cursor); |
5692 gdk_cursor_unref(gtkblist->arrow_cursor); | 5982 gdk_cursor_unref(gtkblist->arrow_cursor); |
5693 gtkblist->hand_cursor = NULL; | 5983 gtkblist->hand_cursor = NULL; |
5694 gtkblist->arrow_cursor = NULL; | 5984 gtkblist->arrow_cursor = NULL; |
5985 | |
5986 priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist); | |
5987 g_free(priv); | |
5695 | 5988 |
5696 g_free(gtkblist); | 5989 g_free(gtkblist); |
5697 accountmenu = NULL; | 5990 accountmenu = NULL; |
5698 gtkblist = NULL; | 5991 gtkblist = NULL; |
5699 purple_prefs_disconnect_by_handle(pidgin_blist_get_handle()); | 5992 purple_prefs_disconnect_by_handle(pidgin_blist_get_handle()); |