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());