pidgin/gtkconv.c

changeset 17861
8c4f798347ea
parent 17492
d23449c414df
parent 17858
14d53a1be2ee
child 17863
bab8f6242bae
equal deleted inserted replaced
17502:173cc15a3abc 17861:8c4f798347ea
269 269
270 static void 270 static void
271 default_formatize(PidginConversation *c) 271 default_formatize(PidginConversation *c)
272 { 272 {
273 PurpleConversation *conv = c->active_conv; 273 PurpleConversation *conv = c->active_conv;
274 274 gtk_imhtml_setup_entry(GTK_IMHTML(c->entry), conv->features);
275 if (conv->features & PURPLE_CONNECTION_HTML)
276 {
277 char color[8];
278 GdkColor fg_color, bg_color;
279
280 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold") != GTK_IMHTML(c->entry)->edit.bold)
281 gtk_imhtml_toggle_bold(GTK_IMHTML(c->entry));
282
283 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic") != GTK_IMHTML(c->entry)->edit.italic)
284 gtk_imhtml_toggle_italic(GTK_IMHTML(c->entry));
285
286 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline") != GTK_IMHTML(c->entry)->edit.underline)
287 gtk_imhtml_toggle_underline(GTK_IMHTML(c->entry));
288
289 gtk_imhtml_toggle_fontface(GTK_IMHTML(c->entry),
290 purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/font_face"));
291
292 if (!(conv->features & PURPLE_CONNECTION_NO_FONTSIZE))
293 {
294 int size = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/font_size");
295
296 /* 3 is the default. */
297 if (size != 3)
298 gtk_imhtml_font_set_size(GTK_IMHTML(c->entry), size);
299 }
300
301 if(strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor"), "") != 0)
302 {
303 gdk_color_parse(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor"),
304 &fg_color);
305 g_snprintf(color, sizeof(color), "#%02x%02x%02x",
306 fg_color.red / 256,
307 fg_color.green / 256,
308 fg_color.blue / 256);
309 } else
310 strcpy(color, "");
311
312 gtk_imhtml_toggle_forecolor(GTK_IMHTML(c->entry), color);
313
314 if(!(conv->features & PURPLE_CONNECTION_NO_BGCOLOR) &&
315 strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor"), "") != 0)
316 {
317 gdk_color_parse(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor"),
318 &bg_color);
319 g_snprintf(color, sizeof(color), "#%02x%02x%02x",
320 bg_color.red / 256,
321 bg_color.green / 256,
322 bg_color.blue / 256);
323 } else
324 strcpy(color, "");
325
326 gtk_imhtml_toggle_background(GTK_IMHTML(c->entry), color);
327
328 if (conv->features & PURPLE_CONNECTION_FORMATTING_WBFO)
329 gtk_imhtml_set_whole_buffer_formatting_only(GTK_IMHTML(c->entry), TRUE);
330 else
331 gtk_imhtml_set_whole_buffer_formatting_only(GTK_IMHTML(c->entry), FALSE);
332 }
333 } 275 }
334 276
335 static void 277 static void
336 clear_formatting_cb(GtkIMHtml *imhtml, PidginConversation *gtkconv) 278 clear_formatting_cb(GtkIMHtml *imhtml, PidginConversation *gtkconv)
337 { 279 {
675 info_cb(GtkWidget *widget, PidginConversation *gtkconv) 617 info_cb(GtkWidget *widget, PidginConversation *gtkconv)
676 { 618 {
677 PurpleConversation *conv = gtkconv->active_conv; 619 PurpleConversation *conv = gtkconv->active_conv;
678 620
679 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 621 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
680 PurpleNotifyUserInfo *info = purple_notify_user_info_new(); 622 pidgin_retrieve_user_info(purple_conversation_get_gc(conv),
681 purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving..."));
682 purple_notify_userinfo(conv->account->gc, purple_conversation_get_name(conv), info, NULL, NULL);
683 purple_notify_user_info_destroy(info);
684
685 serv_get_info(purple_conversation_get_gc(conv),
686 purple_conversation_get_name(conv)); 623 purple_conversation_get_name(conv));
687
688 gtk_widget_grab_focus(gtkconv->entry); 624 gtk_widget_grab_focus(gtkconv->entry);
689 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 625 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
690 /* Get info of the person currently selected in the GtkTreeView */ 626 /* Get info of the person currently selected in the GtkTreeView */
691 PidginChatPane *gtkchat; 627 PidginChatPane *gtkchat;
692 GtkTreeIter iter; 628 GtkTreeIter iter;
2226 **************************************************************************/ 2162 **************************************************************************/
2227 2163
2228 static GList *get_prpl_icon_list(PurpleAccount *account) 2164 static GList *get_prpl_icon_list(PurpleAccount *account)
2229 { 2165 {
2230 GList *l = NULL; 2166 GList *l = NULL;
2231 GdkPixbuf *pixbuf; 2167 PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account));
2232 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account))); 2168 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
2233 const char *prpl = prpl_info->list_icon(account, NULL); 2169 const char *prplname = prpl_info->list_icon(account, NULL);
2234 char *filename, *path; 2170 l = g_hash_table_lookup(prpl_lists, prplname);
2235 l = g_hash_table_lookup(prpl_lists, prpl);
2236 if (l) 2171 if (l)
2237 return l; 2172 return l;
2238 filename = g_strdup_printf("%s.png", prpl); 2173
2239 2174 l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_LARGE));
2240 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "16", filename, NULL); 2175 l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM));
2241 pixbuf = gdk_pixbuf_new_from_file(path, NULL); 2176 l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL));
2242 if (pixbuf) 2177
2243 l = g_list_append(l, pixbuf); 2178 g_hash_table_insert(prpl_lists, g_strdup(prplname), l);
2244 g_free(path);
2245
2246 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "22", filename, NULL);
2247 pixbuf = gdk_pixbuf_new_from_file(path, NULL);
2248 if (pixbuf)
2249 l = g_list_append(l, pixbuf);
2250 g_free(path);
2251
2252 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "48", filename, NULL);
2253 pixbuf = gdk_pixbuf_new_from_file(path, NULL);
2254 if (pixbuf)
2255 l = g_list_append(l, pixbuf);
2256 g_free(path);
2257
2258 g_hash_table_insert(prpl_lists, g_strdup(prpl), l);
2259 return l; 2179 return l;
2260 } 2180 }
2261 2181
2262 static GList * 2182 static GList *
2263 pidgin_conv_get_tab_icons(PurpleConversation *conv) 2183 pidgin_conv_get_tab_icons(PurpleConversation *conv)
2930 } 2850 }
2931 2851
2932 gtk_widget_show_all(menu); 2852 gtk_widget_show_all(menu);
2933 } 2853 }
2934 2854
2855 static void
2856 remove_from_list(GtkWidget *widget, PidginWindow *win)
2857 {
2858 GList *list = g_object_get_data(G_OBJECT(win->window), "plugin-actions");
2859 list = g_list_remove(list, widget);
2860 g_object_set_data(G_OBJECT(win->window), "plugin-actions", list);
2861 }
2862
2863 static void
2864 regenerate_plugins_items(PidginWindow *win)
2865 {
2866 GList *action_items;
2867 GtkWidget *menu;
2868 GList *list;
2869 PidginConversation *gtkconv;
2870 PurpleConversation *conv;
2871 GtkWidget *item;
2872
2873 if (win->window == NULL || win == hidden_convwin)
2874 return;
2875
2876 gtkconv = pidgin_conv_window_get_active_gtkconv(win);
2877 if (gtkconv == NULL)
2878 return;
2879
2880 conv = gtkconv->active_conv;
2881 action_items = g_object_get_data(G_OBJECT(win->window), "plugin-actions");
2882
2883 /* Remove the old menuitems */
2884 while (action_items) {
2885 g_signal_handlers_disconnect_by_func(G_OBJECT(action_items->data),
2886 G_CALLBACK(remove_from_list), win);
2887 gtk_widget_destroy(action_items->data);
2888 action_items = g_list_delete_link(action_items, action_items);
2889 }
2890
2891 menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Options"));
2892
2893 list = purple_conversation_get_extended_menu(conv);
2894 if (list) {
2895 action_items = g_list_prepend(NULL, (item = pidgin_separator(menu)));
2896 g_signal_connect(G_OBJECT(item), "destroy", G_CALLBACK(remove_from_list), win);
2897 }
2898
2899 for(; list; list = g_list_delete_link(list, list)) {
2900 PurpleMenuAction *act = (PurpleMenuAction *) list->data;
2901 item = pidgin_append_menu_action(menu, act, conv);
2902 action_items = g_list_prepend(action_items, item);
2903 gtk_widget_show_all(item);
2904 g_signal_connect(G_OBJECT(item), "destroy", G_CALLBACK(remove_from_list), win);
2905 }
2906 g_object_set_data(G_OBJECT(win->window), "plugin-actions", action_items);
2907 }
2908
2935 static void menubar_activated(GtkWidget *item, gpointer data) 2909 static void menubar_activated(GtkWidget *item, gpointer data)
2936 { 2910 {
2937 PidginWindow *win = data; 2911 PidginWindow *win = data;
2938 regenerate_options_items(win); 2912 regenerate_options_items(win);
2913 regenerate_plugins_items(win);
2939 2914
2940 /* The following are to make sure the 'More' submenu is not regenerated every time 2915 /* The following are to make sure the 'More' submenu is not regenerated every time
2941 * the focus shifts from 'Conversations' to some other menu and back. */ 2916 * the focus shifts from 'Conversations' to some other menu and back. */
2942 g_signal_handlers_block_by_func(G_OBJECT(item), G_CALLBACK(menubar_activated), data); 2917 g_signal_handlers_block_by_func(G_OBJECT(item), G_CALLBACK(menubar_activated), data);
2943 g_signal_connect(G_OBJECT(win->menu.menubar), "deactivate", G_CALLBACK(focus_out_from_menubar), data); 2918 g_signal_connect(G_OBJECT(win->menu.menubar), "deactivate", G_CALLBACK(focus_out_from_menubar), data);
4133 gtk_widget_set_size_request(gtkconv->lower_hbox, -1, height + PIDGIN_HIG_BOX_SPACE); 4108 gtk_widget_set_size_request(gtkconv->lower_hbox, -1, height + PIDGIN_HIG_BOX_SPACE);
4134 g_idle_add(reset_auto_resize_cb, gtkconv); 4109 g_idle_add(reset_auto_resize_cb, gtkconv);
4135 } 4110 }
4136 } 4111 }
4137 4112
4138 static GtkWidget * 4113 static void
4139 setup_chat_pane(PidginConversation *gtkconv) 4114 setup_chat_topic(PidginConversation *gtkconv, GtkWidget *vbox)
4140 { 4115 {
4141 PurplePluginProtocolInfo *prpl_info;
4142 PurpleConversation *conv = gtkconv->active_conv; 4116 PurpleConversation *conv = gtkconv->active_conv;
4143 PidginChatPane *gtkchat; 4117 PurpleConnection *gc = purple_conversation_get_gc(conv);
4144 PurpleConnection *gc; 4118 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
4145 GtkWidget *vpaned, *hpaned;
4146 GtkWidget *vbox, *hbox, *frame;
4147 GtkWidget *imhtml_sw;
4148 GtkPolicyType imhtml_sw_hscroll;
4149 GtkWidget *lbox;
4150 GtkWidget *label;
4151 GtkWidget *list;
4152 GtkWidget *sw;
4153 GtkListStore *ls;
4154 GtkCellRenderer *rend;
4155 GtkTreeViewColumn *col;
4156 void *blist_handle = purple_blist_get_handle();
4157 GList *focus_chain = NULL;
4158 int ul_width;
4159
4160 gtkchat = gtkconv->u.chat;
4161 gc = purple_conversation_get_gc(conv);
4162 g_return_val_if_fail(gc != NULL, NULL);
4163 g_return_val_if_fail(gc->prpl != NULL, NULL);
4164 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
4165
4166 /* Setup the outer pane. */
4167 vpaned = gtk_vpaned_new();
4168 gtk_widget_show(vpaned);
4169
4170 /* Setup the top part of the pane. */
4171 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4172 gtk_paned_pack1(GTK_PANED(vpaned), vbox, TRUE, TRUE);
4173 gtk_widget_show(vbox);
4174
4175 if (prpl_info->options & OPT_PROTO_CHAT_TOPIC) 4119 if (prpl_info->options & OPT_PROTO_CHAT_TOPIC)
4176 { 4120 {
4121 GtkWidget *hbox, *label;
4122 PidginChatPane *gtkchat = gtkconv->u.chat;
4123
4177 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 4124 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4178 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); 4125 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
4179 gtk_widget_show(hbox); 4126 gtk_widget_show(hbox);
4180 4127
4181 label = gtk_label_new(_("Topic:")); 4128 label = gtk_label_new(_("Topic:"));
4192 } 4139 }
4193 4140
4194 gtk_box_pack_start(GTK_BOX(hbox), gtkchat->topic_text, TRUE, TRUE, 0); 4141 gtk_box_pack_start(GTK_BOX(hbox), gtkchat->topic_text, TRUE, TRUE, 0);
4195 gtk_widget_show(gtkchat->topic_text); 4142 gtk_widget_show(gtkchat->topic_text);
4196 } 4143 }
4197 4144 }
4198 /* Setup the horizontal pane. */ 4145
4199 hpaned = gtk_hpaned_new(); 4146 static void
4200 gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0); 4147 setup_chat_userlist(PidginConversation *gtkconv, GtkWidget *hpaned)
4201 gtk_widget_show(hpaned); 4148 {
4202 4149 PidginChatPane *gtkchat = gtkconv->u.chat;
4203 /* Setup gtkihmtml. */ 4150 GtkWidget *lbox, *sw, *list;
4204 frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw); 4151 GtkListStore *ls;
4205 gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml"); 4152 GtkCellRenderer *rend;
4206 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml), TRUE); 4153 GtkTreeViewColumn *col;
4207 gtk_paned_pack1(GTK_PANED(hpaned), frame, TRUE, TRUE); 4154 int ul_width;
4208 gtk_widget_show(frame); 4155 void *blist_handle = purple_blist_get_handle();
4209 gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(imhtml_sw), 4156 PurpleConversation *conv = gtkconv->active_conv;
4210 &imhtml_sw_hscroll, NULL);
4211 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
4212 imhtml_sw_hscroll, GTK_POLICY_ALWAYS);
4213
4214 gtk_widget_set_size_request(gtkconv->imhtml,
4215 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_width"),
4216 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_height"));
4217 g_signal_connect(G_OBJECT(gtkconv->imhtml), "size-allocate",
4218 G_CALLBACK(size_allocate_cb), gtkconv);
4219
4220 g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event",
4221 G_CALLBACK(entry_stop_rclick_cb), NULL);
4222 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event",
4223 G_CALLBACK(refocus_entry_cb), gtkconv);
4224 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event",
4225 G_CALLBACK(refocus_entry_cb), gtkconv);
4226 4157
4227 /* Build the right pane. */ 4158 /* Build the right pane. */
4228 lbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 4159 lbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4229 gtk_paned_pack2(GTK_PANED(hpaned), lbox, FALSE, TRUE); 4160 gtk_paned_pack2(GTK_PANED(hpaned), lbox, FALSE, TRUE);
4230 gtk_widget_show(lbox); 4161 gtk_widget_show(lbox);
4268 G_CALLBACK(right_click_chat_cb), gtkconv); 4199 G_CALLBACK(right_click_chat_cb), gtkconv);
4269 g_signal_connect(G_OBJECT(list), "popup-menu", 4200 g_signal_connect(G_OBJECT(list), "popup-menu",
4270 G_CALLBACK(gtkconv_chat_popup_menu_cb), gtkconv); 4201 G_CALLBACK(gtkconv_chat_popup_menu_cb), gtkconv);
4271 g_signal_connect(G_OBJECT(lbox), "size-allocate", G_CALLBACK(lbox_size_allocate_cb), gtkconv); 4202 g_signal_connect(G_OBJECT(lbox), "size-allocate", G_CALLBACK(lbox_size_allocate_cb), gtkconv);
4272 4203
4273
4274 rend = gtk_cell_renderer_text_new(); 4204 rend = gtk_cell_renderer_text_new();
4275
4276 g_object_set(rend, 4205 g_object_set(rend,
4277 "foreground-set", TRUE, 4206 "foreground-set", TRUE,
4278 "weight-set", TRUE, 4207 "weight-set", TRUE,
4279 NULL); 4208 NULL);
4280 col = gtk_tree_view_column_new_with_attributes(NULL, rend, 4209 col = gtk_tree_view_column_new_with_attributes(NULL, rend,
4301 gtk_widget_show(list); 4230 gtk_widget_show(list);
4302 4231
4303 gtkchat->list = list; 4232 gtkchat->list = list;
4304 4233
4305 gtk_container_add(GTK_CONTAINER(sw), list); 4234 gtk_container_add(GTK_CONTAINER(sw), list);
4235 }
4236
4237 static GtkWidget *
4238 setup_common_pane(PidginConversation *gtkconv)
4239 {
4240 GtkWidget *paned, *vbox, *frame, *imhtml_sw;
4241 PurpleConversation *conv = gtkconv->active_conv;
4242 gboolean chat = (conv->type == PURPLE_CONV_TYPE_CHAT);
4243 GtkPolicyType imhtml_sw_hscroll;
4244
4245 paned = gtk_vpaned_new();
4246 gtk_widget_show(paned);
4247
4248 /* Setup the top part of the pane */
4249 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4250 gtk_paned_pack1(GTK_PANED(paned), vbox, TRUE, TRUE);
4251 gtk_widget_show(vbox);
4252
4253 /* Setup the gtkimhtml widget */
4254 frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw);
4255 if (chat) {
4256 GtkWidget *hpaned;
4257
4258 /* Add the topic */
4259 setup_chat_topic(gtkconv, vbox);
4260
4261 /* Add the gtkimhtml frame */
4262 hpaned = gtk_hpaned_new();
4263 gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0);
4264 gtk_widget_show(hpaned);
4265 gtk_paned_pack1(GTK_PANED(hpaned), frame, TRUE, TRUE);
4266
4267 /* Now add the userlist */
4268 setup_chat_userlist(gtkconv, hpaned);
4269 } else {
4270 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
4271 }
4272 gtk_widget_show(frame);
4273
4274 gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml");
4275 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),TRUE);
4276
4277 gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
4278 &imhtml_sw_hscroll, NULL);
4279 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
4280 imhtml_sw_hscroll, GTK_POLICY_ALWAYS);
4281
4282 gtk_widget_set_size_request(gtkconv->imhtml,
4283 chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_width") :
4284 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_width"),
4285 chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_height") :
4286 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_height"));
4287
4288 g_signal_connect(G_OBJECT(gtkconv->imhtml), "size-allocate",
4289 G_CALLBACK(size_allocate_cb), gtkconv);
4290
4291 g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event",
4292 G_CALLBACK(entry_stop_rclick_cb), NULL);
4293 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event",
4294 G_CALLBACK(refocus_entry_cb), gtkconv);
4295 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event",
4296 G_CALLBACK(refocus_entry_cb), gtkconv);
4306 4297
4307 /* Setup the bottom half of the conversation window */ 4298 /* Setup the bottom half of the conversation window */
4308 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 4299 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4309 gtk_paned_pack2(GTK_PANED(vpaned), vbox, FALSE, TRUE); 4300 gtk_paned_pack2(GTK_PANED(paned), vbox, FALSE, TRUE);
4310 gtk_widget_show(vbox); 4301 gtk_widget_show(vbox);
4311 4302
4312 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 4303 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4313 gtk_box_pack_start(GTK_BOX(vbox), gtkconv->lower_hbox, TRUE, TRUE, 0); 4304 gtk_box_pack_start(GTK_BOX(vbox), gtkconv->lower_hbox, TRUE, TRUE, 0);
4314 gtk_widget_show(gtkconv->lower_hbox); 4305 gtk_widget_show(gtkconv->lower_hbox);
4320 /* Setup the toolbar, entry widget and all signals */ 4311 /* Setup the toolbar, entry widget and all signals */
4321 frame = pidgin_create_imhtml(TRUE, &gtkconv->entry, &gtkconv->toolbar, NULL); 4312 frame = pidgin_create_imhtml(TRUE, &gtkconv->entry, &gtkconv->toolbar, NULL);
4322 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); 4313 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
4323 gtk_widget_show(frame); 4314 gtk_widget_show(frame);
4324 4315
4325 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
4326 G_CALLBACK(entry_popup_menu_cb), gtkconv);
4327
4328 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry"); 4316 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry");
4329 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry), 4317 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry),
4330 purple_account_get_protocol_name(conv->account)); 4318 purple_account_get_protocol_name(conv->account));
4331 gtk_widget_set_size_request(gtkconv->lower_hbox, -1, 4319 gtk_widget_set_size_request(gtkconv->lower_hbox, -1,
4332 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height")); 4320 chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height") :
4333 gtkconv->entry_buffer = 4321 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height"));
4334 gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry)); 4322
4335 g_object_set_data(G_OBJECT(gtkconv->entry_buffer), "user_data", gtkconv); 4323 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
4336 g_signal_connect_swapped(G_OBJECT(gtkconv->entry_buffer), "changed", 4324 G_CALLBACK(entry_popup_menu_cb), gtkconv);
4337 G_CALLBACK(resize_imhtml_cb), gtkconv);
4338
4339 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event", 4325 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event",
4340 G_CALLBACK(entry_key_press_cb), gtkconv); 4326 G_CALLBACK(entry_key_press_cb), gtkconv);
4341 g_signal_connect_after(G_OBJECT(gtkconv->entry), "message_send", 4327 g_signal_connect_after(G_OBJECT(gtkconv->entry), "message_send",
4342 G_CALLBACK(send_cb), gtkconv); 4328 G_CALLBACK(send_cb), gtkconv);
4343 g_signal_connect_after(G_OBJECT(gtkconv->entry), "button_press_event", 4329 g_signal_connect_after(G_OBJECT(gtkconv->entry), "button_press_event",
4344 G_CALLBACK(entry_stop_rclick_cb), NULL); 4330 G_CALLBACK(entry_stop_rclick_cb), NULL);
4345 g_signal_connect(G_OBJECT(gtkconv->lower_hbox), "size-allocate", 4331 g_signal_connect(G_OBJECT(gtkconv->lower_hbox), "size-allocate",
4346 G_CALLBACK(size_allocate_cb), gtkconv); 4332 G_CALLBACK(size_allocate_cb), gtkconv);
4347 4333
4348 default_formatize(gtkconv);
4349
4350 /*
4351 * Focus for chat windows should be as follows:
4352 * Tab title -> chat topic -> conversation scrollback -> user list ->
4353 * user list buttons -> entry -> buttons at bottom
4354 */
4355 focus_chain = g_list_prepend(focus_chain, gtkconv->entry);
4356 gtk_container_set_focus_chain(GTK_CONTAINER(vbox), focus_chain);
4357
4358 return vpaned;
4359 }
4360
4361 static GtkWidget *
4362 setup_im_pane(PidginConversation *gtkconv)
4363 {
4364 PurpleConversation *conv = gtkconv->active_conv;
4365 GtkWidget *frame;
4366 GtkWidget *imhtml_sw;
4367 GtkPolicyType imhtml_sw_hscroll;
4368 GtkWidget *paned;
4369 GtkWidget *vbox;
4370 GtkWidget *vbox2;
4371 GList *focus_chain = NULL;
4372
4373 /* Setup the outer pane */
4374 paned = gtk_vpaned_new();
4375 gtk_widget_show(paned);
4376
4377 /* Setup the top part of the pane */
4378 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4379 gtk_paned_pack1(GTK_PANED(paned), vbox, TRUE, TRUE);
4380 gtk_widget_show(vbox);
4381
4382 /* Setup the gtkimhtml widget */
4383 frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw);
4384 gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml");
4385 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),TRUE);
4386 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
4387 gtk_widget_show(frame);
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 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_width"),
4395 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_height"));
4396 g_signal_connect(G_OBJECT(gtkconv->imhtml), "size-allocate",
4397 G_CALLBACK(size_allocate_cb), gtkconv);
4398
4399 g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event",
4400 G_CALLBACK(entry_stop_rclick_cb), NULL);
4401 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event",
4402 G_CALLBACK(refocus_entry_cb), gtkconv);
4403 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event",
4404 G_CALLBACK(refocus_entry_cb), gtkconv);
4405
4406 /* Setup the bottom half of the conversation window */
4407 vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4408 gtk_paned_pack2(GTK_PANED(paned), vbox2, FALSE, TRUE);
4409 gtk_widget_show(vbox2);
4410
4411 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4412 gtk_box_pack_start(GTK_BOX(vbox2), gtkconv->lower_hbox, TRUE, TRUE, 0);
4413 gtk_widget_show(gtkconv->lower_hbox);
4414
4415 vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4416 gtk_box_pack_end(GTK_BOX(gtkconv->lower_hbox), vbox2, TRUE, TRUE, 0);
4417 gtk_widget_show(vbox2);
4418
4419 /* Setup the toolbar, entry widget and all signals */
4420 frame = pidgin_create_imhtml(TRUE, &gtkconv->entry, &gtkconv->toolbar, NULL);
4421 gtk_box_pack_start(GTK_BOX(vbox2), frame, TRUE, TRUE, 0);
4422 gtk_widget_show(frame);
4423
4424 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
4425 G_CALLBACK(entry_popup_menu_cb), gtkconv);
4426
4427 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry");
4428 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry),
4429 purple_account_get_protocol_name(conv->account));
4430 gtk_widget_set_size_request(gtkconv->lower_hbox, -1,
4431 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height"));
4432 gtkconv->entry_buffer = 4334 gtkconv->entry_buffer =
4433 gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry)); 4335 gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry));
4434 g_object_set_data(G_OBJECT(gtkconv->entry_buffer), "user_data", gtkconv); 4336 g_object_set_data(G_OBJECT(gtkconv->entry_buffer), "user_data", gtkconv);
4435 4337
4436 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event", 4338 if (!chat) {
4437 G_CALLBACK(entry_key_press_cb), gtkconv); 4339 /* For sending typing notifications for IMs */
4438 g_signal_connect_after(G_OBJECT(gtkconv->entry), "message_send", 4340 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "insert_text",
4439 G_CALLBACK(send_cb), gtkconv); 4341 G_CALLBACK(insert_text_cb), gtkconv);
4440 g_signal_connect_after(G_OBJECT(gtkconv->entry), "button_press_event", 4342 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "delete_range",
4441 G_CALLBACK(entry_stop_rclick_cb), NULL); 4343 G_CALLBACK(delete_text_cb), gtkconv);
4442 g_signal_connect(G_OBJECT(gtkconv->lower_hbox), "size-allocate", 4344 gtkconv->u.im->typing_timer = 0;
4443 G_CALLBACK(size_allocate_cb), gtkconv); 4345 gtkconv->u.im->animate = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/animate_buddy_icons");
4444 4346 gtkconv->u.im->show_icon = TRUE;
4445 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "insert_text", 4347 }
4446 G_CALLBACK(insert_text_cb), gtkconv); 4348
4447 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "delete_range",
4448 G_CALLBACK(delete_text_cb), gtkconv);
4449 g_signal_connect_swapped(G_OBJECT(gtkconv->entry_buffer), "changed", 4349 g_signal_connect_swapped(G_OBJECT(gtkconv->entry_buffer), "changed",
4450 G_CALLBACK(resize_imhtml_cb), gtkconv); 4350 G_CALLBACK(resize_imhtml_cb), gtkconv);
4451 4351
4452 /* had to move this after the imtoolbar is attached so that the
4453 * signals get fired to toggle the buttons on the toolbar as well.
4454 */
4455 default_formatize(gtkconv); 4352 default_formatize(gtkconv);
4456
4457 g_signal_connect_after(G_OBJECT(gtkconv->entry), "format_function_clear", 4353 g_signal_connect_after(G_OBJECT(gtkconv->entry), "format_function_clear",
4458 G_CALLBACK(clear_formatting_cb), gtkconv); 4354 G_CALLBACK(clear_formatting_cb), gtkconv);
4459 4355
4460 gtkconv->u.im->animate = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/animate_buddy_icons");
4461 gtkconv->u.im->show_icon = TRUE;
4462
4463 /*
4464 * Focus for IM windows should be as follows:
4465 * Tab title -> conversation scrollback -> entry
4466 */
4467 focus_chain = g_list_prepend(focus_chain, gtkconv->entry);
4468 gtk_container_set_focus_chain(GTK_CONTAINER(vbox2), focus_chain);
4469
4470 gtkconv->u.im->typing_timer = 0;
4471 return paned; 4356 return paned;
4472 } 4357 }
4473 4358
4474 static void 4359 static void
4475 conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, 4360 conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y,
4661 gtkconv->unseen_state = PIDGIN_UNSEEN_NONE; 4546 gtkconv->unseen_state = PIDGIN_UNSEEN_NONE;
4662 gtkconv->unseen_count = 0; 4547 gtkconv->unseen_count = 0;
4663 4548
4664 if (conv_type == PURPLE_CONV_TYPE_IM) { 4549 if (conv_type == PURPLE_CONV_TYPE_IM) {
4665 gtkconv->u.im = g_malloc0(sizeof(PidginImPane)); 4550 gtkconv->u.im = g_malloc0(sizeof(PidginImPane));
4666
4667 pane = setup_im_pane(gtkconv);
4668 } else if (conv_type == PURPLE_CONV_TYPE_CHAT) { 4551 } else if (conv_type == PURPLE_CONV_TYPE_CHAT) {
4669 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane)); 4552 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane));
4670 pane = setup_chat_pane(gtkconv); 4553 }
4671 } 4554 pane = setup_common_pane(gtkconv);
4672 4555
4673 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->imhtml), 4556 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->imhtml),
4674 gtk_imhtml_get_format_functions(GTK_IMHTML(gtkconv->imhtml)) | GTK_IMHTML_IMAGE); 4557 gtk_imhtml_get_format_functions(GTK_IMHTML(gtkconv->imhtml)) | GTK_IMHTML_IMAGE);
4675 4558
4676 if (pane == NULL) { 4559 if (pane == NULL) {
7971 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging), 7854 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging),
7972 purple_conversation_is_logging(conv)); 7855 purple_conversation_is_logging(conv));
7973 7856
7974 generate_send_to_items(win); 7857 generate_send_to_items(win);
7975 regenerate_options_items(win); 7858 regenerate_options_items(win);
7859 regenerate_plugins_items(win);
7976 7860
7977 pidgin_conv_switch_active_conversation(conv); 7861 pidgin_conv_switch_active_conversation(conv);
7978 7862
7979 sound_method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"); 7863 sound_method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method");
7980 if (strcmp(sound_method, "none") != 0) 7864 if (strcmp(sound_method, "none") != 0)
8041 offline_list = make_status_icon_list(PIDGIN_STOCK_STATUS_OFFLINE, w); 7925 offline_list = make_status_icon_list(PIDGIN_STOCK_STATUS_OFFLINE, w);
8042 away_list = make_status_icon_list(PIDGIN_STOCK_STATUS_AWAY, w); 7926 away_list = make_status_icon_list(PIDGIN_STOCK_STATUS_AWAY, w);
8043 prpl_lists = g_hash_table_new(g_str_hash, g_str_equal); 7927 prpl_lists = g_hash_table_new(g_str_hash, g_str_equal);
8044 } 7928 }
8045 7929
7930 static void
7931 plugin_changed_cb(PurplePlugin *p, gpointer data)
7932 {
7933 regenerate_plugins_items(data);
7934 }
7935
8046 PidginWindow * 7936 PidginWindow *
8047 pidgin_conv_window_new() 7937 pidgin_conv_window_new()
8048 { 7938 {
8049 PidginWindow *win; 7939 PidginWindow *win;
8050 GtkPositionType pos; 7940 GtkPositionType pos;
8114 gtk_box_pack_start(GTK_BOX(testidea), win->notebook, TRUE, TRUE, 0); 8004 gtk_box_pack_start(GTK_BOX(testidea), win->notebook, TRUE, TRUE, 0);
8115 8005
8116 gtk_container_add(GTK_CONTAINER(win->window), testidea); 8006 gtk_container_add(GTK_CONTAINER(win->window), testidea);
8117 8007
8118 gtk_widget_show(testidea); 8008 gtk_widget_show(testidea);
8009
8010 /* Update the plugin actions when plugins are (un)loaded */
8011 purple_signal_connect(purple_plugins_get_handle(), "plugin-load",
8012 win, PURPLE_CALLBACK(plugin_changed_cb), win);
8013 purple_signal_connect(purple_plugins_get_handle(), "plugin-unload",
8014 win, PURPLE_CALLBACK(plugin_changed_cb), win);
8015
8119 8016
8120 #ifdef _WIN32 8017 #ifdef _WIN32
8121 g_signal_connect(G_OBJECT(win->window), "show", 8018 g_signal_connect(G_OBJECT(win->window), "show",
8122 G_CALLBACK(winpidgin_ensure_onscreen), win->window); 8019 G_CALLBACK(winpidgin_ensure_onscreen), win->window);
8123 #endif 8020 #endif
8154 gtk_widget_destroy(win->window); 8051 gtk_widget_destroy(win->window);
8155 8052
8156 g_object_unref(G_OBJECT(win->menu.item_factory)); 8053 g_object_unref(G_OBJECT(win->menu.item_factory));
8157 8054
8158 purple_notify_close_with_handle(win); 8055 purple_notify_close_with_handle(win);
8056 purple_signals_disconnect_by_handle(win);
8159 8057
8160 g_free(win); 8058 g_free(win);
8161 } 8059 }
8162 8060
8163 void 8061 void

mercurial