comparison src/conversation.c @ 4469:d76095396a0e

[gaim-migrate @ 4744] Phase 2 of the conversation rewrite! Did you think I was done? Okay everybody, the prefs page was slightly redesigned. Not much, though. It needs an overhaul, and still, not everything works.. What we have now is: Conversations | |- IMs |- Chats `- Tabs But that's not the good part of this patch. Oh no, not close. You see, in Conversations, we now have a "Placement" drop-down box. Though this prefs page is ugly and will eventually be redesigned, this gives you the opportunity to set one of a number of different types of conversation placement options. The defaults are: - Last created window: Adds the new conversation to the last created window, like how things have been lately. - New window: Adds the new conversation to a brand new window, every time. Tabs are still there, so you can drag them between windows if you want to manually group them. - By group: This is my new favorite. This will put the new conversation in whatever window it finds first that has another member from that same group on your buddy list. If it doesn't find one, it creates a new window. If the person you IM'd or the person who IM'd you is not on your list, it gets put in a window with other people not on your list. These are the only ones implemented, but don't think you're limited to that. You see, we have new API functions for registering these Conversation Placement functions. All a plugin would need to do is to write a function, take into account OPT_CONVO_COMBINE (oh yeah, "Show IMs and chats in same tabbed window" works again), make sure the conversation is added _somewhere_, and then just register that function. If the plugin is loaded, the user can select it from the existing drop-down box. Cool, huh? Make sure to unregister the function when the plugin is unloaded. Have fun. committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Thu, 30 Jan 2003 09:22:15 +0000
parents 7d24d409d710
children c800ce24c571
comparison
equal deleted inserted replaced
4468:a046ff4793ca 4469:d76095396a0e
34 34
35 #ifdef _WIN32 35 #ifdef _WIN32
36 #include "win32dep.h" 36 #include "win32dep.h"
37 #endif 37 #endif
38 38
39 struct ConvPlacementData
40 {
41 char *name;
42 gaim_conv_placement_fnc fnc;
43
44 };
45
39 #define SEND_TYPED_TIMEOUT 5000 46 #define SEND_TYPED_TIMEOUT 5000
40 47
41 static GList *conversations = NULL; 48 static GList *conversations = NULL;
42 static GList *ims = NULL; 49 static GList *ims = NULL;
43 static GList *chats = NULL; 50 static GList *chats = NULL;
44 static GList *windows = NULL; 51 static GList *windows = NULL;
52 static GList *conv_placement_fncs = NULL;
53 static gaim_conv_placement_fnc place_conv = NULL;
54 static int place_conv_index = -1;
45 55
46 static gint 56 static gint
47 insertname_compare(gconstpointer one, gconstpointer two) 57 insertname_compare(gconstpointer one, gconstpointer two)
48 { 58 {
49 const char *a = (const char *)one; 59 const char *a = (const char *)one;
768 gaim_get_windows(void) 778 gaim_get_windows(void)
769 { 779 {
770 return windows; 780 return windows;
771 } 781 }
772 782
783 struct gaim_window *
784 gaim_get_first_window_with_type(GaimConversationType type)
785 {
786 GList *wins, *convs;
787 struct gaim_window *win;
788 struct gaim_conversation *conv;
789
790 if (type == GAIM_CONV_UNKNOWN)
791 return NULL;
792
793 for (wins = gaim_get_windows(); wins != NULL; wins = wins->next) {
794 win = (struct gaim_window *)wins->data;
795
796 for (convs = gaim_window_get_conversations(win);
797 convs != NULL;
798 convs = convs->next) {
799
800 conv = (struct gaim_conversation *)convs->data;
801
802 if (gaim_conversation_get_type(conv) == type)
803 return win;
804 }
805 }
806
807 return NULL;
808 }
809
810 struct gaim_window *
811 gaim_get_last_window_with_type(GaimConversationType type)
812 {
813 GList *wins, *convs;
814 struct gaim_window *win;
815 struct gaim_conversation *conv;
816
817 if (type == GAIM_CONV_UNKNOWN)
818 return NULL;
819
820 for (wins = g_list_last(gaim_get_windows());
821 wins != NULL;
822 wins = wins->prev) {
823
824 win = (struct gaim_window *)wins->data;
825
826 for (convs = gaim_window_get_conversations(win);
827 convs != NULL;
828 convs = convs->next) {
829
830 conv = (struct gaim_conversation *)convs->data;
831
832 if (gaim_conversation_get_type(conv) == type)
833 return win;
834 }
835 }
836
837 return NULL;
838 }
773 839
774 /************************************************************************** 840 /**************************************************************************
775 * Conversation API 841 * Conversation API
776 **************************************************************************/ 842 **************************************************************************/
777 struct gaim_conversation * 843 struct gaim_conversation *
778 gaim_conversation_new(GaimConversationType type, const char *name) 844 gaim_conversation_new(GaimConversationType type, const char *name)
779 { 845 {
780 struct gaim_conversation *conv; 846 struct gaim_conversation *conv;
781 struct gaim_window *window;
782 847
783 if (type == GAIM_CONV_UNKNOWN) 848 if (type == GAIM_CONV_UNKNOWN)
784 return NULL; 849 return NULL;
785 850
786 /* Check if this conversation already exists. */ 851 /* Check if this conversation already exists. */
828 893
829 /* 894 /*
830 * Create a window if one does not exist. If it does, use the last 895 * Create a window if one does not exist. If it does, use the last
831 * created window. 896 * created window.
832 */ 897 */
833 /* XXX */ 898 if (windows == NULL) {
834 #if 0 899 struct gaim_window *win;
835 if (windows == NULL || gaim_window_get_conversation_count(windows->data) == 2) 900
836 #endif 901 win = gaim_window_new();
837 if (windows == NULL) 902 gaim_window_add_conversation(win, conv);
838 window = gaim_window_new(); 903
839 else 904 /* Ensure the window is visible. */
840 window = g_list_last(windows)->data; 905 gaim_window_show(win);
841 906 }
842 gaim_window_add_conversation(window, conv); 907 else {
843 908 if (place_conv == NULL)
844 /* Ensure the window is visible. */ 909 gaim_conv_placement_set_active(0);
845 gaim_window_show(window); 910
911 place_conv(conv);
912 }
846 913
847 plugin_event(event_new_conversation, name); 914 plugin_event(event_new_conversation, name);
848 915
849 return conv; 916 return conv;
850 } 917 }
1944 return conv; 2011 return conv;
1945 } 2012 }
1946 2013
1947 return NULL; 2014 return NULL;
1948 } 2015 }
2016
2017 /**************************************************************************
2018 * Conversation placement functions
2019 **************************************************************************/
2020 /* This one places conversations in the last made window. */
2021 static void
2022 conv_placement_last_created_win(struct gaim_conversation *conv)
2023 {
2024 struct gaim_window *win;
2025
2026 if (convo_options & OPT_CONVO_COMBINE)
2027 win = g_list_last(gaim_get_windows())->data;
2028 else
2029 win = gaim_get_last_window_with_type(gaim_conversation_get_type(conv));
2030
2031 if (win == NULL) {
2032 win = gaim_window_new();
2033
2034 gaim_window_add_conversation(win, conv);
2035 gaim_window_show(win);
2036 }
2037 else
2038 gaim_window_add_conversation(win, conv);
2039 }
2040
2041 /* This one places each conversation in its own window. */
2042 static void
2043 conv_placement_new_window(struct gaim_conversation *conv)
2044 {
2045 struct gaim_window *win;
2046
2047 win = gaim_window_new();
2048
2049 gaim_window_add_conversation(win, conv);
2050
2051 gaim_window_show(win);
2052 }
2053
2054 /*
2055 * This groups things by, well, group. Buddies from groups will always be
2056 * grouped together, and a buddy from a group not belonging to any currently
2057 * open windows will get a new window.
2058 */
2059 static void
2060 conv_placement_by_group(struct gaim_conversation *conv)
2061 {
2062 struct gaim_window *win;
2063 GaimConversationType type;
2064
2065 type = gaim_conversation_get_type(conv);
2066
2067 if (type != GAIM_CONV_IM) {
2068 win = gaim_get_last_window_with_type(type);
2069
2070 if (win == NULL)
2071 conv_placement_new_window(conv);
2072 else
2073 gaim_window_add_conversation(win, conv);
2074 }
2075 else {
2076 struct buddy *b;
2077 struct group *grp = NULL;
2078 GList *wins, *convs;
2079
2080 b = find_buddy(gaim_conversation_get_user(conv),
2081 gaim_conversation_get_name(conv));
2082
2083 if (b != NULL)
2084 grp = find_group_by_buddy(b);
2085
2086 /* Go through the list of IMs and find one with this group. */
2087 for (wins = gaim_get_windows(); wins != NULL; wins = wins->next) {
2088 struct gaim_window *win2;
2089 struct gaim_conversation *conv2;
2090 struct buddy *b2;
2091 struct group *grp2 = NULL;
2092
2093 win2 = (struct gaim_window *)wins->data;
2094
2095 for (convs = gaim_window_get_conversations(win2);
2096 convs != NULL;
2097 convs = convs->next) {
2098
2099 conv2 = (struct gaim_conversation *)convs->data;
2100
2101 b2 = find_buddy(gaim_conversation_get_user(conv2),
2102 gaim_conversation_get_name(conv2));
2103
2104 if (b2 != NULL)
2105 grp2 = find_group_by_buddy(b2);
2106
2107 if ((grp == NULL && grp2 == NULL) ||
2108 (grp != NULL && grp2 != NULL &&
2109 !strncmp(grp2->name, grp->name, 80))) {
2110
2111 gaim_window_add_conversation(win2, conv);
2112
2113 return;
2114 }
2115 }
2116 }
2117
2118 /* Make a new window. */
2119 conv_placement_new_window(conv);
2120 }
2121 }
2122
2123 static int
2124 add_conv_placement_fnc(const char *name, gaim_conv_placement_fnc fnc)
2125 {
2126 struct ConvPlacementData *data;
2127
2128 data = g_malloc0(sizeof(struct ConvPlacementData));
2129
2130 data->name = g_strdup(name);
2131 data->fnc = fnc;
2132
2133 conv_placement_fncs = g_list_append(conv_placement_fncs, data);
2134
2135 return gaim_conv_placement_get_fnc_count() - 1;
2136 }
2137
2138 static void
2139 ensure_default_funcs(void)
2140 {
2141 if (conv_placement_fncs == NULL) {
2142 add_conv_placement_fnc(_("Last created window"),
2143 conv_placement_last_created_win);
2144 add_conv_placement_fnc(_("New window"),
2145 conv_placement_new_window);
2146 add_conv_placement_fnc(_("By group"),
2147 conv_placement_by_group);
2148 }
2149 }
2150
2151 int
2152 gaim_conv_placement_add_fnc(const char *name, gaim_conv_placement_fnc fnc)
2153 {
2154 if (name == NULL || fnc == NULL)
2155 return -1;
2156
2157 if (conv_placement_fncs == NULL)
2158 ensure_default_funcs();
2159
2160 return add_conv_placement_fnc(name, fnc);
2161 }
2162
2163 void
2164 gaim_conv_placement_remove_fnc(int index)
2165 {
2166 struct ConvPlacementData *data;
2167 GList *node;
2168
2169 if (index < 0 || index > g_list_length(conv_placement_fncs))
2170 return;
2171
2172 node = g_list_nth(conv_placement_fncs, index);
2173 data = (struct ConvPlacementData *)node->data;
2174
2175 g_free(data->name);
2176 g_free(data);
2177
2178 conv_placement_fncs = g_list_remove_link(conv_placement_fncs, node);
2179 g_list_free_1(node);
2180 }
2181
2182 int
2183 gaim_conv_placement_get_fnc_count(void)
2184 {
2185 ensure_default_funcs();
2186
2187 return g_list_length(conv_placement_fncs);
2188 }
2189
2190 const char *
2191 gaim_conv_placement_get_name(int index)
2192 {
2193 struct ConvPlacementData *data;
2194
2195 ensure_default_funcs();
2196
2197 if (index < 0 || index > g_list_length(conv_placement_fncs))
2198 return NULL;
2199
2200 data = g_list_nth_data(conv_placement_fncs, index);
2201
2202 if (data == NULL)
2203 return NULL;
2204
2205 return data->name;
2206 }
2207
2208 gaim_conv_placement_fnc
2209 gaim_conv_placement_get_fnc(int index)
2210 {
2211 struct ConvPlacementData *data;
2212
2213 ensure_default_funcs();
2214
2215 if (index < 0 || index > g_list_length(conv_placement_fncs))
2216 return NULL;
2217
2218 data = g_list_nth_data(conv_placement_fncs, index);
2219
2220 if (data == NULL)
2221 return NULL;
2222
2223 return data->fnc;
2224 }
2225
2226 int
2227 gaim_conv_placement_get_fnc_index(gaim_conv_placement_fnc fnc)
2228 {
2229 struct ConvPlacementData *data;
2230 GList *node;
2231 int i;
2232
2233 ensure_default_funcs();
2234
2235 for (node = conv_placement_fncs, i = 0;
2236 node != NULL;
2237 node = node->next, i++) {
2238
2239 data = (struct ConvPlacementData *)node->data;
2240
2241 if (data->fnc == fnc)
2242 return i;
2243 }
2244
2245 return -1;
2246 }
2247
2248 int
2249 gaim_conv_placement_get_active(void)
2250 {
2251 return place_conv_index;
2252 }
2253
2254 void
2255 gaim_conv_placement_set_active(int index)
2256 {
2257 gaim_conv_placement_fnc fnc;
2258
2259 ensure_default_funcs();
2260
2261 fnc = gaim_conv_placement_get_fnc(index);
2262
2263 if (fnc == NULL)
2264 return;
2265
2266 place_conv = fnc;
2267 place_conv_index = index;
2268 }