pidgin/gtkblist.c

changeset 18545
5af898e91ec2
parent 18373
f6b2e4dd0e9b
child 18556
9517c517e59d
equal deleted inserted replaced
17398:1edf059a4a26 18545:5af898e91ec2
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
148 static char *dim_grey() 149 static char *dim_grey()
149 { 150 {
150 if (!gtkblist) 151 if (!gtkblist)
151 return "dim grey"; 152 return "dim grey";
152 if (!dim_grey_string[0]) { 153 if (!dim_grey_string[0]) {
153 GtkStyle *style = gtk_widget_get_style(gtkblist->treeview); 154 snprintf(dim_grey_string, sizeof(dim_grey_string), "%s", pidgin_get_dim_grey_string(gtkblist->treeview));
154 snprintf(dim_grey_string, sizeof(dim_grey_string), "#%02x%02x%02x",
155 style->text_aa[GTK_STATE_NORMAL].red >> 8,
156 style->text_aa[GTK_STATE_NORMAL].green >> 8,
157 style->text_aa[GTK_STATE_NORMAL].blue >> 8);
158 } 155 }
159 return dim_grey_string; 156 return dim_grey_string;
160 } 157 }
161 158
162 /*************************************************** 159 /***************************************************
175 return FALSE; 172 return FALSE;
176 } 173 }
177 174
178 static gboolean gtk_blist_window_state_cb(GtkWidget *w, GdkEventWindowState *event, gpointer data) 175 static gboolean gtk_blist_window_state_cb(GtkWidget *w, GdkEventWindowState *event, gpointer data)
179 { 176 {
177 #if GTK_CHECK_VERSION(2,2,0)
180 if(event->changed_mask & GDK_WINDOW_STATE_WITHDRAWN) { 178 if(event->changed_mask & GDK_WINDOW_STATE_WITHDRAWN) {
181 if(event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) 179 if(event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN)
182 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_visible", FALSE); 180 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_visible", FALSE);
183 else { 181 else {
184 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_visible", TRUE); 182 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_visible", TRUE);
196 /* Refresh gtkblist if un-iconifying */ 194 /* Refresh gtkblist if un-iconifying */
197 if (event->changed_mask & GDK_WINDOW_STATE_ICONIFIED){ 195 if (event->changed_mask & GDK_WINDOW_STATE_ICONIFIED){
198 if (!(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED)) 196 if (!(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED))
199 pidgin_blist_refresh_timer(purple_get_blist()); 197 pidgin_blist_refresh_timer(purple_get_blist());
200 } 198 }
199 #else
200 /* At least gtk+ 2.0.6 does not properly set the change_mask when unsetting a
201 * GdkWindowState flag. To work around, the window state will be explicitly
202 * queried on these older versions of gtk+. See pidgin ticket #739.
203 */
204 GdkWindowState new_window_state = gdk_window_get_state(G_OBJECT(gtkblist->window->window));
205
206 if(new_window_state & GDK_WINDOW_STATE_WITHDRAWN) {
207 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_visible", FALSE);
208 } else {
209 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_visible", TRUE);
210 pidgin_blist_refresh_timer(purple_get_blist());
211 }
212
213 if(new_window_state & GDK_WINDOW_STATE_MAXIMIZED)
214 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_maximized", TRUE);
215 else
216 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_maximized", FALSE);
217
218 if (!(new_window_state & GDK_WINDOW_STATE_ICONIFIED))
219 pidgin_blist_refresh_timer(purple_get_blist());
220 #endif
201 221
202 return FALSE; 222 return FALSE;
203 } 223 }
204 224
205 static gboolean gtk_blist_delete_cb(GtkWidget *w, GdkEventAny *event, gpointer data) 225 static gboolean gtk_blist_delete_cb(GtkWidget *w, GdkEventAny *event, gpointer data)
264 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/x", x); 284 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/x", x);
265 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/y", y); 285 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/y", y);
266 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/width", event->width); 286 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/width", event->width);
267 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/height", event->height); 287 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/height", event->height);
268 288
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 */ 289 /* continue to handle event normally */
272 return FALSE; 290 return FALSE;
273 } 291 }
274 292
275 static void gtk_blist_menu_info_cb(GtkWidget *w, PurpleBuddy *b) 293 static void gtk_blist_menu_info_cb(GtkWidget *w, PurpleBuddy *b)
276 { 294 {
277 PurpleNotifyUserInfo *info = purple_notify_user_info_new(); 295 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 } 296 }
284 297
285 static void gtk_blist_menu_im_cb(GtkWidget *w, PurpleBuddy *b) 298 static void gtk_blist_menu_im_cb(GtkWidget *w, PurpleBuddy *b)
286 { 299 {
287 pidgin_dialogs_im_with_user(b->account, b->name); 300 pidgin_dialogs_im_with_user(b->account, b->name);
299 } 312 }
300 313
301 static void gtk_blist_join_chat(PurpleChat *chat) 314 static void gtk_blist_join_chat(PurpleChat *chat)
302 { 315 {
303 PurpleConversation *conv; 316 PurpleConversation *conv;
304 317 PurplePluginProtocolInfo *prpl_info;
305 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, 318 const char *name;
306 purple_chat_get_name(chat), 319 char *chat_name;
320
321 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(chat->account)));
322
323 if (prpl_info && prpl_info->get_chat_name)
324 chat_name = prpl_info->get_chat_name(chat->components);
325 else
326 chat_name = NULL;
327
328 if (chat_name)
329 name = chat_name;
330 else
331 name = purple_chat_get_name(chat);
332
333 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, name,
307 chat->account); 334 chat->account);
308 335
309 if (conv != NULL) 336 if (conv != NULL)
310 purple_conversation_present(conv); 337 purple_conversation_present(conv);
311 338
312 serv_join_chat(chat->account->gc, chat->components); 339 serv_join_chat(chat->account->gc, chat->components);
340 g_free(chat_name);
313 } 341 }
314 342
315 static void gtk_blist_menu_join_cb(GtkWidget *w, PurpleChat *chat) 343 static void gtk_blist_menu_join_cb(GtkWidget *w, PurpleChat *chat)
316 { 344 {
317 gtk_blist_join_chat(chat); 345 gtk_blist_join_chat(chat);
346 }
347
348 #if GTK_CHECK_VERSION(2,6,0)
349 static void gtk_blist_renderer_editing_cancelled_cb(GtkCellRenderer *renderer, PurpleBuddyList *list)
350 {
351 editing_blist = FALSE;
352 pidgin_blist_refresh(list);
318 } 353 }
319 354
320 static void gtk_blist_renderer_editing_started_cb(GtkCellRenderer *renderer, 355 static void gtk_blist_renderer_editing_started_cb(GtkCellRenderer *renderer,
321 GtkCellEditable *editable, 356 GtkCellEditable *editable,
322 gchar *path_str, 357 gchar *path_str,
351 386
352 if (GTK_IS_ENTRY (editable)) { 387 if (GTK_IS_ENTRY (editable)) {
353 GtkEntry *entry = GTK_ENTRY (editable); 388 GtkEntry *entry = GTK_ENTRY (editable);
354 gtk_entry_set_text(entry, text); 389 gtk_entry_set_text(entry, text);
355 } 390 }
356 } 391 editing_blist = TRUE;
392 }
393 #endif
357 394
358 static void gtk_blist_renderer_edited_cb(GtkCellRendererText *text_rend, char *arg1, 395 static void gtk_blist_renderer_edited_cb(GtkCellRendererText *text_rend, char *arg1,
359 char *arg2, gpointer nada) 396 char *arg2, PurpleBuddyList *list)
360 { 397 {
361 GtkTreeIter iter; 398 GtkTreeIter iter;
362 GtkTreePath *path; 399 GtkTreePath *path;
363 GValue val; 400 GValue val;
364 PurpleBlistNode *node; 401 PurpleBlistNode *node;
365 PurpleGroup *dest; 402 PurpleGroup *dest;
366 403
404 editing_blist = FALSE;
367 path = gtk_tree_path_new_from_string (arg1); 405 path = gtk_tree_path_new_from_string (arg1);
368 gtk_tree_model_get_iter (GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); 406 gtk_tree_model_get_iter (GTK_TREE_MODEL(gtkblist->treemodel), &iter, path);
369 gtk_tree_path_free (path); 407 gtk_tree_path_free (path);
370 val.g_type = 0; 408 val.g_type = 0;
371 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); 409 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val);
406 purple_blist_alias_chat((PurpleChat*)node, arg2); 444 purple_blist_alias_chat((PurpleChat*)node, arg2);
407 break; 445 break;
408 default: 446 default:
409 break; 447 break;
410 } 448 }
449 pidgin_blist_refresh(list);
411 } 450 }
412 451
413 static void gtk_blist_menu_alias_cb(GtkWidget *w, PurpleBlistNode *node) 452 static void gtk_blist_menu_alias_cb(GtkWidget *w, PurpleBlistNode *node)
414 { 453 {
415 GtkTreeIter iter; 454 GtkTreeIter iter;
488 pidgin_syslog_show(); 527 pidgin_syslog_show();
489 } 528 }
490 529
491 static void gtk_blist_show_onlinehelp_cb() 530 static void gtk_blist_show_onlinehelp_cb()
492 { 531 {
493 purple_notify_uri(NULL, PURPLE_WEBSITE "documentation.php"); 532 purple_notify_uri(NULL, PURPLE_WEBSITE "documentation");
494 } 533 }
495 534
496 static void 535 static void
497 do_join_chat(PidginJoinChatData *data) 536 do_join_chat(PidginJoinChatData *data)
498 { 537 {
1127 pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy); 1166 pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy);
1128 1167
1129 if (((PurpleBlistNode*)buddy)->parent->child->next && !sub && !contact_expanded) { 1168 if (((PurpleBlistNode*)buddy)->parent->child->next && !sub && !contact_expanded) {
1130 pidgin_separator(menu); 1169 pidgin_separator(menu);
1131 pidgin_append_blist_node_privacy_menu(menu, (PurpleBlistNode *)buddy); 1170 pidgin_append_blist_node_privacy_menu(menu, (PurpleBlistNode *)buddy);
1132 pidgin_new_item_from_stock(menu, _("Alias..."), PIDGIN_STOCK_ALIAS, 1171 pidgin_new_item_from_stock(menu, _("_Alias..."), PIDGIN_STOCK_ALIAS,
1133 G_CALLBACK(gtk_blist_menu_alias_cb), 1172 G_CALLBACK(gtk_blist_menu_alias_cb),
1134 contact, 0, 0, NULL); 1173 contact, 0, 0, NULL);
1135 pidgin_new_item_from_stock(menu, _("Remove"), GTK_STOCK_REMOVE, 1174 pidgin_new_item_from_stock(menu, _("_Remove"), GTK_STOCK_REMOVE,
1136 G_CALLBACK(pidgin_blist_remove_cb), 1175 G_CALLBACK(pidgin_blist_remove_cb),
1137 contact, 0, 0, NULL); 1176 contact, 0, 0, NULL);
1138 } else if (!sub || contact_expanded) { 1177 } else if (!sub || contact_expanded) {
1139 pidgin_separator(menu); 1178 pidgin_separator(menu);
1140 pidgin_append_blist_node_privacy_menu(menu, (PurpleBlistNode *)buddy); 1179 pidgin_append_blist_node_privacy_menu(menu, (PurpleBlistNode *)buddy);
1145 0, 0, NULL); 1184 0, 0, NULL);
1146 } 1185 }
1147 } 1186 }
1148 1187
1149 static gboolean 1188 static gboolean
1150 gtk_blist_key_press_cb(GtkWidget *tv, GdkEventKey *event, gpointer data) { 1189 gtk_blist_key_press_cb(GtkWidget *tv, GdkEventKey *event, gpointer data)
1190 {
1151 PurpleBlistNode *node; 1191 PurpleBlistNode *node;
1152 GValue val; 1192 GValue val;
1153 GtkTreeIter iter; 1193 GtkTreeIter iter;
1154 GtkTreeSelection *sel; 1194 GtkTreeSelection *sel;
1155 1195
1172 buddy = (PurpleBuddy*)node; 1212 buddy = (PurpleBuddy*)node;
1173 } else { 1213 } else {
1174 return FALSE; 1214 return FALSE;
1175 } 1215 }
1176 if(buddy) 1216 if(buddy)
1177 serv_get_info(buddy->account->gc, buddy->name); 1217 pidgin_retrieve_user_info(buddy->account->gc, buddy->name);
1178 } else if (event->keyval == GDK_F2) { 1218 } else if (event->keyval == GDK_F2) {
1179 gtk_blist_menu_alias_cb(tv, node); 1219 gtk_blist_menu_alias_cb(tv, node);
1180 } 1220 }
1181 1221
1182 return FALSE; 1222 return FALSE;
1426 prpl = purple_find_prpl(purple_account_get_protocol_id(b->account)); 1466 prpl = purple_find_prpl(purple_account_get_protocol_id(b->account));
1427 if (prpl != NULL) 1467 if (prpl != NULL)
1428 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); 1468 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
1429 1469
1430 if (prpl && prpl_info->get_info) 1470 if (prpl && prpl_info->get_info)
1431 serv_get_info(b->account->gc, b->name); 1471 pidgin_retrieve_user_info(b->account->gc, b->name);
1432 handled = TRUE; 1472 handled = TRUE;
1433 } 1473 }
1434 1474
1435 #if (1) 1475 #if (1)
1436 /* 1476 /*
2086 } 2126 }
2087 } 2127 }
2088 } 2128 }
2089 } 2129 }
2090 2130
2091 static void
2092 roundify(GdkPixbuf *pixbuf) {
2093 int width, height, rowstride;
2094 guchar *pixels;
2095
2096 if (!gdk_pixbuf_get_has_alpha(pixbuf))
2097 return;
2098
2099 width = gdk_pixbuf_get_width(pixbuf);
2100 height = gdk_pixbuf_get_height(pixbuf);
2101 rowstride = gdk_pixbuf_get_rowstride(pixbuf);
2102 pixels = gdk_pixbuf_get_pixels(pixbuf);
2103
2104 if (width < 6 || height < 6)
2105 return;
2106
2107 /* Top left */
2108 pixels[3] = 0;
2109 pixels[7] = 0x80;
2110 pixels[11] = 0xC0;
2111 pixels[rowstride + 3] = 0x80;
2112 pixels[rowstride * 2 + 3] = 0xC0;
2113
2114 /* Top right */
2115 pixels[width * 4 - 1] = 0;
2116 pixels[width * 4 - 5] = 0x80;
2117 pixels[width * 4 - 9] = 0xC0;
2118 pixels[rowstride + (width * 4) - 1] = 0x80;
2119 pixels[(2 * rowstride) + (width * 4) - 1] = 0xC0;
2120
2121 /* Bottom left */
2122 pixels[(height - 1) * rowstride + 3] = 0;
2123 pixels[(height - 1) * rowstride + 7] = 0x80;
2124 pixels[(height - 1) * rowstride + 11] = 0xC0;
2125 pixels[(height - 2) * rowstride + 3] = 0x80;
2126 pixels[(height - 3) * rowstride + 3] = 0xC0;
2127
2128 /* Bottom right */
2129 pixels[height * rowstride - 1] = 0;
2130 pixels[(height - 1) * rowstride - 1] = 0x80;
2131 pixels[(height - 2) * rowstride - 1] = 0xC0;
2132 pixels[height * rowstride - 5] = 0x80;
2133 pixels[height * rowstride - 9] = 0xC0;
2134 }
2135
2136 /* Altered from do_colorshift in gnome-panel */ 2131 /* Altered from do_colorshift in gnome-panel */
2137 static void 2132 static void
2138 do_alphashift (GdkPixbuf *dest, GdkPixbuf *src, int shift) 2133 do_alphashift (GdkPixbuf *dest, GdkPixbuf *src, int shift)
2139 { 2134 {
2140 gint i, j; 2135 gint i, j;
2267 2262
2268 ret = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 32, 32); 2263 ret = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 32, 32);
2269 gdk_pixbuf_fill(ret, 0x00000000); 2264 gdk_pixbuf_fill(ret, 0x00000000);
2270 gdk_pixbuf_scale(buf, ret, (32-scale_width)/2, (32-scale_height)/2, scale_width, scale_height, (32-scale_width)/2, (32-scale_height)/2, (double)scale_width/(double)orig_width, (double)scale_height/(double)orig_height, GDK_INTERP_BILINEAR); 2265 gdk_pixbuf_scale(buf, ret, (32-scale_width)/2, (32-scale_height)/2, scale_width, scale_height, (32-scale_width)/2, (32-scale_height)/2, (double)scale_width/(double)orig_width, (double)scale_height/(double)orig_height, GDK_INTERP_BILINEAR);
2271 if (pidgin_gdk_pixbuf_is_opaque(ret)) 2266 if (pidgin_gdk_pixbuf_is_opaque(ret))
2272 roundify(ret); 2267 pidgin_gdk_pixbuf_make_round(ret);
2273 } else { 2268 } else {
2274 ret = gdk_pixbuf_scale_simple(buf,scale_width,scale_height, GDK_INTERP_BILINEAR); 2269 ret = gdk_pixbuf_scale_simple(buf,scale_width,scale_height, GDK_INTERP_BILINEAR);
2275 } 2270 }
2276 g_object_unref(G_OBJECT(buf)); 2271 g_object_unref(G_OBJECT(buf));
2277 } 2272 }
2724 static gboolean pidgin_blist_drag_motion_cb(GtkWidget *tv, GdkDragContext *drag_context, 2719 static gboolean pidgin_blist_drag_motion_cb(GtkWidget *tv, GdkDragContext *drag_context,
2725 gint x, gint y, guint time, gpointer user_data) 2720 gint x, gint y, guint time, gpointer user_data)
2726 { 2721 {
2727 GtkTreePath *path; 2722 GtkTreePath *path;
2728 int delay; 2723 int delay;
2724 GdkRectangle rect;
2729 2725
2730 /* 2726 /*
2731 * When dragging a buddy into a contact, this is the delay before 2727 * When dragging a buddy into a contact, this is the delay before
2732 * the contact auto-expands. 2728 * the contact auto-expands.
2733 */ 2729 */
2739 /* We've left the cell. Remove the timeout and create a new one below */ 2735 /* We've left the cell. Remove the timeout and create a new one below */
2740 g_source_remove(gtkblist->drag_timeout); 2736 g_source_remove(gtkblist->drag_timeout);
2741 } 2737 }
2742 2738
2743 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), x, y, &path, NULL, NULL, NULL); 2739 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), x, y, &path, NULL, NULL, NULL);
2744 gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, &gtkblist->tip_rect); 2740 gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, &rect);
2741
2742 /* Only autoexpand when in the middle of the cell to avoid annoying un-intended expands */
2743 if (y < rect.y + (rect.height / 3) ||
2744 y > rect.y + (2 * (rect.height /3)))
2745 return FALSE;
2746
2747 rect.height = rect.height / 3;
2748 rect.y += rect.height;
2749
2750 gtkblist->tip_rect = rect;
2745 2751
2746 if (path) 2752 if (path)
2747 gtk_tree_path_free(path); 2753 gtk_tree_path_free(path);
2748 gtkblist->drag_timeout = g_timeout_add(delay, (GSourceFunc)pidgin_blist_expand_timeout, tv); 2754 gtkblist->drag_timeout = g_timeout_add(delay, (GSourceFunc)pidgin_blist_expand_timeout, tv);
2749 2755
2861 { N_("/Tools/_File Transfers"), "<CTL>T", pidgin_xfer_dialog_show, 0, "<Item>", NULL }, 2867 { N_("/Tools/_File Transfers"), "<CTL>T", pidgin_xfer_dialog_show, 0, "<Item>", NULL },
2862 { N_("/Tools/R_oom List"), NULL, pidgin_roomlist_dialog_show, 0, "<Item>", NULL }, 2868 { N_("/Tools/R_oom List"), NULL, pidgin_roomlist_dialog_show, 0, "<Item>", NULL },
2863 { N_("/Tools/System _Log"), NULL, gtk_blist_show_systemlog_cb, 0, "<Item>", NULL }, 2869 { N_("/Tools/System _Log"), NULL, gtk_blist_show_systemlog_cb, 0, "<Item>", NULL },
2864 { "/Tools/sep3", NULL, NULL, 0, "<Separator>", NULL }, 2870 { "/Tools/sep3", NULL, NULL, 0, "<Separator>", NULL },
2865 { N_("/Tools/Mute _Sounds"), "<CTL>S", pidgin_blist_mute_sounds_cb, 0, "<CheckItem>", NULL }, 2871 { N_("/Tools/Mute _Sounds"), "<CTL>S", pidgin_blist_mute_sounds_cb, 0, "<CheckItem>", NULL },
2866
2867 /* Help */ 2872 /* Help */
2868 { N_("/_Help"), NULL, NULL, 0, "<Branch>", NULL }, 2873 { N_("/_Help"), NULL, NULL, 0, "<Branch>", NULL },
2869 { N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, "<StockItem>", GTK_STOCK_HELP }, 2874 { N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, "<StockItem>", GTK_STOCK_HELP },
2870 { N_("/Help/_Debug Window"), NULL, toggle_debug, 0, "<Item>", NULL }, 2875 { N_("/Help/_Debug Window"), NULL, toggle_debug, 0, "<Item>", NULL },
2871 { N_("/Help/_About"), NULL, pidgin_dialogs_about, 0, "<Item>", NULL }, 2876 { N_("/Help/_About"), NULL, pidgin_dialogs_about, 0, "<Item>", NULL },
2992 2997
2993 /* Logged In */ 2998 /* Logged In */
2994 signon = purple_presence_get_login_time(presence); 2999 signon = purple_presence_get_login_time(presence);
2995 if (full && PURPLE_BUDDY_IS_ONLINE(b) && signon > 0) 3000 if (full && PURPLE_BUDDY_IS_ONLINE(b) && signon > 0)
2996 { 3001 {
2997 tmp = purple_str_seconds_to_string(time(NULL) - signon); 3002 if (signon > time(NULL)) {
3003 /*
3004 * They signed on in the future?! Our local clock
3005 * must be wrong, show the actual date instead of
3006 * "4 days", etc.
3007 */
3008 tmp = g_strdup(purple_date_format_long(localtime(&signon)));
3009 } else
3010 tmp = purple_str_seconds_to_string(time(NULL) - signon);
2998 purple_notify_user_info_add_pair(user_info, _("Logged In"), tmp); 3011 purple_notify_user_info_add_pair(user_info, _("Logged In"), tmp);
2999 g_free(tmp); 3012 g_free(tmp);
3000 } 3013 }
3001 3014
3002 /* Idle */ 3015 /* Idle */
3101 gtkbuddynode = ((PurpleBlistNode*)buddy)->ui_data; 3114 gtkbuddynode = ((PurpleBlistNode*)buddy)->ui_data;
3102 } 3115 }
3103 } else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { 3116 } else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) {
3104 buddy = (PurpleBuddy*)node; 3117 buddy = (PurpleBuddy*)node;
3105 gtkbuddynode = node->ui_data; 3118 gtkbuddynode = node->ui_data;
3119 p = purple_buddy_get_presence(buddy);
3120 if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_MOBILE)) {
3121 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems",
3122 "16", "mobile.png", NULL);
3123 ret = gdk_pixbuf_new_from_file(path, NULL);
3124 g_free(path);
3125 return ret;
3126 }
3127
3106 if (((struct _pidgin_blist_node*)(node->parent->ui_data))->contact_expanded) 3128 if (((struct _pidgin_blist_node*)(node->parent->ui_data))->contact_expanded)
3107 return pidgin_create_prpl_icon(((PurpleBuddy*)node)->account, PIDGIN_PRPL_ICON_SMALL); 3129 return pidgin_create_prpl_icon(((PurpleBuddy*)node)->account, PIDGIN_PRPL_ICON_SMALL);
3108 } else if(PURPLE_BLIST_NODE_IS_CHAT(node)) { 3130 } else if(PURPLE_BLIST_NODE_IS_CHAT(node)) {
3109 return pidgin_create_prpl_icon(((PurpleChat*)node)->account, PIDGIN_PRPL_ICON_SMALL); 3131 return pidgin_create_prpl_icon(((PurpleChat*)node)->account, PIDGIN_PRPL_ICON_SMALL);
3110 } else { 3132 } else {
3242 ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_OFFLINE, 3264 ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_OFFLINE,
3243 icon_size, "GtkTreeView"); 3265 icon_size, "GtkTreeView");
3244 else if (purple_presence_is_idle(p) && size == PIDGIN_STATUS_ICON_SMALL) 3266 else if (purple_presence_is_idle(p) && size == PIDGIN_STATUS_ICON_SMALL)
3245 ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_AVAILABLE_I, 3267 ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_AVAILABLE_I,
3246 icon_size, "GtkTreeView"); 3268 icon_size, "GtkTreeView");
3269 else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_INVISIBLE))
3270 ret = gtk_widget_render_icon(GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_INVISIBLE,
3271 icon_size, "GtkTreeView");
3247 else 3272 else
3248 ret = gtk_widget_render_icon(GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_AVAILABLE, 3273 ret = gtk_widget_render_icon(GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_AVAILABLE,
3249 icon_size, "GtkTreeView"); 3274 icon_size, "GtkTreeView");
3250 } else if (chat) { 3275 } else if (chat) {
3251 ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_CHAT, 3276 ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_CHAT,
3256 } 3281 }
3257 3282
3258 return ret; 3283 return ret;
3259 } 3284 }
3260 3285
3261 static gchar *pidgin_blist_get_name_markup(PurpleBuddy *b, gboolean selected) 3286 gchar *pidgin_blist_get_name_markup(PurpleBuddy *b, gboolean selected, gboolean aliased)
3262 { 3287 {
3263 const char *name; 3288 const char *name;
3264 char *esc, *text = NULL; 3289 char *esc, *text = NULL;
3265 PurplePlugin *prpl; 3290 PurplePlugin *prpl;
3266 PurplePluginProtocolInfo *prpl_info = NULL; 3291 PurplePluginProtocolInfo *prpl_info = NULL;
3281 hidden_conv = TRUE; 3306 hidden_conv = TRUE;
3282 } 3307 }
3283 } 3308 }
3284 3309
3285 /* XXX Good luck cleaning up this crap */ 3310 /* XXX Good luck cleaning up this crap */
3286 3311 if (aliased) {
3287 contact = (PurpleContact*)((PurpleBlistNode*)b)->parent; 3312 contact = (PurpleContact*)((PurpleBlistNode*)b)->parent;
3288 if(contact) 3313 if(contact)
3289 gtkcontactnode = ((PurpleBlistNode*)contact)->ui_data; 3314 gtkcontactnode = ((PurpleBlistNode*)contact)->ui_data;
3290 3315
3291 if(gtkcontactnode && !gtkcontactnode->contact_expanded && contact->alias) 3316 if(gtkcontactnode && !gtkcontactnode->contact_expanded && contact->alias)
3292 name = contact->alias; 3317 name = contact->alias;
3293 else 3318 else
3294 name = purple_buddy_get_alias(b); 3319 name = purple_buddy_get_alias(b);
3320 } else {
3321 name = b->name;
3322 }
3323
3295 esc = g_markup_escape_text(name, strlen(name)); 3324 esc = g_markup_escape_text(name, strlen(name));
3296 3325
3297 presence = purple_buddy_get_presence(b); 3326 presence = purple_buddy_get_presence(b);
3298 3327
3299 if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons")) 3328 if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"))
3411 else if (!selected && !text) 3440 else if (!selected && !text)
3412 text = g_strdup_printf("<span color='%s'>%s</span>\n" 3441 text = g_strdup_printf("<span color='%s'>%s</span>\n"
3413 "<span color='%s' size='smaller'>%s</span>", 3442 "<span color='%s' size='smaller'>%s</span>",
3414 dim_grey(), esc, dim_grey(), 3443 dim_grey(), esc, dim_grey(),
3415 statustext != NULL ? statustext : ""); 3444 statustext != NULL ? statustext : "");
3416 } 3445 } else if (!PURPLE_BUDDY_IS_ONLINE(b)) {
3417 3446 if (!selected && !statustext) /* We handle selected text later */
3447 text = g_strdup_printf("<span color='%s'>%s</span>", dim_grey(), esc);
3448 else if (!selected && !text)
3449 text = g_strdup_printf("<span color='%s'>%s</span>\n"
3450 "<span color='%s' size='smaller'>%s</span>",
3451 dim_grey(), esc, dim_grey(),
3452 statustext != NULL ? statustext : "");
3453
3454 }
3418 /* Not idle and not selected */ 3455 /* Not idle and not selected */
3419 else if (!selected && !text) 3456 else if (!selected && !text)
3420 { 3457 {
3421 text = g_strdup_printf("%s\n" 3458 text = g_strdup_printf("%s\n"
3422 "<span color='%s' size='smaller'>%s</span>", 3459 "<span color='%s' size='smaller'>%s</span>",
3720 node->ui_data = g_new0(struct _pidgin_blist_node, 1); 3757 node->ui_data = g_new0(struct _pidgin_blist_node, 1);
3721 } 3758 }
3722 3759
3723 gboolean pidgin_blist_node_is_contact_expanded(PurpleBlistNode *node) 3760 gboolean pidgin_blist_node_is_contact_expanded(PurpleBlistNode *node)
3724 { 3761 {
3725 if PURPLE_BLIST_NODE_IS_BUDDY(node) 3762 if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
3726 node = node->parent; 3763 node = node->parent;
3764 if (node == NULL)
3765 return FALSE;
3766 }
3727 3767
3728 g_return_val_if_fail(PURPLE_BLIST_NODE_IS_CONTACT(node), FALSE); 3768 g_return_val_if_fail(PURPLE_BLIST_NODE_IS_CONTACT(node), FALSE);
3729 3769
3730 return ((struct _pidgin_blist_node *)node->ui_data)->contact_expanded; 3770 return ((struct _pidgin_blist_node *)node->ui_data)->contact_expanded;
3731 } 3771 }
3822 } 3862 }
3823 3863
3824 static gboolean 3864 static gboolean
3825 gtk_blist_window_key_press_cb(GtkWidget *w, GdkEventKey *event, PidginBuddyList *gtkblist) 3865 gtk_blist_window_key_press_cb(GtkWidget *w, GdkEventKey *event, PidginBuddyList *gtkblist)
3826 { 3866 {
3827 GtkWidget *imhtml; 3867 GtkWidget *widget;
3828 3868
3829 if (!gtkblist) 3869 if (!gtkblist)
3830 return FALSE; 3870 return FALSE;
3831 3871
3832 imhtml = gtk_window_get_focus(GTK_WINDOW(gtkblist->window)); 3872 widget = gtk_window_get_focus(GTK_WINDOW(gtkblist->window));
3833 3873
3834 if (GTK_IS_IMHTML(imhtml) && gtk_bindings_activate(GTK_OBJECT(imhtml), event->keyval, event->state)) 3874 if (GTK_IS_IMHTML(widget) || GTK_IS_ENTRY(widget)) {
3835 return TRUE; 3875 if (gtk_bindings_activate(GTK_OBJECT(widget), event->keyval, event->state))
3876 return TRUE;
3877 }
3836 return FALSE; 3878 return FALSE;
3837 } 3879 }
3838 3880
3839 static gboolean 3881 static gboolean
3840 headline_hover_close(int x, int y) 3882 headline_hover_close(int x, int y)
4202 gtkblist = PIDGIN_BLIST(list); 4244 gtkblist = PIDGIN_BLIST(list);
4203 4245
4204 gtkblist->empty_avatar = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 32, 32); 4246 gtkblist->empty_avatar = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 32, 32);
4205 gdk_pixbuf_fill(gtkblist->empty_avatar, 0x00000000); 4247 gdk_pixbuf_fill(gtkblist->empty_avatar, 0x00000000);
4206 4248
4207 gtkblist->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 4249 gtkblist->window = pidgin_create_window(_("Buddy List"), 0, "buddy_list", TRUE);
4208 gtk_window_set_role(GTK_WINDOW(gtkblist->window), "buddy_list");
4209 gtk_window_set_title(GTK_WINDOW(gtkblist->window), _("Buddy List"));
4210 g_signal_connect(G_OBJECT(gtkblist->window), "focus-in-event", 4250 g_signal_connect(G_OBJECT(gtkblist->window), "focus-in-event",
4211 G_CALLBACK(blist_focus_cb), gtkblist); 4251 G_CALLBACK(blist_focus_cb), gtkblist);
4212 GTK_WINDOW(gtkblist->window)->allow_shrink = TRUE; 4252 GTK_WINDOW(gtkblist->window)->allow_shrink = TRUE;
4213 4253
4214 gtkblist->main_vbox = gtk_vbox_new(FALSE, 0); 4254 gtkblist->main_vbox = gtk_vbox_new(FALSE, 0);
4426 #if GTK_CHECK_VERSION(2,6,0) 4466 #if GTK_CHECK_VERSION(2,6,0)
4427 "cell-background-gdk", BGCOLOR_COLUMN, 4467 "cell-background-gdk", BGCOLOR_COLUMN,
4428 #endif 4468 #endif
4429 "markup", NAME_COLUMN, 4469 "markup", NAME_COLUMN,
4430 NULL); 4470 NULL);
4471 #if GTK_CHECK_VERSION(2,6,0)
4431 g_signal_connect(G_OBJECT(rend), "editing-started", G_CALLBACK(gtk_blist_renderer_editing_started_cb), NULL); 4472 g_signal_connect(G_OBJECT(rend), "editing-started", G_CALLBACK(gtk_blist_renderer_editing_started_cb), NULL);
4432 g_signal_connect(G_OBJECT(rend), "edited", G_CALLBACK(gtk_blist_renderer_edited_cb), NULL); 4473 g_signal_connect(G_OBJECT(rend), "editing-canceled", G_CALLBACK(gtk_blist_renderer_editing_cancelled_cb), list);
4474 #endif
4475 g_signal_connect(G_OBJECT(rend), "edited", G_CALLBACK(gtk_blist_renderer_edited_cb), list);
4433 g_object_set(rend, "ypad", 0, "yalign", 0.5, NULL); 4476 g_object_set(rend, "ypad", 0, "yalign", 0.5, NULL);
4434 #if GTK_CHECK_VERSION(2,6,0) 4477 #if GTK_CHECK_VERSION(2,6,0)
4435 g_object_set(rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL); 4478 g_object_set(rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
4436 #endif 4479 #endif
4437 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), column); 4480 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), column);
4722 if(gtk_tree_selection_get_selected(selection, NULL, &iter)){ 4765 if(gtk_tree_selection_get_selected(selection, NULL, &iter)){
4723 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, 4766 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter,
4724 NODE_COLUMN, &new_selection, -1); 4767 NODE_COLUMN, &new_selection, -1);
4725 } 4768 }
4726 4769
4727 /* we set this up as a timeout, otherwise the blist flickers */ 4770 /* we set this up as a timeout, otherwise the blist flickers ...
4728 g_timeout_add(0, (GSourceFunc)do_selection_changed, new_selection); 4771 * but we don't do it for groups, because it causes total bizarness -
4772 * the previously selected buddy node might rendered at half height.
4773 */
4774 if ((new_selection != NULL) && PURPLE_BLIST_NODE_IS_GROUP(new_selection)) {
4775 do_selection_changed(new_selection);
4776 } else {
4777 g_timeout_add(0, (GSourceFunc)do_selection_changed, new_selection);
4778 }
4729 } 4779 }
4730 4780
4731 static gboolean insert_node(PurpleBuddyList *list, PurpleBlistNode *node, GtkTreeIter *iter) 4781 static gboolean insert_node(PurpleBuddyList *list, PurpleBlistNode *node, GtkTreeIter *iter)
4732 { 4782 {
4733 GtkTreeIter parent_iter, cur, *curptr = NULL; 4783 GtkTreeIter parent_iter, cur, *curptr = NULL;
4762 gtk_tree_row_reference_new(GTK_TREE_MODEL(gtkblist->treemodel), 4812 gtk_tree_row_reference_new(GTK_TREE_MODEL(gtkblist->treemodel),
4763 newpath); 4813 newpath);
4764 4814
4765 gtk_tree_path_free(newpath); 4815 gtk_tree_path_free(newpath);
4766 4816
4767 gtk_tree_store_set(gtkblist->treemodel, iter, 4817 if (!editing_blist)
4768 NODE_COLUMN, node, 4818 gtk_tree_store_set(gtkblist->treemodel, iter,
4769 -1); 4819 NODE_COLUMN, node,
4820 -1);
4770 4821
4771 if(node->parent) { 4822 if(node->parent) {
4772 GtkTreePath *expand = NULL; 4823 GtkTreePath *expand = NULL;
4773 struct _pidgin_blist_node *gtkparentnode = node->parent->ui_data; 4824 struct _pidgin_blist_node *gtkparentnode = node->parent->ui_data;
4774 4825
4797 gboolean show = FALSE; 4848 gboolean show = FALSE;
4798 PurpleBlistNode* gnode; 4849 PurpleBlistNode* gnode;
4799 4850
4800 g_return_if_fail(node != NULL); 4851 g_return_if_fail(node != NULL);
4801 4852
4853 if (editing_blist)
4854 return;
4855
4802 if (PURPLE_BLIST_NODE_IS_GROUP(node)) 4856 if (PURPLE_BLIST_NODE_IS_GROUP(node))
4803 gnode = node; 4857 gnode = node;
4804 else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) 4858 else if (PURPLE_BLIST_NODE_IS_BUDDY(node))
4805 gnode = node->parent->parent; 4859 gnode = node->parent->parent;
4806 else if (PURPLE_BLIST_NODE_IS_CONTACT(node) || PURPLE_BLIST_NODE_IS_CHAT(node)) 4860 else if (PURPLE_BLIST_NODE_IS_CONTACT(node) || PURPLE_BLIST_NODE_IS_CHAT(node))
4864 PurpleGroup *group; 4918 PurpleGroup *group;
4865 GdkColor textcolor; 4919 GdkColor textcolor;
4866 gboolean selected; 4920 gboolean selected;
4867 char group_count[12] = ""; 4921 char group_count[12] = "";
4868 char *mark, *esc; 4922 char *mark, *esc;
4923 PurpleBlistNode *selected_node = NULL;
4924 GtkTreeIter iter;
4869 4925
4870 group = (PurpleGroup*)gnode; 4926 group = (PurpleGroup*)gnode;
4871 textcolor = gtkblist->treeview->style->fg[GTK_STATE_ACTIVE]; 4927 textcolor = gtkblist->treeview->style->fg[GTK_STATE_ACTIVE];
4872 selected = gtkblist ? (gtkblist->selected_node == gnode) : FALSE; 4928
4929 if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkblist->treeview)), NULL, &iter)) {
4930 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter,
4931 NODE_COLUMN, &selected_node, -1);
4932 }
4933 selected = (gnode == selected_node);
4873 4934
4874 if (!expanded) { 4935 if (!expanded) {
4875 g_snprintf(group_count, sizeof(group_count), " (%d/%d)", 4936 g_snprintf(group_count, sizeof(group_count), " (%d/%d)",
4876 purple_blist_get_group_online_count(group), 4937 purple_blist_get_group_online_count(group),
4877 purple_blist_get_group_size(group, FALSE)); 4938 purple_blist_get_group_size(group, FALSE));
4898 gboolean expanded = ((struct _pidgin_blist_node *)(node->parent->ui_data))->contact_expanded; 4959 gboolean expanded = ((struct _pidgin_blist_node *)(node->parent->ui_data))->contact_expanded;
4899 gboolean selected = (gtkblist->selected_node == node); 4960 gboolean selected = (gtkblist->selected_node == node);
4900 gboolean biglist = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"); 4961 gboolean biglist = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons");
4901 presence = purple_buddy_get_presence(buddy); 4962 presence = purple_buddy_get_presence(buddy);
4902 4963
4964 if (editing_blist)
4965 return;
4966
4903 status = pidgin_blist_get_status_icon((PurpleBlistNode*)buddy, 4967 status = pidgin_blist_get_status_icon((PurpleBlistNode*)buddy,
4904 PIDGIN_STATUS_ICON_SMALL); 4968 PIDGIN_STATUS_ICON_SMALL);
4905 4969
4906 /* Speed it up if we don't want buddy icons. */ 4970 /* Speed it up if we don't want buddy icons. */
4907 if(biglist) 4971 if(biglist)
4915 } else if ((!PURPLE_BUDDY_IS_ONLINE(buddy) || purple_presence_is_idle(presence))) { 4979 } else if ((!PURPLE_BUDDY_IS_ONLINE(buddy) || purple_presence_is_idle(presence))) {
4916 do_alphashift(avatar, avatar, 77); 4980 do_alphashift(avatar, avatar, 77);
4917 } 4981 }
4918 4982
4919 emblem = pidgin_blist_get_emblem((PurpleBlistNode*) buddy); 4983 emblem = pidgin_blist_get_emblem((PurpleBlistNode*) buddy);
4920 mark = pidgin_blist_get_name_markup(buddy, selected); 4984 mark = pidgin_blist_get_name_markup(buddy, selected, TRUE);
4921 4985
4922 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_idle_time") && 4986 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_idle_time") &&
4923 purple_presence_is_idle(presence) && 4987 purple_presence_is_idle(presence) &&
4924 !purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons")) 4988 !purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"))
4925 { 4989 {
4976 { 5040 {
4977 PurpleBlistNode *cnode; 5041 PurpleBlistNode *cnode;
4978 PurpleContact *contact; 5042 PurpleContact *contact;
4979 PurpleBuddy *buddy; 5043 PurpleBuddy *buddy;
4980 struct _pidgin_blist_node *gtknode; 5044 struct _pidgin_blist_node *gtknode;
5045
5046 if (editing_blist)
5047 return;
4981 5048
4982 if (PURPLE_BLIST_NODE_IS_BUDDY(node)) 5049 if (PURPLE_BLIST_NODE_IS_BUDDY(node))
4983 cnode = node->parent; 5050 cnode = node->parent;
4984 else 5051 else
4985 cnode = node; 5052 cnode = node;
5073 { 5140 {
5074 PurpleChat *chat; 5141 PurpleChat *chat;
5075 5142
5076 g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); 5143 g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
5077 5144
5145 if (editing_blist)
5146 return;
5147
5078 /* First things first, update the group */ 5148 /* First things first, update the group */
5079 pidgin_blist_update_group(list, node->parent); 5149 pidgin_blist_update_group(list, node->parent);
5080 5150
5081 chat = (PurpleChat*)node; 5151 chat = (PurpleChat*)node;
5082 5152
5384 gtk_table_set_row_spacings(GTK_TABLE(table), 5); 5454 gtk_table_set_row_spacings(GTK_TABLE(table), 5);
5385 gtk_table_set_col_spacings(GTK_TABLE(table), 5); 5455 gtk_table_set_col_spacings(GTK_TABLE(table), 5);
5386 gtk_container_set_border_width(GTK_CONTAINER(table), 0); 5456 gtk_container_set_border_width(GTK_CONTAINER(table), 0);
5387 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); 5457 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
5388 5458
5389 label = gtk_label_new(_("Screen name:")); 5459 /* Set up stuff for the account box */
5460 label = gtk_label_new_with_mnemonic(_("_Account:"));
5390 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 5461 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
5391 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1); 5462 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
5392 5463
5464 data->account_box = pidgin_account_option_menu_new(account, FALSE,
5465 G_CALLBACK(add_buddy_select_account_cb), NULL, data);
5466
5467 gtk_table_attach_defaults(GTK_TABLE(table), data->account_box, 1, 2, 0, 1);
5468 gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->account_box);
5469 pidgin_set_accessible_label (data->account_box, label);
5470 /* End of account box */
5471
5472 label = gtk_label_new_with_mnemonic(_("_Screen name:"));
5473 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
5474 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
5475
5393 data->entry = gtk_entry_new(); 5476 data->entry = gtk_entry_new();
5394 gtk_table_attach_defaults(GTK_TABLE(table), data->entry, 1, 2, 0, 1); 5477 gtk_table_attach_defaults(GTK_TABLE(table), data->entry, 1, 2, 1, 2);
5395 gtk_widget_grab_focus(data->entry); 5478 gtk_widget_grab_focus(data->entry);
5396 5479
5397 if (username != NULL) 5480 if (username != NULL)
5398 gtk_entry_set_text(GTK_ENTRY(data->entry), username); 5481 gtk_entry_set_text(GTK_ENTRY(data->entry), username);
5399 else 5482 else
5400 gtk_dialog_set_response_sensitive(GTK_DIALOG(data->window), 5483 gtk_dialog_set_response_sensitive(GTK_DIALOG(data->window),
5401 GTK_RESPONSE_OK, FALSE); 5484 GTK_RESPONSE_OK, FALSE);
5402 5485
5403 gtk_entry_set_activates_default (GTK_ENTRY(data->entry), TRUE); 5486 gtk_entry_set_activates_default (GTK_ENTRY(data->entry), TRUE);
5487 gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->entry);
5404 pidgin_set_accessible_label (data->entry, label); 5488 pidgin_set_accessible_label (data->entry, label);
5405 5489
5406 g_signal_connect(G_OBJECT(data->entry), "changed", 5490 g_signal_connect(G_OBJECT(data->entry), "changed",
5407 G_CALLBACK(pidgin_set_sensitive_if_input), 5491 G_CALLBACK(pidgin_set_sensitive_if_input),
5408 data->window); 5492 data->window);
5409 5493
5410 label = gtk_label_new(_("Alias:")); 5494 label = gtk_label_new_with_mnemonic(_("A_lias:"));
5411 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 5495 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
5412 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2); 5496 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
5413 5497
5414 data->entry_for_alias = gtk_entry_new(); 5498 data->entry_for_alias = gtk_entry_new();
5415 gtk_table_attach_defaults(GTK_TABLE(table), 5499 gtk_table_attach_defaults(GTK_TABLE(table),
5416 data->entry_for_alias, 1, 2, 1, 2); 5500 data->entry_for_alias, 1, 2, 2, 3);
5417 5501
5418 if (alias != NULL) 5502 if (alias != NULL)
5419 gtk_entry_set_text(GTK_ENTRY(data->entry_for_alias), alias); 5503 gtk_entry_set_text(GTK_ENTRY(data->entry_for_alias), alias);
5420 5504
5421 if (username != NULL) 5505 if (username != NULL)
5422 gtk_widget_grab_focus(GTK_WIDGET(data->entry_for_alias)); 5506 gtk_widget_grab_focus(GTK_WIDGET(data->entry_for_alias));
5423 5507
5424 gtk_entry_set_activates_default (GTK_ENTRY(data->entry_for_alias), TRUE); 5508 gtk_entry_set_activates_default (GTK_ENTRY(data->entry_for_alias), TRUE);
5509 gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->entry_for_alias);
5425 pidgin_set_accessible_label (data->entry_for_alias, label); 5510 pidgin_set_accessible_label (data->entry_for_alias, label);
5426 5511
5427 label = gtk_label_new(_("Group:")); 5512 label = gtk_label_new_with_mnemonic(_("_Group:"));
5428 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 5513 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
5429 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3); 5514 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4);
5430 5515
5431 data->combo = gtk_combo_new(); 5516 data->combo = gtk_combo_new();
5432 gtk_combo_set_popdown_strings(GTK_COMBO(data->combo), groups_tree()); 5517 gtk_combo_set_popdown_strings(GTK_COMBO(data->combo), groups_tree());
5433 gtk_table_attach_defaults(GTK_TABLE(table), data->combo, 1, 2, 2, 3); 5518 gtk_table_attach_defaults(GTK_TABLE(table), data->combo, 1, 2, 3, 4);
5519 gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_COMBO(data->combo)->entry);
5434 pidgin_set_accessible_label (data->combo, label); 5520 pidgin_set_accessible_label (data->combo, label);
5435
5436 /* Set up stuff for the account box */
5437 label = gtk_label_new(_("Account:"));
5438 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
5439 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4);
5440
5441 data->account_box = pidgin_account_option_menu_new(account, FALSE,
5442 G_CALLBACK(add_buddy_select_account_cb), NULL, data);
5443
5444 gtk_table_attach_defaults(GTK_TABLE(table), data->account_box, 1, 2, 3, 4);
5445 pidgin_set_accessible_label (data->account_box, label);
5446 /* End of account box */
5447 5521
5448 g_signal_connect(G_OBJECT(data->window), "response", 5522 g_signal_connect(G_OBJECT(data->window), "response",
5449 G_CALLBACK(add_buddy_cb), data); 5523 G_CALLBACK(add_buddy_cb), data);
5450 5524
5451 gtk_widget_show_all(data->window); 5525 gtk_widget_show_all(data->window);
5748 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); 5822 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
5749 5823
5750 rowbox = gtk_hbox_new(FALSE, 5); 5824 rowbox = gtk_hbox_new(FALSE, 5);
5751 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0); 5825 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0);
5752 5826
5753 label = gtk_label_new(_("Account:")); 5827 label = gtk_label_new_with_mnemonic(_("_Account:"));
5754 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 5828 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
5755 gtk_size_group_add_widget(data->sg, label); 5829 gtk_size_group_add_widget(data->sg, label);
5756 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); 5830 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
5757 5831
5758 data->account_menu = pidgin_account_option_menu_new(account, FALSE, 5832 data->account_menu = pidgin_account_option_menu_new(account, FALSE,
5759 G_CALLBACK(addchat_select_account_cb), 5833 G_CALLBACK(addchat_select_account_cb),
5760 chat_account_filter_func, data); 5834 chat_account_filter_func, data);
5761 gtk_box_pack_start(GTK_BOX(rowbox), data->account_menu, TRUE, TRUE, 0); 5835 gtk_box_pack_start(GTK_BOX(rowbox), data->account_menu, TRUE, TRUE, 0);
5836 gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->account_menu);
5762 pidgin_set_accessible_label (data->account_menu, label); 5837 pidgin_set_accessible_label (data->account_menu, label);
5763 5838
5764 data->entries_box = gtk_vbox_new(FALSE, 5); 5839 data->entries_box = gtk_vbox_new(FALSE, 5);
5765 gtk_container_set_border_width(GTK_CONTAINER(data->entries_box), 0); 5840 gtk_container_set_border_width(GTK_CONTAINER(data->entries_box), 0);
5766 gtk_box_pack_start(GTK_BOX(vbox), data->entries_box, TRUE, TRUE, 0); 5841 gtk_box_pack_start(GTK_BOX(vbox), data->entries_box, TRUE, TRUE, 0);
5768 rebuild_addchat_entries(data); 5843 rebuild_addchat_entries(data);
5769 5844
5770 rowbox = gtk_hbox_new(FALSE, 5); 5845 rowbox = gtk_hbox_new(FALSE, 5);
5771 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0); 5846 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0);
5772 5847
5773 label = gtk_label_new(_("Alias:")); 5848 label = gtk_label_new_with_mnemonic(_("A_lias:"));
5774 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 5849 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
5775 gtk_size_group_add_widget(data->sg, label); 5850 gtk_size_group_add_widget(data->sg, label);
5776 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); 5851 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
5777 5852
5778 data->alias_entry = gtk_entry_new(); 5853 data->alias_entry = gtk_entry_new();
5779 if (alias != NULL) 5854 if (alias != NULL)
5780 gtk_entry_set_text(GTK_ENTRY(data->alias_entry), alias); 5855 gtk_entry_set_text(GTK_ENTRY(data->alias_entry), alias);
5781 gtk_box_pack_end(GTK_BOX(rowbox), data->alias_entry, TRUE, TRUE, 0); 5856 gtk_box_pack_end(GTK_BOX(rowbox), data->alias_entry, TRUE, TRUE, 0);
5782 gtk_entry_set_activates_default(GTK_ENTRY(data->alias_entry), TRUE); 5857 gtk_entry_set_activates_default(GTK_ENTRY(data->alias_entry), TRUE);
5858 gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->alias_entry);
5783 pidgin_set_accessible_label (data->alias_entry, label); 5859 pidgin_set_accessible_label (data->alias_entry, label);
5860 if (name != NULL)
5861 gtk_widget_grab_focus(data->alias_entry);
5784 5862
5785 rowbox = gtk_hbox_new(FALSE, 5); 5863 rowbox = gtk_hbox_new(FALSE, 5);
5786 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0); 5864 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0);
5787 5865
5788 label = gtk_label_new(_("Group:")); 5866 label = gtk_label_new_with_mnemonic(_("_Group:"));
5789 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 5867 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
5790 gtk_size_group_add_widget(data->sg, label); 5868 gtk_size_group_add_widget(data->sg, label);
5791 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); 5869 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
5792 5870
5793 data->group_combo = gtk_combo_new(); 5871 data->group_combo = gtk_combo_new();
5797 if (group) 5875 if (group)
5798 { 5876 {
5799 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(data->group_combo)->entry), 5877 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(data->group_combo)->entry),
5800 group->name); 5878 group->name);
5801 } 5879 }
5880 gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_COMBO(data->group_combo)->entry);
5802 pidgin_set_accessible_label (data->group_combo, label); 5881 pidgin_set_accessible_label (data->group_combo, label);
5803 5882
5804 g_signal_connect(G_OBJECT(data->window), "response", 5883 g_signal_connect(G_OBJECT(data->window), "response",
5805 G_CALLBACK(add_chat_resp_cb), data); 5884 G_CALLBACK(add_chat_resp_cb), data);
5806 5885
6668 gtk_widget_show(menuitem); 6747 gtk_widget_show(menuitem);
6669 } 6748 }
6670 if (activeitem) 6749 if (activeitem)
6671 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(activeitem), TRUE); 6750 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(activeitem), TRUE);
6672 } 6751 }
6752

mercurial