Mercurial > pidgin.yaz
annotate src/gtkblist.c @ 12115:e9790eb93216
[gaim-migrate @ 14415]
quoth charkins:
" This patch has a few small fixes for the visibility
stuff in gtkblist.c.
First, tracking of the ICONIFIED state of the blist was
removed. This was intended to allow the blist to
"remember" if it was minimized between restarts.
Unfortunately, this is not possible because the
ICONIFIED state gets set when the blist is on a
different desktop with many window managers.
Second, while talking about the ICONIFIED issue on
#gtk@GIMPNet, muntyan_ asked about a bug where the
blist would get shown on an account re-connect with
1.5.0. Luke mentioned something about this with cvs as
well. This patch introduces a check in
gaim_gtk_blist_show() to prevent the window from being
shown if it already exists and is visible.
Third, sadrul pointed me to a one-line fix for the
missing blist on startup. I added a second line to make
sure the blist restores its proper size as well.
Finally, when the last visibility manager is removed,
gaim will now minimize the blist if it was previously
hidden, rather than showing it. This could prevent a
race condition with out-of-process applets, preventing
gaim from maintaining the visibility state properly
between restarts.
This was 'cvs diff'ed against the last available anon
cvs from Friday. Hopefully it'll apply cleanly."
it did.
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Wed, 16 Nov 2005 17:55:26 +0000 |
parents | 46fcc0765187 |
children | e75ef7aa913e |
rev | line source |
---|---|
5228 | 1 /* |
10297
ec140184437b
[gaim-migrate @ 11480]
Luke Schierer <lschiere@pidgin.im>
parents:
10288
diff
changeset
|
2 * @file gtkblist.c GTK+ BuddyList API |
ec140184437b
[gaim-migrate @ 11480]
Luke Schierer <lschiere@pidgin.im>
parents:
10288
diff
changeset
|
3 * @ingroup gtkui |
ec140184437b
[gaim-migrate @ 11480]
Luke Schierer <lschiere@pidgin.im>
parents:
10288
diff
changeset
|
4 * |
5228 | 5 * gaim |
6 * | |
8046 | 7 * Gaim is the legal property of its developers, whose names are too numerous |
8 * to list here. Please refer to the COPYRIGHT file distributed with this | |
9 * source distribution. | |
5228 | 10 * |
11 * This program is free software; you can redistribute it and/or modify | |
12 * it under the terms of the GNU General Public License as published by | |
13 * the Free Software Foundation; either version 2 of the License, or | |
14 * (at your option) any later version. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU General Public License | |
22 * along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
24 * | |
25 */ | |
9791 | 26 #include "internal.h" |
27 #include "gtkgaim.h" | |
7620 | 28 |
29 #include "account.h" | |
9015 | 30 #include "connection.h" |
7620 | 31 #include "core.h" |
32 #include "debug.h" | |
33 #include "notify.h" | |
34 #include "prpl.h" | |
35 #include "prefs.h" | |
8986 | 36 #include "plugin.h" |
7620 | 37 #include "request.h" |
38 #include "signals.h" | |
10297
ec140184437b
[gaim-migrate @ 11480]
Luke Schierer <lschiere@pidgin.im>
parents:
10288
diff
changeset
|
39 #include "gtkstock.h" |
7620 | 40 #include "util.h" |
41 | |
42 #include "gtkaccount.h" | |
43 #include "gtkblist.h" | |
44 #include "gtkconv.h" | |
45 #include "gtkdebug.h" | |
9709 | 46 #include "gtkdialogs.h" |
7620 | 47 #include "gtkft.h" |
48 #include "gtklog.h" | |
49 #include "gtkpounce.h" | |
11740 | 50 #include "gtkplugin.h" |
7620 | 51 #include "gtkprefs.h" |
52 #include "gtkprivacy.h" | |
8113 | 53 #include "gtkroomlist.h" |
10643 | 54 #include "gtkstatusbox.h" |
7620 | 55 #include "gtkutils.h" |
56 | |
5228 | 57 #include <gdk/gdkkeysyms.h> |
58 #include <gtk/gtk.h> | |
7620 | 59 #include <gdk/gdk.h> |
60 | |
61 typedef struct | |
62 { | |
63 GaimAccount *account; | |
64 | |
65 GtkWidget *window; | |
66 GtkWidget *combo; | |
67 GtkWidget *entry; | |
68 GtkWidget *entry_for_alias; | |
69 GtkWidget *account_box; | |
70 | |
71 } GaimGtkAddBuddyData; | |
72 | |
73 typedef struct | |
74 { | |
9811 | 75 GaimAccount *account; |
9812 | 76 gchar *default_chat_name; |
9811 | 77 |
78 GtkWidget *window; | |
7620 | 79 GtkWidget *account_menu; |
80 GtkWidget *alias_entry; | |
81 GtkWidget *group_combo; | |
82 GtkWidget *entries_box; | |
83 GtkSizeGroup *sg; | |
84 | |
85 GList *entries; | |
86 | |
87 } GaimGtkAddChatData; | |
88 | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
89 typedef struct |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
90 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
91 GaimAccount *account; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
92 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
93 GtkWidget *window; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
94 GtkWidget *account_menu; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
95 GtkWidget *entries_box; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
96 GtkSizeGroup *sg; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
97 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
98 GList *entries; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
99 } GaimGtkJoinChatData; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
100 |
7620 | 101 |
9949 | 102 static GtkWidget *protomenu = NULL; |
5228 | 103 |
12016
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
104 static guint visibility_manager_count = 0; |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
105 static gboolean gtk_blist_obscured = FALSE; |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
106 |
11796 | 107 static GList *gaim_gtk_blist_sort_methods = NULL; |
5422 | 108 static struct gaim_gtk_blist_sort_method *current_sort_method = NULL; |
7620 | 109 static GtkTreeIter sort_method_none(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur); |
110 | |
111 /* The functions we use for sorting aren't available in gtk 2.0.x, and | |
112 * segfault in 2.2.0. 2.2.1 is known to work, so I'll require that */ | |
113 #if GTK_CHECK_VERSION(2,2,1) | |
114 static GtkTreeIter sort_method_alphabetical(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur); | |
115 static GtkTreeIter sort_method_status(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur); | |
116 static GtkTreeIter sort_method_log(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur); | |
117 #endif | |
118 static GaimGtkBuddyList *gtkblist = NULL; | |
5228 | 119 |
120 static void gaim_gtk_blist_selection_changed(GtkTreeSelection *selection, gpointer data); | |
7620 | 121 static void gaim_gtk_blist_update(GaimBuddyList *list, GaimBlistNode *node); |
5234 | 122 static char *gaim_get_tooltip_text(GaimBlistNode *node); |
5228 | 123 static char *item_factory_translate_func (const char *path, gpointer func_data); |
5273 | 124 static gboolean get_iter_from_node(GaimBlistNode *node, GtkTreeIter *iter); |
7620 | 125 static void redo_buddy_list(GaimBuddyList *list, gboolean remove); |
126 static void gaim_gtk_blist_collapse_contact_cb(GtkWidget *w, GaimBlistNode *node); | |
127 | |
11059
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
128 static void gaim_gtk_blist_tooltip_destroy(); |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
129 |
5256 | 130 struct _gaim_gtk_blist_node { |
131 GtkTreeRowReference *row; | |
7620 | 132 gboolean contact_expanded; |
11910 | 133 gboolean recent_signonoff; |
134 gint recent_signonoff_timer; | |
5256 | 135 }; |
136 | |
10968
e0d5038fbb7e
[gaim-migrate @ 12789]
Christopher O'Brien <siege@pidgin.im>
parents:
10924
diff
changeset
|
137 |
10118 | 138 static char dim_grey_string[8] = ""; |
10144 | 139 static char *dim_grey() |
10118 | 140 { |
141 if (!gtkblist) | |
142 return "dim grey"; | |
143 if (!dim_grey_string[0]) { | |
144 GtkStyle *style = gtk_widget_get_style(gtkblist->treeview); | |
145 snprintf(dim_grey_string, sizeof(dim_grey_string), "#%02x%02x%02x", | |
146 style->text_aa[GTK_STATE_NORMAL].red >> 8, | |
147 style->text_aa[GTK_STATE_NORMAL].green >> 8, | |
148 style->text_aa[GTK_STATE_NORMAL].blue >> 8); | |
149 } | |
150 return dim_grey_string; | |
151 } | |
10144 | 152 |
5228 | 153 /*************************************************** |
154 * Callbacks * | |
155 ***************************************************/ | |
12016
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
156 static gboolean gtk_blist_visibility_cb(GtkWidget *w, GdkEventVisibility *event, gpointer data) |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
157 { |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
158 if (event->state == GDK_VISIBILITY_FULLY_OBSCURED) |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
159 gtk_blist_obscured = TRUE; |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
160 else |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
161 gtk_blist_obscured = FALSE; |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
162 |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
163 /* continue to handle event normally */ |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
164 return FALSE; |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
165 } |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
166 |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
167 static gboolean gtk_blist_window_state_cb(GtkWidget *w, GdkEventWindowState *event, gpointer data) |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
168 { |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
169 if(event->changed_mask & GDK_WINDOW_STATE_WITHDRAWN) { |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
170 if(event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
171 gaim_prefs_set_bool("/gaim/gtk/blist/list_visible", FALSE); |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
172 else |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
173 gaim_prefs_set_bool("/gaim/gtk/blist/list_visible", TRUE); |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
174 } |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
175 |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
176 return FALSE; |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
177 } |
5228 | 178 |
179 static gboolean gtk_blist_delete_cb(GtkWidget *w, GdkEventAny *event, gpointer data) | |
180 { | |
12016
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
181 if(visibility_manager_count) |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
182 gaim_blist_set_visible(FALSE); |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
183 else |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
184 gaim_core_quit(); |
5228 | 185 |
186 /* we handle everything, event should not propogate further */ | |
187 return TRUE; | |
188 } | |
189 | |
190 static gboolean gtk_blist_configure_cb(GtkWidget *w, GdkEventConfigure *event, gpointer data) | |
191 { | |
192 /* unfortunately GdkEventConfigure ignores the window gravity, but * | |
193 * the only way we have of setting the position doesn't. we have to * | |
7620 | 194 * call get_position because it does pay attention to the gravity. * |
195 * this is inefficient and I agree it sucks, but it's more likely * | |
196 * to work correctly. - Robot101 */ | |
5228 | 197 gint x, y; |
198 | |
199 /* check for visibility because when we aren't visible, this will * | |
200 * give us bogus (0,0) coordinates. - xOr */ | |
7620 | 201 if (GTK_WIDGET_VISIBLE(w)) |
5228 | 202 gtk_window_get_position(GTK_WINDOW(w), &x, &y); |
7620 | 203 else |
204 return FALSE; /* carry on normally */ | |
205 | |
206 /* don't save if nothing changed */ | |
207 if (x == gaim_prefs_get_int("/gaim/gtk/blist/x") && | |
208 y == gaim_prefs_get_int("/gaim/gtk/blist/y") && | |
209 event->width == gaim_prefs_get_int("/gaim/gtk/blist/width") && | |
210 event->height == gaim_prefs_get_int("/gaim/gtk/blist/height")) { | |
211 | |
212 return FALSE; /* carry on normally */ | |
5228 | 213 } |
214 | |
7620 | 215 /* don't save off-screen positioning */ |
216 if (x + event->width < 0 || | |
9811 | 217 y + event->height < 0 || |
218 x > gdk_screen_width() || | |
219 y > gdk_screen_height()) { | |
7620 | 220 |
221 return FALSE; /* carry on normally */ | |
222 } | |
223 | |
224 /* store the position */ | |
225 gaim_prefs_set_int("/gaim/gtk/blist/x", x); | |
226 gaim_prefs_set_int("/gaim/gtk/blist/y", y); | |
227 gaim_prefs_set_int("/gaim/gtk/blist/width", event->width); | |
228 gaim_prefs_set_int("/gaim/gtk/blist/height", event->height); | |
229 | |
5228 | 230 /* continue to handle event normally */ |
231 return FALSE; | |
232 } | |
233 | |
7620 | 234 static void gtk_blist_menu_info_cb(GtkWidget *w, GaimBuddy *b) |
5228 | 235 { |
236 serv_get_info(b->account->gc, b->name); | |
237 } | |
238 | |
7620 | 239 static void gtk_blist_menu_im_cb(GtkWidget *w, GaimBuddy *b) |
5228 | 240 { |
9728 | 241 gaim_gtkdialogs_im_with_user(b->account, b->name); |
5228 | 242 } |
243 | |
9466 | 244 static void gtk_blist_menu_send_file_cb(GtkWidget *w, GaimBuddy *b) |
245 { | |
246 serv_send_file(b->account->gc, b->name, NULL); | |
247 } | |
248 | |
12024 | 249 static void gtk_blist_menu_voice_chat_cb(GtkWidget *w, GaimBuddy *b) |
250 { | |
251 serv_voice_chat(b->account->gc, b->name); | |
252 } | |
253 | |
7620 | 254 static void gtk_blist_menu_autojoin_cb(GtkWidget *w, GaimChat *chat) |
255 { | |
7693 | 256 gaim_blist_node_set_bool((GaimBlistNode*)chat, "gtk-autojoin", |
257 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))); | |
7620 | 258 } |
259 | |
260 static void gtk_blist_menu_join_cb(GtkWidget *w, GaimChat *chat) | |
5228 | 261 { |
5234 | 262 serv_join_chat(chat->account->gc, chat->components); |
263 } | |
264 | |
11016 | 265 static void gtk_blist_renderer_edited_cb(GtkCellRendererText *text_rend, char *arg1, |
266 char *arg2, gpointer nada) | |
267 { | |
268 GtkTreeIter iter; | |
269 GtkTreePath *path; | |
270 GValue val = {0,}; | |
271 GaimBlistNode *node; | |
272 | |
273 path = gtk_tree_path_new_from_string (arg1); | |
274 gtk_tree_model_get_iter (GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); | |
275 gtk_tree_path_free (path); | |
276 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
277 node = g_value_get_pointer(&val); | |
278 gtk_tree_view_set_enable_search (GTK_TREE_VIEW(gtkblist->treeview), TRUE); | |
279 g_object_set(G_OBJECT(gtkblist->text_rend), "editable", FALSE, NULL); | |
280 switch (node->type){ | |
281 case GAIM_BLIST_CONTACT_NODE: | |
282 gaim_blist_alias_buddy(gaim_contact_get_priority_buddy((GaimContact*)node), arg2); | |
283 break; | |
284 case GAIM_BLIST_BUDDY_NODE: | |
285 gaim_blist_alias_buddy((GaimBuddy*)node, arg2); | |
286 break; | |
287 case GAIM_BLIST_GROUP_NODE: | |
288 gaim_blist_rename_group((GaimGroup*)node, arg2); | |
289 break; | |
290 case GAIM_BLIST_CHAT_NODE: | |
291 gaim_blist_alias_chat((GaimChat*)node, arg2); | |
292 break; | |
293 default: | |
294 break; | |
295 } | |
296 } | |
297 | |
5234 | 298 static void gtk_blist_menu_alias_cb(GtkWidget *w, GaimBlistNode *node) |
299 { | |
11016 | 300 GtkTreeIter iter; |
301 GtkTreePath *path; | |
11258 | 302 const char *text = NULL; |
11494 | 303 |
11258 | 304 if (!(get_iter_from_node(node, &iter))) { |
11016 | 305 /* This is either a bug, or the buddy is in a collapsed contact */ |
306 node = node->parent; | |
307 if (!get_iter_from_node(node, &iter)) | |
308 /* Now it's definitely a bug */ | |
309 return; | |
310 } | |
11258 | 311 |
312 switch (node->type) { | |
313 case GAIM_BLIST_BUDDY_NODE: | |
314 text = gaim_buddy_get_alias((GaimBuddy *)node); | |
315 break; | |
316 case GAIM_BLIST_CONTACT_NODE: | |
317 text = gaim_buddy_get_alias(gaim_contact_get_priority_buddy((GaimContact *)node)); | |
318 break; | |
319 case GAIM_BLIST_GROUP_NODE: | |
320 text = ((GaimGroup *)node)->name; | |
321 break; | |
322 case GAIM_BLIST_CHAT_NODE: | |
323 text = gaim_chat_get_name((GaimChat *)node); | |
324 break; | |
325 default: | |
326 g_return_if_reached(); | |
327 } | |
328 | |
329 gtk_tree_store_set(gtkblist->treemodel, &iter, NAME_COLUMN, text, -1); | |
330 | |
11016 | 331 path = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); |
332 g_object_set(G_OBJECT(gtkblist->text_rend), "editable", TRUE, NULL); | |
333 gtk_tree_view_set_enable_search (GTK_TREE_VIEW(gtkblist->treeview), FALSE); | |
334 gtk_widget_grab_focus(gtkblist->treeview); | |
335 gtk_tree_view_set_cursor(GTK_TREE_VIEW(gtkblist->treeview), path, gtkblist->text_column, TRUE); | |
336 gtk_tree_path_free(path); | |
5228 | 337 } |
338 | |
7620 | 339 static void gtk_blist_menu_bp_cb(GtkWidget *w, GaimBuddy *b) |
5228 | 340 { |
7620 | 341 gaim_gtkpounce_dialog_show(b->account, b->name, NULL); |
5228 | 342 } |
343 | |
9917 | 344 static void gtk_blist_menu_showlog_cb(GtkWidget *w, GaimBlistNode *node) |
5228 | 345 { |
9917 | 346 GaimLogType type; |
347 GaimAccount *account; | |
348 char *name = NULL; | |
10663 | 349 |
9917 | 350 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { |
351 GaimBuddy *b = (GaimBuddy*) node; | |
352 type = GAIM_LOG_IM; | |
353 name = g_strdup(b->name); | |
354 account = b->account; | |
355 } else if (GAIM_BLIST_NODE_IS_CHAT(node)) { | |
356 GaimChat *c = (GaimChat*) node; | |
357 GaimPluginProtocolInfo *prpl_info = NULL; | |
358 type = GAIM_LOG_CHAT; | |
359 account = c->account; | |
360 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gaim_find_prpl(gaim_account_get_protocol_id(account))); | |
361 if (prpl_info && prpl_info->get_chat_name) { | |
362 name = prpl_info->get_chat_name(c->components); | |
363 } | |
10663 | 364 } else if (GAIM_BLIST_NODE_IS_CONTACT(node)) { |
365 gaim_gtk_log_show_contact((GaimContact *)node); | |
366 return; | |
9917 | 367 } else |
368 return; | |
369 | |
370 if (name && account) { | |
371 gaim_gtk_log_show(type, name, account); | |
372 g_free(name); | |
373 } | |
7620 | 374 } |
375 | |
5228 | 376 static void gtk_blist_show_systemlog_cb() |
377 { | |
8573 | 378 gaim_gtk_syslog_show(); |
5228 | 379 } |
380 | |
381 static void gtk_blist_show_onlinehelp_cb() | |
382 { | |
10240
95ca0db2d01d
[gaim-migrate @ 11377]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
10229
diff
changeset
|
383 gaim_notify_uri(NULL, GAIM_WEBSITE "documentation.php"); |
5228 | 384 } |
385 | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
386 static void |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
387 do_join_chat(GaimGtkJoinChatData *data) |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
388 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
389 if (data) |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
390 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
391 GHashTable *components = |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
392 g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
393 GList *tmp; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
394 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
395 for (tmp = data->entries; tmp != NULL; tmp = tmp->next) |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
396 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
397 if (g_object_get_data(tmp->data, "is_spin")) |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
398 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
399 g_hash_table_replace(components, |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
400 g_strdup(g_object_get_data(tmp->data, "identifier")), |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
401 g_strdup_printf("%d", |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
402 gtk_spin_button_get_value_as_int(tmp->data))); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
403 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
404 else |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
405 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
406 g_hash_table_replace(components, |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
407 g_strdup(g_object_get_data(tmp->data, "identifier")), |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
408 g_strdup(gtk_entry_get_text(tmp->data))); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
409 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
410 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
411 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
412 serv_join_chat(gaim_account_get_connection(data->account), components); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
413 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
414 g_hash_table_destroy(components); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
415 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
416 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
417 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
418 static void |
8940 | 419 do_joinchat(GtkWidget *dialog, int id, GaimGtkJoinChatData *info) |
420 { | |
421 switch(id) | |
422 { | |
423 case GTK_RESPONSE_OK: | |
424 do_join_chat(info); | |
425 | |
426 break; | |
427 } | |
428 | |
429 gtk_widget_destroy(GTK_WIDGET(dialog)); | |
430 g_list_free(info->entries); | |
431 g_free(info); | |
432 } | |
433 | |
10475 | 434 /* |
435 * Check the values of all the text entry boxes. If any required input | |
436 * strings are empty then don't allow the user to click on "OK." | |
437 */ | |
438 static void | |
439 joinchat_set_sensitive_if_input_cb(GtkWidget *entry, gpointer user_data) | |
440 { | |
441 GaimGtkJoinChatData *data; | |
442 GList *tmp; | |
443 const char *text; | |
444 gboolean required; | |
445 gboolean sensitive = TRUE; | |
446 | |
447 data = user_data; | |
448 | |
449 for (tmp = data->entries; tmp != NULL; tmp = tmp->next) | |
450 { | |
451 if (!g_object_get_data(tmp->data, "is_spin")) | |
452 { | |
453 required = GPOINTER_TO_INT(g_object_get_data(tmp->data, "required")); | |
454 text = gtk_entry_get_text(tmp->data); | |
455 if (required && (*text == '\0')) | |
456 sensitive = FALSE; | |
457 } | |
458 } | |
459 | |
460 gtk_dialog_set_response_sensitive(GTK_DIALOG(data->window), GTK_RESPONSE_OK, sensitive); | |
461 } | |
462 | |
8940 | 463 static void |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
464 rebuild_joinchat_entries(GaimGtkJoinChatData *data) |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
465 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
466 GaimConnection *gc; |
9959 | 467 GList *list = NULL, *tmp = NULL; |
9770 | 468 GHashTable *defaults = NULL; |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
469 struct proto_chat_entry *pce; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
470 gboolean focus = TRUE; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
471 |
10127 | 472 g_return_if_fail(data->account != NULL); |
473 | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
474 gc = gaim_account_get_connection(data->account); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
475 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
476 while (GTK_BOX(data->entries_box)->children) |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
477 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
478 gtk_container_remove(GTK_CONTAINER(data->entries_box), |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
479 ((GtkBoxChild *)GTK_BOX(data->entries_box)->children->data)->widget); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
480 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
481 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
482 if (data->entries != NULL) |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
483 g_list_free(data->entries); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
484 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
485 data->entries = NULL; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
486 |
9987 | 487 if (GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info != NULL) |
9959 | 488 list = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info(gc); |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
489 |
9770 | 490 if (GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) |
491 defaults = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, NULL); | |
492 | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
493 for (tmp = list; tmp; tmp = tmp->next) |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
494 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
495 GtkWidget *label; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
496 GtkWidget *rowbox; |
10475 | 497 GtkWidget *input; |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
498 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
499 pce = tmp->data; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
500 |
11243 | 501 rowbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
502 gtk_box_pack_start(GTK_BOX(data->entries_box), rowbox, FALSE, FALSE, 0); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
503 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
504 label = gtk_label_new_with_mnemonic(pce->label); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
505 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
506 gtk_size_group_add_widget(data->sg, label); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
507 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
508 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
509 if (pce->is_int) |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
510 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
511 GtkObject *adjust; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
512 adjust = gtk_adjustment_new(pce->min, pce->min, pce->max, |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
513 1, 10, 10); |
10475 | 514 input = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0); |
515 gtk_widget_set_size_request(input, 50, -1); | |
516 gtk_box_pack_end(GTK_BOX(rowbox), input, FALSE, FALSE, 0); | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
517 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
518 else |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
519 { |
9770 | 520 char *value; |
10475 | 521 input = gtk_entry_new(); |
522 gtk_entry_set_activates_default(GTK_ENTRY(input), TRUE); | |
9770 | 523 value = g_hash_table_lookup(defaults, pce->identifier); |
524 if (value != NULL) | |
10475 | 525 gtk_entry_set_text(GTK_ENTRY(input), value); |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
526 if (pce->secret) |
11986 | 527 { |
10475 | 528 gtk_entry_set_visibility(GTK_ENTRY(input), FALSE); |
11986 | 529 gtk_entry_set_invisible_char(GTK_ENTRY(input), GAIM_INVISIBLE_CHAR); |
530 } | |
10475 | 531 gtk_box_pack_end(GTK_BOX(rowbox), input, TRUE, TRUE, 0); |
532 g_signal_connect(G_OBJECT(input), "changed", | |
533 G_CALLBACK(joinchat_set_sensitive_if_input_cb), data); | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
534 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
535 |
10475 | 536 /* Do the following for any type of input widget */ |
537 if (focus) | |
538 { | |
539 gtk_widget_grab_focus(input); | |
540 focus = FALSE; | |
541 } | |
542 gtk_label_set_mnemonic_widget(GTK_LABEL(label), input); | |
543 gaim_set_accessible_label(input, label); | |
544 g_object_set_data(G_OBJECT(input), "identifier", pce->identifier); | |
545 g_object_set_data(G_OBJECT(input), "is_spin", GINT_TO_POINTER(pce->is_int)); | |
546 g_object_set_data(G_OBJECT(input), "required", GINT_TO_POINTER(pce->required)); | |
547 data->entries = g_list_append(data->entries, input); | |
548 | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
549 g_free(pce); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
550 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
551 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
552 g_list_free(list); |
10475 | 553 g_hash_table_destroy(defaults); |
554 | |
555 /* Set whether the "OK" button should be clickable initially */ | |
556 joinchat_set_sensitive_if_input_cb(NULL, data); | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
557 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
558 gtk_widget_show_all(data->entries_box); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
559 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
560 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
561 static void |
8940 | 562 joinchat_select_account_cb(GObject *w, GaimAccount *account, |
10475 | 563 GaimGtkJoinChatData *data) |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
564 { |
9460 | 565 if (strcmp(gaim_account_get_protocol_id(data->account), |
10475 | 566 gaim_account_get_protocol_id(account)) == 0) |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
567 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
568 data->account = account; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
569 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
570 else |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
571 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
572 data->account = account; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
573 rebuild_joinchat_entries(data); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
574 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
575 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
576 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
577 static gboolean |
9987 | 578 chat_account_filter_func(GaimAccount *account) |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
579 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
580 GaimConnection *gc = gaim_account_get_connection(account); |
8940 | 581 GaimPluginProtocolInfo *prpl_info = NULL; |
582 | |
583 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); | |
584 | |
585 return (prpl_info->chat_info != NULL); | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
586 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
587 |
8940 | 588 gboolean |
589 gaim_gtk_blist_joinchat_is_showable() | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
590 { |
8940 | 591 GList *c; |
592 GaimConnection *gc; | |
593 | |
594 for (c = gaim_connections_get_all(); c != NULL; c = c->next) { | |
595 gc = c->data; | |
596 | |
9987 | 597 if (chat_account_filter_func(gaim_connection_get_account(gc))) |
8940 | 598 return TRUE; |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
599 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
600 |
8940 | 601 return FALSE; |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
602 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
603 |
8305
57bdd25752c1
[gaim-migrate @ 9029]
Christian Hammond <chipx86@chipx86.com>
parents:
8303
diff
changeset
|
604 void |
8940 | 605 gaim_gtk_blist_joinchat_show(void) |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
606 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
607 GtkWidget *hbox, *vbox; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
608 GtkWidget *rowbox; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
609 GtkWidget *label; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
610 GaimGtkBuddyList *gtkblist; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
611 GtkWidget *img = NULL; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
612 GaimGtkJoinChatData *data = NULL; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
613 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
614 gtkblist = GAIM_GTK_BLIST(gaim_get_blist()); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
615 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
616 GTK_ICON_SIZE_DIALOG); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
617 data = g_new0(GaimGtkJoinChatData, 1); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
618 |
8975 | 619 data->window = gtk_dialog_new_with_buttons(_("Join a Chat"), |
620 NULL, GTK_DIALOG_NO_SEPARATOR, | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
621 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
8308 | 622 GAIM_STOCK_CHAT, GTK_RESPONSE_OK, NULL); |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
623 gtk_dialog_set_default_response(GTK_DIALOG(data->window), GTK_RESPONSE_OK); |
11243 | 624 gtk_container_set_border_width(GTK_CONTAINER(data->window), GAIM_HIG_BOX_SPACE); |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
625 gtk_window_set_resizable(GTK_WINDOW(data->window), FALSE); |
11243 | 626 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(data->window)->vbox), GAIM_HIG_BORDER); |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
627 gtk_container_set_border_width( |
11243 | 628 GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), GAIM_HIG_BOX_SPACE); |
8975 | 629 gtk_window_set_role(GTK_WINDOW(data->window), "join_chat"); |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
630 |
11243 | 631 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
632 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), hbox); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
633 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
634 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
635 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
636 vbox = gtk_vbox_new(FALSE, 5); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
637 gtk_container_set_border_width(GTK_CONTAINER(vbox), 0); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
638 gtk_container_add(GTK_CONTAINER(hbox), vbox); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
639 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
640 label = gtk_label_new(_("Please enter the appropriate information " |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
641 "about the chat you would like to join.\n")); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
642 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
643 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
644 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
645 |
11243 | 646 rowbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
647 gtk_box_pack_start(GTK_BOX(vbox), rowbox, TRUE, TRUE, 0); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
648 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
649 data->sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
650 |
8940 | 651 label = gtk_label_new_with_mnemonic(_("_Account:")); |
652 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
653 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); | |
654 gtk_size_group_add_widget(data->sg, label); | |
655 | |
656 data->account_menu = gaim_gtk_account_option_menu_new(NULL, FALSE, | |
657 G_CALLBACK(joinchat_select_account_cb), | |
9987 | 658 chat_account_filter_func, data); |
8940 | 659 gtk_box_pack_start(GTK_BOX(rowbox), data->account_menu, TRUE, TRUE, 0); |
660 gtk_label_set_mnemonic_widget(GTK_LABEL(label), | |
661 GTK_WIDGET(data->account_menu)); | |
662 gaim_set_accessible_label (data->account_menu, label); | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
663 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
664 data->entries_box = gtk_vbox_new(FALSE, 5); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
665 gtk_container_add(GTK_CONTAINER(vbox), data->entries_box); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
666 gtk_container_set_border_width(GTK_CONTAINER(data->entries_box), 0); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
667 |
8940 | 668 data->account = gaim_gtk_account_option_menu_get_selected(data->account_menu); |
669 | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
670 rebuild_joinchat_entries(data); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
671 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
672 g_signal_connect(G_OBJECT(data->window), "response", |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
673 G_CALLBACK(do_joinchat), data); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
674 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
675 g_object_unref(data->sg); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
676 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
677 gtk_widget_show_all(data->window); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
678 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
679 |
5228 | 680 static void gtk_blist_row_expanded_cb(GtkTreeView *tv, GtkTreeIter *iter, GtkTreePath *path, gpointer user_data) { |
681 GaimBlistNode *node; | |
682 GValue val = {0,}; | |
683 | |
684 gtk_tree_model_get_value(GTK_TREE_MODEL(gtkblist->treemodel), iter, NODE_COLUMN, &val); | |
685 | |
686 node = g_value_get_pointer(&val); | |
687 | |
688 if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
7693 | 689 gaim_blist_node_set_bool(node, "collapsed", FALSE); |
5228 | 690 } |
691 } | |
692 | |
693 static void gtk_blist_row_collapsed_cb(GtkTreeView *tv, GtkTreeIter *iter, GtkTreePath *path, gpointer user_data) { | |
694 GaimBlistNode *node; | |
695 GValue val = {0,}; | |
696 | |
697 gtk_tree_model_get_value(GTK_TREE_MODEL(gtkblist->treemodel), iter, NODE_COLUMN, &val); | |
698 | |
699 node = g_value_get_pointer(&val); | |
700 | |
701 if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
7693 | 702 gaim_blist_node_set_bool(node, "collapsed", TRUE); |
7620 | 703 } else if(GAIM_BLIST_NODE_IS_CONTACT(node)) { |
704 gaim_gtk_blist_collapse_contact_cb(NULL, node); | |
5228 | 705 } |
706 } | |
707 | |
708 static void gtk_blist_row_activated_cb(GtkTreeView *tv, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data) { | |
709 GaimBlistNode *node; | |
710 GtkTreeIter iter; | |
711 GValue val = { 0, }; | |
712 | |
713 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); | |
714 | |
715 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
716 node = g_value_get_pointer(&val); | |
717 | |
7620 | 718 if(GAIM_BLIST_NODE_IS_CONTACT(node) || GAIM_BLIST_NODE_IS_BUDDY(node)) { |
719 GaimBuddy *buddy; | |
720 | |
721 if(GAIM_BLIST_NODE_IS_CONTACT(node)) | |
722 buddy = gaim_contact_get_priority_buddy((GaimContact*)node); | |
723 else | |
724 buddy = (GaimBuddy*)node; | |
725 | |
9728 | 726 gaim_gtkdialogs_im_with_user(buddy->account, buddy->name); |
5234 | 727 } else if (GAIM_BLIST_NODE_IS_CHAT(node)) { |
7620 | 728 serv_join_chat(((GaimChat *)node)->account->gc, ((GaimChat *)node)->components); |
5228 | 729 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { |
730 if (gtk_tree_view_row_expanded(tv, path)) | |
731 gtk_tree_view_collapse_row(tv, path); | |
732 else | |
733 gtk_tree_view_expand_row(tv,path,FALSE); | |
734 } | |
735 } | |
736 | |
5234 | 737 static void gaim_gtk_blist_add_chat_cb() |
738 { | |
739 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkblist->treeview)); | |
740 GtkTreeIter iter; | |
741 GaimBlistNode *node; | |
742 | |
743 if(gtk_tree_selection_get_selected(sel, NULL, &iter)){ | |
744 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); | |
7620 | 745 if (GAIM_BLIST_NODE_IS_BUDDY(node)) |
9754 | 746 gaim_blist_request_add_chat(NULL, (GaimGroup*)node->parent->parent, NULL, NULL); |
7620 | 747 if (GAIM_BLIST_NODE_IS_CONTACT(node) || GAIM_BLIST_NODE_IS_CHAT(node)) |
9754 | 748 gaim_blist_request_add_chat(NULL, (GaimGroup*)node->parent, NULL, NULL); |
5234 | 749 else if (GAIM_BLIST_NODE_IS_GROUP(node)) |
9754 | 750 gaim_blist_request_add_chat(NULL, (GaimGroup*)node, NULL, NULL); |
5234 | 751 } |
752 else { | |
9754 | 753 gaim_blist_request_add_chat(NULL, NULL, NULL, NULL); |
5234 | 754 } |
755 } | |
756 | |
5228 | 757 static void gaim_gtk_blist_add_buddy_cb() |
758 { | |
759 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkblist->treeview)); | |
760 GtkTreeIter iter; | |
761 GaimBlistNode *node; | |
762 | |
763 if(gtk_tree_selection_get_selected(sel, NULL, &iter)){ | |
764 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); | |
7620 | 765 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { |
766 gaim_blist_request_add_buddy(NULL, NULL, ((GaimGroup*)node->parent->parent)->name, | |
767 NULL); | |
768 } else if (GAIM_BLIST_NODE_IS_CONTACT(node) | |
769 || GAIM_BLIST_NODE_IS_CHAT(node)) { | |
770 gaim_blist_request_add_buddy(NULL, NULL, ((GaimGroup*)node->parent)->name, NULL); | |
771 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
772 gaim_blist_request_add_buddy(NULL, NULL, ((GaimGroup*)node)->name, NULL); | |
773 } | |
5228 | 774 } |
775 else { | |
7620 | 776 gaim_blist_request_add_buddy(NULL, NULL, NULL, NULL); |
777 } | |
778 } | |
779 | |
780 static void | |
781 gaim_gtk_blist_remove_cb (GtkWidget *w, GaimBlistNode *node) | |
782 { | |
783 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
9730 | 784 gaim_gtkdialogs_remove_buddy((GaimBuddy*)node); |
7620 | 785 } else if (GAIM_BLIST_NODE_IS_CHAT(node)) { |
9730 | 786 gaim_gtkdialogs_remove_chat((GaimChat*)node); |
7620 | 787 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { |
9730 | 788 gaim_gtkdialogs_remove_group((GaimGroup*)node); |
7620 | 789 } else if (GAIM_BLIST_NODE_IS_CONTACT(node)) { |
9730 | 790 gaim_gtkdialogs_remove_contact((GaimContact*)node); |
5228 | 791 } |
792 } | |
793 | |
794 static void | |
7620 | 795 gaim_gtk_blist_expand_contact_cb(GtkWidget *w, GaimBlistNode *node) |
5228 | 796 { |
7620 | 797 struct _gaim_gtk_blist_node *gtknode; |
9632 | 798 GtkTreeIter iter, parent; |
7620 | 799 GaimBlistNode *bnode; |
10325 | 800 GtkTreePath *path; |
7620 | 801 |
802 if(!GAIM_BLIST_NODE_IS_CONTACT(node)) | |
803 return; | |
804 | |
805 gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; | |
806 | |
807 gtknode->contact_expanded = TRUE; | |
808 | |
809 for(bnode = node->child; bnode; bnode = bnode->next) { | |
810 gaim_gtk_blist_update(NULL, bnode); | |
811 } | |
10353 | 812 |
9632 | 813 /* This ensures that the bottom buddy is visible, i.e. not scrolled off the alignment */ |
814 get_iter_from_node(node, &parent); | |
10353 | 815 gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(gtkblist->treemodel), &iter, &parent, |
9811 | 816 gtk_tree_model_iter_n_children(GTK_TREE_MODEL(gtkblist->treemodel), &parent) -1); |
9632 | 817 path = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); |
818 /* Let the treeview draw so it knows where to scroll */ | |
819 while (gtk_events_pending()) | |
820 gtk_main_iteration(); | |
10353 | 821 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(gtkblist->treeview), path, NULL, FALSE, 0, 0); |
822 | |
9632 | 823 |
7620 | 824 gaim_gtk_blist_update(NULL, node); |
9632 | 825 gtk_tree_path_free(path); |
7620 | 826 } |
827 | |
828 static void | |
829 gaim_gtk_blist_collapse_contact_cb(GtkWidget *w, GaimBlistNode *node) | |
830 { | |
831 GaimBlistNode *bnode; | |
832 struct _gaim_gtk_blist_node *gtknode; | |
833 | |
834 if(!GAIM_BLIST_NODE_IS_CONTACT(node)) | |
835 return; | |
836 | |
837 gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; | |
838 | |
839 gtknode->contact_expanded = FALSE; | |
840 | |
841 for(bnode = node->child; bnode; bnode = bnode->next) { | |
842 gaim_gtk_blist_update(NULL, bnode); | |
5228 | 843 } |
844 } | |
845 | |
9030 | 846 |
847 static void | |
848 blist_node_menu_cb(GtkMenuItem *item, GaimBlistNode *node) | |
849 { | |
11638 | 850 void (*callback)(GaimBlistNode *, gpointer); |
851 gpointer data; | |
852 callback = g_object_get_data(G_OBJECT(item), "gaimcallback"); | |
853 data = g_object_get_data(G_OBJECT(item), "gaimcallbackdata"); | |
854 if (callback) | |
855 callback(node, data); | |
9030 | 856 } |
857 | |
858 | |
859 static void | |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
860 append_blist_node_action(GtkWidget *menu, GaimBlistNodeAction *act, |
9030 | 861 GaimBlistNode *node, gboolean *dup_separator) |
5228 | 862 { |
9030 | 863 if(act == NULL) { |
864 if(! *dup_separator) { | |
865 gaim_separator(menu); | |
866 *dup_separator = TRUE; | |
867 } | |
868 } else { | |
869 GtkWidget *menuitem; | |
870 | |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
871 if (act->children == NULL) { |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
872 *dup_separator = FALSE; |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
873 |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
874 menuitem = gtk_menu_item_new_with_mnemonic(act->label); |
11038
aedd557f46dd
[gaim-migrate @ 12935]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
875 if (act->callback != NULL) { |
aedd557f46dd
[gaim-migrate @ 12935]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
876 g_object_set_data(G_OBJECT(menuitem), "gaimcallback", |
11638 | 877 act->callback); |
878 g_object_set_data(G_OBJECT(menuitem), "gaimcallbackdata", | |
879 act->data); | |
11038
aedd557f46dd
[gaim-migrate @ 12935]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
880 g_signal_connect(G_OBJECT(menuitem), "activate", |
aedd557f46dd
[gaim-migrate @ 12935]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
881 G_CALLBACK(blist_node_menu_cb), node); |
aedd557f46dd
[gaim-migrate @ 12935]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
882 } else { |
aedd557f46dd
[gaim-migrate @ 12935]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
883 gtk_widget_set_sensitive(menuitem, FALSE); |
aedd557f46dd
[gaim-migrate @ 12935]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
884 } |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
885 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
886 } else { |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
887 GtkWidget *submenu = NULL; |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
888 GList *l = NULL; |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
889 |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
890 menuitem = gtk_menu_item_new_with_mnemonic(act->label); |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
891 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
892 |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
893 submenu = gtk_menu_new(); |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
894 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
895 |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
896 for (l = act->children; l; l = l->next) { |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
897 GaimBlistNodeAction *act = (GaimBlistNodeAction *) l->data; |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
898 |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
899 append_blist_node_action(submenu, act, node, dup_separator); |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
900 } |
11638 | 901 g_list_free(act->children); |
902 act->children = NULL; | |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
903 } |
11638 | 904 g_free(act); |
9030 | 905 } |
5228 | 906 } |
907 | |
9030 | 908 |
9051 | 909 void |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
910 gaim_gtk_append_blist_node_proto_menu(GtkWidget *menu, GaimConnection *gc, |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
911 GaimBlistNode *node) |
9030 | 912 { |
913 GList *l, *ll; | |
914 gboolean dup_separator = FALSE; | |
915 GaimPluginProtocolInfo *prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); | |
916 | |
917 if(!prpl_info || !prpl_info->blist_node_menu) | |
918 return; | |
919 | |
920 for(l = ll = prpl_info->blist_node_menu(node); l; l = l->next) { | |
921 GaimBlistNodeAction *act = (GaimBlistNodeAction *) l->data; | |
922 append_blist_node_action(menu, act, node, &dup_separator); | |
923 } | |
924 g_list_free(ll); | |
925 } | |
926 | |
927 | |
9051 | 928 void |
929 gaim_gtk_append_blist_node_extended_menu (GtkWidget *menu, GaimBlistNode *node) | |
9030 | 930 { |
931 GList *l, *ll; | |
932 gboolean dup_separator = FALSE; | |
933 | |
934 for(l = ll = gaim_blist_node_get_extended_menu(node); l; l = l->next) { | |
935 GaimBlistNodeAction *act = (GaimBlistNodeAction *) l->data; | |
936 append_blist_node_action(menu, act, node, &dup_separator); | |
937 } | |
938 g_list_free(ll); | |
939 } | |
940 | |
941 | |
9774 | 942 void |
10484 | 943 gaim_gtk_blist_make_buddy_menu(GtkWidget *menu, GaimBuddy *buddy, gboolean sub) { |
9774 | 944 GaimPluginProtocolInfo *prpl_info; |
10663 | 945 GaimContact *contact; |
946 gboolean contact_expanded = FALSE; | |
9774 | 947 |
948 g_return_if_fail(menu); | |
949 g_return_if_fail(buddy); | |
950 | |
951 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(buddy->account->gc->prpl); | |
952 | |
10663 | 953 contact = gaim_buddy_get_contact(buddy); |
954 if (contact) { | |
955 contact_expanded = ((struct _gaim_gtk_blist_node *)(((GaimBlistNode*)contact)->ui_data))->contact_expanded; | |
956 } | |
957 | |
7620 | 958 if (prpl_info && prpl_info->get_info) { |
8137 | 959 gaim_new_item_from_stock(menu, _("Get _Info"), GAIM_STOCK_INFO, |
9774 | 960 G_CALLBACK(gtk_blist_menu_info_cb), buddy, 0, 0, NULL); |
7620 | 961 } |
8137 | 962 gaim_new_item_from_stock(menu, _("I_M"), GAIM_STOCK_IM, |
9774 | 963 G_CALLBACK(gtk_blist_menu_im_cb), buddy, 0, 0, NULL); |
9466 | 964 if (prpl_info && prpl_info->send_file) { |
9774 | 965 if (!prpl_info->can_receive_file || |
966 prpl_info->can_receive_file(buddy->account->gc, buddy->name)) | |
967 { | |
968 gaim_new_item_from_stock(menu, _("_Send File"), | |
969 GAIM_STOCK_FILE_TRANSFER, | |
970 G_CALLBACK(gtk_blist_menu_send_file_cb), | |
971 buddy, 0, 0, NULL); | |
9466 | 972 } |
973 } | |
12024 | 974 |
975 if (prpl_info && prpl_info->media_prpl_ops && prpl_info->media_prpl_ops->call) { | |
976 gaim_new_item_from_stock(menu, _("Start _Voice Chat"), | |
977 GAIM_STOCK_VOICE_CHAT, | |
978 G_CALLBACK(gtk_blist_menu_voice_chat_cb), | |
979 buddy, 0, 0, NULL); | |
980 } | |
981 | |
7620 | 982 gaim_new_item_from_stock(menu, _("Add Buddy _Pounce"), NULL, |
9774 | 983 G_CALLBACK(gtk_blist_menu_bp_cb), buddy, 0, 0, NULL); |
10663 | 984 |
985 if(((GaimBlistNode*)buddy)->parent->child->next && !sub && !contact_expanded) { | |
986 gaim_new_item_from_stock(menu, _("View _Log"), NULL, | |
987 G_CALLBACK(gtk_blist_menu_showlog_cb), | |
988 contact, 0, 0, NULL); | |
989 } else if (!sub) { | |
990 gaim_new_item_from_stock(menu, _("View _Log"), NULL, | |
991 G_CALLBACK(gtk_blist_menu_showlog_cb), buddy, 0, 0, NULL); | |
992 } | |
9774 | 993 |
994 gaim_gtk_append_blist_node_proto_menu(menu, buddy->account->gc, | |
995 (GaimBlistNode *)buddy); | |
996 gaim_gtk_append_blist_node_extended_menu(menu, (GaimBlistNode *)buddy); | |
7620 | 997 |
998 gaim_separator(menu); | |
9030 | 999 |
10663 | 1000 if(((GaimBlistNode*)buddy)->parent->child->next && !sub && !contact_expanded) { |
9925 | 1001 gaim_new_item_from_stock(menu, _("_Alias Buddy..."), GAIM_STOCK_ALIAS, |
1002 G_CALLBACK(gtk_blist_menu_alias_cb), buddy, 0, 0, NULL); | |
1003 gaim_new_item_from_stock(menu, _("_Remove Buddy"), GTK_STOCK_REMOVE, | |
1004 G_CALLBACK(gaim_gtk_blist_remove_cb), buddy, 0, 0, NULL); | |
1005 gaim_new_item_from_stock(menu, _("Alias Contact..."), GAIM_STOCK_ALIAS, | |
1006 G_CALLBACK(gtk_blist_menu_alias_cb), | |
10663 | 1007 contact, 0, 0, NULL); |
9925 | 1008 gaim_new_item_from_stock(menu, _("Remove Contact"), GTK_STOCK_REMOVE, |
1009 G_CALLBACK(gaim_gtk_blist_remove_cb), | |
10663 | 1010 contact, 0, 0, NULL); |
9925 | 1011 } else { |
1012 gaim_new_item_from_stock(menu, _("_Alias..."), GAIM_STOCK_ALIAS, | |
1013 G_CALLBACK(gtk_blist_menu_alias_cb), buddy, 0, 0, NULL); | |
1014 gaim_new_item_from_stock(menu, _("_Remove"), GTK_STOCK_REMOVE, | |
1015 G_CALLBACK(gaim_gtk_blist_remove_cb), buddy, | |
1016 0, 0, NULL); | |
1017 } | |
7620 | 1018 } |
1019 | |
9774 | 1020 static gboolean |
1021 gtk_blist_key_press_cb(GtkWidget *tv, GdkEventKey *event, gpointer data) { | |
7620 | 1022 GaimBlistNode *node; |
1023 GValue val = { 0, }; | |
1024 GtkTreeIter iter; | |
1025 GtkTreeSelection *sel; | |
1026 | |
1027 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv)); | |
1028 if(!gtk_tree_selection_get_selected(sel, NULL, &iter)) | |
1029 return FALSE; | |
1030 | |
1031 gtk_tree_model_get_value(GTK_TREE_MODEL(gtkblist->treemodel), &iter, | |
1032 NODE_COLUMN, &val); | |
1033 node = g_value_get_pointer(&val); | |
1034 | |
1035 if(event->state & GDK_CONTROL_MASK && | |
1036 (event->keyval == 'o' || event->keyval == 'O')) { | |
1037 GaimBuddy *buddy; | |
1038 | |
1039 if(GAIM_BLIST_NODE_IS_CONTACT(node)) { | |
1040 buddy = gaim_contact_get_priority_buddy((GaimContact*)node); | |
1041 } else if(GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
1042 buddy = (GaimBuddy*)node; | |
1043 } else { | |
1044 return FALSE; | |
1045 } | |
1046 if(buddy) | |
1047 serv_get_info(buddy->account->gc, buddy->name); | |
1048 } | |
1049 | |
1050 return FALSE; | |
1051 } | |
1052 | |
9013 | 1053 |
8143 | 1054 static GtkWidget * |
8952 | 1055 create_group_menu (GaimBlistNode *node, GaimGroup *g) |
8143 | 1056 { |
1057 GtkWidget *menu; | |
11988 | 1058 GtkWidget *item; |
8143 | 1059 |
1060 menu = gtk_menu_new(); | |
1061 gaim_new_item_from_stock(menu, _("Add a _Buddy"), GTK_STOCK_ADD, | |
1062 G_CALLBACK(gaim_gtk_blist_add_buddy_cb), node, 0, 0, NULL); | |
11988 | 1063 item = gaim_new_item_from_stock(menu, _("Add a C_hat"), GTK_STOCK_ADD, |
8143 | 1064 G_CALLBACK(gaim_gtk_blist_add_chat_cb), node, 0, 0, NULL); |
11988 | 1065 gtk_widget_set_sensitive(item, gaim_gtk_blist_joinchat_is_showable()); |
8143 | 1066 gaim_new_item_from_stock(menu, _("_Delete Group"), GTK_STOCK_REMOVE, |
1067 G_CALLBACK(gaim_gtk_blist_remove_cb), node, 0, 0, NULL); | |
1068 gaim_new_item_from_stock(menu, _("_Rename"), NULL, | |
11016 | 1069 G_CALLBACK(gtk_blist_menu_alias_cb), node, 0, 0, NULL); |
8952 | 1070 |
9051 | 1071 gaim_gtk_append_blist_node_extended_menu(menu, node); |
8952 | 1072 |
8143 | 1073 return menu; |
1074 } | |
1075 | |
8586 | 1076 |
8143 | 1077 static GtkWidget * |
9774 | 1078 create_chat_menu(GaimBlistNode *node, GaimChat *c) { |
8143 | 1079 GtkWidget *menu; |
9030 | 1080 gboolean autojoin; |
8143 | 1081 |
1082 menu = gtk_menu_new(); | |
9030 | 1083 autojoin = (gaim_blist_node_get_bool(node, "gtk-autojoin") || |
1084 (gaim_blist_node_get_string(node, "gtk-autojoin") != NULL)); | |
1085 | |
8143 | 1086 gaim_new_item_from_stock(menu, _("_Join"), GAIM_STOCK_CHAT, |
9030 | 1087 G_CALLBACK(gtk_blist_menu_join_cb), node, 0, 0, NULL); |
8143 | 1088 gaim_new_check_item(menu, _("Auto-Join"), |
9030 | 1089 G_CALLBACK(gtk_blist_menu_autojoin_cb), node, autojoin); |
9917 | 1090 gaim_new_item_from_stock(menu, _("View _Log"), NULL, |
1091 G_CALLBACK(gtk_blist_menu_showlog_cb), node, 0, 0, NULL); | |
9030 | 1092 |
9051 | 1093 gaim_gtk_append_blist_node_proto_menu(menu, c->account->gc, node); |
1094 gaim_gtk_append_blist_node_extended_menu(menu, node); | |
8586 | 1095 |
1096 gaim_separator(menu); | |
9030 | 1097 |
8302
462ead6fc1a0
[gaim-migrate @ 9026]
Christian Hammond <chipx86@chipx86.com>
parents:
8259
diff
changeset
|
1098 gaim_new_item_from_stock(menu, _("_Alias..."), GAIM_STOCK_ALIAS, |
8143 | 1099 G_CALLBACK(gtk_blist_menu_alias_cb), node, 0, 0, NULL); |
1100 gaim_new_item_from_stock(menu, _("_Remove"), GTK_STOCK_REMOVE, | |
1101 G_CALLBACK(gaim_gtk_blist_remove_cb), node, 0, 0, NULL); | |
8586 | 1102 |
8143 | 1103 return menu; |
1104 } | |
1105 | |
1106 static GtkWidget * | |
1107 create_contact_menu (GaimBlistNode *node) | |
1108 { | |
1109 GtkWidget *menu; | |
1110 | |
1111 menu = gtk_menu_new(); | |
10663 | 1112 |
1113 gaim_new_item_from_stock(menu, _("View _Log"), NULL, | |
1114 G_CALLBACK(gtk_blist_menu_showlog_cb), | |
1115 node, 0, 0, NULL); | |
1116 | |
1117 gaim_separator(menu); | |
1118 | |
8302
462ead6fc1a0
[gaim-migrate @ 9026]
Christian Hammond <chipx86@chipx86.com>
parents:
8259
diff
changeset
|
1119 gaim_new_item_from_stock(menu, _("_Alias..."), GAIM_STOCK_ALIAS, |
8143 | 1120 G_CALLBACK(gtk_blist_menu_alias_cb), node, 0, 0, NULL); |
10663 | 1121 gaim_new_item_from_stock(menu, _("_Remove"), GTK_STOCK_REMOVE, |
1122 G_CALLBACK(gaim_gtk_blist_remove_cb), node, 0, 0, NULL); | |
1123 | |
1124 gaim_separator(menu); | |
1125 | |
8143 | 1126 gaim_new_item_from_stock(menu, _("_Collapse"), GTK_STOCK_ZOOM_OUT, |
1127 G_CALLBACK(gaim_gtk_blist_collapse_contact_cb), | |
1128 node, 0, 0, NULL); | |
9051 | 1129 |
1130 gaim_gtk_append_blist_node_extended_menu(menu, node); | |
1131 | |
8143 | 1132 return menu; |
1133 } | |
1134 | |
1135 static GtkWidget * | |
9774 | 1136 create_buddy_menu(GaimBlistNode *node, GaimBuddy *b) { |
8143 | 1137 struct _gaim_gtk_blist_node *gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; |
1138 GtkWidget *menu; | |
1139 GtkWidget *menuitem; | |
1140 gboolean show_offline = gaim_prefs_get_bool("/gaim/gtk/blist/show_offline_buddies"); | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
1141 |
8143 | 1142 menu = gtk_menu_new(); |
10484 | 1143 gaim_gtk_blist_make_buddy_menu(menu, b, FALSE); |
8143 | 1144 |
1145 if(GAIM_BLIST_NODE_IS_CONTACT(node)) { | |
1146 gaim_separator(menu); | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
1147 |
8143 | 1148 if(gtknode->contact_expanded) { |
1149 gaim_new_item_from_stock(menu, _("_Collapse"), | |
1150 GTK_STOCK_ZOOM_OUT, | |
1151 G_CALLBACK(gaim_gtk_blist_collapse_contact_cb), | |
1152 node, 0, 0, NULL); | |
1153 } else { | |
1154 gaim_new_item_from_stock(menu, _("_Expand"), | |
1155 GTK_STOCK_ZOOM_IN, | |
1156 G_CALLBACK(gaim_gtk_blist_expand_contact_cb), node, | |
1157 0, 0, NULL); | |
1158 } | |
1159 if(node->child->next) { | |
1160 GaimBlistNode *bnode; | |
1161 | |
1162 for(bnode = node->child; bnode; bnode = bnode->next) { | |
1163 GaimBuddy *buddy = (GaimBuddy*)bnode; | |
9340 | 1164 GdkPixbuf *buf; |
8143 | 1165 GtkWidget *submenu; |
1166 GtkWidget *image; | |
1167 | |
1168 if(buddy == b) | |
1169 continue; | |
1170 if(!buddy->account->gc) | |
1171 continue; | |
1172 if(!show_offline && !GAIM_BUDDY_IS_ONLINE(buddy)) | |
1173 continue; | |
1174 | |
1175 menuitem = gtk_image_menu_item_new_with_label(buddy->name); | |
9340 | 1176 buf = gaim_gtk_blist_get_status_icon(bnode, |
1177 GAIM_STATUS_ICON_SMALL); | |
1178 image = gtk_image_new_from_pixbuf(buf); | |
1179 g_object_unref(G_OBJECT(buf)); | |
8143 | 1180 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), |
9811 | 1181 image); |
8143 | 1182 gtk_widget_show(image); |
1183 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
1184 gtk_widget_show(menuitem); | |
1185 | |
1186 submenu = gtk_menu_new(); | |
1187 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); | |
1188 gtk_widget_show(submenu); | |
1189 | |
10484 | 1190 gaim_gtk_blist_make_buddy_menu(submenu, buddy, TRUE); |
8143 | 1191 } |
1192 } | |
1193 } | |
1194 return menu; | |
1195 } | |
1196 | |
1197 static gboolean | |
1198 gaim_gtk_blist_show_context_menu(GaimBlistNode *node, | |
1199 GtkMenuPositionFunc func, | |
1200 GtkWidget *tv, | |
1201 guint button, | |
1202 guint32 time) | |
1203 { | |
1204 struct _gaim_gtk_blist_node *gtknode; | |
1205 GtkWidget *menu = NULL; | |
1206 gboolean handled = FALSE; | |
1207 | |
1208 gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; | |
1209 | |
1210 /* Create a menu based on the thing we right-clicked on */ | |
1211 if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
8952 | 1212 GaimGroup *g = (GaimGroup *)node; |
9774 | 1213 |
8952 | 1214 menu = create_group_menu(node, g); |
8143 | 1215 } else if (GAIM_BLIST_NODE_IS_CHAT(node)) { |
8586 | 1216 GaimChat *c = (GaimChat *)node; |
9774 | 1217 |
1218 menu = create_chat_menu(node, c); | |
8143 | 1219 } else if ((GAIM_BLIST_NODE_IS_CONTACT(node)) && (gtknode->contact_expanded)) { |
1220 menu = create_contact_menu(node); | |
1221 } else if (GAIM_BLIST_NODE_IS_CONTACT(node) || GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
1222 GaimBuddy *b; | |
1223 | |
1224 if (GAIM_BLIST_NODE_IS_CONTACT(node)) | |
1225 b = gaim_contact_get_priority_buddy((GaimContact*)node); | |
1226 else | |
1227 b = (GaimBuddy *)node; | |
1228 | |
9774 | 1229 menu = create_buddy_menu(node, b); |
8143 | 1230 } |
1231 | |
11059
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1232 #ifdef _WIN32 |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1233 /* Unhook the tooltip-timeout since we don't want a tooltip |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1234 * to appear and obscure the context menu we are about to show |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1235 This is a workaround for GTK+ bug 107320. */ |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1236 if (gtkblist->timeout) { |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1237 g_source_remove(gtkblist->timeout); |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1238 gtkblist->timeout = 0; |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1239 } |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1240 #endif |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1241 |
8143 | 1242 /* Now display the menu */ |
1243 if (menu != NULL) { | |
1244 gtk_widget_show_all(menu); | |
1245 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, func, tv, button, time); | |
1246 handled = TRUE; | |
1247 } | |
1248 | |
1249 return handled; | |
1250 } | |
1251 | |
1252 static gboolean gtk_blist_button_press_cb(GtkWidget *tv, GdkEventButton *event, gpointer user_data) | |
5228 | 1253 { |
1254 GtkTreePath *path; | |
1255 GaimBlistNode *node; | |
1256 GValue val = { 0, }; | |
1257 GtkTreeIter iter; | |
1258 GtkTreeSelection *sel; | |
1259 GaimPlugin *prpl = NULL; | |
1260 GaimPluginProtocolInfo *prpl_info = NULL; | |
7620 | 1261 struct _gaim_gtk_blist_node *gtknode; |
1262 gboolean handled = FALSE; | |
5228 | 1263 |
1264 /* Here we figure out which node was clicked */ | |
1265 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), event->x, event->y, &path, NULL, NULL, NULL)) | |
1266 return FALSE; | |
1267 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); | |
8143 | 1268 gtk_tree_model_get_value(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); |
5228 | 1269 node = g_value_get_pointer(&val); |
7620 | 1270 gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; |
1271 | |
8143 | 1272 /* Right click draws a context menu */ |
1273 if ((event->button == 3) && (event->type == GDK_BUTTON_PRESS)) { | |
1274 handled = gaim_gtk_blist_show_context_menu(node, NULL, tv, 3, event->time); | |
1275 | |
1276 /* CTRL+middle click expands or collapse a contact */ | |
1277 } else if ((event->button == 2) && (event->type == GDK_BUTTON_PRESS) && | |
1278 (event->state & GDK_CONTROL_MASK) && (GAIM_BLIST_NODE_IS_CONTACT(node))) { | |
1279 if (gtknode->contact_expanded) | |
7620 | 1280 gaim_gtk_blist_collapse_contact_cb(NULL, node); |
1281 else | |
1282 gaim_gtk_blist_expand_contact_cb(NULL, node); | |
1283 handled = TRUE; | |
8143 | 1284 |
1285 /* Double middle click gets info */ | |
1286 } else if ((event->button == 2) && (event->type == GDK_2BUTTON_PRESS) && | |
1287 ((GAIM_BLIST_NODE_IS_CONTACT(node)) || (GAIM_BLIST_NODE_IS_BUDDY(node)))) { | |
7620 | 1288 GaimBuddy *b; |
1289 if(GAIM_BLIST_NODE_IS_CONTACT(node)) | |
1290 b = gaim_contact_get_priority_buddy((GaimContact*)node); | |
1291 else | |
1292 b = (GaimBuddy *)node; | |
1293 | |
7956 | 1294 prpl = gaim_find_prpl(gaim_account_get_protocol_id(b->account)); |
5228 | 1295 if (prpl != NULL) |
1296 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); | |
1297 | |
8143 | 1298 if (prpl && prpl_info->get_info) |
1299 serv_get_info(b->account->gc, b->name); | |
1300 handled = TRUE; | |
5228 | 1301 } |
1302 | |
8143 | 1303 #if (1) |
1304 /* | |
10814
364a2ef907ae
[gaim-migrate @ 12468]
Luke Schierer <lschiere@pidgin.im>
parents:
10780
diff
changeset
|
1305 * This code only exists because GTK+ doesn't work. If we return |
8143 | 1306 * FALSE here, as would be normal the event propoagates down and |
1307 * somehow gets interpreted as the start of a drag event. | |
1308 * | |
1309 * Um, isn't it _normal_ to return TRUE here? Since the event | |
1310 * was handled? --Mark | |
1311 */ | |
7620 | 1312 if(handled) { |
1313 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv)); | |
1314 gtk_tree_selection_select_path(sel, path); | |
1315 gtk_tree_path_free(path); | |
1316 return TRUE; | |
1317 } | |
5228 | 1318 #endif |
7753 | 1319 gtk_tree_path_free(path); |
8143 | 1320 |
7620 | 1321 return FALSE; |
5228 | 1322 } |
1323 | |
8143 | 1324 static gboolean |
1325 gaim_gtk_blist_popup_menu_cb(GtkWidget *tv, void *user_data) | |
1326 { | |
1327 GaimBlistNode *node; | |
1328 GValue val = { 0, }; | |
1329 GtkTreeIter iter; | |
1330 GtkTreeSelection *sel; | |
1331 gboolean handled = FALSE; | |
1332 | |
1333 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv)); | |
1334 if (!gtk_tree_selection_get_selected(sel, NULL, &iter)) | |
1335 return FALSE; | |
1336 | |
1337 gtk_tree_model_get_value(GTK_TREE_MODEL(gtkblist->treemodel), | |
1338 &iter, NODE_COLUMN, &val); | |
1339 node = g_value_get_pointer(&val); | |
1340 | |
1341 /* Shift+F10 draws a context menu */ | |
1342 handled = gaim_gtk_blist_show_context_menu(node, gaim_gtk_treeview_popup_menu_position_func, tv, 0, GDK_CURRENT_TIME); | |
1343 | |
1344 return handled; | |
1345 } | |
1346 | |
11796 | 1347 static void gaim_gtk_blist_buddy_details_cb(gpointer data, guint action, GtkWidget *item) |
1348 { | |
1349 gaim_prefs_set_bool("/gaim/gtk/blist/show_buddy_icons", | |
1350 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item))); | |
1351 } | |
1352 | |
5228 | 1353 static void gaim_gtk_blist_show_empty_groups_cb(gpointer data, guint action, GtkWidget *item) |
1354 { | |
7620 | 1355 gaim_prefs_set_bool("/gaim/gtk/blist/show_empty_groups", |
1356 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item))); | |
5228 | 1357 } |
1358 | |
1359 static void gaim_gtk_blist_edit_mode_cb(gpointer callback_data, guint callback_action, | |
1360 GtkWidget *checkitem) { | |
1361 if(gtkblist->window->window) { | |
1362 GdkCursor *cursor = gdk_cursor_new(GDK_WATCH); | |
1363 gdk_window_set_cursor(gtkblist->window->window, cursor); | |
1364 while (gtk_events_pending()) | |
1365 gtk_main_iteration(); | |
1366 gdk_cursor_unref(cursor); | |
1367 } | |
1368 | |
7620 | 1369 gaim_prefs_set_bool("/gaim/gtk/blist/show_offline_buddies", |
1370 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(checkitem))); | |
5228 | 1371 |
1372 if(gtkblist->window->window) { | |
1373 GdkCursor *cursor = gdk_cursor_new(GDK_LEFT_PTR); | |
1374 gdk_window_set_cursor(gtkblist->window->window, cursor); | |
1375 gdk_cursor_unref(cursor); | |
1376 } | |
1377 } | |
1378 | |
10074 | 1379 static void gaim_gtk_blist_mute_sounds_cb(gpointer data, guint action, GtkWidget *item) |
1380 { | |
1381 gaim_prefs_set_bool("/gaim/gtk/sound/mute", GTK_CHECK_MENU_ITEM(item)->active); | |
1382 } | |
1383 | |
1384 static void gaim_gtk_blist_mute_pref_cb(const char *name, GaimPrefType type, gpointer value, gpointer data) | |
1385 { | |
1386 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item(gtkblist->ift, | |
1387 N_("/Tools/Mute Sounds"))), (gboolean)GPOINTER_TO_INT(value)); | |
1388 } | |
1389 | |
1390 static void gaim_gtk_blist_sound_method_pref_cb(const char *name, GaimPrefType type, gpointer value, gpointer data) | |
1391 { | |
1392 gboolean sensitive = TRUE; | |
1393 | |
1394 if(!strcmp(value, "none")) | |
1395 sensitive = FALSE; | |
1396 | |
1397 gtk_widget_set_sensitive(gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Mute Sounds")), sensitive); | |
1398 } | |
1399 | |
8089 | 1400 static void |
1401 add_buddies_from_vcard(const char *prpl_id, GaimGroup *group, GList *list, | |
1402 const char *alias) | |
1403 { | |
1404 GList *l; | |
1405 GaimAccount *account = NULL; | |
1406 GaimConnection *gc; | |
1407 | |
1408 if (list == NULL) | |
1409 return; | |
1410 | |
1411 for (l = gaim_connections_get_all(); l != NULL; l = l->next) | |
1412 { | |
1413 gc = (GaimConnection *)l->data; | |
1414 account = gaim_connection_get_account(gc); | |
1415 | |
1416 if (!strcmp(gaim_account_get_protocol_id(account), prpl_id)) | |
1417 break; | |
1418 | |
1419 account = NULL; | |
1420 } | |
1421 | |
1422 if (account != NULL) | |
1423 { | |
1424 for (l = list; l != NULL; l = l->next) | |
1425 { | |
1426 gaim_blist_request_add_buddy(account, l->data, | |
1427 (group ? group->name : NULL), | |
1428 alias); | |
1429 } | |
1430 } | |
1431 | |
1432 g_list_foreach(list, (GFunc)g_free, NULL); | |
1433 g_list_free(list); | |
1434 } | |
1435 | |
1436 static gboolean | |
1437 parse_vcard(const char *vcard, GaimGroup *group) | |
1438 { | |
1439 char *temp_vcard; | |
1440 char *s, *c; | |
1441 char *alias = NULL; | |
1442 GList *aims = NULL; | |
1443 GList *icqs = NULL; | |
1444 GList *yahoos = NULL; | |
1445 GList *msns = NULL; | |
1446 GList *jabbers = NULL; | |
1447 | |
1448 s = temp_vcard = g_strdup(vcard); | |
1449 | |
1450 while (*s != '\0' && strncmp(s, "END:vCard", strlen("END:vCard"))) | |
1451 { | |
1452 char *field, *value; | |
1453 | |
1454 field = s; | |
1455 | |
1456 /* Grab the field */ | |
1457 while (*s != '\r' && *s != '\n' && *s != '\0' && *s != ':') | |
1458 s++; | |
1459 | |
1460 if (*s == '\r') s++; | |
1461 if (*s == '\n') | |
1462 { | |
1463 s++; | |
1464 continue; | |
1465 } | |
1466 | |
1467 if (*s != '\0') *s++ = '\0'; | |
1468 | |
1469 if ((c = strchr(field, ';')) != NULL) | |
1470 *c = '\0'; | |
1471 | |
1472 /* Proceed to the end of the line */ | |
1473 value = s; | |
1474 | |
1475 while (*s != '\r' && *s != '\n' && *s != '\0') | |
1476 s++; | |
1477 | |
1478 if (*s == '\r') *s++ = '\0'; | |
1479 if (*s == '\n') *s++ = '\0'; | |
1480 | |
1481 /* We only want to worry about a few fields here. */ | |
1482 if (!strcmp(field, "FN")) | |
1483 alias = g_strdup(value); | |
1484 else if (!strcmp(field, "X-AIM") || !strcmp(field, "X-ICQ") || | |
1485 !strcmp(field, "X-YAHOO") || !strcmp(field, "X-MSN") || | |
1486 !strcmp(field, "X-JABBER")) | |
1487 { | |
1488 char **values = g_strsplit(value, ":", 0); | |
1489 char **im; | |
1490 | |
1491 for (im = values; *im != NULL; im++) | |
1492 { | |
1493 if (!strcmp(field, "X-AIM")) | |
1494 aims = g_list_append(aims, g_strdup(*im)); | |
1495 else if (!strcmp(field, "X-ICQ")) | |
1496 icqs = g_list_append(icqs, g_strdup(*im)); | |
1497 else if (!strcmp(field, "X-YAHOO")) | |
1498 yahoos = g_list_append(yahoos, g_strdup(*im)); | |
1499 else if (!strcmp(field, "X-MSN")) | |
1500 msns = g_list_append(msns, g_strdup(*im)); | |
1501 else if (!strcmp(field, "X-JABBER")) | |
1502 jabbers = g_list_append(jabbers, g_strdup(*im)); | |
1503 } | |
1504 | |
1505 g_strfreev(values); | |
1506 } | |
1507 } | |
1508 | |
1509 g_free(temp_vcard); | |
1510 | |
1511 if (aims == NULL && icqs == NULL && yahoos == NULL && | |
1512 msns == NULL && jabbers == NULL) | |
1513 { | |
1514 if (alias != NULL) | |
1515 g_free(alias); | |
1516 | |
1517 return FALSE; | |
1518 } | |
1519 | |
1520 add_buddies_from_vcard("prpl-oscar", group, aims, alias); | |
1521 add_buddies_from_vcard("prpl-oscar", group, icqs, alias); | |
1522 add_buddies_from_vcard("prpl-yahoo", group, yahoos, alias); | |
1523 add_buddies_from_vcard("prpl-msn", group, msns, alias); | |
1524 add_buddies_from_vcard("prpl-jabber", group, jabbers, alias); | |
1525 | |
1526 if (alias != NULL) | |
1527 g_free(alias); | |
1528 | |
1529 return TRUE; | |
1530 } | |
1531 | |
11059
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1532 #ifdef _WIN32 |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1533 static void gaim_gtk_blist_drag_begin(GtkWidget *widget, |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1534 GdkDragContext *drag_context, gpointer user_data) |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1535 { |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1536 gaim_gtk_blist_tooltip_destroy(); |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1537 |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1538 |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1539 /* Unhook the tooltip-timeout since we don't want a tooltip |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1540 * to appear and obscure the dragging operation. |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1541 * This is a workaround for GTK+ bug 107320. */ |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1542 if (gtkblist->timeout) { |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1543 g_source_remove(gtkblist->timeout); |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1544 gtkblist->timeout = 0; |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1545 } |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1546 } |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1547 #endif |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1548 |
9811 | 1549 static void gaim_gtk_blist_drag_data_get_cb(GtkWidget *widget, |
1550 GdkDragContext *dc, | |
1551 GtkSelectionData *data, | |
1552 guint info, | |
1553 guint time, | |
11059
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1554 gpointer null) |
5228 | 1555 { |
11059
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1556 |
8089 | 1557 if (data->target == gdk_atom_intern("GAIM_BLIST_NODE", FALSE)) |
1558 { | |
5228 | 1559 GtkTreeRowReference *ref = g_object_get_data(G_OBJECT(dc), "gtk-tree-view-source-row"); |
1560 GtkTreePath *sourcerow = gtk_tree_row_reference_get_path(ref); | |
1561 GtkTreeIter iter; | |
1562 GaimBlistNode *node = NULL; | |
1563 GValue val = {0}; | |
5273 | 1564 if(!sourcerow) |
1565 return; | |
5228 | 1566 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, sourcerow); |
1567 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
1568 node = g_value_get_pointer(&val); | |
1569 gtk_selection_data_set (data, | |
1570 gdk_atom_intern ("GAIM_BLIST_NODE", FALSE), | |
1571 8, /* bits */ | |
1572 (void*)&node, | |
1573 sizeof (node)); | |
5273 | 1574 |
5228 | 1575 gtk_tree_path_free(sourcerow); |
1576 } | |
8089 | 1577 else if (data->target == gdk_atom_intern("application/x-im-contact", FALSE)) |
1578 { | |
7706 | 1579 GtkTreeRowReference *ref; |
1580 GtkTreePath *sourcerow; | |
1581 GtkTreeIter iter; | |
1582 GaimBlistNode *node = NULL; | |
1583 GaimBuddy *buddy; | |
1584 GaimConnection *gc; | |
1585 GValue val = {0}; | |
1586 GString *str; | |
1587 const char *protocol; | |
1588 char *mime_str; | |
1589 | |
1590 ref = g_object_get_data(G_OBJECT(dc), "gtk-tree-view-source-row"); | |
1591 sourcerow = gtk_tree_row_reference_get_path(ref); | |
1592 | |
1593 if (!sourcerow) | |
1594 return; | |
1595 | |
1596 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, | |
1597 sourcerow); | |
1598 gtk_tree_model_get_value(GTK_TREE_MODEL(gtkblist->treemodel), &iter, | |
1599 NODE_COLUMN, &val); | |
1600 | |
1601 node = g_value_get_pointer(&val); | |
1602 | |
1603 if (GAIM_BLIST_NODE_IS_CONTACT(node)) | |
1604 { | |
1605 buddy = gaim_contact_get_priority_buddy((GaimContact *)node); | |
1606 } | |
1607 else if (!GAIM_BLIST_NODE_IS_BUDDY(node)) | |
1608 { | |
1609 gtk_tree_path_free(sourcerow); | |
1610 return; | |
1611 } | |
1612 else | |
1613 { | |
1614 buddy = (GaimBuddy *)node; | |
1615 } | |
1616 | |
1617 gc = gaim_account_get_connection(buddy->account); | |
1618 | |
1619 if (gc == NULL) | |
1620 { | |
1621 gtk_tree_path_free(sourcerow); | |
1622 return; | |
1623 } | |
1624 | |
1625 protocol = | |
1626 GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->list_icon(buddy->account, | |
1627 buddy); | |
1628 | |
1629 str = g_string_new(NULL); | |
1630 g_string_printf(str, | |
1631 "MIME-Version: 1.0\r\n" | |
1632 "Content-Type: application/x-im-contact\r\n" | |
1633 "X-IM-Protocol: %s\r\n" | |
1634 "X-IM-Username: %s\r\n", | |
1635 protocol, | |
1636 buddy->name); | |
1637 | |
1638 if (buddy->alias != NULL) | |
1639 { | |
1640 g_string_append_printf(str, | |
1641 "X-IM-Alias: %s\r\n", | |
1642 buddy->alias); | |
1643 } | |
1644 | |
1645 str = g_string_append(str, "\r\n"); | |
1646 | |
1647 mime_str = g_string_free(str, FALSE); | |
1648 | |
1649 gtk_selection_data_set(data, | |
1650 gdk_atom_intern("application/x-im-contact", FALSE), | |
1651 8, /* bits */ | |
11137 | 1652 (const guchar *)mime_str, |
7706 | 1653 strlen(mime_str) + 1); |
1654 | |
1655 g_free(mime_str); | |
1656 gtk_tree_path_free(sourcerow); | |
1657 } | |
5228 | 1658 } |
1659 | |
1660 static void gaim_gtk_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, | |
1661 GtkSelectionData *sd, guint info, guint t) | |
7620 | 1662 { |
5228 | 1663 if (sd->target == gdk_atom_intern("GAIM_BLIST_NODE", FALSE) && sd->data) { |
1664 GaimBlistNode *n = NULL; | |
1665 GtkTreePath *path = NULL; | |
1666 GtkTreeViewDropPosition position; | |
1667 memcpy(&n, sd->data, sizeof(n)); | |
1668 if(gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget), x, y, &path, &position)) { | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
1669 /* if we're here, I think it means the drop is ok */ |
7642 | 1670 GtkTreeIter iter; |
5228 | 1671 GaimBlistNode *node; |
1672 GValue val = {0}; | |
7620 | 1673 struct _gaim_gtk_blist_node *gtknode; |
1674 | |
1675 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), | |
1676 &iter, path); | |
1677 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), | |
1678 &iter, NODE_COLUMN, &val); | |
5228 | 1679 node = g_value_get_pointer(&val); |
7620 | 1680 gtknode = node->ui_data; |
1681 | |
1682 if (GAIM_BLIST_NODE_IS_CONTACT(n)) { | |
1683 GaimContact *c = (GaimContact*)n; | |
1684 if (GAIM_BLIST_NODE_IS_CONTACT(node) && gtknode->contact_expanded) { | |
1685 gaim_blist_merge_contact(c, node); | |
1686 } else if (GAIM_BLIST_NODE_IS_CONTACT(node) || | |
5234 | 1687 GAIM_BLIST_NODE_IS_CHAT(node)) { |
5228 | 1688 switch(position) { |
1689 case GTK_TREE_VIEW_DROP_AFTER: | |
1690 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: | |
7620 | 1691 gaim_blist_add_contact(c, (GaimGroup*)node->parent, |
1692 node); | |
1693 break; | |
1694 case GTK_TREE_VIEW_DROP_BEFORE: | |
1695 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: | |
1696 gaim_blist_add_contact(c, (GaimGroup*)node->parent, | |
1697 node->prev); | |
1698 break; | |
1699 } | |
1700 } else if(GAIM_BLIST_NODE_IS_GROUP(node)) { | |
1701 gaim_blist_add_contact(c, (GaimGroup*)node, NULL); | |
1702 } else if(GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
1703 gaim_blist_merge_contact(c, node); | |
1704 } | |
1705 } else if (GAIM_BLIST_NODE_IS_BUDDY(n)) { | |
1706 GaimBuddy *b = (GaimBuddy*)n; | |
1707 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
1708 switch(position) { | |
1709 case GTK_TREE_VIEW_DROP_AFTER: | |
1710 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: | |
1711 gaim_blist_add_buddy(b, (GaimContact*)node->parent, | |
1712 (GaimGroup*)node->parent->parent, node); | |
5228 | 1713 break; |
1714 case GTK_TREE_VIEW_DROP_BEFORE: | |
1715 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: | |
7620 | 1716 gaim_blist_add_buddy(b, (GaimContact*)node->parent, |
1717 (GaimGroup*)node->parent->parent, | |
1718 node->prev); | |
5228 | 1719 break; |
1720 } | |
7620 | 1721 } else if(GAIM_BLIST_NODE_IS_CHAT(node)) { |
1722 gaim_blist_add_buddy(b, NULL, (GaimGroup*)node->parent, | |
1723 NULL); | |
5228 | 1724 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { |
7620 | 1725 gaim_blist_add_buddy(b, NULL, (GaimGroup*)node, NULL); |
1726 } else if (GAIM_BLIST_NODE_IS_CONTACT(node)) { | |
1727 if(gtknode->contact_expanded) { | |
1728 switch(position) { | |
1729 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: | |
1730 case GTK_TREE_VIEW_DROP_AFTER: | |
1731 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: | |
1732 gaim_blist_add_buddy(b, (GaimContact*)node, | |
1733 (GaimGroup*)node->parent, NULL); | |
1734 break; | |
1735 case GTK_TREE_VIEW_DROP_BEFORE: | |
1736 gaim_blist_add_buddy(b, NULL, | |
1737 (GaimGroup*)node->parent, node->prev); | |
1738 break; | |
1739 } | |
1740 } else { | |
1741 switch(position) { | |
1742 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: | |
1743 case GTK_TREE_VIEW_DROP_AFTER: | |
1744 gaim_blist_add_buddy(b, NULL, | |
1745 (GaimGroup*)node->parent, NULL); | |
1746 break; | |
1747 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: | |
1748 case GTK_TREE_VIEW_DROP_BEFORE: | |
1749 gaim_blist_add_buddy(b, NULL, | |
1750 (GaimGroup*)node->parent, node->prev); | |
1751 break; | |
1752 } | |
1753 } | |
5228 | 1754 } |
5234 | 1755 } else if (GAIM_BLIST_NODE_IS_CHAT(n)) { |
7620 | 1756 GaimChat *chat = (GaimChat *)n; |
1757 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
1758 switch(position) { | |
1759 case GTK_TREE_VIEW_DROP_AFTER: | |
1760 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: | |
1761 gaim_blist_add_chat(chat, | |
1762 (GaimGroup*)node->parent->parent, node); | |
1763 break; | |
1764 case GTK_TREE_VIEW_DROP_BEFORE: | |
1765 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: | |
1766 gaim_blist_add_chat(chat, | |
1767 (GaimGroup*)node->parent->parent, | |
1768 node->prev); | |
1769 break; | |
1770 } | |
1771 } else if(GAIM_BLIST_NODE_IS_CONTACT(node) || | |
5234 | 1772 GAIM_BLIST_NODE_IS_CHAT(node)) { |
1773 switch(position) { | |
1774 case GTK_TREE_VIEW_DROP_AFTER: | |
1775 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: | |
7620 | 1776 gaim_blist_add_chat(chat, (GaimGroup*)node->parent, node); |
5234 | 1777 break; |
1778 case GTK_TREE_VIEW_DROP_BEFORE: | |
1779 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: | |
7620 | 1780 gaim_blist_add_chat(chat, (GaimGroup*)node->parent, node->prev); |
5234 | 1781 break; |
1782 } | |
1783 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
7620 | 1784 gaim_blist_add_chat(chat, (GaimGroup*)node, NULL); |
5234 | 1785 } |
5228 | 1786 } else if (GAIM_BLIST_NODE_IS_GROUP(n)) { |
7620 | 1787 GaimGroup *g = (GaimGroup*)n; |
5228 | 1788 if (GAIM_BLIST_NODE_IS_GROUP(node)) { |
1789 switch (position) { | |
1790 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: | |
1791 case GTK_TREE_VIEW_DROP_AFTER: | |
1792 gaim_blist_add_group(g, node); | |
1793 break; | |
1794 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: | |
1795 case GTK_TREE_VIEW_DROP_BEFORE: | |
1796 gaim_blist_add_group(g, node->prev); | |
1797 break; | |
1798 } | |
7620 | 1799 } else if(GAIM_BLIST_NODE_IS_BUDDY(node)) { |
1800 gaim_blist_add_group(g, node->parent->parent); | |
1801 } else if(GAIM_BLIST_NODE_IS_CONTACT(node) || | |
5234 | 1802 GAIM_BLIST_NODE_IS_CHAT(node)) { |
5228 | 1803 gaim_blist_add_group(g, node->parent); |
1804 } | |
1805 } | |
1806 | |
1807 gtk_tree_path_free(path); | |
7620 | 1808 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); |
5228 | 1809 } |
1810 } | |
7706 | 1811 else if (sd->target == gdk_atom_intern("application/x-im-contact", |
1812 FALSE) && sd->data) | |
1813 { | |
1814 GaimGroup *group = NULL; | |
1815 GtkTreePath *path = NULL; | |
1816 GtkTreeViewDropPosition position; | |
7712
2823111061ba
[gaim-migrate @ 8357]
Christian Hammond <chipx86@chipx86.com>
parents:
7706
diff
changeset
|
1817 GaimAccount *account; |
7706 | 1818 char *protocol = NULL; |
1819 char *username = NULL; | |
1820 char *alias = NULL; | |
1821 | |
1822 if (gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget), | |
1823 x, y, &path, &position)) | |
1824 { | |
1825 GtkTreeIter iter; | |
1826 GaimBlistNode *node; | |
1827 GValue val = {0}; | |
1828 | |
1829 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), | |
1830 &iter, path); | |
1831 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), | |
1832 &iter, NODE_COLUMN, &val); | |
1833 node = g_value_get_pointer(&val); | |
1834 | |
1835 if (GAIM_BLIST_NODE_IS_BUDDY(node)) | |
1836 { | |
1837 group = (GaimGroup *)node->parent->parent; | |
1838 } | |
1839 else if (GAIM_BLIST_NODE_IS_CHAT(node) || | |
1840 GAIM_BLIST_NODE_IS_CONTACT(node)) | |
1841 { | |
1842 group = (GaimGroup *)node->parent; | |
1843 } | |
1844 else if (GAIM_BLIST_NODE_IS_GROUP(node)) | |
1845 { | |
1846 group = (GaimGroup *)node; | |
1847 } | |
1848 } | |
1849 | |
11137 | 1850 if (gaim_gtk_parse_x_im_contact((const char *)sd->data, FALSE, &account, |
7712
2823111061ba
[gaim-migrate @ 8357]
Christian Hammond <chipx86@chipx86.com>
parents:
7706
diff
changeset
|
1851 &protocol, &username, &alias)) |
7706 | 1852 { |
1853 if (account == NULL) | |
1854 { | |
1855 gaim_notify_error(NULL, NULL, | |
1856 _("You are not currently signed on with an account that " | |
1857 "can add that buddy."), NULL); | |
1858 } | |
1859 else | |
1860 { | |
1861 gaim_blist_request_add_buddy(account, username, | |
1862 (group ? group->name : NULL), | |
1863 alias); | |
1864 } | |
1865 } | |
1866 | |
1867 if (username != NULL) g_free(username); | |
1868 if (protocol != NULL) g_free(protocol); | |
1869 if (alias != NULL) g_free(alias); | |
1870 | |
1871 if (path != NULL) | |
1872 gtk_tree_path_free(path); | |
1873 | |
1874 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); | |
1875 } | |
8089 | 1876 else if (sd->target == gdk_atom_intern("text/x-vcard", FALSE) && sd->data) |
1877 { | |
1878 gboolean result; | |
1879 GaimGroup *group = NULL; | |
1880 GtkTreePath *path = NULL; | |
1881 GtkTreeViewDropPosition position; | |
1882 | |
1883 if (gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget), | |
1884 x, y, &path, &position)) | |
1885 { | |
1886 GtkTreeIter iter; | |
1887 GaimBlistNode *node; | |
1888 GValue val = {0}; | |
1889 | |
1890 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), | |
1891 &iter, path); | |
1892 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), | |
1893 &iter, NODE_COLUMN, &val); | |
1894 node = g_value_get_pointer(&val); | |
1895 | |
1896 if (GAIM_BLIST_NODE_IS_BUDDY(node)) | |
1897 { | |
1898 group = (GaimGroup *)node->parent->parent; | |
1899 } | |
1900 else if (GAIM_BLIST_NODE_IS_CHAT(node) || | |
1901 GAIM_BLIST_NODE_IS_CONTACT(node)) | |
1902 { | |
1903 group = (GaimGroup *)node->parent; | |
1904 } | |
1905 else if (GAIM_BLIST_NODE_IS_GROUP(node)) | |
1906 { | |
1907 group = (GaimGroup *)node; | |
1908 } | |
1909 } | |
1910 | |
11137 | 1911 result = parse_vcard((const gchar *)sd->data, group); |
8089 | 1912 |
1913 gtk_drag_finish(dc, result, (dc->action == GDK_ACTION_MOVE), t); | |
9525 | 1914 } else if (sd->target == gdk_atom_intern("text/uri-list", FALSE) && sd->data) { |
9495 | 1915 GtkTreePath *path = NULL; |
1916 GtkTreeViewDropPosition position; | |
1917 | |
1918 if (gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget), | |
9811 | 1919 x, y, &path, &position)) |
9495 | 1920 { |
1921 GtkTreeIter iter; | |
1922 GaimBlistNode *node; | |
1923 GValue val = {0}; | |
10382
9f28196ed769
[gaim-migrate @ 11608]
Luke Schierer <lschiere@pidgin.im>
parents:
10357
diff
changeset
|
1924 |
9495 | 1925 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), |
1926 &iter, path); | |
1927 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), | |
1928 &iter, NODE_COLUMN, &val); | |
1929 node = g_value_get_pointer(&val); | |
10382
9f28196ed769
[gaim-migrate @ 11608]
Luke Schierer <lschiere@pidgin.im>
parents:
10357
diff
changeset
|
1930 |
9495 | 1931 if (GAIM_BLIST_NODE_IS_BUDDY(node) || GAIM_BLIST_NODE_IS_CONTACT(node)) { |
1932 GaimBuddy *b = GAIM_BLIST_NODE_IS_BUDDY(node) ? (GaimBuddy*)node : gaim_contact_get_priority_buddy((GaimContact*)node); | |
10229 | 1933 gaim_dnd_file_manage(sd, b->account, b->name); |
1934 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); | |
1935 } else { | |
1936 gtk_drag_finish(dc, FALSE, FALSE, t); | |
9495 | 1937 } |
10382
9f28196ed769
[gaim-migrate @ 11608]
Luke Schierer <lschiere@pidgin.im>
parents:
10357
diff
changeset
|
1938 } |
8089 | 1939 } |
5228 | 1940 } |
1941 | |
10482 | 1942 static GdkPixbuf *gaim_gtk_blist_get_buddy_icon(GaimBlistNode *node, |
1943 gboolean scaled, gboolean greyed) | |
1944 { | |
10483 | 1945 GdkPixbuf *buf, *ret = NULL; |
10482 | 1946 GdkPixbufLoader *loader; |
1947 GaimBuddyIcon *icon; | |
11137 | 1948 const guchar *data; |
1949 gsize len; | |
10482 | 1950 GaimBuddy *buddy = (GaimBuddy *)node; |
1951 | |
1952 if(GAIM_BLIST_NODE_IS_CONTACT(node)) { | |
1953 buddy = gaim_contact_get_priority_buddy((GaimContact*)node); | |
1954 } else if(GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
1955 buddy = (GaimBuddy*)node; | |
1956 } else { | |
1957 return NULL; | |
1958 } | |
1959 | |
1960 #if 0 | |
1961 if (!gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons")) | |
1962 return NULL; | |
1963 #endif | |
1964 | |
1965 if (!(icon = gaim_buddy_get_icon(buddy))) | |
1966 if (!(icon = gaim_buddy_icons_find(buddy->account, buddy->name))) /* Not sure I like this...*/ | |
1967 return NULL; | |
1968 | |
1969 loader = gdk_pixbuf_loader_new(); | |
1970 data = gaim_buddy_icon_get_data(icon, &len); | |
1971 gdk_pixbuf_loader_write(loader, data, len, NULL); | |
1972 buf = gdk_pixbuf_loader_get_pixbuf(loader); | |
1973 if (buf) | |
1974 g_object_ref(G_OBJECT(buf)); | |
1975 gdk_pixbuf_loader_close(loader, NULL); | |
1976 g_object_unref(G_OBJECT(loader)); | |
1977 | |
1978 if (buf) { | |
10544 | 1979 GaimAccount *account = gaim_buddy_get_account(buddy); |
1980 GaimPluginProtocolInfo *prpl_info = NULL; | |
1981 int orig_width, orig_height; | |
1982 int scale_width, scale_height; | |
1983 | |
1984 if(account && account->gc) | |
1985 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(account->gc->prpl); | |
1986 | |
10482 | 1987 if (greyed) { |
1988 GaimPresence *presence = gaim_buddy_get_presence(buddy); | |
1989 if (!GAIM_BUDDY_IS_ONLINE(buddy)) | |
1990 gdk_pixbuf_saturate_and_pixelate(buf, buf, 0.0, FALSE); | |
1991 if (gaim_presence_is_idle(presence)) | |
1992 gdk_pixbuf_saturate_and_pixelate(buf, buf, 0.25, FALSE); | |
1993 } | |
1994 | |
10544 | 1995 /* i'd use the gaim_gtk_buddy_icon_get_scale_size() thing, |
1996 * but it won't tell me the original size, which I need for scaling | |
1997 * purposes */ | |
1998 scale_width = orig_width = gdk_pixbuf_get_width(buf); | |
1999 scale_height = orig_height = gdk_pixbuf_get_height(buf); | |
2000 | |
2001 gaim_buddy_icon_get_scale_size(prpl_info ? &prpl_info->icon_spec : NULL, &scale_width, &scale_height); | |
2002 | |
10482 | 2003 if (scaled) { |
10544 | 2004 if(scale_height > scale_width) { |
2005 scale_width = 30.0 * (double)scale_width / (double)scale_height; | |
2006 scale_height = 30; | |
2007 } else { | |
2008 scale_height = 30.0 * (double)scale_height / (double)scale_width; | |
2009 scale_width = 30; | |
2010 } | |
2011 | |
2012 ret = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 30, 30); | |
2013 gdk_pixbuf_fill(ret, 0x00000000); | |
2014 gdk_pixbuf_scale(buf, ret, (30-scale_width)/2, (30-scale_height)/2, scale_width, scale_height, (30-scale_width)/2, (30-scale_height)/2, (double)scale_width/(double)orig_width, (double)scale_height/(double)orig_height, GDK_INTERP_BILINEAR); | |
10483 | 2015 } else { |
2016 ret = gdk_pixbuf_scale_simple(buf,scale_width,scale_height, GDK_INTERP_BILINEAR); | |
2017 } | |
10544 | 2018 g_object_unref(G_OBJECT(buf)); |
10482 | 2019 } |
2020 | |
10483 | 2021 return ret; |
10482 | 2022 } |
2023 | |
11890 | 2024 struct tooltip_data { |
2025 PangoLayout *layout; | |
2026 GdkPixbuf *status_icon; | |
2027 GdkPixbuf *avatar; | |
11892 | 2028 int avatar_width; |
2029 int width; | |
2030 int height; | |
11890 | 2031 }; |
2032 | |
2033 static struct tooltip_data * create_tip_for_node(GaimBlistNode *node) | |
2034 { | |
2035 struct tooltip_data *td = g_new0(struct tooltip_data, 1); | |
2036 char *tooltip_text = gaim_get_tooltip_text(node); | |
2037 | |
2038 td->status_icon = gaim_gtk_blist_get_status_icon(node, GAIM_STATUS_ICON_LARGE); | |
2039 td->avatar = gaim_gtk_blist_get_buddy_icon(node, FALSE, FALSE); | |
2040 | |
2041 td->layout = gtk_widget_create_pango_layout(gtkblist->tipwindow, NULL); | |
2042 pango_layout_set_markup(td->layout, tooltip_text, strlen(tooltip_text)); | |
2043 pango_layout_set_wrap(td->layout, PANGO_WRAP_WORD); | |
2044 pango_layout_set_width(td->layout, 300000); | |
11983 | 2045 |
11892 | 2046 pango_layout_get_size (td->layout, &td->width, &td->height); |
2047 td->width = PANGO_PIXELS(td->width) + 38 + 8; | |
2048 td->height = MAX(PANGO_PIXELS(td->height) + 8, 38); | |
2049 | |
2050 if(td->avatar) { | |
2051 td->avatar_width = gdk_pixbuf_get_width(td->avatar); | |
2052 td->width += td->avatar_width + 8; | |
2053 td->height = MAX(td->height, gdk_pixbuf_get_height(td->avatar) + 8); | |
2054 } | |
11890 | 2055 |
2056 return td; | |
2057 } | |
2058 | |
5234 | 2059 static void gaim_gtk_blist_paint_tip(GtkWidget *widget, GdkEventExpose *event, GaimBlistNode *node) |
5228 | 2060 { |
2061 GtkStyle *style; | |
11892 | 2062 int current_height, max_width; |
11890 | 2063 GList *l; |
2064 | |
2065 if(gtkblist->tooltipdata == NULL) | |
7620 | 2066 return; |
2067 | |
11890 | 2068 style = gtkblist->tipwindow->style; |
2069 gtk_paint_flat_box(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, | |
2070 NULL, gtkblist->tipwindow, "tooltip", 0, 0, -1, -1); | |
2071 | |
11892 | 2072 max_width = 0; |
2073 for(l = gtkblist->tooltipdata; l; l = l->next) | |
2074 { | |
2075 struct tooltip_data *td = l->data; | |
2076 max_width = MAX(max_width, td->width); | |
2077 } | |
2078 | |
11890 | 2079 current_height = 0; |
2080 for(l = gtkblist->tooltipdata; l; l = l->next) | |
10482 | 2081 { |
11890 | 2082 struct tooltip_data *td = l->data; |
5228 | 2083 |
2084 #if GTK_CHECK_VERSION(2,2,0) | |
11890 | 2085 gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, td->status_icon, |
2086 0, 0, 4, current_height + 4, -1 , -1, GDK_RGB_DITHER_NONE, 0, 0); | |
2087 if(td->avatar) | |
2088 gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, | |
11892 | 2089 td->avatar, 0, 0, max_width - (td->avatar_width + 4), current_height + 4, -1 , -1, GDK_RGB_DITHER_NONE, 0, 0); |
5228 | 2090 #else |
11890 | 2091 gdk_pixbuf_render_to_drawable(td->status_icon, GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, 0, 0, 4, current_height + 4, -1, -1, GDK_RGB_DITHER_NONE, 0, 0); |
2092 if(td->avatar) | |
2093 gdk_pixbuf_render_to_drawable(td->avatar, | |
11983 | 2094 GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, 0, 0, |
11892 | 2095 max_width - (td->avatar_width + 4), |
11890 | 2096 current_height + 4, -1, -1, GDK_RGB_DITHER_NONE, 0, 0); |
5228 | 2097 #endif |
2098 | |
11890 | 2099 gtk_paint_layout (style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE, |
2100 NULL, gtkblist->tipwindow, "tooltip", 38 + 4, current_height + 4, td->layout); | |
2101 | |
11895 | 2102 current_height += td->height; |
2103 | |
11894 | 2104 if(l->next) |
11895 | 2105 gtk_paint_hline(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, NULL, NULL, NULL, 4, max_width - 4, current_height-2); |
11890 | 2106 } |
5228 | 2107 } |
2108 | |
8254 | 2109 static void gaim_gtk_blist_tooltip_destroy() |
2110 { | |
11890 | 2111 while(gtkblist->tooltipdata) { |
2112 struct tooltip_data *td = gtkblist->tooltipdata->data; | |
2113 | |
2114 if(td->avatar) | |
2115 g_object_unref(td->avatar); | |
2116 if(td->status_icon) | |
2117 g_object_unref(td->status_icon); | |
2118 g_object_unref(td->layout); | |
2119 g_free(td); | |
2120 gtkblist->tooltipdata = g_list_delete_link(gtkblist->tooltipdata, gtkblist->tooltipdata); | |
2121 } | |
11636 | 2122 |
8254 | 2123 if (gtkblist->tipwindow == NULL) |
2124 return; | |
2125 | |
2126 gtk_widget_destroy(gtkblist->tipwindow); | |
2127 gtkblist->tipwindow = NULL; | |
2128 } | |
2129 | |
10354 | 2130 static gboolean gaim_gtk_blist_expand_timeout(GtkWidget *tv) |
2131 { | |
2132 GtkTreePath *path; | |
2133 GtkTreeIter iter; | |
2134 GaimBlistNode *node; | |
2135 GValue val = {0}; | |
2136 struct _gaim_gtk_blist_node *gtknode; | |
2137 | |
2138 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->tip_rect.x, gtkblist->tip_rect.y, &path, NULL, NULL, NULL)) | |
2139 return FALSE; | |
2140 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); | |
2141 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
2142 node = g_value_get_pointer(&val); | |
2143 | |
10504 | 2144 if(!GAIM_BLIST_NODE_IS_CONTACT(node)) { |
2145 gtk_tree_path_free(path); | |
10354 | 2146 return FALSE; |
10504 | 2147 } |
10354 | 2148 |
2149 gtknode = node->ui_data; | |
2150 | |
2151 if (!gtknode->contact_expanded) { | |
2152 GtkTreeIter i; | |
10382
9f28196ed769
[gaim-migrate @ 11608]
Luke Schierer <lschiere@pidgin.im>
parents:
10357
diff
changeset
|
2153 |
10354 | 2154 gaim_gtk_blist_expand_contact_cb(NULL, node); |
10382
9f28196ed769
[gaim-migrate @ 11608]
Luke Schierer <lschiere@pidgin.im>
parents:
10357
diff
changeset
|
2155 |
10354 | 2156 gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, >kblist->contact_rect); |
2157 gdk_drawable_get_size(GDK_DRAWABLE(tv->window), &(gtkblist->contact_rect.width), NULL); | |
2158 gtkblist->mouseover_contact = node; | |
2159 gtk_tree_path_down (path); | |
2160 while (gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &i, path)) { | |
2161 GdkRectangle rect; | |
2162 gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, &rect); | |
2163 gtkblist->contact_rect.height += rect.height; | |
2164 gtk_tree_path_next(path); | |
2165 } | |
2166 } | |
2167 gtk_tree_path_free(path); | |
2168 return FALSE; | |
2169 } | |
2170 | |
11890 | 2171 static gboolean buddy_is_displayable(GaimBuddy *buddy) |
2172 { | |
11910 | 2173 struct _gaim_gtk_blist_node *gtknode; |
2174 | |
2175 if(!buddy) | |
2176 return FALSE; | |
2177 | |
2178 gtknode = ((GaimBlistNode*)buddy)->ui_data; | |
2179 | |
2180 return (gaim_account_is_connected(buddy->account) && | |
11890 | 2181 (gaim_presence_is_online(buddy->presence) || |
11910 | 2182 (gtknode && gtknode->recent_signonoff) || |
2183 gaim_prefs_get_bool("/gaim/gtk/blist/show_offline_buddies") || | |
2184 gaim_blist_node_get_bool((GaimBlistNode*)buddy, "show_offline"))); | |
11890 | 2185 } |
2186 | |
5228 | 2187 static gboolean gaim_gtk_blist_tooltip_timeout(GtkWidget *tv) |
2188 { | |
2189 GtkTreePath *path; | |
2190 GtkTreeIter iter; | |
2191 GaimBlistNode *node; | |
2192 GValue val = {0}; | |
9869 | 2193 int scr_w, scr_h, w, h, x, y; |
2194 #if GTK_CHECK_VERSION(2,2,0) | |
2195 int mon_num; | |
2196 GdkScreen *screen = NULL; | |
2197 #endif | |
7636 | 2198 gboolean tooltip_top = FALSE; |
2199 struct _gaim_gtk_blist_node *gtknode; | |
9773 | 2200 GdkRectangle mon_size; |
5228 | 2201 |
11636 | 2202 /* |
2203 * Attempt to free the previous tooltip. I have a feeling | |
2204 * this is never needed... but just in case. | |
2205 */ | |
2206 gaim_gtk_blist_tooltip_destroy(); | |
2207 | |
7636 | 2208 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->tip_rect.x, gtkblist->tip_rect.y, &path, NULL, NULL, NULL)) |
5228 | 2209 return FALSE; |
2210 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); | |
2211 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
2212 node = g_value_get_pointer(&val); | |
7620 | 2213 |
10504 | 2214 gtk_tree_path_free(path); |
2215 | |
11890 | 2216 gtkblist->tipwindow = gtk_window_new(GTK_WINDOW_POPUP); |
2217 | |
2218 if(GAIM_BLIST_NODE_IS_CHAT(node) || GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
2219 struct tooltip_data *td = create_tip_for_node(node); | |
2220 gtkblist->tooltipdata = g_list_append(gtkblist->tooltipdata, td); | |
11892 | 2221 w = td->width; |
2222 h = td->height; | |
11890 | 2223 } else if(GAIM_BLIST_NODE_IS_CONTACT(node)) { |
2224 GaimBlistNode *child; | |
11988 | 2225 GaimBuddy *b = gaim_contact_get_priority_buddy((GaimContact *)node); |
11890 | 2226 w = h = 0; |
2227 for(child = node->child; child; child = child->next) | |
2228 { | |
2229 if(GAIM_BLIST_NODE_IS_BUDDY(child) && buddy_is_displayable((GaimBuddy*)child)) { | |
2230 struct tooltip_data *td = create_tip_for_node(child); | |
11988 | 2231 if (b == (GaimBuddy *)child) { |
2232 gtkblist->tooltipdata = g_list_prepend(gtkblist->tooltipdata, td); | |
2233 } else { | |
2234 gtkblist->tooltipdata = g_list_append(gtkblist->tooltipdata, td); | |
2235 } | |
11892 | 2236 w = MAX(w, td->width); |
2237 h += td->height; | |
11890 | 2238 } |
2239 } | |
2240 } else { | |
2241 gtk_widget_destroy(gtkblist->tipwindow); | |
11892 | 2242 gtkblist->tipwindow = NULL; |
5234 | 2243 return FALSE; |
11890 | 2244 } |
2245 | |
2246 if (gtkblist->tooltipdata == NULL) { | |
2247 gtk_widget_destroy(gtkblist->tipwindow); | |
11892 | 2248 gtkblist->tipwindow = NULL; |
11890 | 2249 return FALSE; |
2250 } | |
5228 | 2251 |
7636 | 2252 gtknode = node->ui_data; |
2253 | |
5234 | 2254 gtk_widget_set_app_paintable(gtkblist->tipwindow, TRUE); |
2255 gtk_window_set_resizable(GTK_WINDOW(gtkblist->tipwindow), FALSE); | |
2256 gtk_widget_set_name(gtkblist->tipwindow, "gtk-tooltips"); | |
2257 g_signal_connect(G_OBJECT(gtkblist->tipwindow), "expose_event", | |
11890 | 2258 G_CALLBACK(gaim_gtk_blist_paint_tip), NULL); |
5234 | 2259 gtk_widget_ensure_style (gtkblist->tipwindow); |
7837 | 2260 |
9773 | 2261 |
9869 | 2262 #if GTK_CHECK_VERSION(2,2,0) |
9773 | 2263 gdk_display_get_pointer(gdk_display_get_default(), &screen, &x, &y, NULL); |
2264 mon_num = gdk_screen_get_monitor_at_point(screen, x, y); | |
2265 gdk_screen_get_monitor_geometry(screen, mon_num, &mon_size); | |
2266 | |
2267 scr_w = mon_size.width + mon_size.x; | |
2268 scr_h = mon_size.height + mon_size.y; | |
9869 | 2269 #else |
2270 scr_w = gdk_screen_width(); | |
2271 scr_h = gdk_screen_height(); | |
2272 gdk_window_get_pointer(NULL, &x, &y, NULL); | |
2273 mon_size.x = 0; | |
2274 mon_size.y = 0; | |
2275 #endif | |
9773 | 2276 |
9869 | 2277 #if GTK_CHECK_VERSION(2,2,0) |
10046 | 2278 if (w > mon_size.width) |
9773 | 2279 w = mon_size.width - 10; |
2280 | |
10046 | 2281 if (h > mon_size.height) |
9773 | 2282 h = mon_size.height - 10; |
9869 | 2283 #endif |
9773 | 2284 |
5234 | 2285 if (GTK_WIDGET_NO_WINDOW(gtkblist->window)) |
2286 y+=gtkblist->window->allocation.y; | |
2287 | |
2288 x -= ((w >> 1) + 4); | |
5228 | 2289 |
7636 | 2290 if ((y + h + 4) > scr_h || tooltip_top) |
7620 | 2291 y = y - h - 5; |
5234 | 2292 else |
2293 y = y + 6; | |
7620 | 2294 |
9773 | 2295 if (y < mon_size.y) |
2296 y = mon_size.y; | |
2297 | |
2298 if (y != mon_size.y) { | |
7719 | 2299 if ((x + w) > scr_w) |
2300 x -= (x + w + 5) - scr_w; | |
9773 | 2301 else if (x < mon_size.x) |
2302 x = mon_size.x; | |
7719 | 2303 } else { |
2304 x -= (w / 2 + 10); | |
9773 | 2305 if (x < mon_size.x) |
2306 x = mon_size.x; | |
7719 | 2307 } |
2308 | |
5234 | 2309 gtk_widget_set_size_request(gtkblist->tipwindow, w, h); |
2310 gtk_window_move(GTK_WINDOW(gtkblist->tipwindow), x, y); | |
2311 gtk_widget_show(gtkblist->tipwindow); | |
5228 | 2312 |
2313 return FALSE; | |
2314 } | |
2315 | |
10354 | 2316 static gboolean gaim_gtk_blist_drag_motion_cb(GtkWidget *tv, GdkDragContext *drag_context, |
2317 gint x, gint y, guint time, gpointer user_data) | |
2318 { | |
2319 GtkTreePath *path; | |
2320 int delay; | |
2321 | |
2322 delay = 500; | |
2323 | |
2324 if (gtkblist->drag_timeout) { | |
2325 if ((y > gtkblist->tip_rect.y) && ((y - gtkblist->tip_rect.height) < gtkblist->tip_rect.y)) | |
2326 return FALSE; | |
2327 /* We've left the cell. Remove the timeout and create a new one below */ | |
2328 g_source_remove(gtkblist->drag_timeout); | |
2329 } | |
2330 | |
2331 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), x, y, &path, NULL, NULL, NULL); | |
2332 gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, >kblist->tip_rect); | |
2333 | |
2334 if (path) | |
2335 gtk_tree_path_free(path); | |
2336 gtkblist->drag_timeout = g_timeout_add(delay, (GSourceFunc)gaim_gtk_blist_expand_timeout, tv); | |
2337 | |
2338 if (gtkblist->mouseover_contact) { | |
2339 if ((y < gtkblist->contact_rect.y) || ((y - gtkblist->contact_rect.height) > gtkblist->contact_rect.y)) { | |
2340 gaim_gtk_blist_collapse_contact_cb(NULL, gtkblist->mouseover_contact); | |
2341 gtkblist->mouseover_contact = NULL; | |
2342 } | |
2343 } | |
2344 | |
2345 return FALSE; | |
2346 } | |
2347 | |
5228 | 2348 static gboolean gaim_gtk_blist_motion_cb (GtkWidget *tv, GdkEventMotion *event, gpointer null) |
2349 { | |
2350 GtkTreePath *path; | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2351 int delay; |
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2352 |
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2353 delay = gaim_prefs_get_int("/gaim/gtk/blist/tooltip_delay"); |
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2354 |
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2355 if (delay == 0) |
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2356 return FALSE; |
8083 | 2357 |
5228 | 2358 if (gtkblist->timeout) { |
7636 | 2359 if ((event->y > gtkblist->tip_rect.y) && ((event->y - gtkblist->tip_rect.height) < gtkblist->tip_rect.y)) |
5228 | 2360 return FALSE; |
2361 /* We've left the cell. Remove the timeout and create a new one below */ | |
8254 | 2362 gaim_gtk_blist_tooltip_destroy(); |
5228 | 2363 g_source_remove(gtkblist->timeout); |
2364 } | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2365 |
5228 | 2366 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), event->x, event->y, &path, NULL, NULL, NULL); |
7636 | 2367 gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, >kblist->tip_rect); |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2368 |
5228 | 2369 if (path) |
2370 gtk_tree_path_free(path); | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2371 gtkblist->timeout = g_timeout_add(delay, (GSourceFunc)gaim_gtk_blist_tooltip_timeout, tv); |
7636 | 2372 |
2373 if (gtkblist->mouseover_contact) { | |
2374 if ((event->y < gtkblist->contact_rect.y) || ((event->y - gtkblist->contact_rect.height) > gtkblist->contact_rect.y)) { | |
2375 gaim_gtk_blist_collapse_contact_cb(NULL, gtkblist->mouseover_contact); | |
2376 gtkblist->mouseover_contact = NULL; | |
2377 } | |
2378 } | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2379 |
5228 | 2380 return FALSE; |
2381 } | |
2382 | |
2383 static void gaim_gtk_blist_leave_cb (GtkWidget *w, GdkEventCrossing *e, gpointer n) | |
2384 { | |
8083 | 2385 |
5228 | 2386 if (gtkblist->timeout) { |
2387 g_source_remove(gtkblist->timeout); | |
2388 gtkblist->timeout = 0; | |
2389 } | |
10382
9f28196ed769
[gaim-migrate @ 11608]
Luke Schierer <lschiere@pidgin.im>
parents:
10357
diff
changeset
|
2390 |
10354 | 2391 if (gtkblist->drag_timeout) { |
2392 g_source_remove(gtkblist->drag_timeout); | |
2393 gtkblist->drag_timeout = 0; | |
2394 } | |
2395 | |
8254 | 2396 gaim_gtk_blist_tooltip_destroy(); |
7720 | 2397 |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2398 if (gtkblist->mouseover_contact && |
9811 | 2399 !((e->x > gtkblist->contact_rect.x) && (e->x < (gtkblist->contact_rect.x + gtkblist->contact_rect.width)) && |
2400 (e->y > gtkblist->contact_rect.y) && (e->y < (gtkblist->contact_rect.y + gtkblist->contact_rect.height)))) { | |
2401 gaim_gtk_blist_collapse_contact_cb(NULL, gtkblist->mouseover_contact); | |
7636 | 2402 gtkblist->mouseover_contact = NULL; |
2403 } | |
5228 | 2404 } |
2405 | |
2406 static void | |
2407 toggle_debug(void) | |
2408 { | |
7620 | 2409 gaim_prefs_set_bool("/gaim/gtk/debug/enabled", |
2410 !gaim_prefs_get_bool("/gaim/gtk/debug/enabled")); | |
5228 | 2411 } |
2412 | |
2413 | |
2414 /*************************************************** | |
2415 * Crap * | |
2416 ***************************************************/ | |
2417 static GtkItemFactoryEntry blist_menu[] = | |
2418 { | |
2419 /* Buddies menu */ | |
2420 { N_("/_Buddies"), NULL, NULL, 0, "<Branch>" }, | |
9714 | 2421 { N_("/Buddies/New Instant _Message..."), "<CTL>M", gaim_gtkdialogs_im, 0, "<StockItem>", GAIM_STOCK_IM }, |
8940 | 2422 { N_("/Buddies/Join a _Chat..."), "<CTL>C", gaim_gtk_blist_joinchat_show, 0, "<StockItem>", GAIM_STOCK_CHAT }, |
9714 | 2423 { N_("/Buddies/Get User _Info..."), "<CTL>I", gaim_gtkdialogs_info, 0, "<StockItem>", GAIM_STOCK_INFO }, |
2424 { N_("/Buddies/View User _Log..."), "<CTL>L", gaim_gtkdialogs_log, 0, NULL }, | |
5228 | 2425 { "/Buddies/sep1", NULL, NULL, 0, "<Separator>" }, |
11025 | 2426 { N_("/Buddies/Show _Offline Buddies"), NULL, gaim_gtk_blist_edit_mode_cb, 1, "<CheckItem>"}, |
2427 { N_("/Buddies/Show _Empty Groups"), NULL, gaim_gtk_blist_show_empty_groups_cb, 1, "<CheckItem>"}, | |
11796 | 2428 { N_("/Buddies/Show Buddy _Details"), NULL, gaim_gtk_blist_buddy_details_cb, 1, "<CheckItem>"}, |
11798
01c3eec6ea3c
[gaim-migrate @ 14089]
Etan Reisner <pidgin@unreliablesource.net>
parents:
11797
diff
changeset
|
2429 { N_("/Buddies/Sort Buddies"), NULL, NULL, 0, "<Branch>" }, |
11796 | 2430 { "/Buddies/sep2", NULL, NULL, 0, "<Separator>" }, |
7853 | 2431 { N_("/Buddies/_Add Buddy..."), "<CTL>B", gaim_gtk_blist_add_buddy_cb, 0, "<StockItem>", GTK_STOCK_ADD }, |
2432 { N_("/Buddies/Add C_hat..."), NULL, gaim_gtk_blist_add_chat_cb, 0, "<StockItem>", GTK_STOCK_ADD }, | |
2433 { N_("/Buddies/Add _Group..."), NULL, gaim_blist_request_add_group, 0, "<StockItem>", GTK_STOCK_ADD }, | |
11796 | 2434 { "/Buddies/sep3", NULL, NULL, 0, "<Separator>" }, |
7620 | 2435 { N_("/Buddies/_Quit"), "<CTL>Q", gaim_core_quit, 0, "<StockItem>", GTK_STOCK_QUIT }, |
5228 | 2436 |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2437 /* Tools */ |
5228 | 2438 { N_("/_Tools"), NULL, NULL, 0, "<Branch>" }, |
2439 { N_("/Tools/Buddy _Pounce"), NULL, NULL, 0, "<Branch>" }, | |
8845 | 2440 { N_("/Tools/Account Ac_tions"), NULL, NULL, 0, "<Branch>" }, |
5228 | 2441 { "/Tools/sep1", NULL, NULL, 0, "<Separator>" }, |
7620 | 2442 { N_("/Tools/A_ccounts"), "<CTL>A", gaim_gtk_accounts_window_show, 0, "<StockItem>", GAIM_STOCK_ACCOUNTS }, |
10325 | 2443 { N_("/Tools/Pr_eferences"), "<CTL>P", gaim_gtk_prefs_show, 0, "<StockItem>", GTK_STOCK_PREFERENCES }, |
12113 | 2444 { N_("/Tools/Plu_gins"), "<CTL>U", gaim_gtk_plugin_dialog_show, 0, NULL }, |
10694 | 2445 { N_("/Tools/Pr_ivacy"), NULL, gaim_gtk_privacy_dialog_show, 0, "<StockItem>", GTK_STOCK_DIALOG_ERROR }, |
10019
8cc6f0bfa215
[gaim-migrate @ 10943]
Luke Schierer <lschiere@pidgin.im>
parents:
10018
diff
changeset
|
2446 { N_("/Tools/_File Transfers"), "<CTL>T", gaim_show_xfer_dialog, 0, "<StockItem>", GAIM_STOCK_FILE_TRANSFER }, |
10694 | 2447 { N_("/Tools/R_oom List"), NULL, gaim_gtk_roomlist_dialog_show, 0, "<StockItem>", GTK_STOCK_INDEX }, |
10325 | 2448 { "/Tools/sep2", NULL, NULL, 0, "<Separator>" }, |
10074 | 2449 { N_("/Tools/Mute _Sounds"), "<CTL>S", gaim_gtk_blist_mute_sounds_cb, 0, "<CheckItem>"}, |
7620 | 2450 { N_("/Tools/View System _Log"), NULL, gtk_blist_show_systemlog_cb, 0, NULL }, |
5228 | 2451 |
2452 /* Help */ | |
2453 { N_("/_Help"), NULL, NULL, 0, "<Branch>" }, | |
2454 { N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, "<StockItem>", GTK_STOCK_HELP }, | |
7620 | 2455 { N_("/Help/_Debug Window"), NULL, toggle_debug, 0, NULL }, |
9753 | 2456 { N_("/Help/_About"), NULL, gaim_gtkdialogs_about, 0, "<StockItem>", GAIM_STOCK_ABOUT }, |
5228 | 2457 }; |
2458 | |
2459 /********************************************************* | |
2460 * Private Utility functions * | |
2461 *********************************************************/ | |
2462 | |
5234 | 2463 static char *gaim_get_tooltip_text(GaimBlistNode *node) |
5228 | 2464 { |
10475 | 2465 GString *str = g_string_new(""); |
5237 | 2466 GaimPlugin *prpl; |
2467 GaimPluginProtocolInfo *prpl_info = NULL; | |
10475 | 2468 char *tmp; |
2469 | |
2470 if (GAIM_BLIST_NODE_IS_CHAT(node)) | |
2471 { | |
2472 GaimChat *chat; | |
2473 GList *cur; | |
5274 | 2474 struct proto_chat_entry *pce; |
10475 | 2475 char *name, *value; |
2476 | |
2477 chat = (GaimChat *)node; | |
7956 | 2478 prpl = gaim_find_prpl(gaim_account_get_protocol_id(chat->account)); |
5274 | 2479 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); |
2480 | |
10475 | 2481 tmp = g_markup_escape_text(gaim_chat_get_name(chat), -1); |
2482 g_string_append_printf(str, "<span size='larger' weight='bold'>%s</span>", tmp); | |
2483 g_free(tmp); | |
2484 | |
2485 if (g_list_length(gaim_connections_get_all()) > 1) | |
2486 { | |
2487 tmp = g_markup_escape_text(chat->account->username, -1); | |
2488 g_string_append_printf(str, _("\n<b>Account:</b> %s"), tmp); | |
2489 g_free(tmp); | |
2490 } | |
2491 | |
9959 | 2492 if (prpl_info->chat_info != NULL) |
10475 | 2493 cur = prpl_info->chat_info(chat->account->gc); |
2494 else | |
2495 cur = NULL; | |
2496 | |
2497 while (cur != NULL) | |
2498 { | |
2499 pce = cur->data; | |
2500 | |
2501 if (!pce->secret && (!pce->required && | |
2502 g_hash_table_lookup(chat->components, pce->identifier) == NULL)) | |
2503 { | |
2504 tmp = gaim_text_strip_mnemonic(pce->label); | |
2505 name = g_markup_escape_text(tmp, -1); | |
2506 g_free(tmp); | |
2507 value = g_markup_escape_text(g_hash_table_lookup( | |
2508 chat->components, pce->identifier), -1); | |
10924
7a82d86ab44a
[gaim-migrate @ 12695]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10918
diff
changeset
|
2509 g_string_append_printf(str, "\n<b>%s</b> %s", |
7a82d86ab44a
[gaim-migrate @ 12695]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10918
diff
changeset
|
2510 name ? name : "", |
7a82d86ab44a
[gaim-migrate @ 12695]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10918
diff
changeset
|
2511 value ? value : ""); |
10475 | 2512 g_free(name); |
8020 | 2513 g_free(value); |
2514 } | |
10475 | 2515 |
5274 | 2516 g_free(pce); |
10475 | 2517 cur = g_list_remove(cur, pce); |
5274 | 2518 } |
10475 | 2519 } |
2520 else if (GAIM_BLIST_NODE_IS_CONTACT(node) || GAIM_BLIST_NODE_IS_BUDDY(node)) | |
2521 { | |
2522 GaimContact *c; | |
7620 | 2523 GaimBuddy *b; |
9944 | 2524 GaimPresence *presence; |
10475 | 2525 char *tmp; |
9944 | 2526 gboolean idle; |
10567 | 2527 time_t idle_secs, signon; |
10475 | 2528 |
2529 if (GAIM_BLIST_NODE_IS_CONTACT(node)) | |
2530 { | |
2531 c = (GaimContact *)node; | |
2532 b = gaim_contact_get_priority_buddy(c); | |
2533 } | |
2534 else | |
2535 { | |
7620 | 2536 b = (GaimBuddy *)node; |
10475 | 2537 c = gaim_buddy_get_contact(b); |
7620 | 2538 } |
2539 | |
7956 | 2540 prpl = gaim_find_prpl(gaim_account_get_protocol_id(b->account)); |
5234 | 2541 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); |
2542 | |
10475 | 2543 presence = gaim_buddy_get_presence(b); |
2544 | |
2545 /* Buddy Name */ | |
2546 tmp = g_markup_escape_text(gaim_buddy_get_name(b), -1); | |
2547 g_string_append_printf(str, "<span size='larger' weight='bold'>%s</span>", tmp); | |
2548 g_free(tmp); | |
2549 | |
2550 /* Account */ | |
2551 if (g_list_length(gaim_connections_get_all()) > 1) | |
2552 { | |
2553 tmp = g_markup_escape_text(gaim_account_get_username( | |
2554 gaim_buddy_get_account(b)), -1); | |
2555 g_string_append_printf(str, _("\n<b>Account:</b> %s"), tmp); | |
2556 g_free(tmp); | |
2557 } | |
2558 | |
2559 /* Contact Alias */ | |
2560 if (GAIM_BLIST_NODE_IS_CONTACT(node) && | |
10499 | 2561 (c->alias != NULL)) |
10475 | 2562 { |
10499 | 2563 tmp = g_markup_escape_text(c->alias, -1); |
10475 | 2564 g_string_append_printf(str, _("\n<b>Contact Alias:</b> %s"), tmp); |
2565 g_free(tmp); | |
2566 } | |
2567 | |
2568 /* Alias */ | |
2569 if ((b->alias != NULL) && (b->alias[0] != '\0')) | |
2570 { | |
2571 tmp = g_markup_escape_text(b->alias, -1); | |
2572 g_string_append_printf(str, _("\n<b>Alias:</b> %s"), tmp); | |
2573 g_free(tmp); | |
2574 } | |
2575 | |
2576 /* Nickname/Server Alias */ | |
2577 if (b->server_alias != NULL) | |
2578 { | |
2579 tmp = g_markup_escape_text(b->server_alias, -1); | |
2580 g_string_append_printf(str, _("\n<b>Nickname:</b> %s"), tmp); | |
2581 g_free(tmp); | |
2582 } | |
2583 | |
2584 /* Logged In */ | |
10567 | 2585 signon = gaim_presence_get_login_time(presence); |
10992
2bda44d66641
[gaim-migrate @ 12830]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10968
diff
changeset
|
2586 if (GAIM_BUDDY_IS_ONLINE(b) && signon > 0) |
10475 | 2587 { |
10567 | 2588 tmp = gaim_str_seconds_to_string(time(NULL) - signon); |
10475 | 2589 g_string_append_printf(str, _("\n<b>Logged In:</b> %s"), tmp); |
2590 g_free(tmp); | |
2591 } | |
2592 | |
2593 /* Idle */ | |
2594 idle = gaim_presence_is_idle(presence); | |
2595 if (idle) | |
2596 { | |
2597 idle_secs = gaim_presence_get_idle_time(presence); | |
2598 if (idle_secs > 0) | |
2599 { | |
2600 tmp = gaim_str_seconds_to_string(time(NULL) - idle_secs); | |
2601 g_string_append_printf(str, _("\n<b>Idle:</b> %s"), tmp); | |
2602 g_free(tmp); | |
2603 } | |
2604 } | |
2605 | |
2606 /* Last Seen */ | |
11910 | 2607 if (!GAIM_BUDDY_IS_ONLINE(b)) |
10475 | 2608 { |
11023 | 2609 struct _gaim_gtk_blist_node *gtknode = ((GaimBlistNode *)c)->ui_data; |
2610 GaimBlistNode *bnode; | |
2611 int lastseen = 0; | |
2612 | |
2613 if (!gtknode->contact_expanded || GAIM_BLIST_NODE_IS_CONTACT(node)) | |
2614 { | |
11437
1c20849fc716
[gaim-migrate @ 13674]
Richard Laager <rlaager@wiktel.com>
parents:
11436
diff
changeset
|
2615 /* We're either looking at a buddy for a collapsed contact or |
11438
5451fe2d89c0
[gaim-migrate @ 13675]
Richard Laager <rlaager@wiktel.com>
parents:
11437
diff
changeset
|
2616 * an expanded contact itself so we show the most recent |
11023 | 2617 * (largest) last_seen time for any of the buddies under |
2618 * the contact. */ | |
2619 for (bnode = ((GaimBlistNode *)c)->child ; bnode != NULL ; bnode = bnode->next) | |
2620 { | |
2621 int value = gaim_blist_node_get_int(bnode, "last_seen"); | |
2622 if (value > lastseen) | |
2623 lastseen = value; | |
2624 } | |
2625 } | |
2626 else | |
2627 { | |
2628 /* We're dealing with a buddy under an expanded contact, | |
2629 * so we show the last_seen time for the buddy. */ | |
2630 lastseen = gaim_blist_node_get_int(&b->node, "last_seen"); | |
2631 } | |
2632 | |
10475 | 2633 if (lastseen > 0) |
2634 { | |
2635 tmp = gaim_str_seconds_to_string(time(NULL) - lastseen); | |
2636 g_string_append_printf(str, _("\n<b>Last Seen:</b> %s ago"), tmp); | |
2637 g_free(tmp); | |
5234 | 2638 } |
2639 } | |
2640 | |
10475 | 2641 |
2642 /* Offline? */ | |
2643 if (!GAIM_BUDDY_IS_ONLINE(b)) { | |
2644 g_string_append_printf(str, _("\n<b>Status:</b> Offline")); | |
2645 } | |
10992
2bda44d66641
[gaim-migrate @ 12830]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10968
diff
changeset
|
2646 |
2bda44d66641
[gaim-migrate @ 12830]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10968
diff
changeset
|
2647 if (prpl_info && prpl_info->tooltip_text) |
10475 | 2648 { |
2649 /* Additional text from the PRPL */ | |
2650 const char *end; | |
2651 tmp = prpl_info->tooltip_text(b); | |
2652 | |
2653 if (tmp && !g_utf8_validate(tmp, -1, &end)) | |
2654 { | |
2655 char *new = g_strndup(tmp, g_utf8_pointer_to_offset(tmp, end)); | |
2656 g_free(tmp); | |
2657 tmp = new; | |
2658 } | |
2659 | |
11634 | 2660 if (tmp != NULL) |
2661 g_string_append(str, tmp); | |
10476 | 2662 g_free(tmp); |
10475 | 2663 } |
2664 | |
2665 /* These are Easter Eggs. Patches to remove them will be rejected. */ | |
2666 if (!g_ascii_strcasecmp(b->name, "robflynn")) | |
2667 g_string_append(str, _("\n<b>Description:</b> Spooky")); | |
2668 if (!g_ascii_strcasecmp(b->name, "seanegn")) | |
2669 g_string_append(str, _("\n<b>Status:</b> Awesome")); | |
2670 if (!g_ascii_strcasecmp(b->name, "chipx86")) | |
2671 g_string_append(str, _("\n<b>Status:</b> Rockin'")); | |
5234 | 2672 } |
10475 | 2673 |
8824 | 2674 gaim_signal_emit(gaim_gtk_blist_get_handle(), |
10477 | 2675 "drawing-tooltip", node, str); |
10475 | 2676 |
2677 return g_string_free(str, FALSE); | |
5228 | 2678 } |
2679 | |
7620 | 2680 struct _emblem_data { |
9954 | 2681 const char *filename; |
7620 | 2682 int x; |
2683 int y; | |
2684 }; | |
2685 | |
9944 | 2686 GdkPixbuf * |
2687 gaim_gtk_blist_get_status_icon(GaimBlistNode *node, GaimStatusIconSize size) | |
5228 | 2688 { |
7620 | 2689 GdkPixbuf *scale, *status = NULL; |
2690 int i, scalesize = 30; | |
2691 char *filename; | |
5228 | 2692 const char *protoname = NULL; |
7620 | 2693 struct _gaim_gtk_blist_node *gtknode = node->ui_data; |
11910 | 2694 struct _gaim_gtk_blist_node *gtkbuddynode = NULL; |
7620 | 2695 struct _emblem_data emblems[4] = {{NULL, 15, 15}, {NULL, 0, 15}, |
2696 {NULL, 0, 0}, {NULL, 15, 0}}; | |
9944 | 2697 GaimPresence *presence = NULL; |
7620 | 2698 GaimBuddy *buddy = NULL; |
2699 GaimChat *chat = NULL; | |
2700 | |
2701 if(GAIM_BLIST_NODE_IS_CONTACT(node)) { | |
11910 | 2702 if(!gtknode->contact_expanded) { |
7620 | 2703 buddy = gaim_contact_get_priority_buddy((GaimContact*)node); |
11910 | 2704 gtkbuddynode = ((GaimBlistNode*)buddy)->ui_data; |
2705 } | |
7620 | 2706 } else if(GAIM_BLIST_NODE_IS_BUDDY(node)) { |
2707 buddy = (GaimBuddy*)node; | |
11910 | 2708 gtkbuddynode = node->ui_data; |
7620 | 2709 } else if(GAIM_BLIST_NODE_IS_CHAT(node)) { |
2710 chat = (GaimChat*)node; | |
2711 } else { | |
5228 | 2712 return NULL; |
5234 | 2713 } |
2714 | |
7620 | 2715 if(buddy || chat) { |
2716 GaimAccount *account; | |
2717 GaimPlugin *prpl; | |
2718 GaimPluginProtocolInfo *prpl_info; | |
2719 | |
2720 if(buddy) | |
2721 account = buddy->account; | |
2722 else | |
2723 account = chat->account; | |
2724 | |
7956 | 2725 prpl = gaim_find_prpl(gaim_account_get_protocol_id(account)); |
7620 | 2726 if(!prpl) |
2727 return NULL; | |
2728 | |
2729 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); | |
2730 | |
2731 if(prpl_info && prpl_info->list_icon) { | |
2732 protoname = prpl_info->list_icon(account, buddy); | |
2733 } | |
2734 if(prpl_info && prpl_info->list_emblems && buddy) { | |
11924 | 2735 if(gtknode && !gtknode->recent_signonoff) |
7620 | 2736 prpl_info->list_emblems(buddy, &emblems[0].filename, |
2737 &emblems[1].filename, &emblems[2].filename, | |
2738 &emblems[3].filename); | |
2739 } | |
5234 | 2740 } |
5228 | 2741 |
7620 | 2742 if(size == GAIM_STATUS_ICON_SMALL) { |
5228 | 2743 scalesize = 15; |
7620 | 2744 /* So that only the se icon will composite */ |
2745 emblems[1].filename = emblems[2].filename = emblems[3].filename = NULL; | |
5228 | 2746 } |
2747 | |
11917 | 2748 if(buddy && GAIM_BUDDY_IS_ONLINE(buddy) && gtkbuddynode && gtkbuddynode->recent_signonoff) { |
7620 | 2749 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "login.png", NULL); |
11917 | 2750 } else if(buddy && !GAIM_BUDDY_IS_ONLINE(buddy) && gtkbuddynode && gtkbuddynode->recent_signonoff) { |
7620 | 2751 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "logout.png", NULL); |
2752 } else if(buddy || chat) { | |
5228 | 2753 char *image = g_strdup_printf("%s.png", protoname); |
2754 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
2755 g_free(image); | |
7620 | 2756 } else { |
2757 /* gaim dude */ | |
2758 filename = g_build_filename(DATADIR, "pixmaps", "gaim.png", NULL); | |
5228 | 2759 } |
7620 | 2760 |
2761 status = gdk_pixbuf_new_from_file(filename, NULL); | |
2762 g_free(filename); | |
2763 | |
2764 if(!status) | |
2765 return NULL; | |
2766 | |
2767 scale = gdk_pixbuf_scale_simple(status, scalesize, scalesize, | |
2768 GDK_INTERP_BILINEAR); | |
2769 g_object_unref(status); | |
2770 | |
2771 for(i=0; i<4; i++) { | |
2772 if(emblems[i].filename) { | |
2773 GdkPixbuf *emblem; | |
2774 char *image = g_strdup_printf("%s.png", emblems[i].filename); | |
2775 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
2776 g_free(image); | |
2777 emblem = gdk_pixbuf_new_from_file(filename, NULL); | |
2778 g_free(filename); | |
2779 if(emblem) { | |
2780 if(i == 0 && size == GAIM_STATUS_ICON_SMALL) { | |
2781 gdk_pixbuf_composite(emblem, | |
2782 scale, 5, 5, | |
2783 10, 10, | |
2784 5, 5, | |
2785 .6, .6, | |
2786 GDK_INTERP_BILINEAR, | |
2787 255); | |
2788 } else { | |
2789 gdk_pixbuf_composite(emblem, | |
2790 scale, emblems[i].x, emblems[i].y, | |
2791 15, 15, | |
2792 emblems[i].x, emblems[i].y, | |
2793 1, 1, | |
2794 GDK_INTERP_BILINEAR, | |
2795 255); | |
2796 } | |
2797 g_object_unref(emblem); | |
2798 } | |
5228 | 2799 } |
2800 } | |
7620 | 2801 |
2802 if(buddy) { | |
9944 | 2803 presence = gaim_buddy_get_presence(buddy); |
2804 | |
2805 if (!GAIM_BUDDY_IS_ONLINE(buddy)) | |
7620 | 2806 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.0, FALSE); |
10118 | 2807 else if (gaim_presence_is_idle(presence)) |
9944 | 2808 { |
7620 | 2809 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.25, FALSE); |
9944 | 2810 } |
11111
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2811 |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2812 if (!gaim_privacy_check(buddy->account, gaim_buddy_get_name(buddy))) |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2813 { |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2814 GdkPixbuf *emblem; |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2815 char *filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "blocked.png", NULL); |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2816 |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2817 emblem = gdk_pixbuf_new_from_file(filename, NULL); |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2818 g_free(filename); |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2819 |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2820 if (emblem) |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2821 { |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2822 gdk_pixbuf_composite(emblem, scale, |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2823 0, 0, scalesize, scalesize, |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2824 0, 0, |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2825 (double)scalesize / gdk_pixbuf_get_width(emblem), |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2826 (double)scalesize / gdk_pixbuf_get_height(emblem), |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2827 GDK_INTERP_BILINEAR, |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2828 224); |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2829 g_object_unref(emblem); |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2830 } |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
2831 } |
5228 | 2832 } |
7620 | 2833 |
5228 | 2834 return scale; |
2835 } | |
2836 | |
7620 | 2837 static gchar *gaim_gtk_blist_get_name_markup(GaimBuddy *b, gboolean selected) |
5228 | 2838 { |
7620 | 2839 const char *name; |
2840 char *esc, *text = NULL; | |
5228 | 2841 GaimPlugin *prpl; |
2842 GaimPluginProtocolInfo *prpl_info = NULL; | |
7620 | 2843 GaimContact *contact; |
9944 | 2844 GaimPresence *presence; |
7620 | 2845 struct _gaim_gtk_blist_node *gtkcontactnode = NULL; |
11257 | 2846 char *idletime = NULL, *statustext = NULL; |
5228 | 2847 time_t t; |
7620 | 2848 /* XXX Clean up this crap */ |
2849 | |
2850 contact = (GaimContact*)((GaimBlistNode*)b)->parent; | |
2851 if(contact) | |
2852 gtkcontactnode = ((GaimBlistNode*)contact)->ui_data; | |
2853 | |
2854 if(gtkcontactnode && !gtkcontactnode->contact_expanded && contact->alias) | |
2855 name = contact->alias; | |
2856 else | |
9620 | 2857 name = gaim_buddy_get_alias(b); |
7620 | 2858 esc = g_markup_escape_text(name, strlen(name)); |
2859 | |
7956 | 2860 prpl = gaim_find_prpl(gaim_account_get_protocol_id(b->account)); |
5228 | 2861 |
2862 if (prpl != NULL) | |
2863 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); | |
2864 | |
9944 | 2865 presence = gaim_buddy_get_presence(b); |
2866 | |
7620 | 2867 if (!gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons")) { |
9944 | 2868 |
10118 | 2869 if ((gaim_presence_is_idle(presence) || !GAIM_BUDDY_IS_ONLINE(b)) && !selected) |
9944 | 2870 { |
10118 | 2871 text = g_strdup_printf("<span color='%s'>%s</span>", |
2872 dim_grey(), esc); | |
5228 | 2873 g_free(esc); |
2874 return text; | |
7620 | 2875 } |
9944 | 2876 else |
5228 | 2877 return esc; |
2878 } | |
2879 | |
8122
36674144c510
[gaim-migrate @ 8826]
Christian Hammond <chipx86@chipx86.com>
parents:
8113
diff
changeset
|
2880 if (prpl_info && prpl_info->status_text && b->account->gc) { |
5228 | 2881 char *tmp = prpl_info->status_text(b); |
2882 const char *end; | |
2883 | |
2884 if(tmp && !g_utf8_validate(tmp, -1, &end)) { | |
2885 char *new = g_strndup(tmp, | |
2886 g_utf8_pointer_to_offset(tmp, end)); | |
2887 g_free(tmp); | |
2888 tmp = new; | |
2889 } | |
2890 | |
10288 | 2891 #if !GTK_CHECK_VERSION(2,6,0) |
5228 | 2892 if(tmp) { |
2893 char buf[32]; | |
2894 char *c = tmp; | |
2895 int length = 0, vis=0; | |
2896 gboolean inside = FALSE; | |
2897 g_strdelimit(tmp, "\n", ' '); | |
11920 | 2898 gaim_str_strip_char(tmp, '\r'); |
5228 | 2899 |
2900 while(*c && vis < 20) { | |
2901 if(*c == '&') | |
2902 inside = TRUE; | |
2903 else if(*c == ';') | |
2904 inside = FALSE; | |
2905 if(!inside) | |
2906 vis++; | |
7620 | 2907 c = g_utf8_next_char(c); /* this is fun */ |
5228 | 2908 } |
2909 | |
7620 | 2910 length = c - tmp; |
2911 | |
5228 | 2912 if(vis == 20) |
2913 g_snprintf(buf, sizeof(buf), "%%.%ds...", length); | |
2914 else | |
2915 g_snprintf(buf, sizeof(buf), "%%s "); | |
2916 | |
2917 statustext = g_strdup_printf(buf, tmp); | |
2918 | |
2919 g_free(tmp); | |
2920 } | |
10288 | 2921 #else |
2922 statustext = tmp; | |
2923 #endif | |
5228 | 2924 } |
2925 | |
10351 | 2926 if (gaim_presence_is_idle(presence)) { |
9944 | 2927 time_t idle_secs = gaim_presence_get_idle_time(presence); |
2928 | |
10351 | 2929 if (idle_secs > 0) { |
9944 | 2930 int ihrs, imin; |
2931 | |
2932 time(&t); | |
2933 ihrs = (t - idle_secs) / 3600; | |
2934 imin = ((t - idle_secs) / 60) % 60; | |
2935 | |
2936 if (ihrs) | |
11134
f78e7e982cf4
[gaim-migrate @ 13195]
Richard Laager <rlaager@wiktel.com>
parents:
11111
diff
changeset
|
2937 idletime = g_strdup_printf(_("Idle (%dh %02dm) "), ihrs, imin); |
9944 | 2938 else |
2939 idletime = g_strdup_printf(_("Idle (%dm) "), imin); | |
2940 } | |
5228 | 2941 else |
9944 | 2942 idletime = g_strdup(_("Idle ")); |
5228 | 2943 } |
2944 | |
2945 if(!GAIM_BUDDY_IS_ONLINE(b) && !statustext) | |
7620 | 2946 statustext = g_strdup(_("Offline ")); |
2947 | |
10118 | 2948 if (gaim_presence_is_idle(presence) && !selected) { |
2949 text = g_strdup_printf("<span color='%s'>%s</span>\n" | |
11257 | 2950 "<span color='%s' size='smaller'>%s%s%s</span>", |
10118 | 2951 dim_grey(), esc, dim_grey(), |
5228 | 2952 statustext != NULL ? statustext : "", |
11134
f78e7e982cf4
[gaim-migrate @ 13195]
Richard Laager <rlaager@wiktel.com>
parents:
11111
diff
changeset
|
2953 (idletime != NULL && statustext != NULL) ? " - " : "", |
11257 | 2954 idletime != NULL ? idletime : ""); |
2955 } else if (statustext == NULL && idletime == NULL && GAIM_BUDDY_IS_ONLINE(b)) { | |
5228 | 2956 text = g_strdup(esc); |
2957 } else { | |
10118 | 2958 if (selected) |
2959 text = g_strdup_printf("%s\n" | |
11257 | 2960 "<span size='smaller'>%s%s%s</span>", esc, |
10118 | 2961 statustext != NULL ? statustext : "", |
11134
f78e7e982cf4
[gaim-migrate @ 13195]
Richard Laager <rlaager@wiktel.com>
parents:
11111
diff
changeset
|
2962 (idletime != NULL && statustext != NULL) ? " - " : "", |
11257 | 2963 idletime != NULL ? idletime : ""); |
10118 | 2964 else |
2965 text = g_strdup_printf("%s\n" | |
11257 | 2966 "<span color='%s' size='smaller'>%s%s%s</span>", esc, |
10144 | 2967 dim_grey(), |
10118 | 2968 statustext != NULL ? statustext : "", |
11134
f78e7e982cf4
[gaim-migrate @ 13195]
Richard Laager <rlaager@wiktel.com>
parents:
11111
diff
changeset
|
2969 (idletime != NULL && statustext != NULL) ? " - " : "", |
11257 | 2970 idletime != NULL ? idletime : ""); |
5228 | 2971 } |
2972 if (idletime) | |
2973 g_free(idletime); | |
2974 if (statustext) | |
2975 g_free(statustext); | |
2976 if (esc) | |
2977 g_free(esc); | |
2978 | |
2979 return text; | |
2980 } | |
2981 | |
2982 static void gaim_gtk_blist_restore_position() | |
2983 { | |
7620 | 2984 int blist_x, blist_y, blist_width, blist_height; |
2985 | |
2986 blist_width = gaim_prefs_get_int("/gaim/gtk/blist/width"); | |
2987 | |
2988 /* if the window exists, is hidden, we're saving positions, and the | |
2989 * position is sane... */ | |
2990 if (gtkblist && gtkblist->window && | |
2991 !GTK_WIDGET_VISIBLE(gtkblist->window) && blist_width != 0) { | |
2992 | |
2993 blist_x = gaim_prefs_get_int("/gaim/gtk/blist/x"); | |
2994 blist_y = gaim_prefs_get_int("/gaim/gtk/blist/y"); | |
2995 blist_height = gaim_prefs_get_int("/gaim/gtk/blist/height"); | |
2996 | |
5228 | 2997 /* ...check position is on screen... */ |
7620 | 2998 if (blist_x >= gdk_screen_width()) |
2999 blist_x = gdk_screen_width() - 100; | |
3000 else if (blist_x + blist_width < 0) | |
3001 blist_x = 100; | |
3002 | |
3003 if (blist_y >= gdk_screen_height()) | |
3004 blist_y = gdk_screen_height() - 100; | |
3005 else if (blist_y + blist_height < 0) | |
3006 blist_y = 100; | |
3007 | |
5228 | 3008 /* ...and move it back. */ |
7620 | 3009 gtk_window_move(GTK_WINDOW(gtkblist->window), blist_x, blist_y); |
3010 gtk_window_resize(GTK_WINDOW(gtkblist->window), blist_width, blist_height); | |
5228 | 3011 } |
3012 } | |
3013 | |
7620 | 3014 static gboolean gaim_gtk_blist_refresh_timer(GaimBuddyList *list) |
5228 | 3015 { |
7620 | 3016 GaimBlistNode *gnode, *cnode; |
3017 | |
3018 for(gnode = list->root; gnode; gnode = gnode->next) { | |
3019 if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) | |
5234 | 3020 continue; |
7620 | 3021 for(cnode = gnode->child; cnode; cnode = cnode->next) { |
3022 if(GAIM_BLIST_NODE_IS_CONTACT(cnode)) { | |
9944 | 3023 GaimBuddy *buddy; |
3024 | |
3025 buddy = gaim_contact_get_priority_buddy((GaimContact*)cnode); | |
10012 | 3026 |
3027 if (buddy && | |
3028 gaim_presence_is_idle(gaim_buddy_get_presence(buddy))) | |
9944 | 3029 gaim_gtk_blist_update(list, cnode); |
7620 | 3030 } |
5228 | 3031 } |
3032 } | |
3033 | |
3034 /* keep on going */ | |
3035 return TRUE; | |
3036 } | |
3037 | |
7620 | 3038 static void gaim_gtk_blist_hide_node(GaimBuddyList *list, GaimBlistNode *node) |
5260 | 3039 { |
3040 struct _gaim_gtk_blist_node *gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; | |
3041 GtkTreeIter iter; | |
3042 | |
3043 if (!gtknode || !gtknode->row || !gtkblist) | |
3044 return; | |
3045 | |
3046 if(gtkblist->selected_node == node) | |
3047 gtkblist->selected_node = NULL; | |
3048 | |
3049 if (get_iter_from_node(node, &iter)) { | |
3050 gtk_tree_store_remove(gtkblist->treemodel, &iter); | |
7620 | 3051 if(GAIM_BLIST_NODE_IS_CONTACT(node) || GAIM_BLIST_NODE_IS_BUDDY(node) |
3052 || GAIM_BLIST_NODE_IS_CHAT(node)) { | |
5260 | 3053 gaim_gtk_blist_update(list, node->parent); |
3054 } | |
3055 } | |
3056 gtk_tree_row_reference_free(gtknode->row); | |
3057 gtknode->row = NULL; | |
3058 } | |
3059 | |
10352 | 3060 static const char *require_connection[] = |
7620 | 3061 { |
10352 | 3062 N_("/Buddies/New Instant Message..."), |
3063 N_("/Buddies/Join a Chat..."), | |
3064 N_("/Buddies/Get User Info..."), | |
3065 N_("/Buddies/Add Buddy..."), | |
3066 N_("/Buddies/Add Chat..."), | |
3067 N_("/Buddies/Add Group..."), | |
3068 }; | |
3069 | |
10357 | 3070 static const int require_connection_size = sizeof(require_connection) |
3071 / sizeof(*require_connection); | |
10352 | 3072 |
3073 /** | |
3074 * Rebuild dynamic menus and make menu items sensitive/insensitive | |
3075 * where appropriate. | |
3076 */ | |
3077 static void | |
3078 update_menu_bar(GaimGtkBuddyList *gtkblist) | |
3079 { | |
8937 | 3080 GtkWidget *widget; |
10352 | 3081 gboolean sensitive; |
3082 int i; | |
3083 | |
3084 g_return_if_fail(gtkblist != NULL); | |
8259
4f9f68ab8770
[gaim-migrate @ 8982]
Christian Hammond <chipx86@chipx86.com>
parents:
8254
diff
changeset
|
3085 |
7620 | 3086 gaim_gtk_blist_update_protocol_actions(); |
8235 | 3087 gaim_gtkpounce_menu_build(gtkblist->bpmenu); |
8937 | 3088 |
10352 | 3089 sensitive = (gaim_connections_get_all() != NULL); |
3090 | |
10357 | 3091 for (i = 0; i < require_connection_size; i++) |
10352 | 3092 { |
3093 widget = gtk_item_factory_get_widget(gtkblist->ift, require_connection[i]); | |
3094 gtk_widget_set_sensitive(widget, sensitive); | |
3095 } | |
3096 | |
8940 | 3097 widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Buddies/Join a Chat...")); |
3098 gtk_widget_set_sensitive(widget, gaim_gtk_blist_joinchat_is_showable()); | |
3099 | |
11988 | 3100 widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Buddies/Add Chat...")); |
3101 gtk_widget_set_sensitive(widget, gaim_gtk_blist_joinchat_is_showable()); | |
3102 | |
8937 | 3103 widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Room List")); |
8939 | 3104 gtk_widget_set_sensitive(widget, gaim_gtk_roomlist_is_showable()); |
8938 | 3105 |
3106 widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Privacy")); | |
3107 gtk_widget_set_sensitive(widget, gaim_gtk_privacy_is_showable()); | |
7620 | 3108 } |
3109 | |
10352 | 3110 static void |
3111 sign_on_off_cb(GaimConnection *gc, GaimBuddyList *blist) | |
3112 { | |
3113 GaimGtkBuddyList *gtkblist = GAIM_GTK_BLIST(blist); | |
3114 | |
3115 update_menu_bar(gtkblist); | |
3116 } | |
8986 | 3117 |
3118 static void | |
3119 plugin_changed_cb(GaimPlugin *p, gpointer *data) | |
3120 { | |
3121 gaim_gtk_blist_update_plugin_actions(); | |
3122 } | |
3123 | |
5228 | 3124 /********************************************************************************** |
3125 * Public API Functions * | |
3126 **********************************************************************************/ | |
9774 | 3127 |
7620 | 3128 static void gaim_gtk_blist_new_list(GaimBuddyList *blist) |
5228 | 3129 { |
7620 | 3130 GaimGtkBuddyList *gtkblist; |
3131 | |
3132 gtkblist = g_new0(GaimGtkBuddyList, 1); | |
3133 blist->ui_data = gtkblist; | |
5228 | 3134 } |
3135 | |
5256 | 3136 static void gaim_gtk_blist_new_node(GaimBlistNode *node) |
3137 { | |
3138 node->ui_data = g_new0(struct _gaim_gtk_blist_node, 1); | |
3139 } | |
3140 | |
11018 | 3141 gboolean gaim_gtk_blist_node_is_contact_expanded(GaimBlistNode *node) |
3142 { | |
3143 if GAIM_BLIST_NODE_IS_BUDDY(node) | |
3144 node = node->parent; | |
3145 | |
3146 g_return_val_if_fail(GAIM_BLIST_NODE_IS_CONTACT(node), FALSE); | |
3147 | |
3148 return ((struct _gaim_gtk_blist_node *)node->ui_data)->contact_expanded; | |
3149 } | |
3150 | |
5228 | 3151 void gaim_gtk_blist_update_columns() |
3152 { | |
3153 if(!gtkblist) | |
3154 return; | |
3155 | |
7620 | 3156 if (gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons")) { |
5228 | 3157 gtk_tree_view_column_set_visible(gtkblist->buddy_icon_column, TRUE); |
3158 gtk_tree_view_column_set_visible(gtkblist->idle_column, FALSE); | |
3159 } else { | |
10351 | 3160 gtk_tree_view_column_set_visible(gtkblist->idle_column, TRUE); |
5228 | 3161 gtk_tree_view_column_set_visible(gtkblist->buddy_icon_column, FALSE); |
3162 } | |
3163 } | |
3164 | |
10433 | 3165 enum { |
3166 DRAG_BUDDY, | |
3167 DRAG_ROW, | |
3168 DRAG_VCARD, | |
3169 DRAG_TEXT, | |
3170 DRAG_URI, | |
3171 NUM_TARGETS | |
3172 }; | |
5228 | 3173 |
3174 static char * | |
3175 item_factory_translate_func (const char *path, gpointer func_data) | |
3176 { | |
7620 | 3177 return _((char *)path); |
5228 | 3178 } |
3179 | |
5422 | 3180 void gaim_gtk_blist_setup_sort_methods() |
3181 { | |
11798
01c3eec6ea3c
[gaim-migrate @ 14089]
Etan Reisner <pidgin@unreliablesource.net>
parents:
11797
diff
changeset
|
3182 gaim_gtk_blist_sort_method_reg("none", _("Manually"), sort_method_none); |
7620 | 3183 #if GTK_CHECK_VERSION(2,2,1) |
11798
01c3eec6ea3c
[gaim-migrate @ 14089]
Etan Reisner <pidgin@unreliablesource.net>
parents:
11797
diff
changeset
|
3184 gaim_gtk_blist_sort_method_reg("alphabetical", _("Alphabetically"), sort_method_alphabetical); |
7620 | 3185 gaim_gtk_blist_sort_method_reg("status", _("By status"), sort_method_status); |
3186 gaim_gtk_blist_sort_method_reg("log_size", _("By log size"), sort_method_log); | |
3187 #endif | |
3188 gaim_gtk_blist_sort_method_set(gaim_prefs_get_string("/gaim/gtk/blist/sort_type")); | |
3189 } | |
3190 | |
10433 | 3191 static void _prefs_change_redo_list() |
3192 { | |
7620 | 3193 redo_buddy_list(gaim_get_blist(), TRUE); |
3194 } | |
3195 | |
3196 static void _prefs_change_sort_method(const char *pref_name, GaimPrefType type, | |
10433 | 3197 gpointer val, gpointer data) |
3198 { | |
7620 | 3199 if(!strcmp(pref_name, "/gaim/gtk/blist/sort_type")) |
3200 gaim_gtk_blist_sort_method_set(val); | |
3201 } | |
3202 | |
10433 | 3203 /* |
3204 * "This is so dead sexy." | |
3205 * "Two thumbs up." | |
3206 * "Best movie of the year." | |
3207 * | |
3208 * This is the function that handles CTRL+F searching in the buddy list. | |
3209 * It finds the top-most buddy/group/chat/whatever containing the | |
3210 * entered string. | |
3211 * | |
3212 * It's somewhat ineffecient, because we strip all the HTML from the | |
3213 * "name" column of the buddy list (because the GtkTreeModel does not | |
3214 * contain the screen name in a non-markedup format). But the alternative | |
3215 * is to add an extra column to the GtkTreeModel. And this function is | |
3216 * used rarely, so it shouldn't matter TOO much. | |
3217 */ | |
3218 static gboolean | |
3219 _search_func(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer search_data) | |
3220 { | |
10435 | 3221 gboolean result; |
10433 | 3222 gchar *enteredstring; |
10439 | 3223 gchar *withmarkup; |
10433 | 3224 gchar *nomarkup; |
11490 | 3225 gchar *normalized; |
10435 | 3226 |
3227 gtk_tree_model_get(model, iter, column, &withmarkup, -1); | |
10433 | 3228 |
11490 | 3229 enteredstring = g_utf8_casefold(gaim_normalize(NULL, key), -1); |
10433 | 3230 nomarkup = gaim_markup_strip_html(withmarkup); |
11490 | 3231 normalized = g_utf8_casefold(gaim_normalize(NULL, nomarkup), -1); |
10433 | 3232 |
3233 result = (g_strstr_len(normalized, strlen(normalized), enteredstring) == NULL); | |
3234 | |
10439 | 3235 g_free(withmarkup); |
10433 | 3236 g_free(enteredstring); |
3237 g_free(nomarkup); | |
11490 | 3238 g_free(normalized); |
10433 | 3239 |
3240 return result; | |
3241 } | |
3242 | |
12070 | 3243 static void account_enabled(GaimAccount *account, GaimGtkBuddyList *gtkblist) |
3244 { | |
3245 GtkWidget *box; | |
3246 | |
3247 if (!gtkblist) | |
3248 return; | |
3249 | |
3250 box = gtk_gaim_status_box_new_with_account(account); | |
3251 gtkblist->statusboxes = g_list_append(gtkblist->statusboxes, box); | |
3252 gtk_box_pack_start(GTK_BOX(gtkblist->statusboxbox), box, FALSE, TRUE, 0); | |
3253 gtk_widget_show(box); | |
3254 } | |
3255 | |
3256 static void account_disabled(GaimAccount *account, GaimGtkBuddyList *gtkblist) | |
3257 { | |
3258 GList *iter; | |
3259 | |
3260 if (!gtkblist) | |
3261 return; | |
3262 | |
3263 for (iter = gtkblist->statusboxes; iter; iter = iter->next) | |
3264 { | |
3265 GtkWidget *box = iter->data; | |
3266 GaimAccount *ac = NULL; | |
3267 | |
3268 g_object_get(G_OBJECT(box), "account", &ac, NULL); | |
3269 if (ac == account) | |
3270 { | |
3271 gtkblist->statusboxes = g_list_remove_link(gtkblist->statusboxes, iter); | |
3272 gtk_widget_destroy(box); | |
3273 break; | |
3274 } | |
3275 } | |
3276 } | |
3277 | |
7620 | 3278 static void gaim_gtk_blist_show(GaimBuddyList *list) |
5228 | 3279 { |
10087 | 3280 void *handle; |
5228 | 3281 GtkCellRenderer *rend; |
3282 GtkTreeViewColumn *column; | |
10178
96a850ab30c8
[gaim-migrate @ 11293]
Christian Hammond <chipx86@chipx86.com>
parents:
10144
diff
changeset
|
3283 GtkWidget *menu; |
5228 | 3284 GtkWidget *sw; |
11983 | 3285 GtkWidget *vpane; |
5228 | 3286 GtkAccelGroup *accel_group; |
3287 GtkTreeSelection *selection; | |
9556 | 3288 GtkTargetEntry dte[] = {{"GAIM_BLIST_NODE", GTK_TARGET_SAME_APP, DRAG_ROW}, |
8089 | 3289 {"application/x-im-contact", 0, DRAG_BUDDY}, |
9495 | 3290 {"text/x-vcard", 0, DRAG_VCARD }, |
9525 | 3291 {"text/uri-list", 0, DRAG_URI}, |
3292 {"text/plain", 0, DRAG_TEXT}}; | |
9556 | 3293 GtkTargetEntry ste[] = {{"GAIM_BLIST_NODE", GTK_TARGET_SAME_APP, DRAG_ROW}, |
3294 {"application/x-im-contact", 0, DRAG_BUDDY}, | |
3295 {"text/x-vcard", 0, DRAG_VCARD }}; | |
5228 | 3296 if (gtkblist && gtkblist->window) { |
12115
e9790eb93216
[gaim-migrate @ 14415]
Luke Schierer <lschiere@pidgin.im>
parents:
12113
diff
changeset
|
3297 if(!GTK_WIDGET_VISIBLE(gtkblist->window)) |
e9790eb93216
[gaim-migrate @ 14415]
Luke Schierer <lschiere@pidgin.im>
parents:
12113
diff
changeset
|
3298 gaim_blist_set_visible(gaim_prefs_get_bool("/gaim/gtk/blist/list_visible")); |
5228 | 3299 return; |
3300 } | |
3301 | |
3302 gtkblist = GAIM_GTK_BLIST(list); | |
3303 | |
3304 gtkblist->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
3305 gtk_window_set_role(GTK_WINDOW(gtkblist->window), "buddy_list"); | |
9746 | 3306 gtk_window_set_title(GTK_WINDOW(gtkblist->window), _("Buddy List")); |
5228 | 3307 |
3308 gtkblist->vbox = gtk_vbox_new(FALSE, 0); | |
10178
96a850ab30c8
[gaim-migrate @ 11293]
Christian Hammond <chipx86@chipx86.com>
parents:
10144
diff
changeset
|
3309 gtk_widget_show(gtkblist->vbox); |
5228 | 3310 gtk_container_add(GTK_CONTAINER(gtkblist->window), gtkblist->vbox); |
3311 | |
12016
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
3312 g_signal_connect(G_OBJECT(gtkblist->window), "delete_event", G_CALLBACK(gtk_blist_delete_cb), NULL); |
5228 | 3313 g_signal_connect(G_OBJECT(gtkblist->window), "configure_event", G_CALLBACK(gtk_blist_configure_cb), NULL); |
12016
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
3314 g_signal_connect(G_OBJECT(gtkblist->window), "visibility_notify_event", G_CALLBACK(gtk_blist_visibility_cb), NULL); |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
3315 g_signal_connect(G_OBJECT(gtkblist->window), "window_state_event", G_CALLBACK(gtk_blist_window_state_cb), NULL); |
5228 | 3316 gtk_widget_add_events(gtkblist->window, GDK_VISIBILITY_NOTIFY_MASK); |
3317 | |
3318 /******************************* Menu bar *************************************/ | |
3319 accel_group = gtk_accel_group_new(); | |
3320 gtk_window_add_accel_group(GTK_WINDOW (gtkblist->window), accel_group); | |
3321 g_object_unref(accel_group); | |
5427 | 3322 gtkblist->ift = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<GaimMain>", accel_group); |
9811 | 3323 gtk_item_factory_set_translate_func(gtkblist->ift, |
3324 item_factory_translate_func, | |
3325 NULL, NULL); | |
5427 | 3326 gtk_item_factory_create_items(gtkblist->ift, sizeof(blist_menu) / sizeof(*blist_menu), |
9811 | 3327 blist_menu, NULL); |
7620 | 3328 gaim_gtk_load_accels(); |
3329 g_signal_connect(G_OBJECT(accel_group), "accel-changed", | |
3330 G_CALLBACK(gaim_gtk_save_accels_cb), NULL); | |
10178
96a850ab30c8
[gaim-migrate @ 11293]
Christian Hammond <chipx86@chipx86.com>
parents:
10144
diff
changeset
|
3331 menu = gtk_item_factory_get_widget(gtkblist->ift, "<GaimMain>"); |
96a850ab30c8
[gaim-migrate @ 11293]
Christian Hammond <chipx86@chipx86.com>
parents:
10144
diff
changeset
|
3332 gtk_widget_show(menu); |
96a850ab30c8
[gaim-migrate @ 11293]
Christian Hammond <chipx86@chipx86.com>
parents:
10144
diff
changeset
|
3333 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), menu, FALSE, FALSE, 0); |
5228 | 3334 |
5427 | 3335 gtkblist->bpmenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Buddy Pounce")); |
8844 | 3336 protomenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Account Actions")); |
10352 | 3337 |
11983 | 3338 /****************************** GtkVPaned ************************************/ |
3339 vpane = gtk_vpaned_new(); | |
3340 gtk_widget_show(vpane); | |
3341 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), vpane, TRUE, TRUE, 0); | |
3342 | |
5228 | 3343 /****************************** GtkTreeView **********************************/ |
3344 sw = gtk_scrolled_window_new(NULL,NULL); | |
10178
96a850ab30c8
[gaim-migrate @ 11293]
Christian Hammond <chipx86@chipx86.com>
parents:
10144
diff
changeset
|
3345 gtk_widget_show(sw); |
5228 | 3346 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN); |
3347 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
3348 | |
7620 | 3349 gtkblist->treemodel = gtk_tree_store_new(BLIST_COLUMNS, |
11494 | 3350 GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN, |
11257 | 3351 G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_POINTER); |
5228 | 3352 |
3353 gtkblist->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(gtkblist->treemodel)); | |
10178
96a850ab30c8
[gaim-migrate @ 11293]
Christian Hammond <chipx86@chipx86.com>
parents:
10144
diff
changeset
|
3354 gtk_widget_show(gtkblist->treeview); |
9176 | 3355 gtk_widget_set_name(gtkblist->treeview, "gaim_gtkblist_treeview"); |
5228 | 3356 |
3357 /* Set up selection stuff */ | |
3358 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkblist->treeview)); | |
3359 g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(gaim_gtk_blist_selection_changed), NULL); | |
3360 | |
3361 /* Set up dnd */ | |
7650 | 3362 gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(gtkblist->treeview), |
9811 | 3363 GDK_BUTTON1_MASK, ste, 3, |
3364 GDK_ACTION_COPY); | |
7650 | 3365 gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(gtkblist->treeview), |
9811 | 3366 dte, 5, |
3367 GDK_ACTION_COPY | GDK_ACTION_MOVE); | |
7636 | 3368 |
10544 | 3369 g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-data-received", G_CALLBACK(gaim_gtk_blist_drag_data_rcv_cb), NULL); |
5228 | 3370 g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-data-get", G_CALLBACK(gaim_gtk_blist_drag_data_get_cb), NULL); |
11059
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
3371 #ifdef _WIN32 |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
3372 g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-begin", G_CALLBACK(gaim_gtk_blist_drag_begin), NULL); |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
3373 #endif |
10433 | 3374 |
10354 | 3375 g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-motion", G_CALLBACK(gaim_gtk_blist_drag_motion_cb), NULL); |
5228 | 3376 |
3377 /* Tooltips */ | |
3378 g_signal_connect(G_OBJECT(gtkblist->treeview), "motion-notify-event", G_CALLBACK(gaim_gtk_blist_motion_cb), NULL); | |
3379 g_signal_connect(G_OBJECT(gtkblist->treeview), "leave-notify-event", G_CALLBACK(gaim_gtk_blist_leave_cb), NULL); | |
3380 | |
3381 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(gtkblist->treeview), FALSE); | |
3382 | |
11016 | 3383 gtkblist->text_column = column = gtk_tree_view_column_new (); |
5228 | 3384 |
3385 rend = gtk_cell_renderer_pixbuf_new(); | |
9811 | 3386 gtk_tree_view_column_pack_start(column, rend, FALSE); |
3387 gtk_tree_view_column_set_attributes(column, rend, | |
3388 "pixbuf", STATUS_ICON_COLUMN, | |
3389 "visible", STATUS_ICON_VISIBLE_COLUMN, | |
3390 NULL); | |
5228 | 3391 g_object_set(rend, "xalign", 0.0, "ypad", 0, NULL); |
3392 | |
11016 | 3393 gtkblist->text_rend = rend = gtk_cell_renderer_text_new(); |
5228 | 3394 gtk_tree_view_column_pack_start (column, rend, TRUE); |
9811 | 3395 gtk_tree_view_column_set_attributes(column, rend, |
3396 "markup", NAME_COLUMN, | |
3397 NULL); | |
11016 | 3398 g_signal_connect(G_OBJECT(rend), "edited", G_CALLBACK(gtk_blist_renderer_edited_cb), NULL); |
5228 | 3399 g_object_set(rend, "ypad", 0, "yalign", 0.5, NULL); |
10285 | 3400 #if GTK_CHECK_VERSION(2,6,0) |
3401 gtk_tree_view_column_set_expand (column, TRUE); | |
10501 | 3402 g_object_set(rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL); |
10285 | 3403 #endif |
5228 | 3404 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), column); |
3405 | |
3406 rend = gtk_cell_renderer_text_new(); | |
10351 | 3407 gtkblist->idle_column = gtk_tree_view_column_new_with_attributes("Idle", rend, "markup", IDLE_COLUMN, NULL); |
3408 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), gtkblist->idle_column); | |
5228 | 3409 g_object_set(rend, "xalign", 1.0, "ypad", 0, NULL); |
3410 | |
3411 rend = gtk_cell_renderer_pixbuf_new(); | |
3412 gtkblist->buddy_icon_column = gtk_tree_view_column_new_with_attributes("Buddy Icon", rend, "pixbuf", BUDDY_ICON_COLUMN, NULL); | |
3413 g_object_set(rend, "xalign", 1.0, "ypad", 0, NULL); | |
3414 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), gtkblist->buddy_icon_column); | |
3415 | |
3416 g_signal_connect(G_OBJECT(gtkblist->treeview), "row-activated", G_CALLBACK(gtk_blist_row_activated_cb), NULL); | |
3417 g_signal_connect(G_OBJECT(gtkblist->treeview), "row-expanded", G_CALLBACK(gtk_blist_row_expanded_cb), NULL); | |
3418 g_signal_connect(G_OBJECT(gtkblist->treeview), "row-collapsed", G_CALLBACK(gtk_blist_row_collapsed_cb), NULL); | |
3419 g_signal_connect(G_OBJECT(gtkblist->treeview), "button-press-event", G_CALLBACK(gtk_blist_button_press_cb), NULL); | |
7620 | 3420 g_signal_connect(G_OBJECT(gtkblist->treeview), "key-press-event", G_CALLBACK(gtk_blist_key_press_cb), NULL); |
8143 | 3421 g_signal_connect(G_OBJECT(gtkblist->treeview), "popup-menu", G_CALLBACK(gaim_gtk_blist_popup_menu_cb), NULL); |
5228 | 3422 |
5419 | 3423 /* Enable CTRL+F searching */ |
3424 gtk_tree_view_set_search_column(GTK_TREE_VIEW(gtkblist->treeview), NAME_COLUMN); | |
10433 | 3425 gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(gtkblist->treeview), _search_func, NULL, NULL); |
5419 | 3426 |
11983 | 3427 gtk_paned_pack1(GTK_PANED(vpane), sw, TRUE, FALSE); |
5228 | 3428 gtk_container_add(GTK_CONTAINER(sw), gtkblist->treeview); |
3429 gaim_gtk_blist_update_columns(); | |
3430 | |
11732 | 3431 /* TODO: functionize this */ |
3432 { | |
3433 GList *accounts, *l; | |
11983 | 3434 GtkWidget *sw2 = gtk_scrolled_window_new(NULL, NULL); |
3435 | |
11732 | 3436 /* Set up some per account status boxes */ |
3437 gtkblist->statusboxbox = gtk_vbox_new(FALSE, 0); | |
3438 gtkblist->statusboxes = NULL; | |
11983 | 3439 |
11732 | 3440 for (l = accounts = gaim_accounts_get_all_active(); l; l = l->next) { |
3441 GtkWidget *statusbox = gtk_gaim_status_box_new_with_account(l->data); | |
3442 gtkblist->statusboxes = g_list_append(gtkblist->statusboxes, statusbox); | |
3443 gtk_box_pack_start(GTK_BOX(gtkblist->statusboxbox), statusbox, FALSE, TRUE, 0); | |
3444 gtk_widget_show(statusbox); | |
3445 } | |
3446 g_list_free(accounts); | |
11983 | 3447 |
11732 | 3448 gtk_widget_show(gtkblist->statusboxbox); |
11983 | 3449 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw2), gtkblist->statusboxbox); |
3450 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw2), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); | |
3451 gtk_widget_show(sw2); | |
3452 gtk_paned_pack2(GTK_PANED(vpane), sw2, FALSE, TRUE); | |
11732 | 3453 |
3454 gtkblist->statusbox = gtk_gaim_status_box_new(); | |
3455 | |
3456 gtk_widget_show(gtkblist->statusbox); | |
3457 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->statusbox, FALSE, TRUE, 0); | |
3458 | |
3459 } | |
10178
96a850ab30c8
[gaim-migrate @ 11293]
Christian Hammond <chipx86@chipx86.com>
parents:
10144
diff
changeset
|
3460 |
5228 | 3461 /* set the Show Offline Buddies option. must be done |
3462 * after the treeview or faceprint gets mad. -Robot101 | |
3463 */ | |
5427 | 3464 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show Offline Buddies"))), |
7620 | 3465 gaim_prefs_get_bool("/gaim/gtk/blist/show_offline_buddies")); |
5427 | 3466 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show Empty Groups"))), |
7620 | 3467 gaim_prefs_get_bool("/gaim/gtk/blist/show_empty_groups")); |
10074 | 3468 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Tools/Mute Sounds"))), |
3469 gaim_prefs_get_bool("/gaim/gtk/sound/mute")); | |
11796 | 3470 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show Buddy Details"))), |
11920 | 3471 gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons")); |
10074 | 3472 if(!strcmp(gaim_prefs_get_string("/gaim/gtk/sound/method"), "none")) |
11494 | 3473 gtk_widget_set_sensitive(gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Mute Sounds")), FALSE); |
5228 | 3474 |
10353 | 3475 /* Update some dynamic things */ |
3476 update_menu_bar(gtkblist); | |
3477 gaim_gtk_blist_update_plugin_actions(); | |
11796 | 3478 gaim_gtk_blist_update_sort_methods(); |
10353 | 3479 |
5228 | 3480 /* OK... let's show this bad boy. */ |
12016
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
3481 gaim_gtk_blist_refresh(list); |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
3482 gaim_blist_set_visible(gaim_prefs_get_bool("/gaim/gtk/blist/list_visible")); |
5228 | 3483 |
3484 /* start the refresh timer */ | |
10351 | 3485 gtkblist->refresh_timer = g_timeout_add(30000, (GSourceFunc)gaim_gtk_blist_refresh_timer, list); |
10353 | 3486 |
10087 | 3487 handle = gaim_gtk_blist_get_handle(); |
3488 | |
7620 | 3489 /* things that affect how buddies are displayed */ |
10087 | 3490 gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/show_buddy_icons", |
3491 _prefs_change_redo_list, NULL); | |
3492 gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/show_empty_groups", | |
3493 _prefs_change_redo_list, NULL); | |
3494 gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/show_offline_buddies", | |
3495 _prefs_change_redo_list, NULL); | |
7620 | 3496 |
3497 /* sorting */ | |
10087 | 3498 gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/sort_type", |
3499 _prefs_change_sort_method, NULL); | |
7620 | 3500 |
3501 /* things that affect what columns are displayed */ | |
10087 | 3502 gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/show_buddy_icons", |
3503 gaim_gtk_blist_update_columns, NULL); | |
8259
4f9f68ab8770
[gaim-migrate @ 8982]
Christian Hammond <chipx86@chipx86.com>
parents:
8254
diff
changeset
|
3504 |
10074 | 3505 /* menus */ |
10087 | 3506 gaim_prefs_connect_callback(handle, "/gaim/gtk/sound/mute", |
3507 gaim_gtk_blist_mute_pref_cb, NULL); | |
3508 gaim_prefs_connect_callback(handle, "/gaim/gtk/sound/method", | |
3509 gaim_gtk_blist_sound_method_pref_cb, NULL); | |
10074 | 3510 |
8259
4f9f68ab8770
[gaim-migrate @ 8982]
Christian Hammond <chipx86@chipx86.com>
parents:
8254
diff
changeset
|
3511 /* Setup some gaim signal handlers. */ |
12070 | 3512 gaim_signal_connect(gaim_accounts_get_handle(), "account-disabled", |
3513 gtkblist, GAIM_CALLBACK(account_disabled), gtkblist); | |
3514 gaim_signal_connect(gaim_accounts_get_handle(), "account-enabled", | |
3515 gtkblist, GAIM_CALLBACK(account_enabled), gtkblist); | |
3516 | |
8937 | 3517 gaim_signal_connect(gaim_connections_get_handle(), "signed-on", |
3518 gtkblist, GAIM_CALLBACK(sign_on_off_cb), list); | |
3519 gaim_signal_connect(gaim_connections_get_handle(), "signed-off", | |
3520 gtkblist, GAIM_CALLBACK(sign_on_off_cb), list); | |
8815 | 3521 |
8986 | 3522 gaim_signal_connect(gaim_plugins_get_handle(), "plugin-load", |
3523 gtkblist, GAIM_CALLBACK(plugin_changed_cb), NULL); | |
3524 gaim_signal_connect(gaim_plugins_get_handle(), "plugin-unload", | |
3525 gtkblist, GAIM_CALLBACK(plugin_changed_cb), NULL); | |
3526 | |
8815 | 3527 /* emit our created signal */ |
10087 | 3528 gaim_signal_emit(handle, "gtkblist-created", list); |
5228 | 3529 } |
3530 | |
7620 | 3531 static void redo_buddy_list(GaimBuddyList *list, gboolean remove) |
5228 | 3532 { |
12112 | 3533 GaimBlistNode *node = list->root; |
3534 | |
3535 while (node) | |
3536 { | |
3537 if (!GAIM_BLIST_NODE_IS_GROUP(node) && remove) | |
3538 gaim_gtk_blist_hide_node(list, node); | |
3539 | |
3540 gaim_gtk_blist_update(list, node); | |
3541 node = gaim_blist_node_next(node, FALSE); | |
5228 | 3542 } |
3543 } | |
3544 | |
7620 | 3545 void gaim_gtk_blist_refresh(GaimBuddyList *list) |
5422 | 3546 { |
3547 redo_buddy_list(list, FALSE); | |
3548 } | |
3549 | |
5297 | 3550 void |
3551 gaim_gtk_blist_update_refresh_timeout() | |
3552 { | |
7620 | 3553 GaimBuddyList *blist; |
3554 GaimGtkBuddyList *gtkblist; | |
5297 | 3555 |
3556 blist = gaim_get_blist(); | |
3557 gtkblist = GAIM_GTK_BLIST(gaim_get_blist()); | |
3558 | |
10351 | 3559 gtkblist->refresh_timer = g_timeout_add(30000,(GSourceFunc)gaim_gtk_blist_refresh_timer, blist); |
5297 | 3560 } |
3561 | |
5256 | 3562 static gboolean get_iter_from_node(GaimBlistNode *node, GtkTreeIter *iter) { |
3563 struct _gaim_gtk_blist_node *gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; | |
3564 GtkTreePath *path; | |
5228 | 3565 |
5263 | 3566 if (!gtknode) { |
3567 return FALSE; | |
3568 } | |
3569 | |
3570 if (!gtkblist) { | |
10006 | 3571 gaim_debug_error("gtkblist", "get_iter_from_node was called, but we don't seem to have a blist\n"); |
5263 | 3572 return FALSE; |
3573 } | |
3574 | |
3575 if (!gtknode->row) | |
5228 | 3576 return FALSE; |
11494 | 3577 |
5228 | 3578 |
5256 | 3579 if ((path = gtk_tree_row_reference_get_path(gtknode->row)) == NULL) |
5228 | 3580 return FALSE; |
11016 | 3581 |
5256 | 3582 if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), iter, path)) { |
3583 gtk_tree_path_free(path); | |
3584 return FALSE; | |
3585 } | |
3586 gtk_tree_path_free(path); | |
3587 return TRUE; | |
5228 | 3588 } |
3589 | |
7620 | 3590 static void gaim_gtk_blist_remove(GaimBuddyList *list, GaimBlistNode *node) |
5228 | 3591 { |
11910 | 3592 struct _gaim_gtk_blist_node *gtknode = node->ui_data; |
3593 | |
10222 | 3594 gaim_request_close_with_handle(node); |
3595 | |
5260 | 3596 gaim_gtk_blist_hide_node(list, node); |
5228 | 3597 |
7620 | 3598 if(node->parent) |
3599 gaim_gtk_blist_update(list, node->parent); | |
3600 | |
10504 | 3601 /* There's something I don't understand here - Ethan */ |
3602 /* Ethan said that back in 2003, but this g_free has been left commented | |
3603 * out ever since. I can't find any reason at all why this is bad and | |
3604 * valgrind found several reasons why it's good. If this causes problems | |
3605 * comment it out again. Stu */ | |
10510 | 3606 /* Of course it still causes problems - this breaks dragging buddies into |
10515 | 3607 * contacts, the dragged buddy mysteriously 'disappears'. Stu. */ |
3608 /* I think it's fixed now. Stu. */ | |
11910 | 3609 |
11915 | 3610 if(gtknode) { |
3611 if(gtknode->recent_signonoff_timer > 0) | |
3612 gaim_timeout_remove(gtknode->recent_signonoff_timer); | |
3613 | |
3614 g_free(node->ui_data); | |
3615 node->ui_data = NULL; | |
3616 } | |
5228 | 3617 } |
3618 | |
3619 static gboolean do_selection_changed(GaimBlistNode *new_selection) | |
3620 { | |
5254 | 3621 GaimBlistNode *old_selection = NULL; |
5228 | 3622 |
5254 | 3623 /* test for gtkblist because crazy timeout means we can be called after the blist is gone */ |
3624 if (gtkblist && new_selection != gtkblist->selected_node) { | |
3625 old_selection = gtkblist->selected_node; | |
5228 | 3626 gtkblist->selected_node = new_selection; |
3627 if(new_selection) | |
3628 gaim_gtk_blist_update(NULL, new_selection); | |
3629 if(old_selection) | |
3630 gaim_gtk_blist_update(NULL, old_selection); | |
3631 } | |
3632 | |
3633 return FALSE; | |
3634 } | |
3635 | |
3636 static void gaim_gtk_blist_selection_changed(GtkTreeSelection *selection, gpointer data) | |
3637 { | |
3638 GaimBlistNode *new_selection = NULL; | |
3639 GtkTreeIter iter; | |
3640 | |
3641 if(gtk_tree_selection_get_selected(selection, NULL, &iter)){ | |
3642 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, | |
3643 NODE_COLUMN, &new_selection, -1); | |
3644 } | |
5254 | 3645 |
5228 | 3646 /* we set this up as a timeout, otherwise the blist flickers */ |
3647 g_timeout_add(0, (GSourceFunc)do_selection_changed, new_selection); | |
3648 } | |
3649 | |
8252 | 3650 static gboolean insert_node(GaimBuddyList *list, GaimBlistNode *node, GtkTreeIter *iter) |
7620 | 3651 { |
3652 GtkTreeIter parent_iter, cur, *curptr = NULL; | |
3653 struct _gaim_gtk_blist_node *gtknode = node->ui_data; | |
5256 | 3654 GtkTreePath *newpath; |
7620 | 3655 |
10515 | 3656 if(!iter) |
8252 | 3657 return FALSE; |
7620 | 3658 |
3659 if(node->parent && !get_iter_from_node(node->parent, &parent_iter)) | |
8252 | 3660 return FALSE; |
7620 | 3661 |
3662 if(get_iter_from_node(node, &cur)) | |
3663 curptr = &cur; | |
3664 | |
3665 if(GAIM_BLIST_NODE_IS_CONTACT(node) || GAIM_BLIST_NODE_IS_CHAT(node)) { | |
3666 *iter = current_sort_method->func(node, list, parent_iter, curptr); | |
3667 } else { | |
3668 *iter = sort_method_none(node, list, parent_iter, curptr); | |
5228 | 3669 } |
3670 | |
10515 | 3671 if(gtknode != NULL) { |
3672 gtk_tree_row_reference_free(gtknode->row); | |
3673 } else { | |
3674 gaim_gtk_blist_new_node(node); | |
3675 gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; | |
3676 } | |
3677 | |
7620 | 3678 newpath = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), |
3679 iter); | |
3680 gtknode->row = | |
3681 gtk_tree_row_reference_new(GTK_TREE_MODEL(gtkblist->treemodel), | |
3682 newpath); | |
11494 | 3683 |
5256 | 3684 gtk_tree_path_free(newpath); |
3685 | |
5228 | 3686 gtk_tree_store_set(gtkblist->treemodel, iter, |
3687 NODE_COLUMN, node, | |
3688 -1); | |
7620 | 3689 |
3690 if(node->parent) { | |
3691 GtkTreePath *expand = NULL; | |
3692 struct _gaim_gtk_blist_node *gtkparentnode = node->parent->ui_data; | |
3693 | |
3694 if(GAIM_BLIST_NODE_IS_GROUP(node->parent)) { | |
7693 | 3695 if(!gaim_blist_node_get_bool(node->parent, "collapsed")) |
7620 | 3696 expand = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &parent_iter); |
3697 } else if(GAIM_BLIST_NODE_IS_CONTACT(node->parent) && | |
3698 gtkparentnode->contact_expanded) { | |
3699 expand = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &parent_iter); | |
3700 } | |
3701 if(expand) { | |
7693 | 3702 gtk_tree_view_expand_row(GTK_TREE_VIEW(gtkblist->treeview), expand, FALSE); |
7620 | 3703 gtk_tree_path_free(expand); |
3704 } | |
3705 } | |
3706 | |
8252 | 3707 return TRUE; |
5228 | 3708 } |
3709 | |
7620 | 3710 static void gaim_gtk_blist_update_group(GaimBuddyList *list, GaimBlistNode *node) |
3711 { | |
3712 GaimGroup *group; | |
8203 | 3713 int count; |
7620 | 3714 |
3715 g_return_if_fail(GAIM_BLIST_NODE_IS_GROUP(node)); | |
3716 | |
3717 group = (GaimGroup*)node; | |
3718 | |
8203 | 3719 if(gaim_prefs_get_bool("/gaim/gtk/blist/show_offline_buddies")) |
3720 count = gaim_blist_get_group_size(group, FALSE); | |
3721 else | |
3722 count = gaim_blist_get_group_online_count(group); | |
3723 if(gaim_prefs_get_bool("/gaim/gtk/blist/show_empty_groups") || count > 0) { | |
7620 | 3724 char *mark, *esc; |
3725 GtkTreeIter iter; | |
3726 | |
8252 | 3727 if(!insert_node(list, node, &iter)) |
3728 return; | |
7620 | 3729 |
3730 esc = g_markup_escape_text(group->name, -1); | |
8945 | 3731 mark = g_strdup_printf("<span weight='bold'>%s</span> (%d/%d)", |
3732 esc, gaim_blist_get_group_online_count(group), | |
3733 gaim_blist_get_group_size(group, FALSE)); | |
7620 | 3734 g_free(esc); |
3735 | |
3736 gtk_tree_store_set(gtkblist->treemodel, &iter, | |
3737 STATUS_ICON_COLUMN, NULL, | |
3738 STATUS_ICON_VISIBLE_COLUMN, FALSE, | |
3739 NAME_COLUMN, mark, | |
3740 NODE_COLUMN, node, | |
3741 -1); | |
3742 g_free(mark); | |
3743 } else { | |
3744 gaim_gtk_blist_hide_node(list, node); | |
3745 } | |
3746 } | |
3747 | |
3748 static void buddy_node(GaimBuddy *buddy, GtkTreeIter *iter, GaimBlistNode *node) | |
5228 | 3749 { |
9944 | 3750 GaimPresence *presence; |
7620 | 3751 GdkPixbuf *status, *avatar; |
3752 char *mark; | |
11257 | 3753 char *idle = NULL; |
7620 | 3754 gboolean selected = (gtkblist->selected_node == node); |
3755 | |
9944 | 3756 presence = gaim_buddy_get_presence(buddy); |
3757 | |
7620 | 3758 status = gaim_gtk_blist_get_status_icon((GaimBlistNode*)buddy, |
3759 (gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons") | |
3760 ? GAIM_STATUS_ICON_LARGE : GAIM_STATUS_ICON_SMALL)); | |
3761 | |
10482 | 3762 avatar = gaim_gtk_blist_get_buddy_icon((GaimBlistNode *)buddy, TRUE, TRUE); |
7620 | 3763 mark = gaim_gtk_blist_get_name_markup(buddy, selected); |
3764 | |
9944 | 3765 if (gaim_presence_is_idle(presence)) |
3766 { | |
3767 time_t idle_secs = gaim_presence_get_idle_time(presence); | |
3768 | |
3769 if (idle_secs > 0) | |
3770 { | |
3771 time_t t; | |
3772 int ihrs, imin; | |
3773 time(&t); | |
3774 ihrs = (t - idle_secs) / 3600; | |
3775 imin = ((t - idle_secs) / 60) % 60; | |
3776 | |
3777 if (ihrs > 0) | |
3778 idle = g_strdup_printf("(%d:%02d)", ihrs, imin); | |
3779 else | |
3780 idle = g_strdup_printf("(%d)", imin); | |
3781 } | |
7620 | 3782 } |
3783 | |
10118 | 3784 if (gaim_presence_is_idle(presence)) |
9944 | 3785 { |
3786 if (idle && !selected) { | |
10118 | 3787 char *i2 = g_strdup_printf("<span color='%s'>%s</span>", |
3788 dim_grey(), idle); | |
7620 | 3789 g_free(idle); |
3790 idle = i2; | |
5228 | 3791 } |
7620 | 3792 } |
3793 | |
3794 gtk_tree_store_set(gtkblist->treemodel, iter, | |
3795 STATUS_ICON_COLUMN, status, | |
3796 STATUS_ICON_VISIBLE_COLUMN, TRUE, | |
3797 NAME_COLUMN, mark, | |
3798 IDLE_COLUMN, idle, | |
3799 BUDDY_ICON_COLUMN, avatar, | |
3800 -1); | |
3801 | |
3802 g_free(mark); | |
3803 if(idle) | |
3804 g_free(idle); | |
3805 if(status) | |
3806 g_object_unref(status); | |
3807 if(avatar) | |
3808 g_object_unref(avatar); | |
3809 } | |
3810 | |
11890 | 3811 |
7620 | 3812 static void gaim_gtk_blist_update_contact(GaimBuddyList *list, GaimBlistNode *node) |
3813 { | |
3814 GaimContact *contact; | |
3815 GaimBuddy *buddy; | |
3816 struct _gaim_gtk_blist_node *gtknode; | |
3817 | |
3818 g_return_if_fail(GAIM_BLIST_NODE_IS_CONTACT(node)); | |
3819 | |
3820 /* First things first, update the group */ | |
3821 gaim_gtk_blist_update_group(list, node->parent); | |
3822 | |
3823 contact = (GaimContact*)node; | |
3824 buddy = gaim_contact_get_priority_buddy(contact); | |
3825 | |
11890 | 3826 if (buddy_is_displayable(buddy)) |
10006 | 3827 { |
7620 | 3828 GtkTreeIter iter; |
3829 | |
8252 | 3830 if(!insert_node(list, node, &iter)) |
3831 return; | |
7620 | 3832 |
10515 | 3833 gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; |
3834 | |
7620 | 3835 if(gtknode->contact_expanded) { |
3836 GdkPixbuf *status; | |
5228 | 3837 char *mark; |
3838 | |
7620 | 3839 status = gaim_gtk_blist_get_status_icon(node, |
3840 (gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons") ? | |
3841 GAIM_STATUS_ICON_LARGE : GAIM_STATUS_ICON_SMALL)); | |
3842 | |
3843 mark = g_markup_escape_text(gaim_contact_get_alias(contact), -1); | |
3844 | |
5228 | 3845 gtk_tree_store_set(gtkblist->treemodel, &iter, |
7620 | 3846 STATUS_ICON_COLUMN, status, |
3847 STATUS_ICON_VISIBLE_COLUMN, TRUE, | |
5228 | 3848 NAME_COLUMN, mark, |
7620 | 3849 IDLE_COLUMN, NULL, |
3850 BUDDY_ICON_COLUMN, NULL, | |
5228 | 3851 -1); |
3852 g_free(mark); | |
7620 | 3853 if(status) |
3854 g_object_unref(status); | |
3855 } else { | |
3856 buddy_node(buddy, &iter, node); | |
5228 | 3857 } |
7620 | 3858 } else { |
3859 gaim_gtk_blist_hide_node(list, node); | |
5228 | 3860 } |
7620 | 3861 } |
3862 | |
3863 static void gaim_gtk_blist_update_buddy(GaimBuddyList *list, GaimBlistNode *node) | |
3864 { | |
3865 GaimContact *contact; | |
3866 GaimBuddy *buddy; | |
3867 struct _gaim_gtk_blist_node *gtkparentnode; | |
3868 | |
3869 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); | |
3870 | |
3871 buddy = (GaimBuddy*)node; | |
3872 contact = (GaimContact*)node->parent; | |
3873 | |
11624 | 3874 if (contact == NULL) |
3875 return; | |
3876 | |
7620 | 3877 /* First things first, update the contact */ |
3878 gaim_gtk_blist_update_contact(list, node->parent); | |
3879 | |
10918 | 3880 gtkparentnode = (struct _gaim_gtk_blist_node *)node->parent->ui_data; |
3881 | |
10006 | 3882 if (gtkparentnode->contact_expanded && |
3883 (gaim_presence_is_online(buddy->presence) || | |
11910 | 3884 (0 /* XXX: if we just signed off, need to show logout.png */) || |
7620 | 3885 (gaim_account_is_connected(buddy->account) && |
10006 | 3886 gaim_prefs_get_bool("/gaim/gtk/blist/show_offline_buddies")) || |
3887 gaim_blist_node_get_bool(node->parent, "show_offline"))) | |
3888 { | |
7620 | 3889 GtkTreeIter iter; |
3890 | |
10006 | 3891 if (!insert_node(list, node, &iter)) |
8252 | 3892 return; |
3893 | |
7620 | 3894 buddy_node(buddy, &iter, node); |
3895 | |
3896 } else { | |
3897 gaim_gtk_blist_hide_node(list, node); | |
3898 } | |
3899 | |
3900 } | |
3901 | |
3902 static void gaim_gtk_blist_update_chat(GaimBuddyList *list, GaimBlistNode *node) | |
3903 { | |
3904 GaimChat *chat; | |
3905 | |
3906 g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node)); | |
3907 | |
3908 /* First things first, update the group */ | |
3909 gaim_gtk_blist_update_group(list, node->parent); | |
3910 | |
3911 chat = (GaimChat*)node; | |
3912 | |
3913 if(gaim_account_is_connected(chat->account)) { | |
3914 GtkTreeIter iter; | |
5234 | 3915 GdkPixbuf *status; |
7620 | 3916 char *mark; |
3917 | |
8252 | 3918 if(!insert_node(list, node, &iter)) |
3919 return; | |
5234 | 3920 |
3921 status = gaim_gtk_blist_get_status_icon(node, | |
7620 | 3922 (gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons") ? |
3923 GAIM_STATUS_ICON_LARGE : GAIM_STATUS_ICON_SMALL)); | |
3924 | |
3925 mark = g_markup_escape_text(gaim_chat_get_name(chat), -1); | |
5234 | 3926 |
3927 gtk_tree_store_set(gtkblist->treemodel, &iter, | |
7620 | 3928 STATUS_ICON_COLUMN, status, |
3929 STATUS_ICON_VISIBLE_COLUMN, TRUE, | |
3930 NAME_COLUMN, mark, | |
3931 -1); | |
5228 | 3932 |
3933 g_free(mark); | |
7620 | 3934 if(status) |
5228 | 3935 g_object_unref(status); |
7620 | 3936 } else { |
5260 | 3937 gaim_gtk_blist_hide_node(list, node); |
5228 | 3938 } |
7620 | 3939 } |
3940 | |
3941 static void gaim_gtk_blist_update(GaimBuddyList *list, GaimBlistNode *node) | |
3942 { | |
3943 if(!gtkblist) | |
3944 return; | |
3945 | |
3946 switch(node->type) { | |
3947 case GAIM_BLIST_GROUP_NODE: | |
3948 gaim_gtk_blist_update_group(list, node); | |
3949 break; | |
3950 case GAIM_BLIST_CONTACT_NODE: | |
3951 gaim_gtk_blist_update_contact(list, node); | |
3952 break; | |
3953 case GAIM_BLIST_BUDDY_NODE: | |
3954 gaim_gtk_blist_update_buddy(list, node); | |
3955 break; | |
3956 case GAIM_BLIST_CHAT_NODE: | |
3957 gaim_gtk_blist_update_chat(list, node); | |
3958 break; | |
3959 case GAIM_BLIST_OTHER_NODE: | |
3960 return; | |
3961 } | |
5234 | 3962 |
5228 | 3963 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(gtkblist->treeview)); |
3964 } | |
3965 | |
7620 | 3966 |
3967 static void gaim_gtk_blist_destroy(GaimBuddyList *list) | |
5228 | 3968 { |
3969 if (!gtkblist) | |
3970 return; | |
3971 | |
8937 | 3972 gaim_signal_disconnect(gaim_connections_get_handle(), "signed-on", |
3973 gtkblist, GAIM_CALLBACK(sign_on_off_cb)); | |
3974 gaim_signal_disconnect(gaim_connections_get_handle(), "signed-off", | |
3975 gtkblist, GAIM_CALLBACK(sign_on_off_cb)); | |
8259
4f9f68ab8770
[gaim-migrate @ 8982]
Christian Hammond <chipx86@chipx86.com>
parents:
8254
diff
changeset
|
3976 |
5228 | 3977 gtk_widget_destroy(gtkblist->window); |
7620 | 3978 |
8254 | 3979 gaim_gtk_blist_tooltip_destroy(); |
7620 | 3980 |
5228 | 3981 if (gtkblist->refresh_timer) |
3982 g_source_remove(gtkblist->refresh_timer); | |
3983 if (gtkblist->timeout) | |
3984 g_source_remove(gtkblist->timeout); | |
10354 | 3985 if (gtkblist->drag_timeout) |
3986 g_source_remove(gtkblist->drag_timeout); | |
5228 | 3987 |
3988 gtkblist->refresh_timer = 0; | |
3989 gtkblist->timeout = 0; | |
10354 | 3990 gtkblist->drag_timeout = 0; |
5228 | 3991 gtkblist->window = gtkblist->vbox = gtkblist->treeview = NULL; |
3992 gtkblist->treemodel = NULL; | |
3993 gtkblist->idle_column = NULL; | |
11257 | 3994 gtkblist->buddy_icon_column = NULL; |
5427 | 3995 g_object_unref(G_OBJECT(gtkblist->ift)); |
5228 | 3996 protomenu = NULL; |
3997 gtkblist = NULL; | |
7620 | 3998 |
10087 | 3999 gaim_prefs_disconnect_by_handle(gaim_gtk_blist_get_handle()); |
5228 | 4000 } |
4001 | |
7620 | 4002 static void gaim_gtk_blist_set_visible(GaimBuddyList *list, gboolean show) |
5228 | 4003 { |
4004 if (!(gtkblist && gtkblist->window)) | |
4005 return; | |
10325 | 4006 |
5228 | 4007 if (show) { |
12016
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4008 if(!GAIM_WINDOW_ICONIFIED(gtkblist->window) && !GTK_WIDGET_VISIBLE(gtkblist->window)) |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4009 gaim_signal_emit(gaim_gtk_blist_get_handle(), "gtkblist-unhiding", gtkblist); |
5228 | 4010 gaim_gtk_blist_restore_position(); |
4011 gtk_window_present(GTK_WINDOW(gtkblist->window)); | |
4012 } else { | |
12016
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4013 if(visibility_manager_count) { |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4014 gaim_signal_emit(gaim_gtk_blist_get_handle(), "gtkblist-hiding", gtkblist); |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4015 gtk_widget_hide(gtkblist->window); |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4016 } else { |
12115
e9790eb93216
[gaim-migrate @ 14415]
Luke Schierer <lschiere@pidgin.im>
parents:
12113
diff
changeset
|
4017 gaim_gtk_blist_restore_position(); |
e9790eb93216
[gaim-migrate @ 14415]
Luke Schierer <lschiere@pidgin.im>
parents:
12113
diff
changeset
|
4018 gtk_widget_show_all(GTK_WIDGET(gtkblist->window)); |
12016
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4019 gtk_window_iconify(GTK_WINDOW(gtkblist->window)); |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4020 } |
5228 | 4021 } |
4022 } | |
4023 | |
7620 | 4024 static GList * |
4025 groups_tree(void) | |
4026 { | |
4027 GList *tmp = NULL; | |
4028 char *tmp2; | |
4029 GaimGroup *g; | |
4030 GaimBlistNode *gnode; | |
4031 | |
4032 if (gaim_get_blist()->root == NULL) | |
4033 { | |
4034 tmp2 = g_strdup(_("Buddies")); | |
4035 tmp = g_list_append(tmp, tmp2); | |
4036 } | |
4037 else | |
4038 { | |
4039 for (gnode = gaim_get_blist()->root; | |
4040 gnode != NULL; | |
4041 gnode = gnode->next) | |
4042 { | |
4043 if (GAIM_BLIST_NODE_IS_GROUP(gnode)) | |
4044 { | |
4045 g = (GaimGroup *)gnode; | |
4046 tmp2 = g->name; | |
4047 tmp = g_list_append(tmp, tmp2); | |
4048 } | |
4049 } | |
4050 } | |
4051 | |
4052 return tmp; | |
4053 } | |
4054 | |
4055 static void | |
4056 add_buddy_select_account_cb(GObject *w, GaimAccount *account, | |
4057 GaimGtkAddBuddyData *data) | |
4058 { | |
4059 /* Save our account */ | |
4060 data->account = account; | |
4061 } | |
4062 | |
4063 static void | |
4064 destroy_add_buddy_dialog_cb(GtkWidget *win, GaimGtkAddBuddyData *data) | |
4065 { | |
4066 g_free(data); | |
4067 } | |
4068 | |
4069 static void | |
4070 add_buddy_cb(GtkWidget *w, int resp, GaimGtkAddBuddyData *data) | |
4071 { | |
4072 const char *grp, *who, *whoalias; | |
4073 GaimConversation *c; | |
4074 GaimBuddy *b; | |
4075 GaimGroup *g; | |
4076 | |
4077 if (resp == GTK_RESPONSE_OK) | |
4078 { | |
4079 who = gtk_entry_get_text(GTK_ENTRY(data->entry)); | |
4080 grp = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(data->combo)->entry)); | |
4081 whoalias = gtk_entry_get_text(GTK_ENTRY(data->entry_for_alias)); | |
9658 | 4082 if (*whoalias == '\0') |
4083 whoalias = NULL; | |
7620 | 4084 |
4085 if ((g = gaim_find_group(grp)) == NULL) | |
4086 { | |
4087 g = gaim_group_new(grp); | |
4088 gaim_blist_add_group(g, NULL); | |
4089 } | |
4090 | |
4091 b = gaim_buddy_new(data->account, who, whoalias); | |
4092 gaim_blist_add_buddy(b, NULL, g, NULL); | |
11643 | 4093 gaim_account_add_buddy(data->account, b); |
7620 | 4094 |
7887 | 4095 /* |
9285 | 4096 * XXX |
11643 | 4097 * It really seems like it would be better if the call to |
4098 * gaim_account_add_buddy() and gaim_conversation_update() were done in | |
4099 * blist.c, possibly in the gaim_blist_add_buddy() function. Maybe | |
4100 * gaim_account_add_buddy() should be renamed to | |
4101 * gaim_blist_add_new_buddy() or something, and have it call | |
7887 | 4102 * gaim_blist_add_buddy() after it creates it. --Mark |
9285 | 4103 * |
4104 * No that's not good. blist.c should only deal with adding nodes to the | |
11643 | 4105 * local list. We need a new, non-gtk file that calls both |
4106 * gaim_account_add_buddy and gaim_blist_add_buddy(). | |
4107 * Or something. --Mark | |
7887 | 4108 */ |
4109 | |
11338 | 4110 c = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, who, data->account); |
7620 | 4111 if (c != NULL) { |
4112 gaim_buddy_icon_update(gaim_conv_im_get_icon(GAIM_CONV_IM(c))); | |
4113 gaim_conversation_update(c, GAIM_CONV_UPDATE_ADD); | |
4114 } | |
4115 } | |
4116 | |
4117 gtk_widget_destroy(data->window); | |
4118 } | |
4119 | |
4120 static void | |
4121 gaim_gtk_blist_request_add_buddy(GaimAccount *account, const char *username, | |
4122 const char *group, const char *alias) | |
4123 { | |
4124 GtkWidget *table; | |
4125 GtkWidget *label; | |
4126 GtkWidget *hbox; | |
4127 GtkWidget *vbox; | |
4128 GtkWidget *img; | |
4129 GaimGtkBuddyList *gtkblist; | |
4130 GaimGtkAddBuddyData *data = g_new0(GaimGtkAddBuddyData, 1); | |
4131 | |
4132 data->account = | |
4133 (account != NULL | |
4134 ? account | |
4135 : gaim_connection_get_account(gaim_connections_get_all()->data)); | |
4136 | |
4137 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, | |
4138 GTK_ICON_SIZE_DIALOG); | |
4139 | |
4140 gtkblist = GAIM_GTK_BLIST(gaim_get_blist()); | |
4141 | |
4142 data->window = gtk_dialog_new_with_buttons(_("Add Buddy"), | |
8975 | 4143 NULL, GTK_DIALOG_NO_SEPARATOR, |
7620 | 4144 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
4145 GTK_STOCK_ADD, GTK_RESPONSE_OK, | |
4146 NULL); | |
4147 | |
4148 gtk_dialog_set_default_response(GTK_DIALOG(data->window), GTK_RESPONSE_OK); | |
11243 | 4149 gtk_container_set_border_width(GTK_CONTAINER(data->window), GAIM_HIG_BOX_SPACE); |
7620 | 4150 gtk_window_set_resizable(GTK_WINDOW(data->window), FALSE); |
11243 | 4151 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(data->window)->vbox), GAIM_HIG_BORDER); |
4152 gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), GAIM_HIG_BOX_SPACE); | |
7620 | 4153 gtk_window_set_role(GTK_WINDOW(data->window), "add_buddy"); |
8975 | 4154 gtk_window_set_type_hint(GTK_WINDOW(data->window), |
9811 | 4155 GDK_WINDOW_TYPE_HINT_DIALOG); |
7620 | 4156 |
11243 | 4157 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); |
7620 | 4158 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), hbox); |
4159 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); | |
4160 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); | |
4161 | |
4162 vbox = gtk_vbox_new(FALSE, 0); | |
4163 gtk_container_add(GTK_CONTAINER(hbox), vbox); | |
4164 | |
4165 label = gtk_label_new( | |
4166 _("Please enter the screen name of the person you would like " | |
4167 "to add to your buddy list. You may optionally enter an alias, " | |
4168 "or nickname, for the buddy. The alias will be displayed in " | |
4169 "place of the screen name whenever possible.\n")); | |
4170 | |
4171 gtk_widget_set_size_request(GTK_WIDGET(label), 400, -1); | |
4172 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); | |
4173 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); | |
4174 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); | |
4175 | |
11243 | 4176 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); |
7620 | 4177 gtk_container_add(GTK_CONTAINER(vbox), hbox); |
4178 | |
4179 g_signal_connect(G_OBJECT(data->window), "destroy", | |
4180 G_CALLBACK(destroy_add_buddy_dialog_cb), data); | |
4181 | |
4182 table = gtk_table_new(4, 2, FALSE); | |
4183 gtk_table_set_row_spacings(GTK_TABLE(table), 5); | |
4184 gtk_table_set_col_spacings(GTK_TABLE(table), 5); | |
4185 gtk_container_set_border_width(GTK_CONTAINER(table), 0); | |
4186 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); | |
4187 | |
4188 label = gtk_label_new(_("Screen Name:")); | |
4189 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
4190 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1); | |
4191 | |
4192 data->entry = gtk_entry_new(); | |
4193 gtk_table_attach_defaults(GTK_TABLE(table), data->entry, 1, 2, 0, 1); | |
4194 gtk_widget_grab_focus(data->entry); | |
4195 | |
4196 if (username != NULL) | |
4197 gtk_entry_set_text(GTK_ENTRY(data->entry), username); | |
4198 | |
4199 gtk_entry_set_activates_default (GTK_ENTRY(data->entry), TRUE); | |
8137 | 4200 gaim_set_accessible_label (data->entry, label); |
7620 | 4201 |
4202 label = gtk_label_new(_("Alias:")); | |
4203 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
4204 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2); | |
4205 | |
4206 data->entry_for_alias = gtk_entry_new(); | |
4207 gtk_table_attach_defaults(GTK_TABLE(table), | |
4208 data->entry_for_alias, 1, 2, 1, 2); | |
4209 | |
4210 if (alias != NULL) | |
4211 gtk_entry_set_text(GTK_ENTRY(data->entry_for_alias), alias); | |
4212 | |
10734
8b2c81d9b271
[gaim-migrate @ 12336]
Luke Schierer <lschiere@pidgin.im>
parents:
10694
diff
changeset
|
4213 if (username != NULL) |
8b2c81d9b271
[gaim-migrate @ 12336]
Luke Schierer <lschiere@pidgin.im>
parents:
10694
diff
changeset
|
4214 gtk_widget_grab_focus(GTK_WIDGET(data->entry_for_alias)); |
8b2c81d9b271
[gaim-migrate @ 12336]
Luke Schierer <lschiere@pidgin.im>
parents:
10694
diff
changeset
|
4215 |
7620 | 4216 gtk_entry_set_activates_default (GTK_ENTRY(data->entry_for_alias), TRUE); |
8137 | 4217 gaim_set_accessible_label (data->entry_for_alias, label); |
7620 | 4218 |
4219 label = gtk_label_new(_("Group:")); | |
4220 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
4221 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3); | |
4222 | |
4223 data->combo = gtk_combo_new(); | |
4224 gtk_combo_set_popdown_strings(GTK_COMBO(data->combo), groups_tree()); | |
4225 gtk_table_attach_defaults(GTK_TABLE(table), data->combo, 1, 2, 2, 3); | |
8137 | 4226 gaim_set_accessible_label (data->combo, label); |
7620 | 4227 |
4228 /* Set up stuff for the account box */ | |
4229 label = gtk_label_new(_("Account:")); | |
4230 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
4231 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4); | |
4232 | |
4233 data->account_box = gaim_gtk_account_option_menu_new(account, FALSE, | |
4234 G_CALLBACK(add_buddy_select_account_cb), NULL, data); | |
4235 | |
4236 gtk_table_attach_defaults(GTK_TABLE(table), data->account_box, 1, 2, 3, 4); | |
8137 | 4237 gaim_set_accessible_label (data->account_box, label); |
7620 | 4238 /* End of account box */ |
4239 | |
4240 g_signal_connect(G_OBJECT(data->window), "response", | |
4241 G_CALLBACK(add_buddy_cb), data); | |
4242 | |
4243 gtk_widget_show_all(data->window); | |
4244 | |
4245 if (group != NULL) | |
4246 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(data->combo)->entry), group); | |
4247 } | |
4248 | |
4249 static void | |
4250 add_chat_cb(GtkWidget *w, GaimGtkAddChatData *data) | |
4251 { | |
4252 GHashTable *components; | |
4253 GList *tmp; | |
4254 GaimChat *chat; | |
4255 GaimGroup *group; | |
4256 const char *group_name; | |
9918 | 4257 char *chat_name = NULL; |
4258 GaimConversation *conv = NULL; | |
10475 | 4259 const char *value; |
7620 | 4260 |
4261 components = g_hash_table_new_full(g_str_hash, g_str_equal, | |
4262 g_free, g_free); | |
4263 | |
4264 for (tmp = data->entries; tmp; tmp = tmp->next) | |
4265 { | |
4266 if (g_object_get_data(tmp->data, "is_spin")) | |
4267 { | |
4268 g_hash_table_replace(components, | |
4269 g_strdup(g_object_get_data(tmp->data, "identifier")), | |
4270 g_strdup_printf("%d", | |
4271 gtk_spin_button_get_value_as_int(tmp->data))); | |
4272 } | |
4273 else | |
4274 { | |
10475 | 4275 value = gtk_entry_get_text(tmp->data); |
4276 if (*value != '\0') | |
4277 g_hash_table_replace(components, | |
4278 g_strdup(g_object_get_data(tmp->data, "identifier")), | |
4279 g_strdup(value)); | |
7620 | 4280 } |
4281 } | |
4282 | |
4283 chat = gaim_chat_new(data->account, | |
4284 gtk_entry_get_text(GTK_ENTRY(data->alias_entry)), | |
4285 components); | |
4286 | |
4287 group_name = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(data->group_combo)->entry)); | |
4288 | |
4289 if ((group = gaim_find_group(group_name)) == NULL) | |
4290 { | |
4291 group = gaim_group_new(group_name); | |
4292 gaim_blist_add_group(group, NULL); | |
4293 } | |
4294 | |
4295 if (chat != NULL) | |
4296 { | |
4297 gaim_blist_add_chat(chat, group, NULL); | |
9918 | 4298 |
4299 if (GAIM_PLUGIN_PROTOCOL_INFO(data->account->gc->prpl)->get_chat_name != NULL) | |
4300 chat_name = GAIM_PLUGIN_PROTOCOL_INFO( | |
4301 data->account->gc->prpl)->get_chat_name(chat->components); | |
10246 | 4302 |
9918 | 4303 if (chat_name != NULL) { |
11338 | 4304 conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 4305 chat_name, |
4306 data->account); | |
9918 | 4307 g_free(chat_name); |
4308 } | |
4309 | |
4310 if (conv != NULL) | |
4311 gaim_conversation_update(conv, GAIM_CONV_UPDATE_ADD); | |
7620 | 4312 } |
4313 | |
4314 gtk_widget_destroy(data->window); | |
9812 | 4315 g_free(data->default_chat_name); |
7620 | 4316 g_list_free(data->entries); |
4317 g_free(data); | |
4318 } | |
4319 | |
4320 static void | |
4321 add_chat_resp_cb(GtkWidget *w, int resp, GaimGtkAddChatData *data) | |
4322 { | |
4323 if (resp == GTK_RESPONSE_OK) | |
4324 { | |
4325 add_chat_cb(NULL, data); | |
4326 } | |
4327 else | |
4328 { | |
4329 gtk_widget_destroy(data->window); | |
9812 | 4330 g_free(data->default_chat_name); |
7620 | 4331 g_list_free(data->entries); |
4332 g_free(data); | |
4333 } | |
4334 } | |
4335 | |
10475 | 4336 /* |
4337 * Check the values of all the text entry boxes. If any required input | |
4338 * strings are empty then don't allow the user to click on "OK." | |
4339 */ | |
4340 static void | |
4341 addchat_set_sensitive_if_input_cb(GtkWidget *entry, gpointer user_data) | |
4342 { | |
4343 GaimGtkAddChatData *data; | |
4344 GList *tmp; | |
4345 const char *text; | |
4346 gboolean required; | |
4347 gboolean sensitive = TRUE; | |
4348 | |
4349 data = user_data; | |
4350 | |
4351 for (tmp = data->entries; tmp != NULL; tmp = tmp->next) | |
4352 { | |
4353 if (!g_object_get_data(tmp->data, "is_spin")) | |
4354 { | |
4355 required = GPOINTER_TO_INT(g_object_get_data(tmp->data, "required")); | |
4356 text = gtk_entry_get_text(tmp->data); | |
4357 if (required && (*text == '\0')) | |
4358 sensitive = FALSE; | |
4359 } | |
4360 } | |
4361 | |
4362 gtk_dialog_set_response_sensitive(GTK_DIALOG(data->window), GTK_RESPONSE_OK, sensitive); | |
4363 } | |
4364 | |
7620 | 4365 static void |
4366 rebuild_addchat_entries(GaimGtkAddChatData *data) | |
4367 { | |
4368 GaimConnection *gc; | |
9959 | 4369 GList *list = NULL, *tmp = NULL; |
9754 | 4370 GHashTable *defaults = NULL; |
7620 | 4371 struct proto_chat_entry *pce; |
4372 gboolean focus = TRUE; | |
4373 | |
10127 | 4374 g_return_if_fail(data->account != NULL); |
4375 | |
7620 | 4376 gc = gaim_account_get_connection(data->account); |
4377 | |
4378 while (GTK_BOX(data->entries_box)->children) | |
4379 { | |
4380 gtk_container_remove(GTK_CONTAINER(data->entries_box), | |
10475 | 4381 ((GtkBoxChild *)GTK_BOX(data->entries_box)->children->data)->widget); |
7620 | 4382 } |
4383 | |
4384 if (data->entries != NULL) | |
4385 g_list_free(data->entries); | |
4386 | |
4387 data->entries = NULL; | |
4388 | |
9959 | 4389 if (GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info != NULL) |
4390 list = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info(gc); | |
7620 | 4391 |
9754 | 4392 if (GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) |
10475 | 4393 defaults = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, data->default_chat_name); |
9754 | 4394 |
7620 | 4395 for (tmp = list; tmp; tmp = tmp->next) |
4396 { | |
4397 GtkWidget *label; | |
4398 GtkWidget *rowbox; | |
10475 | 4399 GtkWidget *input; |
7620 | 4400 |
4401 pce = tmp->data; | |
4402 | |
4403 rowbox = gtk_hbox_new(FALSE, 5); | |
4404 gtk_box_pack_start(GTK_BOX(data->entries_box), rowbox, FALSE, FALSE, 0); | |
4405 | |
7889 | 4406 label = gtk_label_new_with_mnemonic(pce->label); |
7620 | 4407 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); |
4408 gtk_size_group_add_widget(data->sg, label); | |
4409 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); | |
4410 | |
4411 if (pce->is_int) | |
4412 { | |
4413 GtkObject *adjust; | |
4414 adjust = gtk_adjustment_new(pce->min, pce->min, pce->max, | |
4415 1, 10, 10); | |
10475 | 4416 input = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0); |
4417 gtk_widget_set_size_request(input, 50, -1); | |
4418 gtk_box_pack_end(GTK_BOX(rowbox), input, FALSE, FALSE, 0); | |
7620 | 4419 } |
4420 else | |
4421 { | |
9754 | 4422 char *value; |
10475 | 4423 input = gtk_entry_new(); |
4424 gtk_entry_set_activates_default(GTK_ENTRY(input), TRUE); | |
9754 | 4425 value = g_hash_table_lookup(defaults, pce->identifier); |
4426 if (value != NULL) | |
10475 | 4427 gtk_entry_set_text(GTK_ENTRY(input), value); |
7620 | 4428 if (pce->secret) |
11986 | 4429 { |
10475 | 4430 gtk_entry_set_visibility(GTK_ENTRY(input), FALSE); |
11986 | 4431 gtk_entry_set_invisible_char(GTK_ENTRY(input), GAIM_INVISIBLE_CHAR); |
4432 } | |
10475 | 4433 gtk_box_pack_end(GTK_BOX(rowbox), input, TRUE, TRUE, 0); |
4434 g_signal_connect(G_OBJECT(input), "changed", | |
4435 G_CALLBACK(addchat_set_sensitive_if_input_cb), data); | |
7620 | 4436 } |
4437 | |
10475 | 4438 /* Do the following for any type of input widget */ |
4439 if (focus) | |
4440 { | |
4441 gtk_widget_grab_focus(input); | |
4442 focus = FALSE; | |
4443 } | |
4444 gtk_label_set_mnemonic_widget(GTK_LABEL(label), input); | |
4445 gaim_set_accessible_label(input, label); | |
4446 g_object_set_data(G_OBJECT(input), "identifier", pce->identifier); | |
4447 g_object_set_data(G_OBJECT(input), "is_spin", GINT_TO_POINTER(pce->is_int)); | |
4448 g_object_set_data(G_OBJECT(input), "required", GINT_TO_POINTER(pce->required)); | |
4449 data->entries = g_list_append(data->entries, input); | |
4450 | |
7620 | 4451 g_free(pce); |
4452 } | |
4453 | |
4454 g_list_free(list); | |
9754 | 4455 g_hash_table_destroy(defaults); |
7620 | 4456 |
10475 | 4457 /* Set whether the "OK" button should be clickable initially */ |
4458 addchat_set_sensitive_if_input_cb(NULL, data); | |
4459 | |
7620 | 4460 gtk_widget_show_all(data->entries_box); |
4461 } | |
4462 | |
4463 static void | |
10475 | 4464 addchat_select_account_cb(GObject *w, GaimAccount *account, |
7620 | 4465 GaimGtkAddChatData *data) |
4466 { | |
9460 | 4467 if (strcmp(gaim_account_get_protocol_id(data->account), |
4468 gaim_account_get_protocol_id(account)) == 0) | |
7620 | 4469 { |
4470 data->account = account; | |
4471 } | |
4472 else | |
4473 { | |
4474 data->account = account; | |
4475 rebuild_addchat_entries(data); | |
4476 } | |
4477 } | |
4478 | |
4479 void | |
7859 | 4480 gaim_gtk_blist_request_add_chat(GaimAccount *account, GaimGroup *group, |
9754 | 4481 const char *alias, const char *name) |
7620 | 4482 { |
4483 GaimGtkAddChatData *data; | |
8975 | 4484 GaimGtkBuddyList *gtkblist; |
4485 GList *l; | |
4486 GaimConnection *gc; | |
7620 | 4487 GtkWidget *label; |
4488 GtkWidget *rowbox; | |
4489 GtkWidget *hbox; | |
4490 GtkWidget *vbox; | |
4491 GtkWidget *img; | |
4492 | |
9812 | 4493 if (account != NULL) { |
4494 gc = gaim_account_get_connection(account); | |
4495 | |
4496 if (GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->join_chat == NULL) { | |
4497 gaim_notify_error(gc, NULL, _("This protocol does not support chat rooms."), NULL); | |
4498 return; | |
4499 } | |
4500 } else { | |
4501 /* Find an account with chat capabilities */ | |
4502 for (l = gaim_connections_get_all(); l != NULL; l = l->next) { | |
4503 gc = (GaimConnection *)l->data; | |
4504 | |
4505 if (GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->join_chat != NULL) { | |
4506 account = gaim_connection_get_account(gc); | |
4507 break; | |
4508 } | |
4509 } | |
4510 | |
4511 if (account == NULL) { | |
4512 gaim_notify_error(NULL, NULL, | |
4513 _("You are not currently signed on with any " | |
4514 "protocols that have the ability to chat."), NULL); | |
4515 return; | |
4516 } | |
4517 } | |
4518 | |
7620 | 4519 data = g_new0(GaimGtkAddChatData, 1); |
9812 | 4520 data->account = account; |
4521 data->default_chat_name = g_strdup(name); | |
7620 | 4522 |
4523 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, | |
4524 GTK_ICON_SIZE_DIALOG); | |
4525 | |
8975 | 4526 gtkblist = GAIM_GTK_BLIST(gaim_get_blist()); |
4527 | |
7620 | 4528 data->sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); |
4529 | |
8975 | 4530 data->window = gtk_dialog_new_with_buttons(_("Add Chat"), |
4531 NULL, GTK_DIALOG_NO_SEPARATOR, | |
4532 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | |
4533 GTK_STOCK_ADD, GTK_RESPONSE_OK, | |
4534 NULL); | |
4535 | |
4536 gtk_dialog_set_default_response(GTK_DIALOG(data->window), GTK_RESPONSE_OK); | |
11243 | 4537 gtk_container_set_border_width(GTK_CONTAINER(data->window), GAIM_HIG_BOX_SPACE); |
8975 | 4538 gtk_window_set_resizable(GTK_WINDOW(data->window), FALSE); |
11243 | 4539 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(data->window)->vbox), GAIM_HIG_BORDER); |
4540 gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), GAIM_HIG_BOX_SPACE); | |
7620 | 4541 gtk_window_set_role(GTK_WINDOW(data->window), "add_chat"); |
8975 | 4542 gtk_window_set_type_hint(GTK_WINDOW(data->window), |
9811 | 4543 GDK_WINDOW_TYPE_HINT_DIALOG); |
7620 | 4544 |
11243 | 4545 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); |
7620 | 4546 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), hbox); |
4547 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); | |
4548 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); | |
4549 | |
4550 vbox = gtk_vbox_new(FALSE, 5); | |
4551 gtk_container_add(GTK_CONTAINER(hbox), vbox); | |
4552 | |
4553 label = gtk_label_new( | |
4554 _("Please enter an alias, and the appropriate information " | |
4555 "about the chat you would like to add to your buddy list.\n")); | |
4556 gtk_widget_set_size_request(label, 400, -1); | |
4557 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); | |
4558 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); | |
4559 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); | |
4560 | |
4561 rowbox = gtk_hbox_new(FALSE, 5); | |
4562 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0); | |
4563 | |
4564 label = gtk_label_new(_("Account:")); | |
4565 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
4566 gtk_size_group_add_widget(data->sg, label); | |
4567 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); | |
4568 | |
4569 data->account_menu = gaim_gtk_account_option_menu_new(account, FALSE, | |
10475 | 4570 G_CALLBACK(addchat_select_account_cb), |
9987 | 4571 chat_account_filter_func, data); |
7620 | 4572 gtk_box_pack_start(GTK_BOX(rowbox), data->account_menu, TRUE, TRUE, 0); |
8137 | 4573 gaim_set_accessible_label (data->account_menu, label); |
7620 | 4574 |
4575 data->entries_box = gtk_vbox_new(FALSE, 5); | |
9811 | 4576 gtk_container_set_border_width(GTK_CONTAINER(data->entries_box), 0); |
7620 | 4577 gtk_box_pack_start(GTK_BOX(vbox), data->entries_box, TRUE, TRUE, 0); |
4578 | |
4579 rebuild_addchat_entries(data); | |
4580 | |
4581 rowbox = gtk_hbox_new(FALSE, 5); | |
4582 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0); | |
4583 | |
4584 label = gtk_label_new(_("Alias:")); | |
4585 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
4586 gtk_size_group_add_widget(data->sg, label); | |
4587 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); | |
4588 | |
4589 data->alias_entry = gtk_entry_new(); | |
7859 | 4590 if (alias != NULL) |
4591 gtk_entry_set_text(GTK_ENTRY(data->alias_entry), alias); | |
7620 | 4592 gtk_box_pack_end(GTK_BOX(rowbox), data->alias_entry, TRUE, TRUE, 0); |
10311 | 4593 gtk_entry_set_activates_default(GTK_ENTRY(data->alias_entry), TRUE); |
8137 | 4594 gaim_set_accessible_label (data->alias_entry, label); |
7620 | 4595 |
4596 rowbox = gtk_hbox_new(FALSE, 5); | |
4597 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0); | |
4598 | |
9811 | 4599 label = gtk_label_new(_("Group:")); |
7620 | 4600 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); |
4601 gtk_size_group_add_widget(data->sg, label); | |
4602 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); | |
4603 | |
9811 | 4604 data->group_combo = gtk_combo_new(); |
4605 gtk_combo_set_popdown_strings(GTK_COMBO(data->group_combo), groups_tree()); | |
7620 | 4606 gtk_box_pack_end(GTK_BOX(rowbox), data->group_combo, TRUE, TRUE, 0); |
4607 | |
4608 if (group) | |
4609 { | |
4610 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(data->group_combo)->entry), | |
4611 group->name); | |
4612 } | |
8137 | 4613 gaim_set_accessible_label (data->group_combo, label); |
7620 | 4614 |
4615 g_signal_connect(G_OBJECT(data->window), "response", | |
4616 G_CALLBACK(add_chat_resp_cb), data); | |
4617 | |
4618 gtk_widget_show_all(data->window); | |
4619 } | |
4620 | |
4621 static void | |
4622 add_group_cb(GaimConnection *gc, const char *group_name) | |
4623 { | |
9285 | 4624 GaimGroup *group; |
4625 | |
4626 group = gaim_group_new(group_name); | |
4627 gaim_blist_add_group(group, NULL); | |
7620 | 4628 } |
4629 | |
4630 void | |
4631 gaim_gtk_blist_request_add_group(void) | |
4632 { | |
7853 | 4633 gaim_request_input(NULL, _("Add Group"), NULL, |
7620 | 4634 _("Please enter the name of the group to be added."), |
8697 | 4635 NULL, FALSE, FALSE, NULL, |
7620 | 4636 _("Add"), G_CALLBACK(add_group_cb), |
4637 _("Cancel"), NULL, NULL); | |
4638 } | |
4639 | |
12016
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4640 void |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4641 gaim_gtk_blist_toggle_visibility() |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4642 { |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4643 if (gtkblist && gtkblist->window) { |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4644 if (GTK_WIDGET_VISIBLE(gtkblist->window)) { |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4645 gaim_blist_set_visible(GAIM_WINDOW_ICONIFIED(gtkblist->window) || gtk_blist_obscured); |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4646 } else { |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4647 gaim_blist_set_visible(TRUE); |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4648 } |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4649 } |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4650 } |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4651 |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4652 void |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4653 gaim_gtk_blist_visibility_manager_add() |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4654 { |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4655 visibility_manager_count++; |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4656 } |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4657 |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4658 void |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4659 gaim_gtk_blist_visibility_manager_remove() |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4660 { |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4661 if (visibility_manager_count) |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4662 visibility_manager_count--; |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4663 if (!visibility_manager_count) |
12115
e9790eb93216
[gaim-migrate @ 14415]
Luke Schierer <lschiere@pidgin.im>
parents:
12113
diff
changeset
|
4664 gaim_blist_set_visible(gaim_prefs_get_bool("/gaim/gtk/blist/list_visible")); |
12016
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4665 } |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4666 |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4667 |
7620 | 4668 static GaimBlistUiOps blist_ui_ops = |
5228 | 4669 { |
4670 gaim_gtk_blist_new_list, | |
5256 | 4671 gaim_gtk_blist_new_node, |
5228 | 4672 gaim_gtk_blist_show, |
4673 gaim_gtk_blist_update, | |
4674 gaim_gtk_blist_remove, | |
4675 gaim_gtk_blist_destroy, | |
7620 | 4676 gaim_gtk_blist_set_visible, |
4677 gaim_gtk_blist_request_add_buddy, | |
4678 gaim_gtk_blist_request_add_chat, | |
10012 | 4679 gaim_gtk_blist_request_add_group |
5228 | 4680 }; |
4681 | |
4682 | |
7620 | 4683 GaimBlistUiOps * |
4684 gaim_gtk_blist_get_ui_ops(void) | |
5228 | 4685 { |
4686 return &blist_ui_ops; | |
4687 } | |
4688 | |
10643 | 4689 GaimGtkBuddyList *gaim_gtk_blist_get_default_gtk_blist() |
4690 { | |
4691 return gtkblist; | |
4692 } | |
4693 | |
7620 | 4694 static void account_signon_cb(GaimConnection *gc, gpointer z) |
4695 { | |
4696 GaimAccount *account = gaim_connection_get_account(gc); | |
4697 GaimBlistNode *gnode, *cnode; | |
4698 for(gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) | |
4699 { | |
4700 if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) | |
4701 continue; | |
4702 for(cnode = gnode->child; cnode; cnode = cnode->next) | |
4703 { | |
4704 GaimChat *chat; | |
4705 | |
4706 if(!GAIM_BLIST_NODE_IS_CHAT(cnode)) | |
4707 continue; | |
4708 | |
4709 chat = (GaimChat *)cnode; | |
4710 | |
4711 if(chat->account != account) | |
4712 continue; | |
4713 | |
8197 | 4714 if(gaim_blist_node_get_bool((GaimBlistNode*)chat, "gtk-autojoin") || |
8198 | 4715 (gaim_blist_node_get_string((GaimBlistNode*)chat, |
4716 "gtk-autojoin") != NULL)) | |
7620 | 4717 serv_join_chat(gc, chat->components); |
4718 } | |
4719 } | |
4720 } | |
4721 | |
8815 | 4722 void * |
4723 gaim_gtk_blist_get_handle() { | |
4724 static int handle; | |
4725 | |
4726 return &handle; | |
4727 } | |
4728 | |
11910 | 4729 static gboolean buddy_signonoff_timeout_cb(GaimBuddy *buddy) |
4730 { | |
4731 struct _gaim_gtk_blist_node *gtknode = ((GaimBlistNode*)buddy)->ui_data; | |
4732 GaimConversation *conv; | |
4733 | |
4734 gtknode->recent_signonoff = FALSE; | |
4735 gtknode->recent_signonoff_timer = 0; | |
4736 | |
4737 gaim_gtk_blist_update(NULL, (GaimBlistNode*)buddy); | |
4738 | |
4739 if((conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, buddy->name, buddy->account))) { | |
4740 if(GAIM_BUDDY_IS_ONLINE(buddy)) { | |
4741 gaim_conversation_update(conv, GAIM_CONV_ACCOUNT_ONLINE); | |
4742 } else { | |
4743 gaim_conversation_update(conv, GAIM_CONV_ACCOUNT_OFFLINE); | |
4744 } | |
4745 } | |
4746 | |
4747 return FALSE; | |
4748 } | |
4749 | |
4750 static void buddy_signonoff_cb(GaimBuddy *buddy) | |
4751 { | |
11915 | 4752 struct _gaim_gtk_blist_node *gtknode; |
4753 | |
4754 if(!((GaimBlistNode*)buddy)->ui_data) { | |
4755 gaim_gtk_blist_new_node((GaimBlistNode*)buddy); | |
4756 } | |
4757 | |
4758 gtknode = ((GaimBlistNode*)buddy)->ui_data; | |
11910 | 4759 |
4760 gtknode->recent_signonoff = TRUE; | |
4761 | |
4762 if(gtknode->recent_signonoff_timer > 0) | |
4763 gaim_timeout_remove(gtknode->recent_signonoff_timer); | |
4764 gtknode->recent_signonoff_timer = gaim_timeout_add(10000, | |
4765 (GSourceFunc)buddy_signonoff_timeout_cb, buddy); | |
4766 } | |
4767 | |
7620 | 4768 void gaim_gtk_blist_init(void) |
4769 { | |
8815 | 4770 void *gtk_blist_handle = gaim_gtk_blist_get_handle(); |
7620 | 4771 |
4772 gaim_signal_connect(gaim_connections_get_handle(), "signed-on", | |
8815 | 4773 gtk_blist_handle, GAIM_CALLBACK(account_signon_cb), |
7620 | 4774 NULL); |
7731 | 4775 |
4776 /* Initialize prefs */ | |
8819 | 4777 gaim_prefs_add_none("/gaim/gtk/blist"); |
4778 gaim_prefs_add_bool("/gaim/gtk/blist/show_buddy_icons", TRUE); | |
4779 gaim_prefs_add_bool("/gaim/gtk/blist/show_empty_groups", FALSE); | |
4780 gaim_prefs_add_bool("/gaim/gtk/blist/show_offline_buddies", FALSE); | |
10282 | 4781 gaim_prefs_add_bool("/gaim/gtk/blist/list_visible", TRUE); |
9711 | 4782 gaim_prefs_add_string("/gaim/gtk/blist/sort_type", "alphabetical"); |
8819 | 4783 gaim_prefs_add_int("/gaim/gtk/blist/x", 0); |
4784 gaim_prefs_add_int("/gaim/gtk/blist/y", 0); | |
9778 | 4785 gaim_prefs_add_int("/gaim/gtk/blist/width", 309); /* Golden ratio, baby */ |
4786 gaim_prefs_add_int("/gaim/gtk/blist/height", 500); /* Golden ratio, baby */ | |
8819 | 4787 gaim_prefs_add_int("/gaim/gtk/blist/tooltip_delay", 500); |
7731 | 4788 |
8815 | 4789 /* Register our signals */ |
12016
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4790 gaim_signal_register(gtk_blist_handle, "gtkblist-hiding", |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4791 gaim_marshal_VOID__POINTER, NULL, 1, |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4792 gaim_value_new(GAIM_TYPE_POINTER)); |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4793 |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4794 gaim_signal_register(gtk_blist_handle, "gtkblist-unhiding", |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4795 gaim_marshal_VOID__POINTER, NULL, 1, |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4796 gaim_value_new(GAIM_TYPE_SUBTYPE)); |
24c7fb94d3a3
[gaim-migrate @ 14309]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11988
diff
changeset
|
4797 |
8815 | 4798 gaim_signal_register(gtk_blist_handle, "gtkblist-created", |
9811 | 4799 gaim_marshal_VOID__POINTER, NULL, 1, |
4800 gaim_value_new(GAIM_TYPE_SUBTYPE, | |
4801 GAIM_SUBTYPE_BLIST)); | |
8819 | 4802 |
4803 gaim_signal_register(gtk_blist_handle, "drawing-tooltip", | |
9811 | 4804 gaim_marshal_VOID__POINTER_POINTER, NULL, 2, |
4805 gaim_value_new(GAIM_TYPE_SUBTYPE, GAIM_SUBTYPE_BLIST_NODE), | |
10477 | 4806 gaim_value_new_outgoing(GAIM_TYPE_BOXED, "GString *")); |
11910 | 4807 |
4808 | |
4809 gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-on", gtk_blist_handle, GAIM_CALLBACK(buddy_signonoff_cb), NULL); | |
4810 gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-off", gtk_blist_handle, GAIM_CALLBACK(buddy_signonoff_cb), NULL); | |
7620 | 4811 } |
4812 | |
8815 | 4813 void |
4814 gaim_gtk_blist_uninit(void) { | |
4815 gaim_signals_unregister_by_instance(gaim_gtk_blist_get_handle()); | |
4816 } | |
5228 | 4817 |
4818 /********************************************************************* | |
9811 | 4819 * Buddy List sorting functions * |
5422 | 4820 *********************************************************************/ |
4821 | |
11796 | 4822 GList *gaim_gtk_blist_get_sort_methods() |
4823 { | |
4824 return gaim_gtk_blist_sort_methods; | |
4825 } | |
4826 | |
7620 | 4827 void gaim_gtk_blist_sort_method_reg(const char *id, const char *name, gaim_gtk_blist_sort_function func) |
5422 | 4828 { |
4829 struct gaim_gtk_blist_sort_method *method = g_new0(struct gaim_gtk_blist_sort_method, 1); | |
7620 | 4830 method->id = g_strdup(id); |
5422 | 4831 method->name = g_strdup(name); |
9775 | 4832 method->func = func; |
11796 | 4833 gaim_gtk_blist_sort_methods = g_list_append(gaim_gtk_blist_sort_methods, method); |
4834 gaim_gtk_blist_update_sort_methods(); | |
5422 | 4835 } |
4836 | |
7620 | 4837 void gaim_gtk_blist_sort_method_unreg(const char *id){ |
11796 | 4838 GList *l = gaim_gtk_blist_sort_methods; |
7620 | 4839 |
4840 while(l) { | |
4841 struct gaim_gtk_blist_sort_method *method = l->data; | |
4842 if(!strcmp(method->id, id)) { | |
11796 | 4843 gaim_gtk_blist_sort_methods = g_list_delete_link(gaim_gtk_blist_sort_methods, l); |
7620 | 4844 g_free(method->id); |
4845 g_free(method->name); | |
4846 g_free(method); | |
4847 break; | |
4848 } | |
4849 } | |
11796 | 4850 gaim_gtk_blist_update_sort_methods(); |
5422 | 4851 } |
4852 | |
7620 | 4853 void gaim_gtk_blist_sort_method_set(const char *id){ |
11796 | 4854 GList *l = gaim_gtk_blist_sort_methods; |
7620 | 4855 |
4856 if(!id) | |
4857 id = "none"; | |
4858 | |
4859 while (l && strcmp(((struct gaim_gtk_blist_sort_method*)l->data)->id, id)) | |
5422 | 4860 l = l->next; |
7620 | 4861 |
5422 | 4862 if (l) { |
4863 current_sort_method = l->data; | |
4864 } else if (!current_sort_method) { | |
7620 | 4865 gaim_gtk_blist_sort_method_set("none"); |
5422 | 4866 return; |
4867 } | |
4868 redo_buddy_list(gaim_get_blist(), TRUE); | |
4869 | |
4870 } | |
4871 | |
4872 /****************************************** | |
4873 ** Sort Methods | |
4874 ******************************************/ | |
4875 | |
7620 | 4876 static GtkTreeIter sort_method_none(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter parent_iter, GtkTreeIter *cur) |
5422 | 4877 { |
7620 | 4878 GtkTreeIter iter; |
4879 GaimBlistNode *sibling = node->prev; | |
4880 GtkTreeIter sibling_iter; | |
4881 | |
4882 if(cur) | |
5422 | 4883 return *cur; |
7620 | 4884 |
4885 while (sibling && !get_iter_from_node(sibling, &sibling_iter)) { | |
4886 sibling = sibling->prev; | |
5422 | 4887 } |
7620 | 4888 |
4889 gtk_tree_store_insert_after(gtkblist->treemodel, &iter, | |
4890 node->parent ? &parent_iter : NULL, | |
4891 sibling ? &sibling_iter : NULL); | |
4892 | |
5422 | 4893 return iter; |
4894 } | |
4895 | |
7620 | 4896 #if GTK_CHECK_VERSION(2,2,1) |
4897 | |
4898 static GtkTreeIter sort_method_alphabetical(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur) | |
5422 | 4899 { |
4900 GtkTreeIter more_z, iter; | |
4901 GaimBlistNode *n; | |
4902 GValue val = {0,}; | |
7620 | 4903 |
4904 const char *my_name; | |
4905 | |
4906 if(GAIM_BLIST_NODE_IS_CONTACT(node)) { | |
4907 my_name = gaim_contact_get_alias((GaimContact*)node); | |
4908 } else if(GAIM_BLIST_NODE_IS_CHAT(node)) { | |
4909 my_name = gaim_chat_get_name((GaimChat*)node); | |
4910 } else { | |
4911 return sort_method_none(node, blist, groupiter, cur); | |
4912 } | |
4913 | |
5422 | 4914 |
4915 if (!gtk_tree_model_iter_children(GTK_TREE_MODEL(gtkblist->treemodel), &more_z, &groupiter)) { | |
4916 gtk_tree_store_insert(gtkblist->treemodel, &iter, &groupiter, 0); | |
7620 | 4917 return iter; |
4918 } | |
4919 | |
4920 do { | |
4921 const char *this_name; | |
4922 int cmp; | |
4923 | |
4924 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &more_z, NODE_COLUMN, &val); | |
4925 n = g_value_get_pointer(&val); | |
4926 | |
4927 if(GAIM_BLIST_NODE_IS_CONTACT(n)) { | |
4928 this_name = gaim_contact_get_alias((GaimContact*)n); | |
4929 } else if(GAIM_BLIST_NODE_IS_CHAT(n)) { | |
4930 this_name = gaim_chat_get_name((GaimChat*)n); | |
4931 } else { | |
4932 this_name = NULL; | |
4933 } | |
4934 | |
4935 cmp = gaim_utf8_strcasecmp(my_name, this_name); | |
4936 | |
4937 if(this_name && (cmp < 0 || (cmp == 0 && node < n))) { | |
4938 if(cur) { | |
4939 gtk_tree_store_move_before(gtkblist->treemodel, cur, &more_z); | |
4940 return *cur; | |
4941 } else { | |
4942 gtk_tree_store_insert_before(gtkblist->treemodel, &iter, | |
4943 &groupiter, &more_z); | |
4944 return iter; | |
4945 } | |
4946 } | |
4947 g_value_unset(&val); | |
4948 } while (gtk_tree_model_iter_next (GTK_TREE_MODEL(gtkblist->treemodel), &more_z)); | |
4949 | |
4950 if(cur) { | |
4951 gtk_tree_store_move_before(gtkblist->treemodel, cur, NULL); | |
4952 return *cur; | |
4953 } else { | |
4954 gtk_tree_store_append(gtkblist->treemodel, &iter, &groupiter); | |
4955 return iter; | |
4956 } | |
4957 } | |
4958 | |
4959 static GtkTreeIter sort_method_status(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur) | |
4960 { | |
4961 GtkTreeIter more_z, iter; | |
4962 GaimBlistNode *n; | |
4963 GValue val = {0,}; | |
4964 | |
4965 GaimBuddy *my_buddy, *this_buddy; | |
4966 | |
4967 if(GAIM_BLIST_NODE_IS_CONTACT(node)) { | |
4968 my_buddy = gaim_contact_get_priority_buddy((GaimContact*)node); | |
4969 } else if(GAIM_BLIST_NODE_IS_CHAT(node)) { | |
4970 if(cur) | |
4971 return *cur; | |
4972 | |
4973 gtk_tree_store_append(gtkblist->treemodel, &iter, &groupiter); | |
4974 return iter; | |
4975 } else { | |
4976 return sort_method_none(node, blist, groupiter, cur); | |
4977 } | |
4978 | |
4979 | |
4980 if (!gtk_tree_model_iter_children(GTK_TREE_MODEL(gtkblist->treemodel), &more_z, &groupiter)) { | |
4981 gtk_tree_store_insert(gtkblist->treemodel, &iter, &groupiter, 0); | |
5422 | 4982 return iter; |
4983 } | |
4984 | |
4985 do { | |
9944 | 4986 gint name_cmp; |
4987 gint presence_cmp; | |
7620 | 4988 |
5422 | 4989 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &more_z, NODE_COLUMN, &val); |
4990 n = g_value_get_pointer(&val); | |
7620 | 4991 |
4992 if(GAIM_BLIST_NODE_IS_CONTACT(n)) { | |
4993 this_buddy = gaim_contact_get_priority_buddy((GaimContact*)n); | |
4994 } else { | |
4995 this_buddy = NULL; | |
4996 } | |
4997 | |
9944 | 4998 name_cmp = gaim_utf8_strcasecmp( |
4999 (my_buddy | |
5000 ? gaim_contact_get_alias(gaim_buddy_get_contact(my_buddy)) | |
5001 : NULL), | |
5002 (this_buddy | |
5003 ? gaim_contact_get_alias(gaim_buddy_get_contact(this_buddy)) | |
5004 : NULL)); | |
5005 | |
5006 presence_cmp = gaim_presence_compare( | |
5007 gaim_buddy_get_presence(my_buddy), | |
5008 gaim_buddy_get_presence(this_buddy)); | |
5009 | |
5010 if (this_buddy == NULL || | |
10860 | 5011 (presence_cmp < 0 || |
9944 | 5012 (presence_cmp == 0 && |
5013 (name_cmp < 0 || (name_cmp == 0 && node < n))))) | |
5014 { | |
5015 if (cur != NULL) | |
5016 { | |
7620 | 5017 gtk_tree_store_move_before(gtkblist->treemodel, cur, &more_z); |
5018 return *cur; | |
9944 | 5019 } |
5020 else | |
5021 { | |
7620 | 5022 gtk_tree_store_insert_before(gtkblist->treemodel, &iter, |
9944 | 5023 &groupiter, &more_z); |
7620 | 5024 return iter; |
5025 } | |
5422 | 5026 } |
9944 | 5027 |
5422 | 5028 g_value_unset(&val); |
9944 | 5029 } |
5030 while (gtk_tree_model_iter_next(GTK_TREE_MODEL(gtkblist->treemodel), | |
5031 &more_z)); | |
7620 | 5032 |
5033 if(cur) { | |
5034 gtk_tree_store_move_before(gtkblist->treemodel, cur, NULL); | |
5035 return *cur; | |
5036 } else { | |
5037 gtk_tree_store_append(gtkblist->treemodel, &iter, &groupiter); | |
5038 return iter; | |
5039 } | |
5422 | 5040 } |
5041 | |
7620 | 5042 static GtkTreeIter sort_method_log(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur) |
5422 | 5043 { |
5044 GtkTreeIter more_z, iter; | |
7620 | 5045 GaimBlistNode *n = NULL, *n2; |
5422 | 5046 GValue val = {0,}; |
7620 | 5047 |
5048 int log_size = 0, this_log_size = 0; | |
5049 const char *buddy_name, *this_buddy_name; | |
5050 | |
5051 if(cur && (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(gtkblist->treemodel), &groupiter) == 1)) | |
5052 return *cur; | |
5053 | |
5054 if(GAIM_BLIST_NODE_IS_CONTACT(node)) { | |
5055 for (n = node->child; n; n = n->next) | |
8898 | 5056 log_size += gaim_log_get_total_size(GAIM_LOG_IM, ((GaimBuddy*)(n))->name, ((GaimBuddy*)(n))->account); |
7620 | 5057 buddy_name = gaim_contact_get_alias((GaimContact*)node); |
5058 } else if(GAIM_BLIST_NODE_IS_CHAT(node)) { | |
5059 /* we don't have a reliable way of getting the log filename | |
5060 * from the chat info in the blist, yet */ | |
5061 if(cur) | |
5062 return *cur; | |
5063 | |
5064 gtk_tree_store_append(gtkblist->treemodel, &iter, &groupiter); | |
5065 return iter; | |
5066 } else { | |
5067 return sort_method_none(node, blist, groupiter, cur); | |
5068 } | |
5069 | |
5070 | |
5422 | 5071 if (!gtk_tree_model_iter_children(GTK_TREE_MODEL(gtkblist->treemodel), &more_z, &groupiter)) { |
5072 gtk_tree_store_insert(gtkblist->treemodel, &iter, &groupiter, 0); | |
5073 return iter; | |
5074 } | |
5075 | |
5076 do { | |
7620 | 5077 int cmp; |
5078 | |
5422 | 5079 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &more_z, NODE_COLUMN, &val); |
5080 n = g_value_get_pointer(&val); | |
7620 | 5081 this_log_size = 0; |
5082 | |
5083 if(GAIM_BLIST_NODE_IS_CONTACT(n)) { | |
5084 for (n2 = n->child; n2; n2 = n2->next) | |
8898 | 5085 this_log_size += gaim_log_get_total_size(GAIM_LOG_IM, ((GaimBuddy*)(n2))->name, ((GaimBuddy*)(n2))->account); |
7620 | 5086 this_buddy_name = gaim_contact_get_alias((GaimContact*)n); |
5087 } else { | |
5088 this_buddy_name = NULL; | |
5422 | 5089 } |
7620 | 5090 |
5091 cmp = gaim_utf8_strcasecmp(buddy_name, this_buddy_name); | |
5092 | |
5093 if (!GAIM_BLIST_NODE_IS_CONTACT(n) || log_size > this_log_size || | |
5094 ((log_size == this_log_size) && | |
5095 (cmp < 0 || (cmp == 0 && node < n)))) { | |
5096 if(cur) { | |
5097 gtk_tree_store_move_before(gtkblist->treemodel, cur, &more_z); | |
5098 return *cur; | |
5099 } else { | |
5100 gtk_tree_store_insert_before(gtkblist->treemodel, &iter, | |
5101 &groupiter, &more_z); | |
5102 return iter; | |
5103 } | |
5422 | 5104 } |
5105 g_value_unset(&val); | |
5106 } while (gtk_tree_model_iter_next (GTK_TREE_MODEL(gtkblist->treemodel), &more_z)); | |
7620 | 5107 |
5108 if(cur) { | |
5109 gtk_tree_store_move_before(gtkblist->treemodel, cur, NULL); | |
5110 return *cur; | |
5111 } else { | |
5112 gtk_tree_store_append(gtkblist->treemodel, &iter, &groupiter); | |
5113 return iter; | |
5114 } | |
5115 } | |
5116 | |
5117 #endif | |
5118 | |
5119 static void | |
9015 | 5120 plugin_act(GtkObject *obk, GaimPluginAction *pam) |
7620 | 5121 { |
10352 | 5122 if (pam->callback) |
5123 pam->callback(pam); | |
5422 | 5124 } |
7620 | 5125 |
11742 | 5126 static GList *plugin_menu_items = NULL; |
5127 static int plugin_menu_index = 8; | |
5128 | |
8986 | 5129 static void |
9015 | 5130 build_plugin_actions(GtkWidget *menu, GaimPlugin *plugin, gpointer context) |
8986 | 5131 { |
9015 | 5132 GtkWidget *menuitem = NULL; |
5133 GaimPluginAction *action = NULL; | |
5134 GList *l, *ll; | |
5135 | |
5136 for (l = ll = GAIM_PLUGIN_ACTIONS(plugin, context); l; l = l->next) { | |
5137 if (l->data) { | |
5138 action = (GaimPluginAction *) l->data; | |
5139 action->plugin = plugin; | |
5140 action->context = context; | |
5141 | |
5142 menuitem = gtk_menu_item_new_with_label(action->label); | |
11745 | 5143 if (context) { |
5144 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
5145 } else { | |
5146 plugin_menu_items = g_list_append(plugin_menu_items, menuitem); | |
5147 plugin_menu_index++; | |
5148 gtk_menu_shell_insert(GTK_MENU_SHELL(menu), menuitem, plugin_menu_index); | |
5149 } | |
9015 | 5150 g_signal_connect(G_OBJECT(menuitem), "activate", |
5151 G_CALLBACK(plugin_act), action); | |
5152 g_object_set_data(G_OBJECT(menuitem), "plugin_action", action); | |
5153 gtk_widget_show(menuitem); | |
5154 } | |
5155 else | |
5156 gaim_separator(menu); | |
5157 } | |
5158 | |
5159 g_list_free(ll); | |
8986 | 5160 } |
5161 | |
5162 | |
7620 | 5163 void |
5164 gaim_gtk_blist_update_protocol_actions(void) | |
5165 { | |
9015 | 5166 GtkWidget *menuitem, *submenu; |
7620 | 5167 GList *l; |
5168 GaimConnection *gc = NULL; | |
9015 | 5169 GaimPlugin *plugin = NULL; |
7620 | 5170 int count = 0; |
9015 | 5171 |
9019 | 5172 if (protomenu == NULL) |
7620 | 5173 return; |
5174 | |
9019 | 5175 /* Clear the old Account Actions menu */ |
9015 | 5176 for (l = gtk_container_get_children(GTK_CONTAINER(protomenu)); l; l = l->next) { |
5177 GaimPluginAction *action; | |
9987 | 5178 |
7620 | 5179 menuitem = l->data; |
9015 | 5180 action = (GaimPluginAction *) g_object_get_data(G_OBJECT(menuitem), |
5181 "plugin_action"); | |
5182 g_free(action); | |
7620 | 5183 |
5184 gtk_container_remove(GTK_CONTAINER(protomenu), GTK_WIDGET(menuitem)); | |
5185 } | |
5186 | |
9019 | 5187 /* Count the number of accounts with actions */ |
9015 | 5188 for (l = gaim_connections_get_all(); l; l = l->next) { |
5189 gc = l->data; | |
5190 plugin = gc->prpl; | |
5191 | |
9019 | 5192 if (GAIM_CONNECTION_IS_CONNECTED(gc) && GAIM_PLUGIN_HAS_ACTIONS(plugin)) |
5193 count++; | |
5194 | |
9015 | 5195 /* no need to count past 2, so don't */ |
9019 | 5196 if (count > 1) |
9015 | 5197 break; |
7620 | 5198 } |
5199 | |
9015 | 5200 if (count == 0) { |
5201 menuitem = gtk_menu_item_new_with_label(_("No actions available")); | |
7620 | 5202 gtk_menu_shell_append(GTK_MENU_SHELL(protomenu), menuitem); |
9015 | 5203 gtk_widget_set_sensitive(menuitem, FALSE); |
7620 | 5204 gtk_widget_show(menuitem); |
5205 } | |
9019 | 5206 |
5207 else if (count == 1) { | |
5208 /* Find the one account that has actions */ | |
5209 for (l = gaim_connections_get_all(); l; l = l->next) { | |
5210 gc = l->data; | |
5211 plugin = gc->prpl; | |
5212 | |
5213 if (GAIM_CONNECTION_IS_CONNECTED(gc) && GAIM_PLUGIN_HAS_ACTIONS(plugin)) | |
5214 break; | |
5215 } | |
5216 | |
9015 | 5217 build_plugin_actions(protomenu, plugin, gc); |
7620 | 5218 } |
9019 | 5219 |
7620 | 5220 else { |
9015 | 5221 for (l = gaim_connections_get_all(); l; l = l->next) { |
7620 | 5222 GaimAccount *account; |
5223 GdkPixbuf *pixbuf, *scale; | |
5224 GtkWidget *image; | |
9015 | 5225 char *buf; |
5226 | |
5227 gc = l->data; | |
5228 plugin = gc->prpl; | |
5229 | |
9019 | 5230 if (!GAIM_CONNECTION_IS_CONNECTED(gc) || !GAIM_PLUGIN_HAS_ACTIONS(plugin)) |
7620 | 5231 continue; |
5232 | |
5233 account = gaim_connection_get_account(gc); | |
9015 | 5234 buf = g_strconcat(gaim_account_get_username(account), " (", |
5235 plugin->info->name, ")", NULL); | |
7620 | 5236 menuitem = gtk_image_menu_item_new_with_label(buf); |
9015 | 5237 g_free(buf); |
5238 | |
10884 | 5239 pixbuf = gaim_gtk_create_prpl_icon(account); |
9019 | 5240 if (pixbuf) { |
7620 | 5241 scale = gdk_pixbuf_scale_simple(pixbuf, 16, 16, |
5242 GDK_INTERP_BILINEAR); | |
5243 image = gtk_image_new_from_pixbuf(scale); | |
5244 g_object_unref(G_OBJECT(pixbuf)); | |
5245 g_object_unref(G_OBJECT(scale)); | |
5246 gtk_widget_show(image); | |
9015 | 5247 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image); |
7620 | 5248 } |
5249 | |
5250 gtk_menu_shell_append(GTK_MENU_SHELL(protomenu), menuitem); | |
5251 gtk_widget_show(menuitem); | |
5252 | |
5253 submenu = gtk_menu_new(); | |
5254 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); | |
5255 gtk_widget_show(submenu); | |
5256 | |
9015 | 5257 build_plugin_actions(submenu, plugin, gc); |
7620 | 5258 } |
5259 } | |
5260 } | |
8986 | 5261 |
5262 void | |
5263 gaim_gtk_blist_update_plugin_actions(void) | |
5264 { | |
11742 | 5265 GtkWidget *menuitem; |
9015 | 5266 GaimPlugin *plugin = NULL; |
8986 | 5267 GList *l; |
5268 int count = 0; | |
5269 | |
11742 | 5270 GtkWidget *pluginmenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools")); |
5271 | |
9019 | 5272 if (pluginmenu == NULL) |
8986 | 5273 return; |
5274 | |
9019 | 5275 /* Clear the old Account Actions menu */ |
11742 | 5276 for (l = plugin_menu_items; l; l = l->next) { |
9015 | 5277 GaimPluginAction *action; |
11742 | 5278 plugin_menu_index--; |
8986 | 5279 menuitem = l->data; |
9015 | 5280 action = g_object_get_data(G_OBJECT(menuitem), "plugin_action"); |
5281 g_free(action); | |
8986 | 5282 |
5283 gtk_container_remove(GTK_CONTAINER(pluginmenu), GTK_WIDGET(menuitem)); | |
5284 } | |
11742 | 5285 g_list_free(plugin_menu_items); |
5286 plugin_menu_items = NULL; | |
8986 | 5287 |
9019 | 5288 /* Count the number of plugins with actions */ |
9015 | 5289 for (l = gaim_plugins_get_loaded(); l; l = l->next) { |
5290 plugin = (GaimPlugin *) l->data; | |
5291 | |
9019 | 5292 if (!GAIM_IS_PROTOCOL_PLUGIN(plugin) && GAIM_PLUGIN_HAS_ACTIONS(plugin)) |
5293 count++; | |
5294 | |
5295 /* no need to count past 2, so don't */ | |
5296 if (count > 1) | |
9015 | 5297 break; |
8986 | 5298 } |
5299 | |
11742 | 5300 for (l = gaim_plugins_get_loaded(); l; l = l->next) { |
11923 | 5301 |
11742 | 5302 plugin = (GaimPlugin *) l->data; |
11923 | 5303 |
11742 | 5304 if (GAIM_IS_PROTOCOL_PLUGIN(plugin)) |
5305 continue; | |
5306 | |
5307 if (!GAIM_PLUGIN_HAS_ACTIONS(plugin)) | |
5308 continue; | |
9019 | 5309 |
9015 | 5310 build_plugin_actions(pluginmenu, plugin, NULL); |
8986 | 5311 } |
5312 } | |
11796 | 5313 |
5314 void sortmethod_act(GtkCheckMenuItem *checkmenuitem, char *id) | |
5315 { | |
5316 if (gtk_check_menu_item_get_active(checkmenuitem)) | |
11923 | 5317 { |
11796 | 5318 gaim_gtk_blist_sort_method_set(id); |
11923 | 5319 gaim_prefs_set_string("/gaim/gtk/blist/sort_type", id); |
5320 } | |
11796 | 5321 } |
5322 | |
5323 void | |
5324 gaim_gtk_blist_update_sort_methods(void) | |
5325 { | |
5326 GtkWidget *menuitem = NULL, *activeitem = NULL; | |
5327 GaimGtkBlistSortMethod *method = NULL; | |
5328 GList *l; | |
5329 GSList *sl = NULL; | |
5330 GtkWidget *sortmenu; | |
11797 | 5331 const char *m = gaim_prefs_get_string("/gaim/gtk/blist/sort_type"); |
11796 | 5332 |
5333 if (gtkblist == NULL) | |
5334 return; | |
5335 | |
11798
01c3eec6ea3c
[gaim-migrate @ 14089]
Etan Reisner <pidgin@unreliablesource.net>
parents:
11797
diff
changeset
|
5336 sortmenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Buddies/Sort Buddies")); |
11796 | 5337 |
5338 if (sortmenu == NULL) | |
5339 return; | |
5340 | |
5341 /* Clear the old menu */ | |
5342 for (l = gtk_container_get_children(GTK_CONTAINER(sortmenu)); l; l = l->next) { | |
5343 menuitem = l->data; | |
5344 gtk_widget_destroy(GTK_WIDGET(menuitem)); | |
5345 } | |
11923 | 5346 |
11796 | 5347 for (l = gaim_gtk_blist_sort_methods; l; l = l->next) { |
5348 method = (GaimGtkBlistSortMethod *) l->data; | |
5349 menuitem = gtk_radio_menu_item_new_with_label(sl, _(method->name)); | |
5350 if (!strcmp(m, method->id)) | |
5351 activeitem = menuitem; | |
5352 sl = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem)); | |
5353 gtk_menu_shell_append(GTK_MENU_SHELL(sortmenu), menuitem); | |
5354 g_signal_connect(G_OBJECT(menuitem), "toggled", | |
5355 G_CALLBACK(sortmethod_act), method->id); | |
11923 | 5356 gtk_widget_show(menuitem); |
11796 | 5357 } |
5358 if (activeitem) | |
5359 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(activeitem), TRUE); | |
5360 | |
5361 } |