203
203
switch (purple_conversation_get_type(conv)) {
204
204
case PURPLE_CONV_TYPE_IM:
205
node = (PurpleBlistNode*)purple_find_buddy(conv->account, conv->name);
205
node = PURPLE_BLIST_NODE(purple_find_buddy(conv->account, conv->name));
206
206
node = node ? node->parent : NULL;
208
208
case PURPLE_CONV_TYPE_CHAT:
209
node = (PurpleBlistNode*)purple_blist_find_chat(conv->account, conv->name);
209
node = PURPLE_BLIST_NODE(purple_blist_find_chat(conv->account, conv->name));
1201
1207
gtk_widget_grab_focus(s->entry);
1212
menu_initiate_media_call_cb(gpointer data, guint action, GtkWidget *widget)
1214
PidginWindow *win = (PidginWindow *)data;
1215
PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
1216
PurpleAccount *account = purple_conversation_get_account(conv);
1218
purple_prpl_initiate_media(account,
1219
purple_conversation_get_name(conv),
1220
action == 0 ? PURPLE_MEDIA_AUDIO :
1221
action == 1 ? PURPLE_MEDIA_VIDEO :
1222
action == 2 ? PURPLE_MEDIA_AUDIO |
1223
PURPLE_MEDIA_VIDEO : PURPLE_MEDIA_NONE);
1205
1228
menu_send_file_cb(gpointer data, guint action, GtkWidget *widget)
1753
1776
g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free);
1756
button = pidgin_new_item_from_stock(menu, _("Last said"), GTK_STOCK_INDEX,
1779
button = pidgin_new_item_from_stock(menu, _("Last Said"), GTK_STOCK_INDEX,
1757
1780
G_CALLBACK(menu_last_said_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL);
1758
1781
g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free);
1759
1782
if (!get_mark_for_user(PIDGIN_CONVERSATION(conv), who))
2495
2518
return get_prpl_icon_list(account);
2522
pidgin_conv_get_icon_stock(PurpleConversation *conv)
2524
PurpleAccount *account = NULL;
2525
const char *stock = NULL;
2527
g_return_val_if_fail(conv != NULL, NULL);
2529
account = purple_conversation_get_account(conv);
2530
g_return_val_if_fail(account != NULL, NULL);
2532
/* Use the buddy icon, if possible */
2533
if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
2534
const char *name = NULL;
2536
name = purple_conversation_get_name(conv);
2537
b = purple_find_buddy(account, name);
2539
PurplePresence *p = purple_buddy_get_presence(b);
2540
PurpleStatus *active = purple_presence_get_active_status(p);
2541
PurpleStatusType *type = purple_status_get_type(active);
2542
PurpleStatusPrimitive prim = purple_status_type_get_primitive(type);
2543
stock = pidgin_stock_id_from_status_primitive(prim);
2545
stock = PIDGIN_STOCK_STATUS_PERSON;
2548
stock = PIDGIN_STOCK_STATUS_CHAT;
2498
2554
static GdkPixbuf *
2499
2555
pidgin_conv_get_icon(PurpleConversation *conv, GtkWidget *parent, const char *icon_size)
2501
2557
PurpleAccount *account = NULL;
2502
2558
const char *name = NULL;
2559
const char *stock = NULL;
2503
2560
GdkPixbuf *status = NULL;
2504
2561
PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
2505
2564
g_return_val_if_fail(conv != NULL, NULL);
2507
2566
account = purple_conversation_get_account(conv);
2514
2573
if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
2515
2574
PurpleBuddy *b = purple_find_buddy(account, name);
2516
2575
if (b != NULL) {
2517
PurplePresence *p = purple_buddy_get_presence(b);
2518
2576
/* I hate this hack. It fixes a bug where the pending message icon
2519
2577
* displays in the conv tab even though it shouldn't.
2520
2578
* A better solution would be great. */
2521
2579
if (ops && ops->update)
2522
2580
ops->update(NULL, (PurpleBlistNode*)b);
2524
/* XXX Seanegan: We really need a util function to return a pixbuf for a Presence to avoid all this switching */
2525
if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AWAY))
2526
status = pidgin_create_status_icon(PURPLE_STATUS_AWAY, parent, icon_size);
2527
else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_EXTENDED_AWAY))
2528
status = pidgin_create_status_icon(PURPLE_STATUS_EXTENDED_AWAY, parent, icon_size);
2529
else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_OFFLINE))
2530
status = pidgin_create_status_icon(PURPLE_STATUS_OFFLINE, parent, icon_size);
2531
else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AVAILABLE))
2532
status = pidgin_create_status_icon(PURPLE_STATUS_AVAILABLE, parent, icon_size);
2533
else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_INVISIBLE))
2534
status = pidgin_create_status_icon(PURPLE_STATUS_INVISIBLE, parent, icon_size);
2535
else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_UNAVAILABLE))
2536
status = pidgin_create_status_icon(PURPLE_STATUS_UNAVAILABLE, parent, icon_size);
2540
/* If they don't have a buddy icon, then use the PRPL icon */
2541
if (status == NULL) {
2542
GtkIconSize size = gtk_icon_size_from_name(icon_size);
2543
if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
2544
status = gtk_widget_render_icon (parent, PIDGIN_STOCK_STATUS_PERSON,
2547
status = gtk_widget_render_icon (parent, PIDGIN_STOCK_STATUS_CHAT,
2584
stock = pidgin_conv_get_icon_stock(conv);
2585
size = gtk_icon_size_from_name(icon_size);
2586
status = gtk_widget_render_icon (parent, stock, size, "GtkWidget");
2588
2623
g_return_if_fail(status != NULL);
2590
gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->icon), status);
2591
gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->menu_icon), status);
2625
g_object_set(G_OBJECT(gtkconv->icon), "stock", status, NULL);
2626
g_object_set(G_OBJECT(gtkconv->menu_icon), "stock", status, NULL);
2593
gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model),
2628
gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model),
2594
2629
&(gtkconv->infopane_iter),
2595
2630
CONV_ICON_COLUMN, infopane_status, -1);
2597
gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model),
2632
gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model),
2598
2633
&(gtkconv->infopane_iter),
2599
2634
CONV_EMBLEM_COLUMN, emblem, -1);
2674
2706
scale_width = gdk_pixbuf_get_width(buf);
2675
2707
scale_height = gdk_pixbuf_get_height(buf);
2677
gtk_widget_get_size_request(gtkconv->infopane_hbox, NULL, &size);
2709
gtk_widget_get_size_request(gtkconv->u.im->icon_container, NULL, &size);
2678
2710
size = MIN(size, MIN(scale_width, scale_height));
2679
2711
size = CLAMP(size, BUDDYICON_SIZE_MIN, BUDDYICON_SIZE_MAX);
2733
2765
remove_icon(GtkWidget *widget, PidginConversation *gtkconv)
2735
2769
PurpleConversation *conv = gtkconv->active_conv;
2736
2770
PidginWindow *gtkwin;
2738
2772
g_return_if_fail(conv != NULL);
2740
if (gtkconv->u.im->icon_container != NULL)
2741
gtk_widget_destroy(gtkconv->u.im->icon_container);
2774
gtk_widget_set_size_request(gtkconv->u.im->icon_container, -1, BUDDYICON_SIZE_MIN);
2775
children = gtk_container_get_children(GTK_CONTAINER(gtkconv->u.im->icon_container));
2777
/* We know there's only one child here. It'd be nice to shortcut to the
2778
event box, but we can't change the PidginConversation until 3.0 */
2779
event = (GtkWidget *)children->data;
2780
gtk_container_remove(GTK_CONTAINER(gtkconv->u.im->icon_container), event);
2781
g_list_free(children);
2743
2784
if (gtkconv->u.im->anim != NULL)
2744
2785
g_object_unref(G_OBJECT(gtkconv->u.im->anim));
3054
3094
PurpleConversation *conv = (PurpleConversation*)l->data;
3055
3095
PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
3057
GtkWidget *icon = gtk_image_new();
3058
GdkPixbuf *pbuf = pidgin_conv_get_icon(conv, icon, PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC);
3097
GtkWidget *icon = gtk_image_new_from_stock(pidgin_conv_get_icon_stock(conv),
3098
gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC));
3059
3099
GtkWidget *item;
3060
3100
gchar *text = g_strdup_printf("%s (%d)",
3061
3101
gtk_label_get_text(GTK_LABEL(gtkconv->tab_label)),
3062
3102
gtkconv->unseen_count);
3064
gtk_image_set_from_pixbuf(GTK_IMAGE(icon), pbuf);
3065
g_object_unref(pbuf);
3067
3104
item = gtk_image_menu_item_new_with_label(text);
3068
3105
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), icon);
3069
3106
g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(unseen_conv_menu_cb), conv);
3103
3140
{ N_("/Conversation/New Instant _Message..."), "<CTL>M", menu_new_conv_cb,
3104
3141
0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW },
3142
{ N_("/Conversation/Join a _Chat..."), NULL, menu_join_chat_cb,
3143
0, "<StockItem>", PIDGIN_STOCK_CHAT },
3106
3145
{ "/Conversation/sep0", NULL, NULL, 0, "<Separator>", NULL },
3115
3154
{ "/Conversation/sep1", NULL, NULL, 0, "<Separator>", NULL },
3157
{ N_("/Conversation/M_edia"), NULL, NULL, 0, "<Branch>", NULL },
3159
{ N_("/Conversation/Media/_Audio Call"), NULL, menu_initiate_media_call_cb, 0,
3160
"<StockItem>", PIDGIN_STOCK_TOOLBAR_AUDIO_CALL },
3161
{ N_("/Conversation/Media/_Video Call"), NULL, menu_initiate_media_call_cb, 1,
3162
"<StockItem>", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL },
3163
{ N_("/Conversation/Media/Audio\\/Video _Call"), NULL, menu_initiate_media_call_cb, 2,
3164
"<StockItem>", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL },
3117
3167
{ N_("/Conversation/Se_nd File..."), NULL, menu_send_file_cb, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_SEND_FILE },
3118
3168
{ N_("/Conversation/Add Buddy _Pounce..."), NULL, menu_add_pounce_cb,
3119
3169
0, "<Item>", NULL },
3337
regenerate_media_items(PidginWindow *win)
3340
PurpleAccount *account;
3341
PurpleConversation *conv;
3343
conv = pidgin_conv_window_get_active_conversation(win);
3346
purple_debug_error("gtkconv", "couldn't get active conversation"
3347
" when regenerating media items\n");
3351
account = purple_conversation_get_account(conv);
3353
if (account == NULL) {
3354
purple_debug_error("gtkconv", "couldn't get account when"
3355
" regenerating media items\n");
3360
* Check if account support voice and/or calls, and
3361
* if the current buddy supports it.
3363
if (account != NULL && purple_conversation_get_type(conv)
3364
== PURPLE_CONV_TYPE_IM) {
3365
PurpleMediaCaps caps =
3366
purple_prpl_get_media_caps(account,
3367
purple_conversation_get_name(conv));
3369
gtk_widget_set_sensitive(win->audio_call,
3370
caps & PURPLE_MEDIA_CAPS_AUDIO
3372
gtk_widget_set_sensitive(win->video_call,
3373
caps & PURPLE_MEDIA_CAPS_VIDEO
3375
gtk_widget_set_sensitive(win->audio_video_call,
3376
caps & PURPLE_MEDIA_CAPS_AUDIO_VIDEO
3378
} else if (purple_conversation_get_type(conv)
3379
== PURPLE_CONV_TYPE_CHAT) {
3380
/* for now, don't care about chats... */
3381
gtk_widget_set_sensitive(win->audio_call, FALSE);
3382
gtk_widget_set_sensitive(win->video_call, FALSE);
3383
gtk_widget_set_sensitive(win->audio_video_call, FALSE);
3385
gtk_widget_set_sensitive(win->audio_call, FALSE);
3386
gtk_widget_set_sensitive(win->video_call, FALSE);
3387
gtk_widget_set_sensitive(win->audio_video_call, FALSE);
3287
3393
regenerate_options_items(PidginWindow *win)
3289
3395
GtkWidget *menu;
3424
3531
gtk_item_factory_get_widget(win->menu.item_factory,
3425
3532
N_("/Conversation/View Log"));
3536
gtk_item_factory_get_widget(win->menu.item_factory,
3537
N_("/Conversation/Media/Audio Call"));
3539
gtk_item_factory_get_widget(win->menu.item_factory,
3540
N_("/Conversation/Media/Video Call"));
3541
win->audio_video_call =
3542
gtk_item_factory_get_widget(win->menu.item_factory,
3543
N_("/Conversation/Media/Audio\\/Video Call"));
3429
3548
win->menu.send_file =
3926
pixbuf = gtk_widget_render_icon (gtkconv->tab_cont, image, gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL),
3932
scale = gdk_pixbuf_scale_simple(pixbuf, 16, 16, GDK_INTERP_BILINEAR);
3933
g_object_unref(pixbuf);
3935
if (flags && purple_conv_chat_is_user_ignored(chat, name)) {
3936
/* TODO: the .../status/default directory isn't installed, should it be? */
3937
filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "status", "default", "ignored.png", NULL);
3938
pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
3940
scale2 = gdk_pixbuf_scale_simple(pixbuf, 16, 16, GDK_INTERP_BILINEAR);
3941
g_object_unref(pixbuf);
3942
gdk_pixbuf_composite(scale2, scale, 0, 0, 16, 16, 0, 0, 1, 1, GDK_INTERP_BILINEAR, 192);
3943
g_object_unref(scale2);
3995
4090
g_object_get(tag, "foreground-gdk", &color, NULL);
4093
if ((tag = get_buddy_tag(conv, name, 0, FALSE)))
4094
g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_NORMAL, NULL);
4095
if ((tag = get_buddy_tag(conv, name, PURPLE_MESSAGE_NICK, FALSE)))
4096
g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_NORMAL, NULL);
3997
4097
color = (GdkColor*)get_nick_color(gtkconv, name);
4007
4107
* Inserting in the "wrong" location has no visible ill effects. - F.P.
4009
4109
-1, /* "row" */
4010
CHAT_USERS_ICON_COLUMN, pixbuf,
4110
CHAT_USERS_ICON_STOCK_COLUMN, stock,
4011
4111
CHAT_USERS_ALIAS_COLUMN, alias,
4012
4112
CHAT_USERS_ALIAS_KEY_COLUMN, alias_key,
4013
4113
CHAT_USERS_NAME_COLUMN, name,
4019
4119
gtk_list_store_append(ls, &iter);
4020
4120
gtk_list_store_set(ls, &iter,
4021
CHAT_USERS_ICON_COLUMN, pixbuf,
4121
CHAT_USERS_ICON_STOCK_COLUMN, stock,
4022
4122
CHAT_USERS_ALIAS_COLUMN, alias,
4023
4123
CHAT_USERS_ALIAS_KEY_COLUMN, alias_key,
4024
4124
CHAT_USERS_NAME_COLUMN, name,
4474
buddy_added_cb(PurpleBuddy *buddy, PurpleConversation *conv)
4576
buddy_added_cb(PurpleBlistNode *node, PurpleConversation *conv)
4476
buddy_cb_common(buddy, conv, TRUE);
4578
if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
4581
buddy_cb_common(PURPLE_BUDDY(node), conv, TRUE);
4480
buddy_removed_cb(PurpleBuddy *buddy, PurpleConversation *conv)
4585
buddy_removed_cb(PurpleBlistNode *node, PurpleConversation *conv)
4587
if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
4482
4590
/* If there's another buddy for the same "dude" on the list, do nothing. */
4483
if (purple_find_buddy(buddy->account, buddy->name) != NULL)
4591
if (purple_find_buddy(purple_buddy_get_account(PURPLE_BUDDY(node)),
4592
purple_buddy_get_name(PURPLE_BUDDY(node))) != NULL)
4486
buddy_cb_common(buddy, conv, FALSE);
4595
buddy_cb_common(PURPLE_BUDDY(node), conv, FALSE);
4489
4598
static void send_menu_cb(GtkWidget *widget, PidginConversation *gtkconv)
4677
4787
ls = gtk_list_store_new(CHAT_USERS_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING,
4678
4788
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT,
4679
GDK_TYPE_COLOR, G_TYPE_INT);
4789
GDK_TYPE_COLOR, G_TYPE_INT, G_TYPE_STRING);
4680
4790
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(ls), CHAT_USERS_ALIAS_KEY_COLUMN,
4681
4791
sort_chat_users, NULL, NULL);
4683
4793
list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ls));
4685
4795
rend = gtk_cell_renderer_pixbuf_new();
4796
g_object_set(G_OBJECT(rend),
4797
"stock-size", gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL),
4687
4799
col = gtk_tree_view_column_new_with_attributes(NULL, rend,
4688
"pixbuf", CHAT_USERS_ICON_COLUMN, NULL);
4800
"stock-id", CHAT_USERS_ICON_STOCK_COLUMN, NULL);
4689
4801
gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
4690
4802
gtk_tree_view_append_column(GTK_TREE_VIEW(list), col);
4691
4803
ul_width = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/userlist_width");
4720
4832
"weight", CHAT_USERS_WEIGHT_COLUMN,
4723
purple_signal_connect(blist_handle, "buddy-added",
4835
purple_signal_connect(blist_handle, "blist-node-added",
4724
4836
gtkchat, PURPLE_CALLBACK(buddy_added_cb), conv);
4725
purple_signal_connect(blist_handle, "buddy-removed",
4837
purple_signal_connect(blist_handle, "blist-node-removed",
4726
4838
gtkchat, PURPLE_CALLBACK(buddy_removed_cb), conv);
4727
4839
purple_signal_connect(blist_handle, "blist-node-aliased",
4728
4840
gtkchat, PURPLE_CALLBACK(blist_node_aliased_cb), conv);
4803
4915
pidgin_conv_create_tooltip, NULL);
4805
4917
gtkconv->infopane = gtk_cell_view_new();
4806
gtkconv->infopane_model = gtk_list_store_new(CONV_NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, GDK_TYPE_PIXBUF, GDK_TYPE_PIXBUF);
4807
gtk_cell_view_set_model(GTK_CELL_VIEW(gtkconv->infopane),
4918
gtkconv->infopane_model = gtk_list_store_new(CONV_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF, GDK_TYPE_PIXBUF);
4919
gtk_cell_view_set_model(GTK_CELL_VIEW(gtkconv->infopane),
4808
4920
GTK_TREE_MODEL(gtkconv->infopane_model));
4809
4921
g_object_unref(gtkconv->infopane_model);
4810
4922
gtk_list_store_append(gtkconv->infopane_model, &(gtkconv->infopane_iter));
4813
4925
gtk_cell_view_set_displayed_row(GTK_CELL_VIEW(gtkconv->infopane), path);
4814
4926
gtk_tree_path_free(path);
4816
if ((buddy = purple_find_buddy(purple_conversation_get_account(conv),
4817
purple_conversation_get_name(conv))) != NULL) {
4818
PurpleContact *contact = purple_buddy_get_contact(buddy);
4820
buddyicon_size = purple_blist_node_get_int((PurpleBlistNode*)contact, "pidgin-infopane-iconsize");
4929
/* This empty widget is used to ensure that the infopane is consistently
4930
sized for chat windows. The correct fix is to put an icon in the chat
4931
window as well, because that would make "Set Custom Icon" consistent
4932
for both the buddy list and the chat window, but PidginConversation
4933
is pretty much stuck until 3.0. */
4934
GtkWidget *sizing_vbox;
4935
sizing_vbox = gtk_vbox_new(FALSE, 0);
4936
gtk_widget_set_size_request(sizing_vbox, -1, BUDDYICON_SIZE_MIN);
4937
gtk_box_pack_start(GTK_BOX(gtkconv->infopane_hbox), sizing_vbox, FALSE, FALSE, 0);
4938
gtk_widget_show(sizing_vbox);
4941
gtkconv->u.im->icon_container = gtk_vbox_new(FALSE, 0);
4943
if ((buddy = purple_find_buddy(purple_conversation_get_account(conv),
4944
purple_conversation_get_name(conv))) != NULL) {
4945
PurpleContact *contact = purple_buddy_get_contact(buddy);
4947
buddyicon_size = purple_blist_node_get_int((PurpleBlistNode*)contact, "pidgin-infopane-iconsize");
4950
buddyicon_size = CLAMP(buddyicon_size, BUDDYICON_SIZE_MIN, BUDDYICON_SIZE_MAX);
4951
gtk_widget_set_size_request(gtkconv->u.im->icon_container, -1, buddyicon_size);
4953
gtk_box_pack_start(GTK_BOX(gtkconv->infopane_hbox),
4954
gtkconv->u.im->icon_container, FALSE, FALSE, 0);
4956
gtk_widget_show(gtkconv->u.im->icon_container);
4823
buddyicon_size = CLAMP(buddyicon_size, BUDDYICON_SIZE_MIN, BUDDYICON_SIZE_MAX);
4824
gtk_widget_set_size_request(gtkconv->infopane_hbox, -1, buddyicon_size);
4825
4959
gtk_widget_show(gtkconv->infopane);
4827
4961
rend = gtk_cell_renderer_pixbuf_new();
4828
4962
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkconv->infopane), rend, FALSE);
4829
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkconv->infopane), rend, "pixbuf", CONV_ICON_COLUMN, NULL);
4830
g_object_set(rend, "xalign", 0.0, "xpad", 6, "ypad", 0, NULL);
4963
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkconv->infopane), rend, "stock-id", CONV_ICON_COLUMN, NULL);
4964
g_object_set(rend, "xalign", 0.0, "xpad", 6, "ypad", 0,
4965
"stock-size", gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL),
4832
4968
rend = gtk_cell_renderer_text_new();
4833
4969
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkconv->infopane), rend, TRUE);
4941
5078
PurpleConversation *conv = gtkconv->active_conv;
4942
5079
PidginWindow *win = gtkconv->win;
4943
5080
PurpleConversation *c;
5081
PurpleAccount *convaccount = purple_conversation_get_account(conv);
5082
PurpleConnection *gc = purple_account_get_connection(convaccount);
5083
PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl) : NULL;
4944
5085
if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE))
4946
5087
PurpleBlistNode *n = NULL;
4947
5088
PurpleBuddy *b;
4948
5089
PidginConversation *gtkconv = NULL;
5090
PurpleAccount *buddyaccount;
5091
const char *buddyname;
4950
5093
n = *(PurpleBlistNode **)sd->data;
5102
buddyaccount = purple_buddy_get_account(b);
5103
buddyname = purple_buddy_get_name(b);
4960
* If we already have an open conversation with this buddy, then
4961
* just move the conv to this window. Otherwise, create a new
4962
* conv and add it to this window.
5105
* If a buddy is dragged to a chat window of the same protocol,
5106
* invite him to the chat.
4964
c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, b->name, b->account);
4966
PidginWindow *oldwin;
4967
gtkconv = PIDGIN_CONVERSATION(c);
4968
oldwin = gtkconv->win;
4969
if (oldwin != win) {
4970
pidgin_conv_window_remove_gtkconv(oldwin, gtkconv);
4971
pidgin_conv_window_add_gtkconv(win, gtkconv);
5108
if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT &&
5109
prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, chat_invite) &&
5110
strcmp(purple_account_get_protocol_id(convaccount),
5111
purple_account_get_protocol_id(buddyaccount)) == 0) {
5112
purple_conv_chat_invite_user(PURPLE_CONV_CHAT(conv), buddyname, NULL, TRUE);
4974
c = purple_conversation_new(PURPLE_CONV_TYPE_IM, b->account, b->name);
4975
gtkconv = PIDGIN_CONVERSATION(c);
4976
if (gtkconv->win != win)
4978
pidgin_conv_window_remove_gtkconv(gtkconv->win, gtkconv);
4979
pidgin_conv_window_add_gtkconv(win, gtkconv);
5115
* If we already have an open conversation with this buddy, then
5116
* just move the conv to this window. Otherwise, create a new
5117
* conv and add it to this window.
5119
c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddyname, buddyaccount);
5121
PidginWindow *oldwin;
5122
gtkconv = PIDGIN_CONVERSATION(c);
5123
oldwin = gtkconv->win;
5124
if (oldwin != win) {
5125
pidgin_conv_window_remove_gtkconv(oldwin, gtkconv);
5126
pidgin_conv_window_add_gtkconv(win, gtkconv);
5129
c = purple_conversation_new(PURPLE_CONV_TYPE_IM, buddyaccount, buddyname);
5130
gtkconv = PIDGIN_CONVERSATION(c);
5131
if (gtkconv->win != win) {
5132
pidgin_conv_window_remove_gtkconv(gtkconv->win, gtkconv);
5133
pidgin_conv_window_add_gtkconv(win, gtkconv);
5137
/* Make this conversation the active conversation */
5138
pidgin_conv_window_switch_gtkconv(win, gtkconv);
4983
/* Make this conversation the active conversation */
4984
pidgin_conv_window_switch_gtkconv(win, gtkconv);
4986
5141
gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t);
4988
5143
else if (sd->target == gdk_atom_intern("application/x-im-contact", FALSE))
5000
5155
purple_notify_error(win, NULL,
5001
5156
_("You are not currently signed on with an account that "
5002
5157
"can add that buddy."), NULL);
5006
c = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, username);
5007
gtkconv = PIDGIN_CONVERSATION(c);
5008
if (gtkconv->win != win)
5010
pidgin_conv_window_remove_gtkconv(gtkconv->win, gtkconv);
5011
pidgin_conv_window_add_gtkconv(win, gtkconv);
5160
* If a buddy is dragged to a chat window of the same protocol,
5161
* invite him to the chat.
5163
if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT &&
5164
prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, chat_invite) &&
5165
strcmp(purple_account_get_protocol_id(convaccount), protocol) == 0) {
5166
purple_conv_chat_invite_user(PURPLE_CONV_CHAT(conv), username, NULL, TRUE);
5168
c = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, username);
5169
gtkconv = PIDGIN_CONVERSATION(c);
5170
if (gtkconv->win != win) {
5171
pidgin_conv_window_remove_gtkconv(gtkconv->win, gtkconv);
5172
pidgin_conv_window_add_gtkconv(win, gtkconv);
5538
/* Returns true if the given HTML contains RTL text */
5540
html_is_rtl(const char *html)
5543
const gchar *start, *end;
5544
gboolean res = FALSE;
5546
if (purple_markup_find_tag("span", html, &start, &end, &attributes))
5548
/* tmp is a member of attributes and is free with g_datalist_clear call */
5549
const char *tmp = g_datalist_get_data(&attributes, "dir");
5550
if (tmp && !g_ascii_strcasecmp(tmp, "RTL"))
5554
tmp = g_datalist_get_data(&attributes, "style");
5557
char *tmp2 = purple_markup_get_css_property(tmp, "direction");
5558
if (tmp2 && !g_ascii_strcasecmp(tmp2, "RTL"))
5564
g_datalist_clear(&attributes);
5571
5711
pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *alias,
5572
5712
const char *message, PurpleMessageFlags flags,
6168
if ((tag = get_buddy_tag(conv, old_name, 0, FALSE)))
6169
g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL);
6170
if ((tag = get_buddy_tag(conv, old_name, PURPLE_MESSAGE_NICK, FALSE)))
6171
g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL);
6027
6173
if (!purple_conv_chat_find_user(chat, old_name))
6229
if ((tag = get_buddy_tag(conv, l->data, 0, FALSE)))
6230
g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL);
6231
if ((tag = get_buddy_tag(conv, l->data, PURPLE_MESSAGE_NICK, FALSE)))
6232
g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL);
6083
6235
g_snprintf(tmp, sizeof(tmp),
6730
6886
wrote_msg_update_unseen_cb(PurpleAccount *account, const char *who, const char *message,
6731
6887
PurpleConversation *conv, PurpleMessageFlags flags, gpointer null)
6733
if (conv == NULL || PIDGIN_IS_PIDGIN_CONVERSATION(conv))
6889
PidginConversation *gtkconv = conv ? PIDGIN_CONVERSATION(conv) : NULL;
6890
if (conv == NULL || (gtkconv && gtkconv->win != hidden_convwin))
6735
6892
if (flags & (PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_RECV)) {
6736
6893
PidginUnseenState unseen = PIDGIN_UNSEEN_NONE;
6826
6984
prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(account->gc->prpl);
6828
6986
/* Remove the current icon stuff */
6829
if (gtkconv->u.im->icon_container != NULL)
6830
gtk_widget_destroy(gtkconv->u.im->icon_container);
6831
gtkconv->u.im->icon_container = NULL;
6987
children = gtk_container_get_children(GTK_CONTAINER(gtkconv->u.im->icon_container));
6989
/* We know there's only one child here. It'd be nice to shortcut to the
6990
event box, but we can't change the PidginConversation until 3.0 */
6991
event = (GtkWidget *)children->data;
6992
gtk_container_remove(GTK_CONTAINER(gtkconv->u.im->icon_container), event);
6993
g_list_free(children);
6833
6996
if (gtkconv->u.im->anim != NULL)
6834
6997
g_object_unref(G_OBJECT(gtkconv->u.im->anim));
7919
8084
handle, PURPLE_CALLBACK(account_status_changed_cb), NULL);
7921
8086
/* Callbacks to update a conversation */
7922
purple_signal_connect(blist_handle, "buddy-added", handle,
8087
purple_signal_connect(blist_handle, "blist-node-added", handle,
7923
8088
G_CALLBACK(buddy_update_cb), NULL);
7924
purple_signal_connect(blist_handle, "buddy-removed", handle,
8089
purple_signal_connect(blist_handle, "blist-node-removed", handle,
7925
8090
G_CALLBACK(buddy_update_cb), NULL);
7926
8091
purple_signal_connect(blist_handle, "buddy-signed-on",
7927
8092
handle, PURPLE_CALLBACK(update_buddy_sign), "on");
8088
8253
build_warn_close_dialog(PidginWindow *gtkwin)
8091
GtkWidget *vbox, *hbox;
8255
GtkWidget *label, *vbox, *hbox, *img;
8094
8257
g_return_if_fail(warn_close_dialog == NULL);
8097
warn_close_dialog = gtk_dialog_new_with_buttons(
8259
warn_close_dialog = gtk_dialog_new_with_buttons(_("Confirm close"),
8099
8260
GTK_WINDOW(gtkwin->window), GTK_DIALOG_MODAL,
8100
8261
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
8101
8262
GTK_STOCK_CLOSE, GTK_RESPONSE_OK, NULL);
9320
9484
/* Status icon. */
9321
9485
gtkconv->icon = gtk_image_new();
9322
9486
gtkconv->menu_icon = gtk_image_new();
9487
g_object_set(G_OBJECT(gtkconv->icon),
9488
"icon-size", gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC),
9490
g_object_set(G_OBJECT(gtkconv->menu_icon),
9491
"icon-size", gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC),
9323
9493
gtk_widget_show(gtkconv->icon);
9324
9494
update_tab_icon(conv);
9445
9615
gtk_notebook_set_tab_label(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, ebox);
9448
gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont,
9449
!tabs_side && !angle,
9618
gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont,
9619
!tabs_side && !angle,
9450
9620
TRUE, GTK_PACK_START);
9452
if (pidgin_conv_window_get_gtkconv_count(win) == 1)
9622
if (pidgin_conv_window_get_gtkconv_count(win) == 1)
9453
9623
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook),
9454
9624
purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/tabs") &&
9455
9625
(!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons") ||
9742
9912
purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/width"),
9743
9913
purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/height"));
9746
9916
pidgin_conv_window_add_gtkconv(win, conv);
9747
9917
pidgin_conv_window_show(win);
9749
g_signal_connect(G_OBJECT(win->window), "configure_event",
9919
g_signal_connect(G_OBJECT(win->window), "configure_event",
9750
9920
G_CALLBACK(conv_placement_last_created_win_type_configured_cb), conv);
9752
9922
pidgin_conv_window_add_gtkconv(win, conv);