Mercurial > pidgin.yaz
comparison pidgin/gtkconv.c @ 20049:7af1af2b7ad3
propagate from branch 'im.pidgin.pidgin' (head 02b9fa9cd591c94c082a8ff02ea27fe33b278a0a)
to branch 'im.pidgin.sadrul.conv.persistent' (head f0287adbcd60b64f6209cc00141e15d1a67a4c7f)
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Sat, 15 Sep 2007 06:26:35 +0000 |
parents | a2b4eac83902 501c05b1e3e5 |
children | 20c336838629 |
comparison
equal
deleted
inserted
replaced
20044:4fdf9c1212e2 | 20049:7af1af2b7ad3 |
---|---|
67 #include "gtkutils.h" | 67 #include "gtkutils.h" |
68 #include "pidginstock.h" | 68 #include "pidginstock.h" |
69 | 69 |
70 #include "gtknickcolors.h" | 70 #include "gtknickcolors.h" |
71 | 71 |
72 #define CLOSE_CONV_TIMEOUT_SECS (10 * 60) | |
73 | |
72 #define AUTO_RESPONSE "<AUTO-REPLY> : " | 74 #define AUTO_RESPONSE "<AUTO-REPLY> : " |
73 | 75 |
74 typedef enum | 76 typedef enum |
75 { | 77 { |
76 PIDGIN_CONV_SET_TITLE = 1 << 0, | 78 PIDGIN_CONV_SET_TITLE = 1 << 0, |
120 } InviteBuddyInfo; | 122 } InviteBuddyInfo; |
121 | 123 |
122 static GtkWidget *invite_dialog = NULL; | 124 static GtkWidget *invite_dialog = NULL; |
123 static GtkWidget *warn_close_dialog = NULL; | 125 static GtkWidget *warn_close_dialog = NULL; |
124 | 126 |
125 static PidginWindow *hidden_convwin = NULL; | |
126 static GList *window_list = NULL; | 127 static GList *window_list = NULL; |
127 | 128 |
128 /* Lists of status icons at all available sizes for use as window icons */ | 129 /* Lists of status icons at all available sizes for use as window icons */ |
129 static GList *available_list = NULL; | 130 static GList *available_list = NULL; |
130 static GList *away_list = NULL; | 131 static GList *away_list = NULL; |
158 static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win); | 159 static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win); |
159 static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv); | 160 static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv); |
160 static gboolean infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *conv); | 161 static gboolean infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *conv); |
161 static gboolean pidgin_userlist_motion_cb (GtkWidget *w, GdkEventMotion *event, PidginConversation *gtkconv); | 162 static gboolean pidgin_userlist_motion_cb (GtkWidget *w, GdkEventMotion *event, PidginConversation *gtkconv); |
162 static void pidgin_conv_leave_cb (GtkWidget *w, GdkEventCrossing *e, PidginConversation *gtkconv); | 163 static void pidgin_conv_leave_cb (GtkWidget *w, GdkEventCrossing *e, PidginConversation *gtkconv); |
164 static void hide_conv(PidginConversation *gtkconv, gboolean closetimer); | |
163 | 165 |
164 static void pidgin_conv_set_position_size(PidginWindow *win, int x, int y, | 166 static void pidgin_conv_set_position_size(PidginWindow *win, int x, int y, |
165 int width, int height); | 167 int width, int height); |
166 | 168 |
167 static GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name) { | 169 static GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name) { |
205 /************************************************************************** | 207 /************************************************************************** |
206 * Callbacks | 208 * Callbacks |
207 **************************************************************************/ | 209 **************************************************************************/ |
208 | 210 |
209 static gboolean | 211 static gboolean |
210 close_conv_cb(GtkWidget *w, GdkEventButton *event, PidginConversation *gtkconv) | 212 close_this_sucker(gpointer data) |
211 { | 213 { |
214 PidginConversation *gtkconv = data; | |
212 GList *list = g_list_copy(gtkconv->convs); | 215 GList *list = g_list_copy(gtkconv->convs); |
213 | |
214 g_list_foreach(list, (GFunc)purple_conversation_destroy, NULL); | 216 g_list_foreach(list, (GFunc)purple_conversation_destroy, NULL); |
215 g_list_free(list); | 217 g_list_free(list); |
218 return FALSE; | |
219 } | |
220 | |
221 static gboolean | |
222 close_conv_cb(GtkWidget *w, GdkEventButton *event, PidginConversation *gtkconv) | |
223 { | |
224 /* We are going to destroy the conversations immediately only if the 'close immediately' | |
225 * preference is selected. Otherwise, close the conversation after a reasonable timeout | |
226 * (I am going to consider 10 minutes as a 'reasonable timeout' here. | |
227 * For chats, close immediately if the chat is not in the buddylist, or if the chat is | |
228 * not marked 'Persistent' */ | |
229 PurpleConversation *conv = gtkconv->active_conv; | |
230 PurpleAccount *account = purple_conversation_get_account(conv); | |
231 const char *name = purple_conversation_get_name(conv); | |
232 | |
233 switch (purple_conversation_get_type(conv)) { | |
234 case PURPLE_CONV_TYPE_IM: | |
235 { | |
236 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/close_immediately")) | |
237 close_this_sucker(gtkconv); | |
238 else | |
239 hide_conv(gtkconv, TRUE); | |
240 break; | |
241 } | |
242 case PURPLE_CONV_TYPE_CHAT: | |
243 { | |
244 PurpleChat *chat = purple_blist_find_chat(account, name); | |
245 if (!chat || | |
246 !purple_blist_node_get_bool(&chat->node, "gtk-persistent")) | |
247 close_this_sucker(gtkconv); | |
248 else | |
249 hide_conv(gtkconv, FALSE); | |
250 break; | |
251 } | |
252 default: | |
253 ; | |
254 } | |
216 | 255 |
217 return TRUE; | 256 return TRUE; |
218 } | 257 } |
219 | 258 |
220 static gboolean | 259 static gboolean |
1312 conv = pidgin_conv_window_get_active_conversation(win); | 1351 conv = pidgin_conv_window_get_active_conversation(win); |
1313 | 1352 |
1314 add_remove_cb(NULL, PIDGIN_CONVERSATION(conv)); | 1353 add_remove_cb(NULL, PIDGIN_CONVERSATION(conv)); |
1315 } | 1354 } |
1316 | 1355 |
1317 #if 0 | 1356 static gboolean |
1318 static void | 1357 close_already(gpointer data) |
1319 menu_hide_conv_cb(gpointer data, guint action, GtkWidget *widget) | 1358 { |
1320 { | 1359 purple_conversation_destroy(data); |
1321 PidginWindow *win = data; | 1360 return FALSE; |
1322 PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(win); | 1361 } |
1323 PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); | 1362 |
1363 static void | |
1364 hide_conv(PidginConversation *gtkconv, gboolean closetimer) | |
1365 { | |
1366 GList *list; | |
1367 | |
1324 purple_signal_emit(pidgin_conversations_get_handle(), | 1368 purple_signal_emit(pidgin_conversations_get_handle(), |
1325 "conversation-hiding", gtkconv); | 1369 "conversation-hiding", gtkconv); |
1326 purple_conversation_set_ui_ops(conv, NULL); | 1370 |
1327 } | 1371 for (list = g_list_copy(gtkconv->convs); list; list = g_list_delete_link(list, list)) { |
1328 #endif | 1372 PurpleConversation *conv = list->data; |
1373 if (closetimer) { | |
1374 guint timer = GPOINTER_TO_INT(purple_conversation_get_data(conv, "close-timer")); | |
1375 if (timer) | |
1376 purple_timeout_remove(timer); | |
1377 timer = purple_timeout_add_seconds(CLOSE_CONV_TIMEOUT_SECS, close_already, conv); | |
1378 purple_conversation_set_data(conv, "close-timer", GINT_TO_POINTER(timer)); | |
1379 } | |
1380 purple_conversation_set_ui_ops(conv, NULL); | |
1381 } | |
1382 } | |
1329 | 1383 |
1330 static void | 1384 static void |
1331 menu_close_conv_cb(gpointer data, guint action, GtkWidget *widget) | 1385 menu_close_conv_cb(gpointer data, guint action, GtkWidget *widget) |
1332 { | 1386 { |
1333 PidginWindow *win = data; | 1387 PidginWindow *win = data; |
2338 } | 2392 } |
2339 | 2393 |
2340 return get_prpl_icon_list(account); | 2394 return get_prpl_icon_list(account); |
2341 } | 2395 } |
2342 | 2396 |
2343 GdkPixbuf * | 2397 static GdkPixbuf * |
2344 pidgin_conv_get_tab_icon(PurpleConversation *conv, gboolean small_icon) | 2398 pidgin_conv_get_icon(PurpleConversation *conv, GtkWidget *parent, const char *icon_size) |
2345 { | 2399 { |
2346 PurpleAccount *account = NULL; | 2400 PurpleAccount *account = NULL; |
2347 const char *name = NULL; | 2401 const char *name = NULL; |
2348 GdkPixbuf *status = NULL; | 2402 GdkPixbuf *status = NULL; |
2349 PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); | 2403 PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); |
2350 const char *icon_size = small_icon ? PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC : PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL; | 2404 g_return_val_if_fail(conv != NULL, NULL); |
2351 g_return_val_if_fail(conv != NULL, NULL); | 2405 |
2352 | 2406 account = purple_conversation_get_account(conv); |
2353 account = purple_conversation_get_account(conv); | 2407 name = purple_conversation_get_name(conv); |
2354 name = purple_conversation_get_name(conv); | 2408 |
2355 | 2409 g_return_val_if_fail(account != NULL, NULL); |
2356 g_return_val_if_fail(account != NULL, NULL); | 2410 g_return_val_if_fail(name != NULL, NULL); |
2357 g_return_val_if_fail(name != NULL, NULL); | 2411 |
2358 | 2412 /* Use the buddy icon, if possible */ |
2359 /* Use the buddy icon, if possible */ | 2413 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { |
2360 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { | 2414 PurpleBuddy *b = purple_find_buddy(account, name); |
2361 PurpleBuddy *b = purple_find_buddy(account, name); | 2415 if (b != NULL) { |
2362 if (b != NULL) { | |
2363 PurplePresence *p = purple_buddy_get_presence(b); | 2416 PurplePresence *p = purple_buddy_get_presence(b); |
2364 /* I hate this hack. It fixes a bug where the pending message icon | 2417 /* I hate this hack. It fixes a bug where the pending message icon |
2365 * displays in the conv tab even though it shouldn't. | 2418 * displays in the conv tab even though it shouldn't. |
2366 * A better solution would be great. */ | 2419 * A better solution would be great. */ |
2367 if (ops && ops->update) | 2420 if (ops && ops->update) |
2368 ops->update(NULL, (PurpleBlistNode*)b); | 2421 ops->update(NULL, (PurpleBlistNode*)b); |
2369 | 2422 |
2370 /* XXX Seanegan: We really need a util function to return a pixbuf for a Presence to avoid all this switching */ | 2423 /* XXX Seanegan: We really need a util function to return a pixbuf for a Presence to avoid all this switching */ |
2371 if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AWAY)) | 2424 if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AWAY)) |
2372 status = pidgin_create_status_icon(PURPLE_STATUS_AWAY, PIDGIN_CONVERSATION(conv)->icon, icon_size); | 2425 status = pidgin_create_status_icon(PURPLE_STATUS_AWAY, parent, icon_size); |
2373 else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_EXTENDED_AWAY)) | 2426 else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_EXTENDED_AWAY)) |
2374 status = pidgin_create_status_icon(PURPLE_STATUS_EXTENDED_AWAY, PIDGIN_CONVERSATION(conv)->icon, icon_size); | 2427 status = pidgin_create_status_icon(PURPLE_STATUS_EXTENDED_AWAY, parent, icon_size); |
2375 else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_OFFLINE)) | 2428 else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_OFFLINE)) |
2376 status = pidgin_create_status_icon(PURPLE_STATUS_OFFLINE, PIDGIN_CONVERSATION(conv)->icon, icon_size); | 2429 status = pidgin_create_status_icon(PURPLE_STATUS_OFFLINE, parent, icon_size); |
2377 else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AVAILABLE)) | 2430 else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AVAILABLE)) |
2378 status = pidgin_create_status_icon(PURPLE_STATUS_AVAILABLE, PIDGIN_CONVERSATION(conv)->icon, icon_size); | 2431 status = pidgin_create_status_icon(PURPLE_STATUS_AVAILABLE, parent, icon_size); |
2379 else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_INVISIBLE)) | 2432 else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_INVISIBLE)) |
2380 status = pidgin_create_status_icon(PURPLE_STATUS_INVISIBLE, PIDGIN_CONVERSATION(conv)->icon, icon_size); | 2433 status = pidgin_create_status_icon(PURPLE_STATUS_INVISIBLE, parent, icon_size); |
2381 else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_UNAVAILABLE)) | 2434 else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_UNAVAILABLE)) |
2382 status = pidgin_create_status_icon(PURPLE_STATUS_UNAVAILABLE, PIDGIN_CONVERSATION(conv)->icon, icon_size); | 2435 status = pidgin_create_status_icon(PURPLE_STATUS_UNAVAILABLE, parent, icon_size); |
2383 } | 2436 } |
2384 } | 2437 } |
2385 | 2438 |
2386 /* If they don't have a buddy icon, then use the PRPL icon */ | 2439 /* If they don't have a buddy icon, then use the PRPL icon */ |
2387 if (status == NULL) { | 2440 if (status == NULL) { |
2388 GtkIconSize size = gtk_icon_size_from_name(icon_size); | 2441 GtkIconSize size = gtk_icon_size_from_name(icon_size); |
2389 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { | 2442 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { |
2390 status = gtk_widget_render_icon (PIDGIN_CONVERSATION(conv)->icon, PIDGIN_STOCK_STATUS_PERSON, | 2443 status = gtk_widget_render_icon (parent, PIDGIN_STOCK_STATUS_PERSON, |
2391 size, "GtkWidget"); | 2444 size, "GtkWidget"); |
2392 } else { | 2445 } else { |
2393 status = gtk_widget_render_icon (PIDGIN_CONVERSATION(conv)->icon, PIDGIN_STOCK_STATUS_CHAT, | 2446 status = gtk_widget_render_icon (parent, PIDGIN_STOCK_STATUS_CHAT, |
2394 size, "GtkWidget"); | 2447 size, "GtkWidget"); |
2395 } | 2448 } |
2396 } | 2449 } |
2397 return status; | 2450 return status; |
2451 } | |
2452 | |
2453 GdkPixbuf * | |
2454 pidgin_conv_get_tab_icon(PurpleConversation *conv, gboolean small_icon) | |
2455 { | |
2456 const char *icon_size = small_icon ? PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC : PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL; | |
2457 return pidgin_conv_get_icon(conv, PIDGIN_CONVERSATION(conv)->icon, icon_size); | |
2398 } | 2458 } |
2399 | 2459 |
2400 | 2460 |
2401 static void | 2461 static void |
2402 update_tab_icon(PurpleConversation *conv) | 2462 update_tab_icon(PurpleConversation *conv) |
2746 pidgin_conv_present_conversation(PurpleConversation *conv) | 2806 pidgin_conv_present_conversation(PurpleConversation *conv) |
2747 { | 2807 { |
2748 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); | 2808 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); |
2749 GdkModifierType state; | 2809 GdkModifierType state; |
2750 | 2810 |
2751 if(gtkconv->win==hidden_convwin) { | 2811 if (gtkconv == NULL) { |
2752 pidgin_conv_window_remove_gtkconv(hidden_convwin, gtkconv); | 2812 pidgin_conv_attach_to_conversation(conv); |
2753 pidgin_conv_placement_place(gtkconv); | 2813 gtkconv = PIDGIN_CONVERSATION(conv); |
2754 } | 2814 } |
2755 | 2815 |
2756 pidgin_conv_switch_active_conversation(conv); | 2816 pidgin_conv_switch_active_conversation(conv); |
2757 /* Switch the tab only if the user initiated the event by pressing | 2817 /* Switch the tab only if the user initiated the event by pressing |
2758 * a button or hitting a key. */ | 2818 * a button or hitting a key. */ |
2781 | 2841 |
2782 for (; l != NULL && (max_count == 0 || c < max_count); l = l->next) { | 2842 for (; l != NULL && (max_count == 0 || c < max_count); l = l->next) { |
2783 PurpleConversation *conv = (PurpleConversation*)l->data; | 2843 PurpleConversation *conv = (PurpleConversation*)l->data; |
2784 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); | 2844 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); |
2785 | 2845 |
2786 if(gtkconv == NULL || gtkconv->active_conv != conv) | 2846 if (gtkconv != NULL && gtkconv->active_conv != conv) |
2787 continue; | 2847 continue; |
2788 | 2848 if (gtkconv == NULL) { |
2789 if (gtkconv->unseen_state >= min_state | 2849 if (!hidden_only || |
2790 && (!hidden_only || | 2850 !purple_conversation_get_data(conv, "unseen-count")) |
2791 (hidden_only && gtkconv->win == hidden_convwin))) { | 2851 continue; |
2792 | |
2793 r = g_list_prepend(r, conv); | 2852 r = g_list_prepend(r, conv); |
2794 c++; | 2853 c++; |
2854 } else { | |
2855 if (gtkconv->unseen_state >= min_state && !hidden_only) { | |
2856 r = g_list_prepend(r, conv); | |
2857 c++; | |
2858 } | |
2795 } | 2859 } |
2796 } | 2860 } |
2797 | 2861 |
2798 return r; | 2862 return r; |
2799 } | 2863 } |
2829 for (l = convs; l != NULL ; l = l->next) { | 2893 for (l = convs; l != NULL ; l = l->next) { |
2830 PurpleConversation *conv = (PurpleConversation*)l->data; | 2894 PurpleConversation *conv = (PurpleConversation*)l->data; |
2831 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); | 2895 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); |
2832 | 2896 |
2833 GtkWidget *icon = gtk_image_new(); | 2897 GtkWidget *icon = gtk_image_new(); |
2834 GdkPixbuf *pbuf = pidgin_conv_get_tab_icon(conv, TRUE); | 2898 GdkPixbuf *pbuf = pidgin_conv_get_icon(conv, icon, PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC); |
2835 GtkWidget *item; | 2899 GtkWidget *item; |
2836 gchar *text = g_strdup_printf("%s (%d)", | 2900 gchar *text = g_strdup_printf("%s (%d)", |
2837 gtk_label_get_text(GTK_LABEL(gtkconv->tab_label)), | 2901 gtkconv ? gtk_label_get_text(GTK_LABEL(gtkconv->tab_label)) : purple_conversation_get_name(conv), |
2838 gtkconv->unseen_count); | 2902 gtkconv ? gtkconv->unseen_count : GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count"))); |
2839 | 2903 |
2840 gtk_image_set_from_pixbuf(GTK_IMAGE(icon), pbuf); | 2904 gtk_image_set_from_pixbuf(GTK_IMAGE(icon), pbuf); |
2841 g_object_unref(pbuf); | 2905 g_object_unref(pbuf); |
2842 | 2906 |
2843 item = gtk_image_menu_item_new_with_label(text); | 2907 item = gtk_image_menu_item_new_with_label(text); |
3091 GList *list; | 3155 GList *list; |
3092 PidginConversation *gtkconv; | 3156 PidginConversation *gtkconv; |
3093 PurpleConversation *conv; | 3157 PurpleConversation *conv; |
3094 GtkWidget *item; | 3158 GtkWidget *item; |
3095 | 3159 |
3096 if (win->window == NULL || win == hidden_convwin) | 3160 if (win->window == NULL) |
3097 return; | 3161 return; |
3098 | 3162 |
3099 gtkconv = pidgin_conv_window_get_active_gtkconv(win); | 3163 gtkconv = pidgin_conv_window_get_active_gtkconv(win); |
3100 if (gtkconv == NULL) | 3164 if (gtkconv == NULL) |
3101 return; | 3165 return; |
4940 PurpleConversationType conv_type = purple_conversation_get_type(conv); | 5004 PurpleConversationType conv_type = purple_conversation_get_type(conv); |
4941 GtkWidget *pane = NULL; | 5005 GtkWidget *pane = NULL; |
4942 GtkWidget *tab_cont; | 5006 GtkWidget *tab_cont; |
4943 PurpleBlistNode *convnode; | 5007 PurpleBlistNode *convnode; |
4944 | 5008 |
5009 if (hidden) | |
5010 return; | |
5011 | |
4945 if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) { | 5012 if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) { |
4946 conv->ui_data = gtkconv; | 5013 conv->ui_data = gtkconv; |
4947 if (!g_list_find(gtkconv->convs, conv)) | 5014 if (!g_list_find(gtkconv->convs, conv)) |
4948 gtkconv->convs = g_list_prepend(gtkconv->convs, conv); | 5015 gtkconv->convs = g_list_prepend(gtkconv->convs, conv); |
4949 pidgin_conv_switch_active_conversation(conv); | 5016 pidgin_conv_switch_active_conversation(conv); |
5039 | 5106 |
5040 g_signal_connect_swapped(G_OBJECT(pane), "focus", | 5107 g_signal_connect_swapped(G_OBJECT(pane), "focus", |
5041 G_CALLBACK(gtk_widget_grab_focus), | 5108 G_CALLBACK(gtk_widget_grab_focus), |
5042 gtkconv->entry); | 5109 gtkconv->entry); |
5043 | 5110 |
5044 if (hidden) | 5111 pidgin_conv_placement_place(gtkconv); |
5045 pidgin_conv_window_add_gtkconv(hidden_convwin, gtkconv); | |
5046 else | |
5047 pidgin_conv_placement_place(gtkconv); | |
5048 | 5112 |
5049 if (nick_colors == NULL) { | 5113 if (nick_colors == NULL) { |
5050 nbr_nick_colors = NUM_NICK_COLORS; | 5114 nbr_nick_colors = NUM_NICK_COLORS; |
5051 nick_colors = generate_nick_colors(&nbr_nick_colors, gtk_widget_get_style(gtkconv->imhtml)->base[GTK_STATE_NORMAL]); | 5115 nick_colors = generate_nick_colors(&nbr_nick_colors, gtk_widget_get_style(gtkconv->imhtml)->base[GTK_STATE_NORMAL]); |
5052 } | 5116 } |
5053 } | 5117 } |
5054 | 5118 |
5119 #if 0 | |
5055 static void | 5120 static void |
5056 pidgin_conv_new_hidden(PurpleConversation *conv) | 5121 pidgin_conv_new_hidden(PurpleConversation *conv) |
5057 { | 5122 { |
5058 private_gtkconv_new(conv, TRUE); | 5123 private_gtkconv_new(conv, TRUE); |
5059 } | 5124 } |
5125 #endif | |
5060 | 5126 |
5061 void | 5127 void |
5062 pidgin_conv_new(PurpleConversation *conv) | 5128 pidgin_conv_new(PurpleConversation *conv) |
5063 { | 5129 { |
5064 private_gtkconv_new(conv, FALSE); | 5130 private_gtkconv_new(conv, FALSE); |
5071 PurpleConversationUiOps *ui_ops = pidgin_conversations_get_conv_ui_ops(); | 5137 PurpleConversationUiOps *ui_ops = pidgin_conversations_get_conv_ui_ops(); |
5072 if (conv != NULL) | 5138 if (conv != NULL) |
5073 return; | 5139 return; |
5074 | 5140 |
5075 /* create hidden conv if hide_new pref is always */ | 5141 /* create hidden conv if hide_new pref is always */ |
5076 if (strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "always") == 0) | 5142 /* or if hide_new pref is away and account is away */ |
5077 { | 5143 if ((strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "always") == 0) || |
5078 ui_ops->create_conversation = pidgin_conv_new_hidden; | 5144 (strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "away") == 0 && |
5079 purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sender); | 5145 !purple_status_is_available(purple_account_get_active_status(account)))) { |
5080 ui_ops->create_conversation = pidgin_conv_new; | 5146 if (!conv) { |
5147 ui_ops->create_conversation = NULL; | |
5148 conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sender); | |
5149 purple_conversation_set_ui_ops(conv, NULL); | |
5150 ui_ops->create_conversation = pidgin_conv_new; | |
5151 } | |
5152 } else { | |
5153 /* new message for an IM */ | |
5154 if (conv && conv->type == PURPLE_CONV_TYPE_IM) | |
5155 pidgin_conv_attach_to_conversation(conv); | |
5156 } | |
5157 } | |
5158 | |
5159 static void | |
5160 pidgin_conv_destroy(PurpleConversation *conv) | |
5161 { | |
5162 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); | |
5163 | |
5164 if (!gtkconv) | |
5081 return; | 5165 return; |
5082 } | |
5083 | |
5084 /* create hidden conv if hide_new pref is away and account is away */ | |
5085 if (strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "away") == 0 && | |
5086 !purple_status_is_available(purple_account_get_active_status(account))) | |
5087 { | |
5088 ui_ops->create_conversation = pidgin_conv_new_hidden; | |
5089 purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sender); | |
5090 ui_ops->create_conversation = pidgin_conv_new; | |
5091 return; | |
5092 } | |
5093 } | |
5094 | |
5095 static void | |
5096 pidgin_conv_destroy(PurpleConversation *conv) | |
5097 { | |
5098 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); | |
5099 | 5166 |
5100 gtkconv->convs = g_list_remove(gtkconv->convs, conv); | 5167 gtkconv->convs = g_list_remove(gtkconv->convs, conv); |
5101 /* Don't destroy ourselves until all our convos are gone */ | 5168 /* Don't destroy ourselves until all our convos are gone */ |
5102 if (gtkconv->convs) { | 5169 if (gtkconv->convs) { |
5103 /* Make sure the destroyed conversation is not the active one */ | 5170 /* Make sure the destroyed conversation is not the active one */ |
6567 } | 6634 } |
6568 | 6635 |
6569 pidgin_conv_update_fields(conv, flags); | 6636 pidgin_conv_update_fields(conv, flags); |
6570 } | 6637 } |
6571 | 6638 |
6639 static void | |
6640 wrote_msg_update_unseen_cb(PurpleAccount *account, const char *who, const char *message, | |
6641 PurpleConversation *conv, PurpleMessageFlags flag, gpointer null) | |
6642 { | |
6643 if (conv == NULL || PIDGIN_IS_PIDGIN_CONVERSATION(conv)) | |
6644 return; | |
6645 if (flag & (PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_RECV)) { | |
6646 purple_conversation_set_data(conv, "unseen-count", | |
6647 GINT_TO_POINTER(GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count")) + 1)); | |
6648 purple_conversation_update(conv, PURPLE_CONV_UPDATE_UNSEEN); | |
6649 } | |
6650 } | |
6651 | |
6572 static PurpleConversationUiOps conversation_ui_ops = | 6652 static PurpleConversationUiOps conversation_ui_ops = |
6573 { | 6653 { |
6574 pidgin_conv_new, | 6654 pidgin_conv_new, |
6575 pidgin_conv_destroy, /* destroy_conversation */ | 6655 pidgin_conv_destroy, /* destroy_conversation */ |
6576 NULL, /* write_chat */ | 6656 NULL, /* write_chat */ |
7064 | 7144 |
7065 static void | 7145 static void |
7066 account_status_changed_cb(PurpleAccount *account, PurpleStatus *oldstatus, | 7146 account_status_changed_cb(PurpleAccount *account, PurpleStatus *oldstatus, |
7067 PurpleStatus *newstatus) | 7147 PurpleStatus *newstatus) |
7068 { | 7148 { |
7149 #if 0 | |
7069 GList *l; | 7150 GList *l; |
7070 PurpleConversation *conv = NULL; | 7151 PurpleConversation *conv = NULL; |
7071 PidginConversation *gtkconv; | 7152 PidginConversation *gtkconv; |
7072 | 7153 |
7073 if(strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "away")!=0) | 7154 if(strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "away")!=0) |
7074 return; | 7155 return; |
7075 | 7156 |
7076 if(purple_status_is_available(oldstatus) || !purple_status_is_available(newstatus)) | 7157 if(purple_status_is_available(oldstatus) || !purple_status_is_available(newstatus)) |
7077 return; | 7158 return; |
7078 | 7159 #endif |
7079 while ((l = hidden_convwin->gtkconvs) != NULL) | |
7080 { | |
7081 gtkconv = l->data; | |
7082 | |
7083 conv = gtkconv->active_conv; | |
7084 | |
7085 while(l && !purple_status_is_available( | |
7086 purple_account_get_active_status( | |
7087 purple_conversation_get_account(conv)))) | |
7088 l = l->next; | |
7089 if (!l) | |
7090 break; | |
7091 | |
7092 pidgin_conv_window_remove_gtkconv(hidden_convwin, gtkconv); | |
7093 pidgin_conv_placement_place(gtkconv); | |
7094 | |
7095 /* TODO: do we need to do anything for any other conversations that are in the same gtkconv here? | |
7096 * I'm a little concerned that not doing so will cause the "pending" indicator in the gtkblist not to be cleared. -DAA*/ | |
7097 purple_conversation_update(conv, PURPLE_CONV_UPDATE_UNSEEN); | |
7098 } | |
7099 } | 7160 } |
7100 | 7161 |
7101 static void | 7162 static void |
7102 hide_new_pref_cb(const char *name, PurplePrefType type, | 7163 hide_new_pref_cb(const char *name, PurplePrefType type, |
7103 gconstpointer value, gpointer data) | 7164 gconstpointer value, gpointer data) |
7104 { | 7165 { |
7105 GList *l; | 7166 GList *l; |
7106 PurpleConversation *conv = NULL; | |
7107 PidginConversation *gtkconv; | |
7108 gboolean when_away = FALSE; | 7167 gboolean when_away = FALSE; |
7109 | |
7110 if(!hidden_convwin) | |
7111 return; | |
7112 | 7168 |
7113 if(strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "always")==0) | 7169 if(strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "always")==0) |
7114 return; | 7170 return; |
7115 | 7171 |
7116 if(strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "away")==0) | 7172 if(strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "away")==0) |
7117 when_away = TRUE; | 7173 when_away = TRUE; |
7118 | 7174 |
7119 while ((l = hidden_convwin->gtkconvs) != NULL) | 7175 for (l = purple_get_conversations(); l; l = l->next) |
7120 { | 7176 { |
7121 gtkconv = l->data; | 7177 PurpleConversation *conv = l->data; |
7122 | 7178 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); |
7123 conv = gtkconv->active_conv; | 7179 if (gtkconv) |
7124 | 7180 continue; |
7125 if(when_away && !purple_status_is_available( | 7181 if(when_away && !purple_status_is_available( |
7126 purple_account_get_active_status( | 7182 purple_account_get_active_status( |
7127 purple_conversation_get_account(conv)))) | 7183 purple_conversation_get_account(conv)))) |
7128 continue; | 7184 continue; |
7129 | 7185 pidgin_conv_attach_to_conversation(conv); |
7130 pidgin_conv_window_remove_gtkconv(hidden_convwin, gtkconv); | |
7131 pidgin_conv_placement_place(gtkconv); | |
7132 } | 7186 } |
7133 } | 7187 } |
7134 | 7188 |
7135 | 7189 |
7136 static void | 7190 static void |
7312 int count = 0; | 7366 int count = 0; |
7313 int timer = gtkconv->attach.timer; | 7367 int timer = gtkconv->attach.timer; |
7314 gtkconv->attach.timer = 0; | 7368 gtkconv->attach.timer = 0; |
7315 while (gtkconv->attach.current && count < 100) { /* XXX: 100 is a random value here */ | 7369 while (gtkconv->attach.current && count < 100) { /* XXX: 100 is a random value here */ |
7316 PurpleConvMessage *msg = gtkconv->attach.current->data; | 7370 PurpleConvMessage *msg = gtkconv->attach.current->data; |
7371 if (gtkconv->attach.when && gtkconv->attach.when < msg->when) { | |
7372 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<HR>", 0); | |
7373 gtkconv->attach.when = 0; | |
7374 } | |
7317 pidgin_conv_write_conv(gtkconv->active_conv, msg->who, msg->who, msg->what, msg->flags, msg->when); | 7375 pidgin_conv_write_conv(gtkconv->active_conv, msg->who, msg->who, msg->what, msg->flags, msg->when); |
7318 gtkconv->attach.current = gtkconv->attach.current->prev; | 7376 gtkconv->attach.current = gtkconv->attach.current->prev; |
7319 count++; | 7377 count++; |
7320 } | 7378 } |
7321 gtkconv->attach.timer = timer; | 7379 gtkconv->attach.timer = timer; |
7331 | 7389 |
7332 gboolean pidgin_conv_attach_to_conversation(PurpleConversation *conv) | 7390 gboolean pidgin_conv_attach_to_conversation(PurpleConversation *conv) |
7333 { | 7391 { |
7334 GList *list; | 7392 GList *list; |
7335 PidginConversation *gtkconv; | 7393 PidginConversation *gtkconv; |
7394 int timer; | |
7336 | 7395 |
7337 if (PIDGIN_IS_PIDGIN_CONVERSATION(conv)) | 7396 if (PIDGIN_IS_PIDGIN_CONVERSATION(conv)) |
7338 return FALSE; | 7397 return FALSE; |
7339 | 7398 |
7399 purple_conversation_set_data(conv, "unseen-count", NULL); | |
7340 purple_conversation_set_ui_ops(conv, pidgin_conversations_get_conv_ui_ops()); | 7400 purple_conversation_set_ui_ops(conv, pidgin_conversations_get_conv_ui_ops()); |
7341 private_gtkconv_new(conv, FALSE); | 7401 private_gtkconv_new(conv, FALSE); |
7342 gtkconv = PIDGIN_CONVERSATION(conv); | 7402 gtkconv = PIDGIN_CONVERSATION(conv); |
7343 | 7403 |
7344 list = purple_conversation_get_message_history(conv); | 7404 list = purple_conversation_get_message_history(conv); |
7345 if (list) { | 7405 if (list) { |
7346 list = g_list_last(list); | 7406 gtkconv->attach.when = ((PurpleConvMessage*)(list->data))->when; |
7347 gtkconv->attach.current = list; | 7407 gtkconv->attach.current = g_list_last(list); |
7348 gtkconv->attach.timer = g_idle_add(add_message_history_to_gtkconv, gtkconv); | 7408 gtkconv->attach.timer = g_idle_add(add_message_history_to_gtkconv, gtkconv); |
7349 } else { | 7409 } else { |
7350 purple_signal_emit(pidgin_conversations_get_handle(), | 7410 purple_signal_emit(pidgin_conversations_get_handle(), |
7351 "conversation-displayed", gtkconv); | 7411 "conversation-displayed", gtkconv); |
7352 } | 7412 } |
7353 | 7413 |
7354 if (conv->type == PURPLE_CONV_TYPE_CHAT) { | 7414 if (conv->type == PURPLE_CONV_TYPE_CHAT) { |
7355 pidgin_conv_update_fields(conv, PIDGIN_CONV_TOPIC); | 7415 pidgin_conv_update_fields(conv, PIDGIN_CONV_TOPIC); |
7356 pidgin_conv_chat_add_users(conv, PURPLE_CONV_CHAT(conv)->in_room, TRUE); | 7416 pidgin_conv_chat_add_users(conv, PURPLE_CONV_CHAT(conv)->in_room, TRUE); |
7357 } | 7417 } |
7418 | |
7419 timer = GPOINTER_TO_INT(purple_conversation_get_data(conv, "close-timer")); | |
7420 if (timer) | |
7421 purple_timeout_remove(timer); | |
7358 | 7422 |
7359 return TRUE; | 7423 return TRUE; |
7360 } | 7424 } |
7361 | 7425 |
7362 void * | 7426 void * |
7419 | 7483 |
7420 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height", 54); | 7484 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height", 54); |
7421 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons", TRUE); | 7485 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons", TRUE); |
7422 | 7486 |
7423 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new", "never"); | 7487 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new", "never"); |
7488 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/im/close_immediately", FALSE); | |
7424 | 7489 |
7425 #ifdef _WIN32 | 7490 #ifdef _WIN32 |
7426 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/win32/minimize_new_convs", FALSE); | 7491 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/win32/minimize_new_convs", FALSE); |
7427 #endif | 7492 #endif |
7428 | 7493 |
7581 | 7646 |
7582 purple_signal_connect(purple_conversations_get_handle(), "received-im-msg", | 7647 purple_signal_connect(purple_conversations_get_handle(), "received-im-msg", |
7583 handle, G_CALLBACK(received_im_msg_cb), NULL); | 7648 handle, G_CALLBACK(received_im_msg_cb), NULL); |
7584 | 7649 |
7585 purple_conversations_set_ui_ops(&conversation_ui_ops); | 7650 purple_conversations_set_ui_ops(&conversation_ui_ops); |
7586 | |
7587 hidden_convwin = pidgin_conv_window_new(); | |
7588 window_list = g_list_remove(window_list, hidden_convwin); | |
7589 | 7651 |
7590 purple_signal_connect(purple_accounts_get_handle(), "account-status-changed", | 7652 purple_signal_connect(purple_accounts_get_handle(), "account-status-changed", |
7591 handle, PURPLE_CALLBACK(account_status_changed_cb), NULL); | 7653 handle, PURPLE_CALLBACK(account_status_changed_cb), NULL); |
7592 | 7654 |
7593 /* Callbacks to update a conversation */ | 7655 /* Callbacks to update a conversation */ |
7620 purple_signal_connect(purple_conversations_get_handle(), "chat-topic-changed", handle, | 7682 purple_signal_connect(purple_conversations_get_handle(), "chat-topic-changed", handle, |
7621 PURPLE_CALLBACK(update_chat_topic), NULL); | 7683 PURPLE_CALLBACK(update_chat_topic), NULL); |
7622 purple_signal_connect_priority(purple_conversations_get_handle(), "conversation-updated", handle, | 7684 purple_signal_connect_priority(purple_conversations_get_handle(), "conversation-updated", handle, |
7623 PURPLE_CALLBACK(pidgin_conv_updated), NULL, | 7685 PURPLE_CALLBACK(pidgin_conv_updated), NULL, |
7624 PURPLE_SIGNAL_PRIORITY_LOWEST); | 7686 PURPLE_SIGNAL_PRIORITY_LOWEST); |
7687 purple_signal_connect(purple_conversations_get_handle(), "wrote-im-msg", handle, | |
7688 PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL); | |
7689 purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", handle, | |
7690 PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL); | |
7625 } | 7691 } |
7626 | 7692 |
7627 void | 7693 void |
7628 pidgin_conversations_uninit(void) | 7694 pidgin_conversations_uninit(void) |
7629 { | 7695 { |
7630 purple_prefs_disconnect_by_handle(pidgin_conversations_get_handle()); | 7696 purple_prefs_disconnect_by_handle(pidgin_conversations_get_handle()); |
7631 purple_signals_disconnect_by_handle(pidgin_conversations_get_handle()); | 7697 purple_signals_disconnect_by_handle(pidgin_conversations_get_handle()); |
7632 purple_signals_unregister_by_instance(pidgin_conversations_get_handle()); | 7698 purple_signals_unregister_by_instance(pidgin_conversations_get_handle()); |
7633 pidgin_conv_window_destroy(hidden_convwin); | |
7634 hidden_convwin=NULL; | |
7635 } | 7699 } |
7636 | 7700 |
7637 | 7701 |
7638 | 7702 |
7639 | 7703 |
9046 0, 0, NULL, NULL, gtkconv); | 9110 0, 0, NULL, NULL, gtkconv); |
9047 | 9111 |
9048 if (win->gtkconvs && win->gtkconvs->next == NULL) | 9112 if (win->gtkconvs && win->gtkconvs->next == NULL) |
9049 pidgin_conv_tab_pack(win, win->gtkconvs->data); | 9113 pidgin_conv_tab_pack(win, win->gtkconvs->data); |
9050 | 9114 |
9051 if (!win->gtkconvs && win != hidden_convwin) | 9115 if (!win->gtkconvs) |
9052 pidgin_conv_window_destroy(win); | 9116 pidgin_conv_window_destroy(win); |
9053 } | 9117 } |
9054 | 9118 |
9055 PidginConversation * | 9119 PidginConversation * |
9056 pidgin_conv_window_get_gtkconv_at_index(const PidginWindow *win, int index) | 9120 pidgin_conv_window_get_gtkconv_at_index(const PidginWindow *win, int index) |
9585 } | 9649 } |
9586 | 9650 |
9587 gboolean | 9651 gboolean |
9588 pidgin_conv_is_hidden(PidginConversation *gtkconv) | 9652 pidgin_conv_is_hidden(PidginConversation *gtkconv) |
9589 { | 9653 { |
9590 g_return_val_if_fail(gtkconv != NULL, FALSE); | 9654 return (gtkconv == NULL); |
9591 | |
9592 return (gtkconv->win == hidden_convwin); | |
9593 } | 9655 } |
9594 | 9656 |
9595 | 9657 |
9596 /* Algorithm from http://www.w3.org/TR/AERT#color-contrast */ | 9658 /* Algorithm from http://www.w3.org/TR/AERT#color-contrast */ |
9597 static gboolean | 9659 static gboolean |
9688 *color_count = i; | 9750 *color_count = i; |
9689 } | 9751 } |
9690 | 9752 |
9691 return colors; | 9753 return colors; |
9692 } | 9754 } |
9755 |