Mercurial > pidgin
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 } |