comparison pidgin/gtkblist.c @ 20453:69febfa6d307

propagate from branch 'im.pidgin.pidgin' (head d3e5a5add3f39caa08b46c83177328e51c2d961a) to branch 'im.pidgin.cpw.khc.msnp14' (head a8f6c999b039b4097aa70cd8d2597f3127615435)
author Carlos Silva <typ0@pidgin.im>
date Sat, 16 Jun 2007 04:00:32 +0000
parents 40d51793f2d7
children 97b735ca9d7a 59aec2d6ec43
comparison
equal deleted inserted replaced
20452:5c34a0a3c362 20453:69febfa6d307
106 106
107 static GtkWidget *accountmenu = NULL; 107 static GtkWidget *accountmenu = NULL;
108 108
109 static guint visibility_manager_count = 0; 109 static guint visibility_manager_count = 0;
110 static gboolean gtk_blist_obscured = FALSE; 110 static gboolean gtk_blist_obscured = FALSE;
111 static gboolean editing_blist = FALSE;
111 112
112 static GList *pidgin_blist_sort_methods = NULL; 113 static GList *pidgin_blist_sort_methods = NULL;
113 static struct pidgin_blist_sort_method *current_sort_method = NULL; 114 static struct pidgin_blist_sort_method *current_sort_method = NULL;
114 static void sort_method_none(PurpleBlistNode *node, PurpleBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter); 115 static void sort_method_none(PurpleBlistNode *node, PurpleBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter);
115 116
264 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/x", x); 265 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/x", x);
265 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/y", y); 266 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/y", y);
266 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/width", event->width); 267 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/width", event->width);
267 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/height", event->height); 268 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/height", event->height);
268 269
269 gtk_widget_set_size_request(gtkblist->headline_label,
270 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width")-25,-1);
271 /* continue to handle event normally */ 270 /* continue to handle event normally */
272 return FALSE; 271 return FALSE;
273 } 272 }
274 273
275 static void gtk_blist_menu_info_cb(GtkWidget *w, PurpleBuddy *b) 274 static void gtk_blist_menu_info_cb(GtkWidget *w, PurpleBuddy *b)
276 { 275 {
277 PurpleNotifyUserInfo *info = purple_notify_user_info_new(); 276 pidgin_retrieve_user_info(b->account->gc, purple_buddy_get_name(b));
278 purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving..."));
279 purple_notify_userinfo(b->account->gc, purple_buddy_get_name(b), info, NULL, NULL);
280 purple_notify_user_info_destroy(info);
281
282 serv_get_info(b->account->gc, b->name);
283 } 277 }
284 278
285 static void gtk_blist_menu_im_cb(GtkWidget *w, PurpleBuddy *b) 279 static void gtk_blist_menu_im_cb(GtkWidget *w, PurpleBuddy *b)
286 { 280 {
287 pidgin_dialogs_im_with_user(b->account, b->name); 281 pidgin_dialogs_im_with_user(b->account, b->name);
313 } 307 }
314 308
315 static void gtk_blist_menu_join_cb(GtkWidget *w, PurpleChat *chat) 309 static void gtk_blist_menu_join_cb(GtkWidget *w, PurpleChat *chat)
316 { 310 {
317 gtk_blist_join_chat(chat); 311 gtk_blist_join_chat(chat);
312 }
313
314 static void gtk_blist_renderer_editing_cancelled_cb(GtkCellRenderer *renderer, PurpleBuddyList *list)
315 {
316 editing_blist = FALSE;
317 pidgin_blist_refresh(list);
318 } 318 }
319 319
320 static void gtk_blist_renderer_editing_started_cb(GtkCellRenderer *renderer, 320 static void gtk_blist_renderer_editing_started_cb(GtkCellRenderer *renderer,
321 GtkCellEditable *editable, 321 GtkCellEditable *editable,
322 gchar *path_str, 322 gchar *path_str,
351 351
352 if (GTK_IS_ENTRY (editable)) { 352 if (GTK_IS_ENTRY (editable)) {
353 GtkEntry *entry = GTK_ENTRY (editable); 353 GtkEntry *entry = GTK_ENTRY (editable);
354 gtk_entry_set_text(entry, text); 354 gtk_entry_set_text(entry, text);
355 } 355 }
356 editing_blist = TRUE;
356 } 357 }
357 358
358 static void gtk_blist_renderer_edited_cb(GtkCellRendererText *text_rend, char *arg1, 359 static void gtk_blist_renderer_edited_cb(GtkCellRendererText *text_rend, char *arg1,
359 char *arg2, gpointer nada) 360 char *arg2, PurpleBuddyList *list)
360 { 361 {
361 GtkTreeIter iter; 362 GtkTreeIter iter;
362 GtkTreePath *path; 363 GtkTreePath *path;
363 GValue val; 364 GValue val;
364 PurpleBlistNode *node; 365 PurpleBlistNode *node;
365 PurpleGroup *dest; 366 PurpleGroup *dest;
366 367
368 editing_blist = FALSE;
367 path = gtk_tree_path_new_from_string (arg1); 369 path = gtk_tree_path_new_from_string (arg1);
368 gtk_tree_model_get_iter (GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); 370 gtk_tree_model_get_iter (GTK_TREE_MODEL(gtkblist->treemodel), &iter, path);
369 gtk_tree_path_free (path); 371 gtk_tree_path_free (path);
370 val.g_type = 0; 372 val.g_type = 0;
371 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); 373 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val);
406 purple_blist_alias_chat((PurpleChat*)node, arg2); 408 purple_blist_alias_chat((PurpleChat*)node, arg2);
407 break; 409 break;
408 default: 410 default:
409 break; 411 break;
410 } 412 }
413 pidgin_blist_refresh(list);
411 } 414 }
412 415
413 static void gtk_blist_menu_alias_cb(GtkWidget *w, PurpleBlistNode *node) 416 static void gtk_blist_menu_alias_cb(GtkWidget *w, PurpleBlistNode *node)
414 { 417 {
415 GtkTreeIter iter; 418 GtkTreeIter iter;
484 } 487 }
485 488
486 static void gtk_blist_show_systemlog_cb() 489 static void gtk_blist_show_systemlog_cb()
487 { 490 {
488 pidgin_syslog_show(); 491 pidgin_syslog_show();
492 }
493
494 static void gtk_blist_show_onlinehelp_cb()
495 {
496 purple_notify_uri(NULL, PURPLE_WEBSITE "documentation");
489 } 497 }
490 498
491 static void 499 static void
492 do_join_chat(PidginJoinChatData *data) 500 do_join_chat(PidginJoinChatData *data)
493 { 501 {
686 } 694 }
687 695
688 gboolean 696 gboolean
689 pidgin_blist_joinchat_is_showable() 697 pidgin_blist_joinchat_is_showable()
690 { 698 {
691 GList *c; 699 const GList *c;
692 PurpleConnection *gc; 700 PurpleConnection *gc;
693 701
694 for (c = purple_connections_get_all(); c != NULL; c = c->next) { 702 for (c = purple_connections_get_all(); c != NULL; c = c->next) {
695 gc = c->data; 703 gc = c->data;
696 704
1122 pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy); 1130 pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy);
1123 1131
1124 if (((PurpleBlistNode*)buddy)->parent->child->next && !sub && !contact_expanded) { 1132 if (((PurpleBlistNode*)buddy)->parent->child->next && !sub && !contact_expanded) {
1125 pidgin_separator(menu); 1133 pidgin_separator(menu);
1126 pidgin_append_blist_node_privacy_menu(menu, (PurpleBlistNode *)buddy); 1134 pidgin_append_blist_node_privacy_menu(menu, (PurpleBlistNode *)buddy);
1127 pidgin_new_item_from_stock(menu, _("Alias..."), PIDGIN_STOCK_ALIAS, 1135 pidgin_new_item_from_stock(menu, _("_Alias..."), PIDGIN_STOCK_ALIAS,
1128 G_CALLBACK(gtk_blist_menu_alias_cb), 1136 G_CALLBACK(gtk_blist_menu_alias_cb),
1129 contact, 0, 0, NULL); 1137 contact, 0, 0, NULL);
1130 pidgin_new_item_from_stock(menu, _("Remove"), GTK_STOCK_REMOVE, 1138 pidgin_new_item_from_stock(menu, _("_Remove"), GTK_STOCK_REMOVE,
1131 G_CALLBACK(pidgin_blist_remove_cb), 1139 G_CALLBACK(pidgin_blist_remove_cb),
1132 contact, 0, 0, NULL); 1140 contact, 0, 0, NULL);
1133 } else if (!sub || contact_expanded) { 1141 } else if (!sub || contact_expanded) {
1134 pidgin_separator(menu); 1142 pidgin_separator(menu);
1135 pidgin_append_blist_node_privacy_menu(menu, (PurpleBlistNode *)buddy); 1143 pidgin_append_blist_node_privacy_menu(menu, (PurpleBlistNode *)buddy);
1140 0, 0, NULL); 1148 0, 0, NULL);
1141 } 1149 }
1142 } 1150 }
1143 1151
1144 static gboolean 1152 static gboolean
1145 gtk_blist_key_press_cb(GtkWidget *tv, GdkEventKey *event, gpointer data) { 1153 gtk_blist_key_press_cb(GtkWidget *tv, GdkEventKey *event, gpointer data)
1154 {
1146 PurpleBlistNode *node; 1155 PurpleBlistNode *node;
1147 GValue val; 1156 GValue val;
1148 GtkTreeIter iter; 1157 GtkTreeIter iter;
1149 GtkTreeSelection *sel; 1158 GtkTreeSelection *sel;
1150 1159
1167 buddy = (PurpleBuddy*)node; 1176 buddy = (PurpleBuddy*)node;
1168 } else { 1177 } else {
1169 return FALSE; 1178 return FALSE;
1170 } 1179 }
1171 if(buddy) 1180 if(buddy)
1172 serv_get_info(buddy->account->gc, buddy->name); 1181 pidgin_retrieve_user_info(buddy->account->gc, buddy->name);
1173 } else if (event->keyval == GDK_F2) { 1182 } else if (event->keyval == GDK_F2) {
1174 gtk_blist_menu_alias_cb(tv, node); 1183 gtk_blist_menu_alias_cb(tv, node);
1175 } 1184 }
1176 1185
1177 return FALSE; 1186 return FALSE;
1421 prpl = purple_find_prpl(purple_account_get_protocol_id(b->account)); 1430 prpl = purple_find_prpl(purple_account_get_protocol_id(b->account));
1422 if (prpl != NULL) 1431 if (prpl != NULL)
1423 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); 1432 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
1424 1433
1425 if (prpl && prpl_info->get_info) 1434 if (prpl && prpl_info->get_info)
1426 serv_get_info(b->account->gc, b->name); 1435 pidgin_retrieve_user_info(b->account->gc, b->name);
1427 handled = TRUE; 1436 handled = TRUE;
1428 } 1437 }
1429 1438
1430 #if (1) 1439 #if (1)
1431 /* 1440 /*
1540 1549
1541 static void 1550 static void
1542 add_buddies_from_vcard(const char *prpl_id, PurpleGroup *group, GList *list, 1551 add_buddies_from_vcard(const char *prpl_id, PurpleGroup *group, GList *list,
1543 const char *alias) 1552 const char *alias)
1544 { 1553 {
1545 GList *l; 1554 const GList *l;
1546 PurpleAccount *account = NULL; 1555 PurpleAccount *account = NULL;
1547 PurpleConnection *gc; 1556 PurpleConnection *gc;
1548 1557
1549 if (list == NULL) 1558 if (list == NULL)
1550 return; 1559 return;
2869 { N_("/Tools/R_oom List"), NULL, pidgin_roomlist_dialog_show, 0, "<Item>", NULL }, 2878 { N_("/Tools/R_oom List"), NULL, pidgin_roomlist_dialog_show, 0, "<Item>", NULL },
2870 { N_("/Tools/System _Log"), NULL, gtk_blist_show_systemlog_cb, 0, "<Item>", NULL }, 2879 { N_("/Tools/System _Log"), NULL, gtk_blist_show_systemlog_cb, 0, "<Item>", NULL },
2871 { N_("/Tools/_Debug Window"), NULL, toggle_debug, 0, "<Item>", NULL }, 2880 { N_("/Tools/_Debug Window"), NULL, toggle_debug, 0, "<Item>", NULL },
2872 { "/Tools/sep3", NULL, NULL, 0, "<Separator>", NULL }, 2881 { "/Tools/sep3", NULL, NULL, 0, "<Separator>", NULL },
2873 { N_("/Tools/Mute _Sounds"), "<CTL>S", pidgin_blist_mute_sounds_cb, 0, "<CheckItem>", NULL }, 2882 { N_("/Tools/Mute _Sounds"), "<CTL>S", pidgin_blist_mute_sounds_cb, 0, "<CheckItem>", NULL },
2883 /* Help */
2884 { N_("/_Help"), NULL, NULL, 0, "<Branch>", NULL },
2885 { N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, "<StockItem>", GTK_STOCK_HELP },
2886 { N_("/Help/_Debug Window"), NULL, toggle_debug, 0, "<Item>", NULL },
2887 { N_("/Help/_About"), NULL, pidgin_dialogs_about, 0, "<Item>", NULL },
2874 }; 2888 };
2875 2889
2876 /********************************************************* 2890 /*********************************************************
2877 * Private Utility functions * 2891 * Private Utility functions *
2878 *********************************************************/ 2892 *********************************************************/
2893 2907
2894 chat = (PurpleChat *)node; 2908 chat = (PurpleChat *)node;
2895 prpl = purple_find_prpl(purple_account_get_protocol_id(chat->account)); 2909 prpl = purple_find_prpl(purple_account_get_protocol_id(chat->account));
2896 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); 2910 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
2897 2911
2898 if (g_list_length(purple_connections_get_all()) > 1) 2912 if (g_list_length((GList *)purple_connections_get_all()) > 1)
2899 { 2913 {
2900 tmp = g_markup_escape_text(chat->account->username, -1); 2914 tmp = g_markup_escape_text(chat->account->username, -1);
2901 g_string_append_printf(str, _("\n<b>Account:</b> %s"), tmp); 2915 g_string_append_printf(str, _("\n<b>Account:</b> %s"), tmp);
2902 g_free(tmp); 2916 g_free(tmp);
2903 } 2917 }
2958 2972
2959 presence = purple_buddy_get_presence(b); 2973 presence = purple_buddy_get_presence(b);
2960 user_info = purple_notify_user_info_new(); 2974 user_info = purple_notify_user_info_new();
2961 2975
2962 /* Account */ 2976 /* Account */
2963 if (full && g_list_length(purple_connections_get_all()) > 1) 2977 if (full && g_list_length((GList *)purple_connections_get_all()) > 1)
2964 { 2978 {
2965 tmp = g_markup_escape_text(purple_account_get_username( 2979 tmp = g_markup_escape_text(purple_account_get_username(
2966 purple_buddy_get_account(b)), -1); 2980 purple_buddy_get_account(b)), -1);
2967 purple_notify_user_info_add_pair(user_info, _("Account"), tmp); 2981 purple_notify_user_info_add_pair(user_info, _("Account"), tmp);
2968 g_free(tmp); 2982 g_free(tmp);
2994 3008
2995 /* Logged In */ 3009 /* Logged In */
2996 signon = purple_presence_get_login_time(presence); 3010 signon = purple_presence_get_login_time(presence);
2997 if (full && PURPLE_BUDDY_IS_ONLINE(b) && signon > 0) 3011 if (full && PURPLE_BUDDY_IS_ONLINE(b) && signon > 0)
2998 { 3012 {
2999 tmp = purple_str_seconds_to_string(time(NULL) - signon); 3013 if (time(NULL) - signon > 63072000 /* 2 years */) {
3014 /*
3015 * Our local clock must be wrong, show the actual
3016 * date instead of "4 days", etc.
3017 */
3018 tmp = g_strdup(purple_date_format_long(localtime(&signon)));
3019 } else
3020 tmp = purple_str_seconds_to_string(time(NULL) - signon);
3000 purple_notify_user_info_add_pair(user_info, _("Logged In"), tmp); 3021 purple_notify_user_info_add_pair(user_info, _("Logged In"), tmp);
3001 g_free(tmp); 3022 g_free(tmp);
3002 } 3023 }
3003 3024
3004 /* Idle */ 3025 /* Idle */
3733 node->ui_data = g_new0(struct _pidgin_blist_node, 1); 3754 node->ui_data = g_new0(struct _pidgin_blist_node, 1);
3734 } 3755 }
3735 3756
3736 gboolean pidgin_blist_node_is_contact_expanded(PurpleBlistNode *node) 3757 gboolean pidgin_blist_node_is_contact_expanded(PurpleBlistNode *node)
3737 { 3758 {
3738 if PURPLE_BLIST_NODE_IS_BUDDY(node) 3759 if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
3739 node = node->parent; 3760 node = node->parent;
3761 if (node == NULL)
3762 return FALSE;
3763 }
3740 3764
3741 g_return_val_if_fail(PURPLE_BLIST_NODE_IS_CONTACT(node), FALSE); 3765 g_return_val_if_fail(PURPLE_BLIST_NODE_IS_CONTACT(node), FALSE);
3742 3766
3743 return ((struct _pidgin_blist_node *)node->ui_data)->contact_expanded; 3767 return ((struct _pidgin_blist_node *)node->ui_data)->contact_expanded;
3744 } 3768 }
3835 } 3859 }
3836 3860
3837 static gboolean 3861 static gboolean
3838 gtk_blist_window_key_press_cb(GtkWidget *w, GdkEventKey *event, PidginBuddyList *gtkblist) 3862 gtk_blist_window_key_press_cb(GtkWidget *w, GdkEventKey *event, PidginBuddyList *gtkblist)
3839 { 3863 {
3840 GtkWidget *imhtml; 3864 GtkWidget *widget;
3841 3865
3842 if (!gtkblist) 3866 if (!gtkblist)
3843 return FALSE; 3867 return FALSE;
3844 3868
3845 imhtml = gtk_window_get_focus(GTK_WINDOW(gtkblist->window)); 3869 widget = gtk_window_get_focus(GTK_WINDOW(gtkblist->window));
3846 3870
3847 if (GTK_IS_IMHTML(imhtml) && gtk_bindings_activate(GTK_OBJECT(imhtml), event->keyval, event->state)) 3871 if (GTK_IS_IMHTML(widget) || GTK_IS_ENTRY(widget)) {
3848 return TRUE; 3872 if (gtk_bindings_activate(GTK_OBJECT(widget), event->keyval, event->state))
3873 return TRUE;
3874 }
3849 return FALSE; 3875 return FALSE;
3850 } 3876 }
3851 3877
3852 static gboolean 3878 static gboolean
3853 headline_hover_close(int x, int y) 3879 headline_hover_close(int x, int y)
4206 {"text/plain", 0, DRAG_TEXT}}; 4232 {"text/plain", 0, DRAG_TEXT}};
4207 GtkTargetEntry ste[] = {{"PURPLE_BLIST_NODE", GTK_TARGET_SAME_APP, DRAG_ROW}, 4233 GtkTargetEntry ste[] = {{"PURPLE_BLIST_NODE", GTK_TARGET_SAME_APP, DRAG_ROW},
4208 {"application/x-im-contact", 0, DRAG_BUDDY}, 4234 {"application/x-im-contact", 0, DRAG_BUDDY},
4209 {"text/x-vcard", 0, DRAG_VCARD }}; 4235 {"text/x-vcard", 0, DRAG_VCARD }};
4210 if (gtkblist && gtkblist->window) { 4236 if (gtkblist && gtkblist->window) {
4211 purple_blist_set_visible(purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/list_visible")); 4237 purple_blist_set_visible(TRUE);
4212 return; 4238 return;
4213 } 4239 }
4214 4240
4215 gtkblist = PIDGIN_BLIST(list); 4241 gtkblist = PIDGIN_BLIST(list);
4216 4242
4217 gtkblist->empty_avatar = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 32, 32); 4243 gtkblist->empty_avatar = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 32, 32);
4218 gdk_pixbuf_fill(gtkblist->empty_avatar, 0x00000000); 4244 gdk_pixbuf_fill(gtkblist->empty_avatar, 0x00000000);
4219 4245
4220 gtkblist->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 4246 gtkblist->window = pidgin_create_window(_("Buddy List"), 0, "buddy_list", TRUE);
4221 gtk_window_set_role(GTK_WINDOW(gtkblist->window), "buddy_list");
4222 gtk_window_set_title(GTK_WINDOW(gtkblist->window), _("Buddy List"));
4223 g_signal_connect(G_OBJECT(gtkblist->window), "focus-in-event", 4247 g_signal_connect(G_OBJECT(gtkblist->window), "focus-in-event",
4224 G_CALLBACK(blist_focus_cb), gtkblist); 4248 G_CALLBACK(blist_focus_cb), gtkblist);
4225 GTK_WINDOW(gtkblist->window)->allow_shrink = TRUE; 4249 GTK_WINDOW(gtkblist->window)->allow_shrink = TRUE;
4226 4250
4227 gtkblist->main_vbox = gtk_vbox_new(FALSE, 0); 4251 gtkblist->main_vbox = gtk_vbox_new(FALSE, 0);
4440 "cell-background-gdk", BGCOLOR_COLUMN, 4464 "cell-background-gdk", BGCOLOR_COLUMN,
4441 #endif 4465 #endif
4442 "markup", NAME_COLUMN, 4466 "markup", NAME_COLUMN,
4443 NULL); 4467 NULL);
4444 g_signal_connect(G_OBJECT(rend), "editing-started", G_CALLBACK(gtk_blist_renderer_editing_started_cb), NULL); 4468 g_signal_connect(G_OBJECT(rend), "editing-started", G_CALLBACK(gtk_blist_renderer_editing_started_cb), NULL);
4445 g_signal_connect(G_OBJECT(rend), "edited", G_CALLBACK(gtk_blist_renderer_edited_cb), NULL); 4469 g_signal_connect(G_OBJECT(rend), "editing-canceled", G_CALLBACK(gtk_blist_renderer_editing_cancelled_cb), list);
4470 g_signal_connect(G_OBJECT(rend), "edited", G_CALLBACK(gtk_blist_renderer_edited_cb), list);
4446 g_object_set(rend, "ypad", 0, "yalign", 0.5, NULL); 4471 g_object_set(rend, "ypad", 0, "yalign", 0.5, NULL);
4447 #if GTK_CHECK_VERSION(2,6,0) 4472 #if GTK_CHECK_VERSION(2,6,0)
4448 g_object_set(rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL); 4473 g_object_set(rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
4449 #endif 4474 #endif
4450 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), column); 4475 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), column);
4735 if(gtk_tree_selection_get_selected(selection, NULL, &iter)){ 4760 if(gtk_tree_selection_get_selected(selection, NULL, &iter)){
4736 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, 4761 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter,
4737 NODE_COLUMN, &new_selection, -1); 4762 NODE_COLUMN, &new_selection, -1);
4738 } 4763 }
4739 4764
4740 /* we set this up as a timeout, otherwise the blist flickers */ 4765 /* we set this up as a timeout, otherwise the blist flickers ...
4741 g_timeout_add(0, (GSourceFunc)do_selection_changed, new_selection); 4766 * but we don't do it for groups, because it causes total bizarness -
4767 * the previously selected buddy node might rendered at half height.
4768 */
4769 if ((new_selection != NULL) && PURPLE_BLIST_NODE_IS_GROUP(new_selection)) {
4770 do_selection_changed(new_selection);
4771 } else {
4772 g_timeout_add(0, (GSourceFunc)do_selection_changed, new_selection);
4773 }
4742 } 4774 }
4743 4775
4744 static gboolean insert_node(PurpleBuddyList *list, PurpleBlistNode *node, GtkTreeIter *iter) 4776 static gboolean insert_node(PurpleBuddyList *list, PurpleBlistNode *node, GtkTreeIter *iter)
4745 { 4777 {
4746 GtkTreeIter parent_iter, cur, *curptr = NULL; 4778 GtkTreeIter parent_iter, cur, *curptr = NULL;
4775 gtk_tree_row_reference_new(GTK_TREE_MODEL(gtkblist->treemodel), 4807 gtk_tree_row_reference_new(GTK_TREE_MODEL(gtkblist->treemodel),
4776 newpath); 4808 newpath);
4777 4809
4778 gtk_tree_path_free(newpath); 4810 gtk_tree_path_free(newpath);
4779 4811
4780 gtk_tree_store_set(gtkblist->treemodel, iter, 4812 if (!editing_blist)
4781 NODE_COLUMN, node, 4813 gtk_tree_store_set(gtkblist->treemodel, iter,
4782 -1); 4814 NODE_COLUMN, node,
4815 -1);
4783 4816
4784 if(node->parent) { 4817 if(node->parent) {
4785 GtkTreePath *expand = NULL; 4818 GtkTreePath *expand = NULL;
4786 struct _pidgin_blist_node *gtkparentnode = node->parent->ui_data; 4819 struct _pidgin_blist_node *gtkparentnode = node->parent->ui_data;
4787 4820
4810 gboolean show = FALSE; 4843 gboolean show = FALSE;
4811 PurpleBlistNode* gnode; 4844 PurpleBlistNode* gnode;
4812 4845
4813 g_return_if_fail(node != NULL); 4846 g_return_if_fail(node != NULL);
4814 4847
4848 if (editing_blist)
4849 return;
4850
4815 if (PURPLE_BLIST_NODE_IS_GROUP(node)) 4851 if (PURPLE_BLIST_NODE_IS_GROUP(node))
4816 gnode = node; 4852 gnode = node;
4817 else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) 4853 else if (PURPLE_BLIST_NODE_IS_BUDDY(node))
4818 gnode = node->parent->parent; 4854 gnode = node->parent->parent;
4819 else if (PURPLE_BLIST_NODE_IS_CONTACT(node) || PURPLE_BLIST_NODE_IS_CHAT(node)) 4855 else if (PURPLE_BLIST_NODE_IS_CONTACT(node) || PURPLE_BLIST_NODE_IS_CHAT(node))
4911 gboolean expanded = ((struct _pidgin_blist_node *)(node->parent->ui_data))->contact_expanded; 4947 gboolean expanded = ((struct _pidgin_blist_node *)(node->parent->ui_data))->contact_expanded;
4912 gboolean selected = (gtkblist->selected_node == node); 4948 gboolean selected = (gtkblist->selected_node == node);
4913 gboolean biglist = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"); 4949 gboolean biglist = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons");
4914 presence = purple_buddy_get_presence(buddy); 4950 presence = purple_buddy_get_presence(buddy);
4915 4951
4952 if (editing_blist)
4953 return;
4954
4916 status = pidgin_blist_get_status_icon((PurpleBlistNode*)buddy, 4955 status = pidgin_blist_get_status_icon((PurpleBlistNode*)buddy,
4917 PIDGIN_STATUS_ICON_SMALL); 4956 PIDGIN_STATUS_ICON_SMALL);
4918 4957
4919 /* Speed it up if we don't want buddy icons. */ 4958 /* Speed it up if we don't want buddy icons. */
4920 if(biglist) 4959 if(biglist)
4989 { 5028 {
4990 PurpleBlistNode *cnode; 5029 PurpleBlistNode *cnode;
4991 PurpleContact *contact; 5030 PurpleContact *contact;
4992 PurpleBuddy *buddy; 5031 PurpleBuddy *buddy;
4993 struct _pidgin_blist_node *gtknode; 5032 struct _pidgin_blist_node *gtknode;
5033 if (editing_blist)
5034 return;
4994 5035
4995 if (PURPLE_BLIST_NODE_IS_BUDDY(node)) 5036 if (PURPLE_BLIST_NODE_IS_BUDDY(node))
4996 cnode = node->parent; 5037 cnode = node->parent;
4997 else 5038 else
4998 cnode = node; 5039 cnode = node;
5085 static void pidgin_blist_update_chat(PurpleBuddyList *list, PurpleBlistNode *node) 5126 static void pidgin_blist_update_chat(PurpleBuddyList *list, PurpleBlistNode *node)
5086 { 5127 {
5087 PurpleChat *chat; 5128 PurpleChat *chat;
5088 5129
5089 g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); 5130 g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
5131 if (editing_blist)
5132 return;
5090 5133
5091 /* First things first, update the group */ 5134 /* First things first, update the group */
5092 pidgin_blist_update_group(list, node->parent); 5135 pidgin_blist_update_group(list, node->parent);
5093 5136
5094 chat = (PurpleChat*)node; 5137 chat = (PurpleChat*)node;
5397 gtk_table_set_row_spacings(GTK_TABLE(table), 5); 5440 gtk_table_set_row_spacings(GTK_TABLE(table), 5);
5398 gtk_table_set_col_spacings(GTK_TABLE(table), 5); 5441 gtk_table_set_col_spacings(GTK_TABLE(table), 5);
5399 gtk_container_set_border_width(GTK_CONTAINER(table), 0); 5442 gtk_container_set_border_width(GTK_CONTAINER(table), 0);
5400 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); 5443 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
5401 5444
5402 label = gtk_label_new(_("Screen name:")); 5445 /* Set up stuff for the account box */
5446 label = gtk_label_new_with_mnemonic(_("_Account:"));
5403 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 5447 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
5404 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1); 5448 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
5405 5449
5450 data->account_box = pidgin_account_option_menu_new(account, FALSE,
5451 G_CALLBACK(add_buddy_select_account_cb), NULL, data);
5452
5453 gtk_table_attach_defaults(GTK_TABLE(table), data->account_box, 1, 2, 0, 1);
5454 gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->account_box);
5455 pidgin_set_accessible_label (data->account_box, label);
5456 /* End of account box */
5457
5458 label = gtk_label_new_with_mnemonic(_("_Screen name:"));
5459 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
5460 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
5461
5406 data->entry = gtk_entry_new(); 5462 data->entry = gtk_entry_new();
5407 gtk_table_attach_defaults(GTK_TABLE(table), data->entry, 1, 2, 0, 1); 5463 gtk_table_attach_defaults(GTK_TABLE(table), data->entry, 1, 2, 1, 2);
5408 gtk_widget_grab_focus(data->entry); 5464 gtk_widget_grab_focus(data->entry);
5409 5465
5410 if (username != NULL) 5466 if (username != NULL)
5411 gtk_entry_set_text(GTK_ENTRY(data->entry), username); 5467 gtk_entry_set_text(GTK_ENTRY(data->entry), username);
5412 else 5468 else
5413 gtk_dialog_set_response_sensitive(GTK_DIALOG(data->window), 5469 gtk_dialog_set_response_sensitive(GTK_DIALOG(data->window),
5414 GTK_RESPONSE_OK, FALSE); 5470 GTK_RESPONSE_OK, FALSE);
5415 5471
5416 gtk_entry_set_activates_default (GTK_ENTRY(data->entry), TRUE); 5472 gtk_entry_set_activates_default (GTK_ENTRY(data->entry), TRUE);
5473 gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->entry);
5417 pidgin_set_accessible_label (data->entry, label); 5474 pidgin_set_accessible_label (data->entry, label);
5418 5475
5419 g_signal_connect(G_OBJECT(data->entry), "changed", 5476 g_signal_connect(G_OBJECT(data->entry), "changed",
5420 G_CALLBACK(pidgin_set_sensitive_if_input), 5477 G_CALLBACK(pidgin_set_sensitive_if_input),
5421 data->window); 5478 data->window);
5422 5479
5423 label = gtk_label_new(_("Alias:")); 5480 label = gtk_label_new_with_mnemonic(_("A_lias:"));
5424 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 5481 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
5425 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2); 5482 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
5426 5483
5427 data->entry_for_alias = gtk_entry_new(); 5484 data->entry_for_alias = gtk_entry_new();
5428 gtk_table_attach_defaults(GTK_TABLE(table), 5485 gtk_table_attach_defaults(GTK_TABLE(table),
5429 data->entry_for_alias, 1, 2, 1, 2); 5486 data->entry_for_alias, 1, 2, 2, 3);
5430 5487
5431 if (alias != NULL) 5488 if (alias != NULL)
5432 gtk_entry_set_text(GTK_ENTRY(data->entry_for_alias), alias); 5489 gtk_entry_set_text(GTK_ENTRY(data->entry_for_alias), alias);
5433 5490
5434 if (username != NULL) 5491 if (username != NULL)
5435 gtk_widget_grab_focus(GTK_WIDGET(data->entry_for_alias)); 5492 gtk_widget_grab_focus(GTK_WIDGET(data->entry_for_alias));
5436 5493
5437 gtk_entry_set_activates_default (GTK_ENTRY(data->entry_for_alias), TRUE); 5494 gtk_entry_set_activates_default (GTK_ENTRY(data->entry_for_alias), TRUE);
5495 gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->entry_for_alias);
5438 pidgin_set_accessible_label (data->entry_for_alias, label); 5496 pidgin_set_accessible_label (data->entry_for_alias, label);
5439 5497
5440 label = gtk_label_new(_("Group:")); 5498 label = gtk_label_new_with_mnemonic(_("_Group:"));
5441 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 5499 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
5442 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3); 5500 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4);
5443 5501
5444 data->combo = gtk_combo_new(); 5502 data->combo = gtk_combo_new();
5445 gtk_combo_set_popdown_strings(GTK_COMBO(data->combo), groups_tree()); 5503 gtk_combo_set_popdown_strings(GTK_COMBO(data->combo), groups_tree());
5446 gtk_table_attach_defaults(GTK_TABLE(table), data->combo, 1, 2, 2, 3); 5504 gtk_table_attach_defaults(GTK_TABLE(table), data->combo, 1, 2, 3, 4);
5505 gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_COMBO(data->combo)->entry);
5447 pidgin_set_accessible_label (data->combo, label); 5506 pidgin_set_accessible_label (data->combo, label);
5448
5449 /* Set up stuff for the account box */
5450 label = gtk_label_new(_("Account:"));
5451 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
5452 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4);
5453
5454 data->account_box = pidgin_account_option_menu_new(account, FALSE,
5455 G_CALLBACK(add_buddy_select_account_cb), NULL, data);
5456
5457 gtk_table_attach_defaults(GTK_TABLE(table), data->account_box, 1, 2, 3, 4);
5458 pidgin_set_accessible_label (data->account_box, label);
5459 /* End of account box */
5460 5507
5461 g_signal_connect(G_OBJECT(data->window), "response", 5508 g_signal_connect(G_OBJECT(data->window), "response",
5462 G_CALLBACK(add_buddy_cb), data); 5509 G_CALLBACK(add_buddy_cb), data);
5463 5510
5464 gtk_widget_show_all(data->window); 5511 gtk_widget_show_all(data->window);
5682 pidgin_blist_request_add_chat(PurpleAccount *account, PurpleGroup *group, 5729 pidgin_blist_request_add_chat(PurpleAccount *account, PurpleGroup *group,
5683 const char *alias, const char *name) 5730 const char *alias, const char *name)
5684 { 5731 {
5685 PidginAddChatData *data; 5732 PidginAddChatData *data;
5686 PidginBuddyList *gtkblist; 5733 PidginBuddyList *gtkblist;
5687 GList *l; 5734 const GList *l;
5688 PurpleConnection *gc; 5735 PurpleConnection *gc;
5689 GtkWidget *label; 5736 GtkWidget *label;
5690 GtkWidget *rowbox; 5737 GtkWidget *rowbox;
5691 GtkWidget *hbox; 5738 GtkWidget *hbox;
5692 GtkWidget *vbox; 5739 GtkWidget *vbox;
5761 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); 5808 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
5762 5809
5763 rowbox = gtk_hbox_new(FALSE, 5); 5810 rowbox = gtk_hbox_new(FALSE, 5);
5764 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0); 5811 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0);
5765 5812
5766 label = gtk_label_new(_("Account:")); 5813 label = gtk_label_new_with_mnemonic(_("_Account:"));
5767 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 5814 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
5768 gtk_size_group_add_widget(data->sg, label); 5815 gtk_size_group_add_widget(data->sg, label);
5769 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); 5816 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
5770 5817
5771 data->account_menu = pidgin_account_option_menu_new(account, FALSE, 5818 data->account_menu = pidgin_account_option_menu_new(account, FALSE,
5772 G_CALLBACK(addchat_select_account_cb), 5819 G_CALLBACK(addchat_select_account_cb),
5773 chat_account_filter_func, data); 5820 chat_account_filter_func, data);
5774 gtk_box_pack_start(GTK_BOX(rowbox), data->account_menu, TRUE, TRUE, 0); 5821 gtk_box_pack_start(GTK_BOX(rowbox), data->account_menu, TRUE, TRUE, 0);
5822 gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->account_menu);
5775 pidgin_set_accessible_label (data->account_menu, label); 5823 pidgin_set_accessible_label (data->account_menu, label);
5776 5824
5777 data->entries_box = gtk_vbox_new(FALSE, 5); 5825 data->entries_box = gtk_vbox_new(FALSE, 5);
5778 gtk_container_set_border_width(GTK_CONTAINER(data->entries_box), 0); 5826 gtk_container_set_border_width(GTK_CONTAINER(data->entries_box), 0);
5779 gtk_box_pack_start(GTK_BOX(vbox), data->entries_box, TRUE, TRUE, 0); 5827 gtk_box_pack_start(GTK_BOX(vbox), data->entries_box, TRUE, TRUE, 0);
5781 rebuild_addchat_entries(data); 5829 rebuild_addchat_entries(data);
5782 5830
5783 rowbox = gtk_hbox_new(FALSE, 5); 5831 rowbox = gtk_hbox_new(FALSE, 5);
5784 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0); 5832 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0);
5785 5833
5786 label = gtk_label_new(_("Alias:")); 5834 label = gtk_label_new_with_mnemonic(_("A_lias:"));
5787 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 5835 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
5788 gtk_size_group_add_widget(data->sg, label); 5836 gtk_size_group_add_widget(data->sg, label);
5789 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); 5837 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
5790 5838
5791 data->alias_entry = gtk_entry_new(); 5839 data->alias_entry = gtk_entry_new();
5792 if (alias != NULL) 5840 if (alias != NULL)
5793 gtk_entry_set_text(GTK_ENTRY(data->alias_entry), alias); 5841 gtk_entry_set_text(GTK_ENTRY(data->alias_entry), alias);
5794 gtk_box_pack_end(GTK_BOX(rowbox), data->alias_entry, TRUE, TRUE, 0); 5842 gtk_box_pack_end(GTK_BOX(rowbox), data->alias_entry, TRUE, TRUE, 0);
5795 gtk_entry_set_activates_default(GTK_ENTRY(data->alias_entry), TRUE); 5843 gtk_entry_set_activates_default(GTK_ENTRY(data->alias_entry), TRUE);
5844 gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->alias_entry);
5796 pidgin_set_accessible_label (data->alias_entry, label); 5845 pidgin_set_accessible_label (data->alias_entry, label);
5797 if (name != NULL) 5846 if (name != NULL)
5798 gtk_widget_grab_focus(data->alias_entry); 5847 gtk_widget_grab_focus(data->alias_entry);
5799 5848
5800 rowbox = gtk_hbox_new(FALSE, 5); 5849 rowbox = gtk_hbox_new(FALSE, 5);
5801 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0); 5850 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0);
5802 5851
5803 label = gtk_label_new(_("Group:")); 5852 label = gtk_label_new_with_mnemonic(_("_Group:"));
5804 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 5853 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
5805 gtk_size_group_add_widget(data->sg, label); 5854 gtk_size_group_add_widget(data->sg, label);
5806 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); 5855 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
5807 5856
5808 data->group_combo = gtk_combo_new(); 5857 data->group_combo = gtk_combo_new();
5812 if (group) 5861 if (group)
5813 { 5862 {
5814 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(data->group_combo)->entry), 5863 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(data->group_combo)->entry),
5815 group->name); 5864 group->name);
5816 } 5865 }
5866 gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_COMBO(data->group_combo)->entry);
5817 pidgin_set_accessible_label (data->group_combo, label); 5867 pidgin_set_accessible_label (data->group_combo, label);
5818 5868
5819 g_signal_connect(G_OBJECT(data->window), "response", 5869 g_signal_connect(G_OBJECT(data->window), "response",
5820 G_CALLBACK(add_chat_resp_cb), data); 5870 G_CALLBACK(add_chat_resp_cb), data);
5821 5871
6446 void 6496 void
6447 pidgin_blist_update_accounts_menu(void) 6497 pidgin_blist_update_accounts_menu(void)
6448 { 6498 {
6449 GtkWidget *menuitem = NULL, *submenu = NULL; 6499 GtkWidget *menuitem = NULL, *submenu = NULL;
6450 GtkAccelGroup *accel_group = NULL; 6500 GtkAccelGroup *accel_group = NULL;
6451 GList *l = NULL, *accounts = NULL; 6501 GList *l = NULL;
6502 const GList *accounts;
6452 gboolean disabled_accounts = FALSE; 6503 gboolean disabled_accounts = FALSE;
6453 6504
6454 if (accountmenu == NULL) 6505 if (accountmenu == NULL)
6455 return; 6506 return;
6456 6507