pidgin/gtkconv.c

changeset 17879
3e3f85138f1a
parent 17715
9536709ee696
parent 17878
f0ac85a33d8e
child 18185
d4f1719d812b
equal deleted inserted replaced
17751:87854ccfae54 17879:3e3f85138f1a
270 270
271 static void 271 static void
272 default_formatize(PidginConversation *c) 272 default_formatize(PidginConversation *c)
273 { 273 {
274 PurpleConversation *conv = c->active_conv; 274 PurpleConversation *conv = c->active_conv;
275 275 gtk_imhtml_setup_entry(GTK_IMHTML(c->entry), conv->features);
276 if (conv->features & PURPLE_CONNECTION_HTML)
277 {
278 char color[8];
279 GdkColor fg_color, bg_color;
280
281 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold") != GTK_IMHTML(c->entry)->edit.bold)
282 gtk_imhtml_toggle_bold(GTK_IMHTML(c->entry));
283
284 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic") != GTK_IMHTML(c->entry)->edit.italic)
285 gtk_imhtml_toggle_italic(GTK_IMHTML(c->entry));
286
287 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline") != GTK_IMHTML(c->entry)->edit.underline)
288 gtk_imhtml_toggle_underline(GTK_IMHTML(c->entry));
289
290 gtk_imhtml_toggle_fontface(GTK_IMHTML(c->entry),
291 purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/font_face"));
292
293 if (!(conv->features & PURPLE_CONNECTION_NO_FONTSIZE))
294 {
295 int size = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/font_size");
296
297 /* 3 is the default. */
298 if (size != 3)
299 gtk_imhtml_font_set_size(GTK_IMHTML(c->entry), size);
300 }
301
302 if(strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor"), "") != 0)
303 {
304 gdk_color_parse(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor"),
305 &fg_color);
306 g_snprintf(color, sizeof(color), "#%02x%02x%02x",
307 fg_color.red / 256,
308 fg_color.green / 256,
309 fg_color.blue / 256);
310 } else
311 strcpy(color, "");
312
313 gtk_imhtml_toggle_forecolor(GTK_IMHTML(c->entry), color);
314
315 if(!(conv->features & PURPLE_CONNECTION_NO_BGCOLOR) &&
316 strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor"), "") != 0)
317 {
318 gdk_color_parse(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor"),
319 &bg_color);
320 g_snprintf(color, sizeof(color), "#%02x%02x%02x",
321 bg_color.red / 256,
322 bg_color.green / 256,
323 bg_color.blue / 256);
324 } else
325 strcpy(color, "");
326
327 gtk_imhtml_toggle_background(GTK_IMHTML(c->entry), color);
328
329 if (conv->features & PURPLE_CONNECTION_FORMATTING_WBFO)
330 gtk_imhtml_set_whole_buffer_formatting_only(GTK_IMHTML(c->entry), TRUE);
331 else
332 gtk_imhtml_set_whole_buffer_formatting_only(GTK_IMHTML(c->entry), FALSE);
333 }
334 } 276 }
335 277
336 static void 278 static void
337 clear_formatting_cb(GtkIMHtml *imhtml, PidginConversation *gtkconv) 279 clear_formatting_cb(GtkIMHtml *imhtml, PidginConversation *gtkconv)
338 { 280 {
665 { 607 {
666 prpl_info->get_cb_info(gc, 608 prpl_info->get_cb_info(gc,
667 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who); 609 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who);
668 } 610 }
669 else 611 else
670 prpl_info->get_info(gc, who); 612 pidgin_retrieve_user_info(gc, who);
671 } 613 }
672 } 614 }
673 615
674 616
675 static void 617 static void
676 info_cb(GtkWidget *widget, PidginConversation *gtkconv) 618 info_cb(GtkWidget *widget, PidginConversation *gtkconv)
677 { 619 {
678 PurpleConversation *conv = gtkconv->active_conv; 620 PurpleConversation *conv = gtkconv->active_conv;
679 621
680 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 622 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
681 PurpleNotifyUserInfo *info = purple_notify_user_info_new(); 623 pidgin_retrieve_user_info(purple_conversation_get_gc(conv),
682 purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving..."));
683 purple_notify_userinfo(conv->account->gc, purple_conversation_get_name(conv), info, NULL, NULL);
684 purple_notify_user_info_destroy(info);
685
686 serv_get_info(purple_conversation_get_gc(conv),
687 purple_conversation_get_name(conv)); 624 purple_conversation_get_name(conv));
688
689 gtk_widget_grab_focus(gtkconv->entry); 625 gtk_widget_grab_focus(gtkconv->entry);
690 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 626 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
691 /* Get info of the person currently selected in the GtkTreeView */ 627 /* Get info of the person currently selected in the GtkTreeView */
692 PidginChatPane *gtkchat; 628 PidginChatPane *gtkchat;
693 GtkTreeIter iter; 629 GtkTreeIter iter;
2271 **************************************************************************/ 2207 **************************************************************************/
2272 2208
2273 static GList *get_prpl_icon_list(PurpleAccount *account) 2209 static GList *get_prpl_icon_list(PurpleAccount *account)
2274 { 2210 {
2275 GList *l = NULL; 2211 GList *l = NULL;
2276 GdkPixbuf *pixbuf; 2212 PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account));
2277 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account))); 2213 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
2278 const char *prpl = prpl_info->list_icon(account, NULL); 2214 const char *prplname = prpl_info->list_icon(account, NULL);
2279 char *filename, *path; 2215 l = g_hash_table_lookup(prpl_lists, prplname);
2280 l = g_hash_table_lookup(prpl_lists, prpl);
2281 if (l) 2216 if (l)
2282 return l; 2217 return l;
2283 filename = g_strdup_printf("%s.png", prpl); 2218
2284 2219 l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_LARGE));
2285 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "16", filename, NULL); 2220 l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM));
2286 pixbuf = gdk_pixbuf_new_from_file(path, NULL); 2221 l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL));
2287 if (pixbuf) 2222
2288 l = g_list_append(l, pixbuf); 2223 g_hash_table_insert(prpl_lists, g_strdup(prplname), l);
2289 g_free(path);
2290
2291 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "22", filename, NULL);
2292 pixbuf = gdk_pixbuf_new_from_file(path, NULL);
2293 if (pixbuf)
2294 l = g_list_append(l, pixbuf);
2295 g_free(path);
2296
2297 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "48", filename, NULL);
2298 pixbuf = gdk_pixbuf_new_from_file(path, NULL);
2299 if (pixbuf)
2300 l = g_list_append(l, pixbuf);
2301 g_free(path);
2302
2303 g_hash_table_insert(prpl_lists, g_strdup(prpl), l);
2304 return l; 2224 return l;
2305 } 2225 }
2306 2226
2307 static GList * 2227 static GList *
2308 pidgin_conv_get_tab_icons(PurpleConversation *conv) 2228 pidgin_conv_get_tab_icons(PurpleConversation *conv)
3027 } 2947 }
3028 2948
3029 gtk_widget_show_all(menu); 2949 gtk_widget_show_all(menu);
3030 } 2950 }
3031 2951
2952 static void
2953 remove_from_list(GtkWidget *widget, PidginWindow *win)
2954 {
2955 GList *list = g_object_get_data(G_OBJECT(win->window), "plugin-actions");
2956 list = g_list_remove(list, widget);
2957 g_object_set_data(G_OBJECT(win->window), "plugin-actions", list);
2958 }
2959
2960 static void
2961 regenerate_plugins_items(PidginWindow *win)
2962 {
2963 GList *action_items;
2964 GtkWidget *menu;
2965 GList *list;
2966 PidginConversation *gtkconv;
2967 PurpleConversation *conv;
2968 GtkWidget *item;
2969
2970 if (win->window == NULL || win == hidden_convwin)
2971 return;
2972
2973 gtkconv = pidgin_conv_window_get_active_gtkconv(win);
2974 if (gtkconv == NULL)
2975 return;
2976
2977 conv = gtkconv->active_conv;
2978 action_items = g_object_get_data(G_OBJECT(win->window), "plugin-actions");
2979
2980 /* Remove the old menuitems */
2981 while (action_items) {
2982 g_signal_handlers_disconnect_by_func(G_OBJECT(action_items->data),
2983 G_CALLBACK(remove_from_list), win);
2984 gtk_widget_destroy(action_items->data);
2985 action_items = g_list_delete_link(action_items, action_items);
2986 }
2987
2988 menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Options"));
2989
2990 list = purple_conversation_get_extended_menu(conv);
2991 if (list) {
2992 action_items = g_list_prepend(NULL, (item = pidgin_separator(menu)));
2993 g_signal_connect(G_OBJECT(item), "destroy", G_CALLBACK(remove_from_list), win);
2994 }
2995
2996 for(; list; list = g_list_delete_link(list, list)) {
2997 PurpleMenuAction *act = (PurpleMenuAction *) list->data;
2998 item = pidgin_append_menu_action(menu, act, conv);
2999 action_items = g_list_prepend(action_items, item);
3000 gtk_widget_show_all(item);
3001 g_signal_connect(G_OBJECT(item), "destroy", G_CALLBACK(remove_from_list), win);
3002 }
3003 g_object_set_data(G_OBJECT(win->window), "plugin-actions", action_items);
3004 }
3005
3032 static void menubar_activated(GtkWidget *item, gpointer data) 3006 static void menubar_activated(GtkWidget *item, gpointer data)
3033 { 3007 {
3034 PidginWindow *win = data; 3008 PidginWindow *win = data;
3035 regenerate_options_items(win); 3009 regenerate_options_items(win);
3010 regenerate_plugins_items(win);
3036 3011
3037 /* The following are to make sure the 'More' submenu is not regenerated every time 3012 /* The following are to make sure the 'More' submenu is not regenerated every time
3038 * the focus shifts from 'Conversations' to some other menu and back. */ 3013 * the focus shifts from 'Conversations' to some other menu and back. */
3039 g_signal_handlers_block_by_func(G_OBJECT(item), G_CALLBACK(menubar_activated), data); 3014 g_signal_handlers_block_by_func(G_OBJECT(item), G_CALLBACK(menubar_activated), data);
3040 g_signal_connect(G_OBJECT(win->menu.menubar), "deactivate", G_CALLBACK(focus_out_from_menubar), data); 3015 g_signal_connect(G_OBJECT(win->menu.menubar), "deactivate", G_CALLBACK(focus_out_from_menubar), data);
4242 gtk_widget_set_size_request(gtkconv->lower_hbox, -1, height + PIDGIN_HIG_BOX_SPACE); 4217 gtk_widget_set_size_request(gtkconv->lower_hbox, -1, height + PIDGIN_HIG_BOX_SPACE);
4243 g_idle_add(reset_auto_resize_cb, gtkconv); 4218 g_idle_add(reset_auto_resize_cb, gtkconv);
4244 } 4219 }
4245 } 4220 }
4246 4221
4247 static GtkWidget * 4222 static void
4248 setup_chat_pane(PidginConversation *gtkconv) 4223 setup_chat_topic(PidginConversation *gtkconv, GtkWidget *vbox)
4249 { 4224 {
4250 PurplePluginProtocolInfo *prpl_info;
4251 PurpleConversation *conv = gtkconv->active_conv; 4225 PurpleConversation *conv = gtkconv->active_conv;
4252 PidginChatPane *gtkchat; 4226 PurpleConnection *gc = purple_conversation_get_gc(conv);
4253 PurpleConnection *gc; 4227 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
4254 GtkWidget *vpaned, *hpaned;
4255 GtkWidget *vbox, *hbox, *frame;
4256 GtkWidget *imhtml_sw;
4257 GtkPolicyType imhtml_sw_hscroll;
4258 GtkWidget *lbox;
4259 GtkWidget *label;
4260 GtkWidget *list;
4261 GtkWidget *sw;
4262 GtkListStore *ls;
4263 GtkCellRenderer *rend;
4264 GtkTreeViewColumn *col;
4265 void *blist_handle = purple_blist_get_handle();
4266 GList *focus_chain = NULL;
4267 int ul_width;
4268
4269 gtkchat = gtkconv->u.chat;
4270 gc = purple_conversation_get_gc(conv);
4271 g_return_val_if_fail(gc != NULL, NULL);
4272 g_return_val_if_fail(gc->prpl != NULL, NULL);
4273 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
4274
4275 /* Setup the outer pane. */
4276 vpaned = gtk_vpaned_new();
4277 gtk_widget_show(vpaned);
4278
4279 /* Setup the top part of the pane. */
4280 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4281 gtk_paned_pack1(GTK_PANED(vpaned), vbox, TRUE, TRUE);
4282 gtk_widget_show(vbox);
4283
4284 if (prpl_info->options & OPT_PROTO_CHAT_TOPIC) 4228 if (prpl_info->options & OPT_PROTO_CHAT_TOPIC)
4285 { 4229 {
4230 GtkWidget *hbox, *label;
4231 PidginChatPane *gtkchat = gtkconv->u.chat;
4232
4286 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 4233 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4287 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); 4234 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
4288 gtk_widget_show(hbox); 4235 gtk_widget_show(hbox);
4289 4236
4290 label = gtk_label_new(_("Topic:")); 4237 label = gtk_label_new(_("Topic:"));
4303 gtk_box_pack_start(GTK_BOX(hbox), gtkchat->topic_text, TRUE, TRUE, 0); 4250 gtk_box_pack_start(GTK_BOX(hbox), gtkchat->topic_text, TRUE, TRUE, 0);
4304 gtk_widget_show(gtkchat->topic_text); 4251 gtk_widget_show(gtkchat->topic_text);
4305 g_signal_connect(G_OBJECT(gtkchat->topic_text), "key_press_event", 4252 g_signal_connect(G_OBJECT(gtkchat->topic_text), "key_press_event",
4306 G_CALLBACK(entry_key_press_cb), gtkconv); 4253 G_CALLBACK(entry_key_press_cb), gtkconv);
4307 } 4254 }
4308 4255 }
4309 /* Setup the horizontal pane. */ 4256
4310 hpaned = gtk_hpaned_new(); 4257 static void
4311 gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0); 4258 setup_chat_userlist(PidginConversation *gtkconv, GtkWidget *hpaned)
4312 gtk_widget_show(hpaned); 4259 {
4313 4260 PidginChatPane *gtkchat = gtkconv->u.chat;
4314 /* Setup gtkihmtml. */ 4261 GtkWidget *lbox, *sw, *list;
4315 frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw); 4262 GtkListStore *ls;
4316 gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml"); 4263 GtkCellRenderer *rend;
4317 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml), TRUE); 4264 GtkTreeViewColumn *col;
4318 gtk_paned_pack1(GTK_PANED(hpaned), frame, TRUE, TRUE); 4265 int ul_width;
4319 gtk_widget_show(frame); 4266 void *blist_handle = purple_blist_get_handle();
4320 gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(imhtml_sw), 4267 PurpleConversation *conv = gtkconv->active_conv;
4321 &imhtml_sw_hscroll, NULL);
4322 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
4323 imhtml_sw_hscroll, GTK_POLICY_ALWAYS);
4324
4325 gtk_widget_set_size_request(gtkconv->imhtml,
4326 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_width"),
4327 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_height"));
4328 g_signal_connect(G_OBJECT(gtkconv->imhtml), "size-allocate",
4329 G_CALLBACK(size_allocate_cb), gtkconv);
4330
4331 g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event",
4332 G_CALLBACK(entry_stop_rclick_cb), NULL);
4333 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event",
4334 G_CALLBACK(refocus_entry_cb), gtkconv);
4335 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event",
4336 G_CALLBACK(refocus_entry_cb), gtkconv);
4337 4268
4338 /* Build the right pane. */ 4269 /* Build the right pane. */
4339 lbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 4270 lbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4340 gtk_paned_pack2(GTK_PANED(hpaned), lbox, FALSE, TRUE); 4271 gtk_paned_pack2(GTK_PANED(hpaned), lbox, FALSE, TRUE);
4341 gtk_widget_show(lbox); 4272 gtk_widget_show(lbox);
4379 G_CALLBACK(right_click_chat_cb), gtkconv); 4310 G_CALLBACK(right_click_chat_cb), gtkconv);
4380 g_signal_connect(G_OBJECT(list), "popup-menu", 4311 g_signal_connect(G_OBJECT(list), "popup-menu",
4381 G_CALLBACK(gtkconv_chat_popup_menu_cb), gtkconv); 4312 G_CALLBACK(gtkconv_chat_popup_menu_cb), gtkconv);
4382 g_signal_connect(G_OBJECT(lbox), "size-allocate", G_CALLBACK(lbox_size_allocate_cb), gtkconv); 4313 g_signal_connect(G_OBJECT(lbox), "size-allocate", G_CALLBACK(lbox_size_allocate_cb), gtkconv);
4383 4314
4384
4385 rend = gtk_cell_renderer_text_new(); 4315 rend = gtk_cell_renderer_text_new();
4386
4387 g_object_set(rend, 4316 g_object_set(rend,
4388 "foreground-set", TRUE, 4317 "foreground-set", TRUE,
4389 "weight-set", TRUE, 4318 "weight-set", TRUE,
4390 NULL); 4319 NULL);
4391 col = gtk_tree_view_column_new_with_attributes(NULL, rend, 4320 col = gtk_tree_view_column_new_with_attributes(NULL, rend,
4412 gtk_widget_show(list); 4341 gtk_widget_show(list);
4413 4342
4414 gtkchat->list = list; 4343 gtkchat->list = list;
4415 4344
4416 gtk_container_add(GTK_CONTAINER(sw), list); 4345 gtk_container_add(GTK_CONTAINER(sw), list);
4346 }
4347
4348 static GtkWidget *
4349 setup_common_pane(PidginConversation *gtkconv)
4350 {
4351 GtkWidget *paned, *vbox, *frame, *imhtml_sw;
4352 PurpleConversation *conv = gtkconv->active_conv;
4353 gboolean chat = (conv->type == PURPLE_CONV_TYPE_CHAT);
4354 GtkPolicyType imhtml_sw_hscroll;
4355
4356 paned = gtk_vpaned_new();
4357 gtk_widget_show(paned);
4358
4359 /* Setup the top part of the pane */
4360 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4361 gtk_paned_pack1(GTK_PANED(paned), vbox, TRUE, TRUE);
4362 gtk_widget_show(vbox);
4363
4364 /* Setup the gtkimhtml widget */
4365 frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw);
4366 if (chat) {
4367 GtkWidget *hpaned;
4368
4369 /* Add the topic */
4370 setup_chat_topic(gtkconv, vbox);
4371
4372 /* Add the gtkimhtml frame */
4373 hpaned = gtk_hpaned_new();
4374 gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0);
4375 gtk_widget_show(hpaned);
4376 gtk_paned_pack1(GTK_PANED(hpaned), frame, TRUE, TRUE);
4377
4378 /* Now add the userlist */
4379 setup_chat_userlist(gtkconv, hpaned);
4380 } else {
4381 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
4382 }
4383 gtk_widget_show(frame);
4384
4385 gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml");
4386 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),TRUE);
4387
4388 gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
4389 &imhtml_sw_hscroll, NULL);
4390 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
4391 imhtml_sw_hscroll, GTK_POLICY_ALWAYS);
4392
4393 gtk_widget_set_size_request(gtkconv->imhtml,
4394 chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_width") :
4395 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_width"),
4396 chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_height") :
4397 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_height"));
4398
4399 g_signal_connect(G_OBJECT(gtkconv->imhtml), "size-allocate",
4400 G_CALLBACK(size_allocate_cb), gtkconv);
4401
4402 g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event",
4403 G_CALLBACK(entry_stop_rclick_cb), NULL);
4404 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event",
4405 G_CALLBACK(refocus_entry_cb), gtkconv);
4406 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event",
4407 G_CALLBACK(refocus_entry_cb), gtkconv);
4417 4408
4418 /* Setup the bottom half of the conversation window */ 4409 /* Setup the bottom half of the conversation window */
4419 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 4410 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4420 gtk_paned_pack2(GTK_PANED(vpaned), vbox, FALSE, TRUE); 4411 gtk_paned_pack2(GTK_PANED(paned), vbox, FALSE, TRUE);
4421 gtk_widget_show(vbox); 4412 gtk_widget_show(vbox);
4422 4413
4423 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 4414 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4424 gtk_box_pack_start(GTK_BOX(vbox), gtkconv->lower_hbox, TRUE, TRUE, 0); 4415 gtk_box_pack_start(GTK_BOX(vbox), gtkconv->lower_hbox, TRUE, TRUE, 0);
4425 gtk_widget_show(gtkconv->lower_hbox); 4416 gtk_widget_show(gtkconv->lower_hbox);
4431 /* Setup the toolbar, entry widget and all signals */ 4422 /* Setup the toolbar, entry widget and all signals */
4432 frame = pidgin_create_imhtml(TRUE, &gtkconv->entry, &gtkconv->toolbar, NULL); 4423 frame = pidgin_create_imhtml(TRUE, &gtkconv->entry, &gtkconv->toolbar, NULL);
4433 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); 4424 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
4434 gtk_widget_show(frame); 4425 gtk_widget_show(frame);
4435 4426
4436 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
4437 G_CALLBACK(entry_popup_menu_cb), gtkconv);
4438
4439 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry"); 4427 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry");
4440 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry), 4428 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry),
4441 purple_account_get_protocol_name(conv->account)); 4429 purple_account_get_protocol_name(conv->account));
4442 gtk_widget_set_size_request(gtkconv->lower_hbox, -1, 4430 gtk_widget_set_size_request(gtkconv->lower_hbox, -1,
4443 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height")); 4431 chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height") :
4444 gtkconv->entry_buffer = 4432 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height"));
4445 gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry)); 4433
4446 g_object_set_data(G_OBJECT(gtkconv->entry_buffer), "user_data", gtkconv); 4434 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
4447 g_signal_connect_swapped(G_OBJECT(gtkconv->entry_buffer), "changed", 4435 G_CALLBACK(entry_popup_menu_cb), gtkconv);
4448 G_CALLBACK(resize_imhtml_cb), gtkconv);
4449
4450 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event", 4436 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event",
4451 G_CALLBACK(entry_key_press_cb), gtkconv); 4437 G_CALLBACK(entry_key_press_cb), gtkconv);
4452 g_signal_connect_after(G_OBJECT(gtkconv->entry), "message_send", 4438 g_signal_connect_after(G_OBJECT(gtkconv->entry), "message_send",
4453 G_CALLBACK(send_cb), gtkconv); 4439 G_CALLBACK(send_cb), gtkconv);
4454 g_signal_connect_after(G_OBJECT(gtkconv->entry), "button_press_event", 4440 g_signal_connect_after(G_OBJECT(gtkconv->entry), "button_press_event",
4455 G_CALLBACK(entry_stop_rclick_cb), NULL); 4441 G_CALLBACK(entry_stop_rclick_cb), NULL);
4456 g_signal_connect(G_OBJECT(gtkconv->lower_hbox), "size-allocate", 4442 g_signal_connect(G_OBJECT(gtkconv->lower_hbox), "size-allocate",
4457 G_CALLBACK(size_allocate_cb), gtkconv); 4443 G_CALLBACK(size_allocate_cb), gtkconv);
4458 4444
4459 default_formatize(gtkconv);
4460
4461 /*
4462 * Focus for chat windows should be as follows:
4463 * Tab title -> chat topic -> conversation scrollback -> user list ->
4464 * user list buttons -> entry -> buttons at bottom
4465 */
4466 focus_chain = g_list_prepend(focus_chain, gtkconv->entry);
4467 gtk_container_set_focus_chain(GTK_CONTAINER(vbox), focus_chain);
4468
4469 return vpaned;
4470 }
4471
4472 static GtkWidget *
4473 setup_im_pane(PidginConversation *gtkconv)
4474 {
4475 PurpleConversation *conv = gtkconv->active_conv;
4476 GtkWidget *frame;
4477 GtkWidget *imhtml_sw;
4478 GtkPolicyType imhtml_sw_hscroll;
4479 GtkWidget *paned;
4480 GtkWidget *vbox;
4481 GtkWidget *vbox2;
4482 GList *focus_chain = NULL;
4483
4484 /* Setup the outer pane */
4485 paned = gtk_vpaned_new();
4486 gtk_widget_show(paned);
4487
4488 /* Setup the top part of the pane */
4489 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4490 gtk_paned_pack1(GTK_PANED(paned), vbox, TRUE, TRUE);
4491 gtk_widget_show(vbox);
4492
4493 /* Setup the gtkimhtml widget */
4494 frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw);
4495 gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml");
4496 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),TRUE);
4497 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
4498 gtk_widget_show(frame);
4499 gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
4500 &imhtml_sw_hscroll, NULL);
4501 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
4502 imhtml_sw_hscroll, GTK_POLICY_ALWAYS);
4503
4504 gtk_widget_set_size_request(gtkconv->imhtml,
4505 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_width"),
4506 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_height"));
4507 g_signal_connect(G_OBJECT(gtkconv->imhtml), "size-allocate",
4508 G_CALLBACK(size_allocate_cb), gtkconv);
4509
4510 g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event",
4511 G_CALLBACK(entry_stop_rclick_cb), NULL);
4512 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event",
4513 G_CALLBACK(refocus_entry_cb), gtkconv);
4514 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event",
4515 G_CALLBACK(refocus_entry_cb), gtkconv);
4516
4517 /* Setup the bottom half of the conversation window */
4518 vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4519 gtk_paned_pack2(GTK_PANED(paned), vbox2, FALSE, TRUE);
4520 gtk_widget_show(vbox2);
4521
4522 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4523 gtk_box_pack_start(GTK_BOX(vbox2), gtkconv->lower_hbox, TRUE, TRUE, 0);
4524 gtk_widget_show(gtkconv->lower_hbox);
4525
4526 vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4527 gtk_box_pack_end(GTK_BOX(gtkconv->lower_hbox), vbox2, TRUE, TRUE, 0);
4528 gtk_widget_show(vbox2);
4529
4530 /* Setup the toolbar, entry widget and all signals */
4531 frame = pidgin_create_imhtml(TRUE, &gtkconv->entry, &gtkconv->toolbar, NULL);
4532 gtk_box_pack_start(GTK_BOX(vbox2), frame, TRUE, TRUE, 0);
4533 gtk_widget_show(frame);
4534
4535 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
4536 G_CALLBACK(entry_popup_menu_cb), gtkconv);
4537
4538 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry");
4539 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry),
4540 purple_account_get_protocol_name(conv->account));
4541 gtk_widget_set_size_request(gtkconv->lower_hbox, -1,
4542 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height"));
4543 gtkconv->entry_buffer = 4445 gtkconv->entry_buffer =
4544 gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry)); 4446 gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry));
4545 g_object_set_data(G_OBJECT(gtkconv->entry_buffer), "user_data", gtkconv); 4447 g_object_set_data(G_OBJECT(gtkconv->entry_buffer), "user_data", gtkconv);
4546 4448
4547 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event", 4449 if (!chat) {
4548 G_CALLBACK(entry_key_press_cb), gtkconv); 4450 /* For sending typing notifications for IMs */
4549 g_signal_connect_after(G_OBJECT(gtkconv->entry), "message_send", 4451 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "insert_text",
4550 G_CALLBACK(send_cb), gtkconv); 4452 G_CALLBACK(insert_text_cb), gtkconv);
4551 g_signal_connect_after(G_OBJECT(gtkconv->entry), "button_press_event", 4453 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "delete_range",
4552 G_CALLBACK(entry_stop_rclick_cb), NULL); 4454 G_CALLBACK(delete_text_cb), gtkconv);
4553 g_signal_connect(G_OBJECT(gtkconv->lower_hbox), "size-allocate", 4455 gtkconv->u.im->typing_timer = 0;
4554 G_CALLBACK(size_allocate_cb), gtkconv); 4456 gtkconv->u.im->animate = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/animate_buddy_icons");
4555 4457 gtkconv->u.im->show_icon = TRUE;
4556 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "insert_text", 4458 }
4557 G_CALLBACK(insert_text_cb), gtkconv); 4459
4558 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "delete_range",
4559 G_CALLBACK(delete_text_cb), gtkconv);
4560 g_signal_connect_swapped(G_OBJECT(gtkconv->entry_buffer), "changed", 4460 g_signal_connect_swapped(G_OBJECT(gtkconv->entry_buffer), "changed",
4561 G_CALLBACK(resize_imhtml_cb), gtkconv); 4461 G_CALLBACK(resize_imhtml_cb), gtkconv);
4562 4462
4563 /* had to move this after the imtoolbar is attached so that the
4564 * signals get fired to toggle the buttons on the toolbar as well.
4565 */
4566 default_formatize(gtkconv); 4463 default_formatize(gtkconv);
4567
4568 g_signal_connect_after(G_OBJECT(gtkconv->entry), "format_function_clear", 4464 g_signal_connect_after(G_OBJECT(gtkconv->entry), "format_function_clear",
4569 G_CALLBACK(clear_formatting_cb), gtkconv); 4465 G_CALLBACK(clear_formatting_cb), gtkconv);
4570 4466
4571 gtkconv->u.im->animate = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/animate_buddy_icons");
4572 gtkconv->u.im->show_icon = TRUE;
4573
4574 /*
4575 * Focus for IM windows should be as follows:
4576 * Tab title -> conversation scrollback -> entry
4577 */
4578 focus_chain = g_list_prepend(focus_chain, gtkconv->entry);
4579 gtk_container_set_focus_chain(GTK_CONTAINER(vbox2), focus_chain);
4580
4581 gtkconv->u.im->typing_timer = 0;
4582 return paned; 4467 return paned;
4583 } 4468 }
4584 4469
4585 static void 4470 static void
4586 conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, 4471 conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y,
4772 gtkconv->unseen_state = PIDGIN_UNSEEN_NONE; 4657 gtkconv->unseen_state = PIDGIN_UNSEEN_NONE;
4773 gtkconv->unseen_count = 0; 4658 gtkconv->unseen_count = 0;
4774 4659
4775 if (conv_type == PURPLE_CONV_TYPE_IM) { 4660 if (conv_type == PURPLE_CONV_TYPE_IM) {
4776 gtkconv->u.im = g_malloc0(sizeof(PidginImPane)); 4661 gtkconv->u.im = g_malloc0(sizeof(PidginImPane));
4777
4778 pane = setup_im_pane(gtkconv);
4779 } else if (conv_type == PURPLE_CONV_TYPE_CHAT) { 4662 } else if (conv_type == PURPLE_CONV_TYPE_CHAT) {
4780 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane)); 4663 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane));
4781 pane = setup_chat_pane(gtkconv); 4664 }
4782 } 4665 pane = setup_common_pane(gtkconv);
4783 4666
4784 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->imhtml), 4667 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->imhtml),
4785 gtk_imhtml_get_format_functions(GTK_IMHTML(gtkconv->imhtml)) | GTK_IMHTML_IMAGE); 4668 gtk_imhtml_get_format_functions(GTK_IMHTML(gtkconv->imhtml)) | GTK_IMHTML_IMAGE);
4786 4669
4787 if (pane == NULL) { 4670 if (pane == NULL) {
8090 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging), 7973 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging),
8091 purple_conversation_is_logging(conv)); 7974 purple_conversation_is_logging(conv));
8092 7975
8093 generate_send_to_items(win); 7976 generate_send_to_items(win);
8094 regenerate_options_items(win); 7977 regenerate_options_items(win);
7978 regenerate_plugins_items(win);
8095 7979
8096 pidgin_conv_switch_active_conversation(conv); 7980 pidgin_conv_switch_active_conversation(conv);
8097 7981
8098 sound_method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"); 7982 sound_method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method");
8099 if (strcmp(sound_method, "none") != 0) 7983 if (strcmp(sound_method, "none") != 0)
8160 offline_list = make_status_icon_list(PIDGIN_STOCK_STATUS_OFFLINE, w); 8044 offline_list = make_status_icon_list(PIDGIN_STOCK_STATUS_OFFLINE, w);
8161 away_list = make_status_icon_list(PIDGIN_STOCK_STATUS_AWAY, w); 8045 away_list = make_status_icon_list(PIDGIN_STOCK_STATUS_AWAY, w);
8162 prpl_lists = g_hash_table_new(g_str_hash, g_str_equal); 8046 prpl_lists = g_hash_table_new(g_str_hash, g_str_equal);
8163 } 8047 }
8164 8048
8049 static void
8050 plugin_changed_cb(PurplePlugin *p, gpointer data)
8051 {
8052 regenerate_plugins_items(data);
8053 }
8054
8165 PidginWindow * 8055 PidginWindow *
8166 pidgin_conv_window_new() 8056 pidgin_conv_window_new()
8167 { 8057 {
8168 PidginWindow *win; 8058 PidginWindow *win;
8169 GtkPositionType pos; 8059 GtkPositionType pos;
8233 gtk_box_pack_start(GTK_BOX(testidea), win->notebook, TRUE, TRUE, 0); 8123 gtk_box_pack_start(GTK_BOX(testidea), win->notebook, TRUE, TRUE, 0);
8234 8124
8235 gtk_container_add(GTK_CONTAINER(win->window), testidea); 8125 gtk_container_add(GTK_CONTAINER(win->window), testidea);
8236 8126
8237 gtk_widget_show(testidea); 8127 gtk_widget_show(testidea);
8128
8129 /* Update the plugin actions when plugins are (un)loaded */
8130 purple_signal_connect(purple_plugins_get_handle(), "plugin-load",
8131 win, PURPLE_CALLBACK(plugin_changed_cb), win);
8132 purple_signal_connect(purple_plugins_get_handle(), "plugin-unload",
8133 win, PURPLE_CALLBACK(plugin_changed_cb), win);
8134
8238 8135
8239 #ifdef _WIN32 8136 #ifdef _WIN32
8240 g_signal_connect(G_OBJECT(win->window), "show", 8137 g_signal_connect(G_OBJECT(win->window), "show",
8241 G_CALLBACK(winpidgin_ensure_onscreen), win->window); 8138 G_CALLBACK(winpidgin_ensure_onscreen), win->window);
8242 #endif 8139 #endif
8273 gtk_widget_destroy(win->window); 8170 gtk_widget_destroy(win->window);
8274 8171
8275 g_object_unref(G_OBJECT(win->menu.item_factory)); 8172 g_object_unref(G_OBJECT(win->menu.item_factory));
8276 8173
8277 purple_notify_close_with_handle(win); 8174 purple_notify_close_with_handle(win);
8175 purple_signals_disconnect_by_handle(win);
8278 8176
8279 g_free(win); 8177 g_free(win);
8280 } 8178 }
8281 8179
8282 void 8180 void

mercurial