Mercurial > pidgin
annotate src/buddy.c @ 4960:42bd8ab53234
[gaim-migrate @ 5294]
I "made" some status icons for ICQ away states. They suck. Someone
with some skills of an artist please to try improve them. Or even just
whichever one you hate the most. Really, new icons are welcome. Email
them to mark izat kingant dizot net and we'll put them under
consideration.
I actually think the DND and free for chat icons look pretty nice. The
NA on the NA icon is not readable enough. The invisible is plain and
not very meaningful. The occupied is not easily discernable and stupid.
I also removed the option to have buddy list tabs at the top or bottom
of the buddy list.
And I took out my April Fools joke.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Wed, 02 Apr 2003 06:32:54 +0000 |
parents | aa273fba7b09 |
children | b9b2d7665721 |
rev | line source |
---|---|
1 | 1 /* |
2 * gaim | |
3 * | |
4 * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> | |
5 * | |
6 * This program is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program; if not, write to the Free Software | |
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 * | |
20 */ | |
21 | |
349
b402a23f35df
[gaim-migrate @ 359]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
342
diff
changeset
|
22 #ifdef HAVE_CONFIG_H |
2090
b66aca8e8dce
[gaim-migrate @ 2100]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2048
diff
changeset
|
23 #include <config.h> |
349
b402a23f35df
[gaim-migrate @ 359]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
342
diff
changeset
|
24 #endif |
391
be408b41c172
[gaim-migrate @ 401]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
350
diff
changeset
|
25 #ifdef GAIM_PLUGINS |
3630 | 26 #ifndef _WIN32 |
391
be408b41c172
[gaim-migrate @ 401]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
350
diff
changeset
|
27 #include <dlfcn.h> |
3630 | 28 #endif |
391
be408b41c172
[gaim-migrate @ 401]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
350
diff
changeset
|
29 #endif /* GAIM_PLUGINS */ |
1 | 30 #include <string.h> |
31 #include <stdio.h> | |
32 #include <stdlib.h> | |
3159 | 33 #include <ctype.h> |
1 | 34 #include <math.h> |
35 #include <time.h> | |
3630 | 36 #include <ctype.h> |
37 | |
38 #ifdef _WIN32 | |
39 #include <gdk/gdkwin32.h> | |
40 #else | |
1233
728a90516211
[gaim-migrate @ 1243]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1230
diff
changeset
|
41 #include <unistd.h> |
3630 | 42 #include <gdk/gdkx.h> |
43 #endif | |
1 | 44 |
1634
d029dc28a61e
[gaim-migrate @ 1644]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1625
diff
changeset
|
45 #include <gdk/gdkkeysyms.h> |
1 | 46 #include <gtk/gtk.h> |
1030
38452403563b
[gaim-migrate @ 1040]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1002
diff
changeset
|
47 #include "prpl.h" |
4561 | 48 #include "sound.h" |
1 | 49 #include "gaim.h" |
4687 | 50 #include "gtklist.h" |
51 #include "gtkft.h" | |
3630 | 52 |
53 #ifdef _WIN32 | |
54 #include "win32dep.h" | |
55 #endif | |
56 | |
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
57 static struct gaim_gtk_buddy_list *gtkblist = NULL; |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
58 |
4840 | 59 /* part of the best damn Docklet code this side of Tahiti */ |
4698 | 60 static gboolean gaim_gtk_blist_obscured = FALSE; |
61 | |
4810 | 62 static void gaim_gtk_blist_selection_changed(GtkTreeSelection *selection, gpointer data); |
4687 | 63 static void gaim_gtk_blist_update(struct gaim_buddy_list *list, GaimBlistNode *node); |
4724 | 64 static char *gaim_get_tooltip_text(struct buddy *b); |
65 static GdkPixbuf *gaim_gtk_blist_get_status_icon(struct buddy *b, GaimStatusIconSize size); | |
4834 | 66 static char *item_factory_translate_func (const char *path, gpointer func_data); |
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
67 |
4687 | 68 /*************************************************** |
69 * Callbacks * | |
70 ***************************************************/ | |
3869 | 71 |
4840 | 72 static gboolean gtk_blist_delete_cb(GtkWidget *w, GdkEventAny *event, gpointer data) |
4698 | 73 { |
74 if (docklet_count) | |
75 gaim_blist_set_visible(FALSE); | |
76 else | |
77 do_quit(); | |
4840 | 78 |
79 /* we handle everything, event should not propogate further */ | |
80 return TRUE; | |
81 } | |
82 | |
83 static gboolean gtk_blist_save_prefs_cb(gpointer data) | |
84 { | |
85 save_prefs(); | |
86 | |
87 /* only run once */ | |
88 return FALSE; | |
89 } | |
90 | |
91 static gboolean gtk_blist_configure_cb(GtkWidget *w, GdkEventConfigure *event, gpointer data) | |
92 { | |
93 /* unfortunately GdkEventConfigure ignores the window gravity, but * | |
94 * the only way we have of setting the position doesn't. we have to * | |
95 * call get_position and get_size because they do pay attention to * | |
96 * the gravity. this is inefficient and I agree it sucks, but it's * | |
97 * more likely to work correctly. - Robot101 */ | |
98 gint x, y; | |
99 | |
100 /* check for visibility because when we aren't visible, this will * | |
101 * give us bogus (0,0) coordinates. - xOr */ | |
102 if (GTK_WIDGET_VISIBLE(w)) { | |
103 gtk_window_get_position(GTK_WINDOW(w), &x, &y); | |
104 | |
105 if (x != blist_pos.x || | |
106 y != blist_pos.y || | |
107 event->width != blist_pos.width || | |
108 event->height != blist_pos.height) { | |
109 blist_pos.x = x; | |
110 blist_pos.y = y; | |
111 blist_pos.width = event->width; | |
112 blist_pos.height = event->height; | |
113 | |
114 if (!g_main_context_find_source_by_user_data(NULL, >k_blist_save_prefs_cb)) { | |
115 g_timeout_add(5000, gtk_blist_save_prefs_cb, >k_blist_save_prefs_cb); | |
116 } | |
117 } | |
118 } | |
119 | |
120 /* continue to handle event normally */ | |
121 return FALSE; | |
122 } | |
123 | |
124 static gboolean gtk_blist_visibility_cb(GtkWidget *w, GdkEventVisibility *event, gpointer data) | |
125 { | |
126 if (event->state == GDK_VISIBILITY_FULLY_OBSCURED) | |
127 gaim_gtk_blist_obscured = TRUE; | |
128 else | |
129 gaim_gtk_blist_obscured = FALSE; | |
130 | |
131 /* continue to handle event normally */ | |
132 return FALSE; | |
4698 | 133 } |
134 | |
4732 | 135 static void gtk_blist_menu_info_cb(GtkWidget *w, struct buddy *b) |
136 { | |
137 serv_get_info(b->account->gc, b->name); | |
138 } | |
139 | |
4697 | 140 static void gtk_blist_menu_im_cb(GtkWidget *w, struct buddy *b) |
141 { | |
142 gaim_conversation_new(GAIM_CONV_IM, b->account, b->name); | |
143 } | |
144 | |
145 static void gtk_blist_menu_alias_cb(GtkWidget *w, struct buddy *b) | |
146 { | |
147 alias_dialog_bud(b); | |
148 } | |
149 | |
150 static void gtk_blist_menu_bp_cb(GtkWidget *w, struct buddy *b) | |
151 { | |
152 show_new_bp(b->name, b->account->gc, b->idle, | |
153 b->uc & UC_UNAVAILABLE, NULL); | |
154 } | |
155 | |
156 static void gtk_blist_menu_showlog_cb(GtkWidget *w, struct buddy *b) | |
157 { | |
158 show_log(b->name); | |
159 } | |
160 | |
161 static void gtk_blist_show_systemlog_cb() | |
162 { | |
163 show_log(NULL); | |
164 } | |
165 | |
4776 | 166 static void gtk_blist_show_onlinehelp_cb() |
167 { | |
4916 | 168 open_url(NULL, WEBSITE "documentation.php"); |
4776 | 169 } |
170 | |
4692 | 171 static void gtk_blist_button_im_cb(GtkWidget *w, GtkTreeView *tv) |
172 { | |
173 GtkTreeIter iter; | |
174 GtkTreeModel *model = gtk_tree_view_get_model(tv); | |
175 GtkTreeSelection *sel = gtk_tree_view_get_selection(tv); | |
176 | |
177 if(gtk_tree_selection_get_selected(sel, &model, &iter)){ | |
178 GaimBlistNode *node; | |
179 | |
180 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); | |
181 if (GAIM_BLIST_NODE_IS_BUDDY(node)) | |
182 gaim_conversation_new(GAIM_CONV_IM, ((struct buddy*)node)->account, ((struct buddy*)node)->name); | |
183 } | |
4694 | 184 } |
4692 | 185 |
4694 | 186 static void gtk_blist_button_info_cb(GtkWidget *w, GtkTreeView *tv) |
187 { | |
188 GtkTreeIter iter; | |
189 GtkTreeModel *model = gtk_tree_view_get_model(tv); | |
190 GtkTreeSelection *sel = gtk_tree_view_get_selection(tv); | |
4692 | 191 |
4694 | 192 if(gtk_tree_selection_get_selected(sel, &model, &iter)){ |
193 GaimBlistNode *node; | |
194 | |
195 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); | |
196 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
197 serv_get_info(((struct buddy*)node)->account->gc, ((struct buddy*)node)->name); | |
198 return; | |
199 } | |
200 } | |
201 show_info_dialog(); | |
202 } | |
203 | |
204 static void gtk_blist_button_chat_cb(GtkWidget *w, gpointer data) | |
205 { | |
206 /* FIXME: someday, we can check to see if we've selected a chat node */ | |
207 join_chat(); | |
208 } | |
209 | |
210 static void gtk_blist_button_away_cb(GtkWidget *w, gpointer data) | |
211 { | |
212 gtk_menu_popup(GTK_MENU(awaymenu), NULL, NULL, NULL, NULL, 1, GDK_CURRENT_TIME); | |
4692 | 213 } |
214 | |
4687 | 215 static void gtk_blist_row_activated_cb(GtkTreeView *tv, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data) { |
216 GaimBlistNode *node; | |
217 GtkTreeIter iter; | |
218 GValue val = { 0, }; | |
4936 | 219 |
4687 | 220 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); |
4936 | 221 |
4687 | 222 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); |
223 node = g_value_get_pointer(&val); | |
4936 | 224 |
4687 | 225 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { |
4911 | 226 struct gaim_conversation *conv = |
227 gaim_conversation_new(GAIM_CONV_IM, ((struct buddy*)node)->account, ((struct buddy*)node)->name); | |
228 if(conv) { | |
229 gaim_window_raise(gaim_conversation_get_window(conv)); | |
230 gaim_window_switch_conversation( | |
231 gaim_conversation_get_window(conv), | |
232 gaim_conversation_get_index(conv)); | |
233 } | |
4697 | 234 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { |
235 if (gtk_tree_view_row_expanded(tv, path)) | |
236 gtk_tree_view_collapse_row(tv, path); | |
237 else | |
238 gtk_tree_view_expand_row(tv,path,FALSE); | |
1 | 239 } |
240 } | |
241 | |
4916 | 242 static void gaim_gtk_blist_add_buddy_cb() |
243 { | |
244 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkblist->treeview)); | |
245 GtkTreeIter iter; | |
246 GaimBlistNode *node; | |
247 | |
248 if(gtk_tree_selection_get_selected(sel, NULL, &iter)){ | |
249 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); | |
250 if (GAIM_BLIST_NODE_IS_BUDDY(node)) | |
251 show_add_buddy(NULL, NULL, ((struct group*)node->parent)->name, NULL); | |
252 else if (GAIM_BLIST_NODE_IS_GROUP(node)) | |
253 show_add_buddy(NULL, NULL, ((struct group*)node)->name, NULL); | |
254 } | |
255 else { | |
256 show_add_buddy(NULL, NULL, NULL, NULL); | |
257 } | |
258 } | |
4921 | 259 static void |
4916 | 260 gaim_gtk_blist_remove_cb (GtkWidget *w, GaimBlistNode *node) |
261 { | |
262 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
263 struct buddy *b = (struct buddy*)node; | |
264 show_confirm_del(b->account->gc, b->name); | |
265 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
266 struct group *g = (struct group*)node; | |
267 show_confirm_del_group(g); | |
268 } | |
269 } | |
270 | |
4687 | 271 static void gaim_proto_menu_cb(GtkMenuItem *item, struct buddy *b) |
1 | 272 { |
4687 | 273 struct proto_buddy_menu *pbm = g_object_get_data(G_OBJECT(item), "gaimcallback"); |
274 if (pbm->callback) | |
275 pbm->callback(pbm->gc, b->name); | |
1396
df7c3cacac92
[gaim-migrate @ 1406]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1392
diff
changeset
|
276 } |
1 | 277 |
4687 | 278 static gboolean gtk_blist_button_press_cb(GtkWidget *tv, GdkEventButton *event, gpointer null) |
1391
d606da211acb
[gaim-migrate @ 1401]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1376
diff
changeset
|
279 { |
4687 | 280 GtkTreePath *path; |
281 GaimBlistNode *node; | |
282 GValue val = { 0, }; | |
283 GtkTreeIter iter; | |
284 GtkWidget *menu, *menuitem; | |
285 GtkWidget *image; | |
4702 | 286 GtkTreeSelection *sel; |
4687 | 287 GList *list; |
288 struct prpl *prpl; | |
1391
d606da211acb
[gaim-migrate @ 1401]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1376
diff
changeset
|
289 |
4687 | 290 if (event->button != 3) |
291 return FALSE; | |
4718 | 292 |
4687 | 293 /* Here we figure out which node was clicked */ |
294 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), event->x, event->y, &path, NULL, NULL, NULL)) | |
295 return FALSE; | |
296 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); | |
297 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
298 node = g_value_get_pointer(&val); | |
299 menu = gtk_menu_new(); | |
3251 | 300 |
4916 | 301 if (GAIM_BLIST_NODE_IS_GROUP(node)) { |
302 menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Add a Buddy")); | |
303 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gaim_gtk_blist_add_buddy_cb), node); | |
304 image = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU); | |
305 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image); | |
306 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
307 | |
308 menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Delete Group")); | |
309 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gaim_gtk_blist_remove_cb), node); | |
310 image = gtk_image_new_from_stock(GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU); | |
311 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image); | |
312 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
313 | |
314 menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Rename")); | |
315 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(show_rename_group), node); | |
316 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
317 } else if (GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
318 /* Protocol specific options */ | |
319 prpl = find_prpl(((struct buddy*)node)->account->protocol); | |
320 | |
321 if(prpl && prpl->get_info) { | |
322 menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Get Info")); | |
323 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_info_cb), node); | |
324 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
325 } | |
4732 | 326 |
4916 | 327 menuitem = gtk_image_menu_item_new_with_mnemonic(_("_IM")); |
328 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_im_cb), node); | |
329 image = gtk_image_new_from_stock(GAIM_STOCK_IM, GTK_ICON_SIZE_MENU); | |
330 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image); | |
331 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
332 | |
333 menuitem = gtk_image_menu_item_new_with_mnemonic(_("Add Buddy _Pounce")); | |
334 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_bp_cb), node); | |
335 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
336 | |
337 menuitem = gtk_image_menu_item_new_with_mnemonic(_("View _Log")); | |
338 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_showlog_cb), node); | |
339 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
340 | |
341 if (prpl) { | |
342 list = prpl->buddy_menu(((struct buddy*)node)->account->gc, ((struct buddy*)node)->name); | |
343 while (list) { | |
344 struct proto_buddy_menu *pbm = list->data; | |
345 menuitem = gtk_menu_item_new_with_mnemonic(pbm->label); | |
346 g_object_set_data(G_OBJECT(menuitem), "gaimcallback", pbm); | |
347 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gaim_proto_menu_cb), node); | |
348 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
349 list = list->next; | |
350 } | |
351 } | |
352 | |
353 gaim_separator(menu); | |
354 | |
355 menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Alias")); | |
356 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_alias_cb), node); | |
357 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
358 | |
359 menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Remove")); | |
360 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gaim_gtk_blist_remove_cb), node); | |
361 image = gtk_image_new_from_stock(GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU); | |
362 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image); | |
4732 | 363 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); |
364 } | |
4916 | 365 |
4687 | 366 gtk_widget_show_all(menu); |
367 | |
368 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, event->time); | |
1 | 369 |
4702 | 370 #if (1) /* This code only exists because GTK doesn't work. If we return FALSE here, as would be normal |
371 * the event propoagates down and somehow gets interpreted as the start of a drag event. */ | |
372 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv)); | |
373 gtk_tree_selection_select_path(sel, path); | |
4721 | 374 gtk_tree_path_free(path); |
4702 | 375 return TRUE; |
376 #endif | |
1 | 377 } |
378 | |
4944 | 379 static void gaim_gtk_blist_edit_mode_cb(gpointer callback_data, guint callback_action, |
4936 | 380 GtkWidget *checkitem) { |
4916 | 381 GdkCursor *cursor = gdk_cursor_new(GDK_WATCH); |
382 gdk_window_set_cursor(gtkblist->window->window, cursor); | |
383 while (gtk_events_pending()) | |
384 gtk_main_iteration(); | |
4936 | 385 if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(checkitem))) |
386 blist_options |= OPT_BLIST_SHOW_OFFLINE; | |
387 else | |
388 blist_options &= ~OPT_BLIST_SHOW_OFFLINE; | |
4929 | 389 save_prefs(); |
4916 | 390 gdk_cursor_unref(cursor); |
391 cursor = gdk_cursor_new(GDK_LEFT_PTR); | |
392 gdk_window_set_cursor(gtkblist->window->window, cursor); | |
393 gdk_cursor_unref(cursor); | |
394 gaim_gtk_blist_refresh(gaim_get_blist()); | |
395 } | |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4349
diff
changeset
|
396 |
4944 | 397 /* This is called 10 seconds after the buddy logs in. It removes the "logged in" icon and replaces it with |
398 * the normal status icon. Make sure they didn't sign off in the mean-time though. */ | |
1 | 399 |
4944 | 400 static gboolean gaim_reset_present_icon (GaimBlistNode *b) |
401 { | |
402 if (((struct buddy *)b)->present == 2) { | |
403 ((struct buddy *)b)->present = 1; | |
404 gaim_gtk_blist_update(NULL, b); | |
4697 | 405 } |
4944 | 406 |
407 return FALSE; | |
4697 | 408 } |
1 | 409 |
4702 | 410 static void gaim_gtk_blist_drag_data_get_cb (GtkWidget *widget, |
411 GdkDragContext *dc, | |
412 GtkSelectionData *data, | |
413 guint info, | |
414 guint time, | |
415 gpointer *null) | |
416 { | |
4781 | 417 if (data->target == gdk_atom_intern("GAIM_BLIST_NODE", FALSE)) { |
4702 | 418 GtkTreeRowReference *ref = g_object_get_data(G_OBJECT(dc), "gtk-tree-view-source-row"); |
419 GtkTreePath *sourcerow = gtk_tree_row_reference_get_path(ref); | |
420 GtkTreeIter iter; | |
421 GaimBlistNode *node = NULL; | |
422 GValue val = {0}; | |
423 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, sourcerow); | |
424 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
425 node = g_value_get_pointer(&val); | |
4781 | 426 gtk_selection_data_set (data, |
427 gdk_atom_intern ("GAIM_BLIST_NODE", FALSE), | |
428 8, /* bits */ | |
429 (void*)&node, | |
430 sizeof (node)); | |
431 | |
4721 | 432 gtk_tree_path_free(sourcerow); |
4702 | 433 } |
4781 | 434 |
4702 | 435 } |
436 | |
437 static void gaim_gtk_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, | |
438 GtkSelectionData *sd, guint info, guint t) | |
439 { | |
4781 | 440 if (sd->target == gdk_atom_intern("GAIM_BLIST_NODE", FALSE) && sd->data) { |
441 GaimBlistNode *n = NULL; | |
4702 | 442 GtkTreePath *path = NULL; |
4704 | 443 GtkTreeViewDropPosition position; |
4781 | 444 memcpy(&n, sd->data, sizeof(n)); |
4704 | 445 if(gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget), x, y, &path, &position)) { |
446 /* if we're here, I think it means the drop is ok */ | |
4770 | 447 GtkTreeIter iter; |
448 GaimBlistNode *node; | |
449 GValue val = {0}; | |
450 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); | |
451 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
452 node = g_value_get_pointer(&val); | |
4781 | 453 |
454 if (GAIM_BLIST_NODE_IS_BUDDY(n)) { | |
455 struct buddy *b = (struct buddy*)n; | |
456 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
4795 | 457 switch(position) { |
458 case GTK_TREE_VIEW_DROP_AFTER: | |
459 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: | |
460 gaim_blist_add_buddy(b, (struct group*)node->parent, node); | |
461 break; | |
462 case GTK_TREE_VIEW_DROP_BEFORE: | |
463 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: | |
464 gaim_blist_add_buddy(b, (struct group*)node->parent, node->prev); | |
465 break; | |
4781 | 466 } |
467 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
468 gaim_blist_add_buddy(b, (struct group*)node, NULL); | |
4795 | 469 } |
4781 | 470 } else if (GAIM_BLIST_NODE_IS_GROUP(n)) { |
471 struct group *g = (struct group*)n; | |
472 if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
473 switch (position) { | |
474 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: | |
475 case GTK_TREE_VIEW_DROP_AFTER: | |
476 gaim_blist_add_group(g, node); | |
477 break; | |
478 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: | |
479 case GTK_TREE_VIEW_DROP_BEFORE: | |
480 gaim_blist_add_group(g, node->prev); | |
481 break; | |
482 } | |
483 | |
4770 | 484 } |
4781 | 485 |
4777 | 486 } |
4781 | 487 |
4721 | 488 gtk_tree_path_free(path); |
4704 | 489 } |
4702 | 490 } |
491 } | |
492 | |
4724 | 493 static void gaim_gtk_blist_paint_tip(GtkWidget *widget, GdkEventExpose *event, struct buddy *b) |
494 { | |
495 GtkStyle *style; | |
496 GdkPixbuf *pixbuf = gaim_gtk_blist_get_status_icon(b, GAIM_STATUS_ICON_LARGE); | |
497 PangoLayout *layout; | |
498 char *tooltiptext = gaim_get_tooltip_text(b); | |
499 | |
500 layout = gtk_widget_create_pango_layout (gtkblist->tipwindow, NULL); | |
501 pango_layout_set_markup(layout, tooltiptext, strlen(tooltiptext)); | |
4732 | 502 pango_layout_set_wrap(layout, PANGO_WRAP_WORD); |
4733 | 503 pango_layout_set_width(layout, 300000); |
4724 | 504 style = gtkblist->tipwindow->style; |
4732 | 505 |
4724 | 506 gtk_paint_flat_box (style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, |
507 NULL, gtkblist->tipwindow, "tooltip", 0, 0, -1, -1); | |
4729 | 508 |
509 #if GTK_CHECK_VERSION(2,2,0) | |
4724 | 510 gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, pixbuf, |
511 0, 0, 4, 4, -1 , -1, GDK_RGB_DITHER_NONE, 0, 0); | |
4729 | 512 #else |
4758 | 513 gdk_pixbuf_render_to_drawable(pixbuf, GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, 0, 0, 4, 4, -1, -1, GDK_RGB_DITHER_NONE, 0, 0); |
4729 | 514 #endif |
4724 | 515 |
516 gtk_paint_layout (style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, TRUE, | |
517 NULL, gtkblist->tipwindow, "tooltip", 38, 4, layout); | |
518 | |
519 g_object_unref (pixbuf); | |
520 g_object_unref (layout); | |
521 g_free(tooltiptext); | |
522 return; | |
523 } | |
524 | |
525 static gboolean gaim_gtk_blist_tooltip_timeout(GtkWidget *tv) | |
526 { | |
527 GtkTreePath *path; | |
528 GtkTreeIter iter; | |
529 GaimBlistNode *node; | |
530 GValue val = {0}; | |
531 | |
532 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->rect.x, gtkblist->rect.y, &path, NULL, NULL, NULL)) | |
533 return FALSE; | |
534 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); | |
535 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
536 node = g_value_get_pointer(&val); | |
537 | |
538 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
539 int scr_w,scr_h, w, h, x, y; | |
540 PangoLayout *layout; | |
541 struct buddy *buddy = (struct buddy*)node; | |
542 char *tooltiptext = gaim_get_tooltip_text(buddy); | |
543 gtkblist->tipwindow = gtk_window_new(GTK_WINDOW_POPUP); | |
4907
68e2b07ef8d7
[gaim-migrate @ 5241]
Christian Hammond <chipx86@chipx86.com>
parents:
4883
diff
changeset
|
544 gtkblist->tipwindow->parent = tv; |
4724 | 545 gtk_widget_set_app_paintable(gtkblist->tipwindow, TRUE); |
4729 | 546 gtk_window_set_resizable(GTK_WINDOW(gtkblist->tipwindow), FALSE); |
4724 | 547 gtk_widget_set_name(gtkblist->tipwindow, "gtk-tooltips"); |
4883
3c3bafae42e8
[gaim-migrate @ 5213]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
4879
diff
changeset
|
548 gtk_widget_realize(gtkblist->tipwindow); |
4724 | 549 g_signal_connect(G_OBJECT(gtkblist->tipwindow), "expose_event", |
550 G_CALLBACK(gaim_gtk_blist_paint_tip), buddy); | |
551 gtk_widget_ensure_style (gtkblist->tipwindow); | |
552 | |
553 layout = gtk_widget_create_pango_layout (gtkblist->tipwindow, NULL); | |
4733 | 554 pango_layout_set_wrap(layout, PANGO_WRAP_WORD); |
555 pango_layout_set_width(layout, 300000); | |
4724 | 556 pango_layout_set_markup(layout, tooltiptext, strlen(tooltiptext)); |
557 scr_w = gdk_screen_width(); | |
558 scr_h = gdk_screen_height(); | |
559 pango_layout_get_size (layout, &w, &h); | |
560 w = PANGO_PIXELS(w) + 8; | |
561 h = PANGO_PIXELS(h) + 8; | |
562 | |
563 /* 38 is the size of a large status icon plus 4 pixels padding on each side. | |
564 I should #define this or something */ | |
565 w = w + 38; | |
566 h = MAX(h, 38); | |
567 | |
568 gdk_window_get_pointer(NULL, &x, &y, NULL); | |
569 if (GTK_WIDGET_NO_WINDOW(gtkblist->window)) | |
570 y+=gtkblist->window->allocation.y; | |
571 | |
572 x -= ((w >> 1) + 4); | |
573 | |
574 if ((x + w) > scr_w) | |
575 x -= (x + w) - scr_w; | |
576 else if (x < 0) | |
577 x = 0; | |
578 | |
579 if ((y + h + 4) > scr_h) | |
580 y = y - h; | |
581 else | |
582 y = y + 6; | |
583 g_object_unref (layout); | |
584 g_free(tooltiptext); | |
585 gtk_widget_set_size_request(gtkblist->tipwindow, w, h); | |
4729 | 586 gtk_window_move(GTK_WINDOW(gtkblist->tipwindow), x, y); |
4724 | 587 gtk_widget_show(gtkblist->tipwindow); |
588 } | |
4729 | 589 |
4724 | 590 gtk_tree_path_free(path); |
591 return FALSE; | |
592 } | |
593 | |
4730 | 594 static gboolean gaim_gtk_blist_motion_cb (GtkWidget *tv, GdkEventMotion *event, gpointer null) |
4724 | 595 { |
596 GtkTreePath *path; | |
597 if (gtkblist->timeout) { | |
598 if ((event->y > gtkblist->rect.y) && ((event->y - gtkblist->rect.height) < gtkblist->rect.y)) | |
4732 | 599 return FALSE; |
4724 | 600 /* We've left the cell. Remove the timeout and create a new one below */ |
601 if (gtkblist->tipwindow) { | |
602 gtk_widget_destroy(gtkblist->tipwindow); | |
603 gtkblist->tipwindow = NULL; | |
604 } | |
605 | |
606 g_source_remove(gtkblist->timeout); | |
607 } | |
608 | |
609 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), event->x, event->y, &path, NULL, NULL, NULL); | |
610 gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, >kblist->rect); | |
611 if (path) | |
612 gtk_tree_path_free(path); | |
613 gtkblist->timeout = g_timeout_add(500, (GSourceFunc)gaim_gtk_blist_tooltip_timeout, tv); | |
4730 | 614 return FALSE; |
4724 | 615 } |
616 | |
617 static void gaim_gtk_blist_leave_cb (GtkWidget *w, GdkEventCrossing *e, gpointer n) | |
618 { | |
619 if (gtkblist->timeout == 0) | |
620 return; | |
621 if (gtkblist->tipwindow) { | |
622 gtk_widget_destroy(gtkblist->tipwindow); | |
623 gtkblist->tipwindow = NULL; | |
624 } | |
625 g_source_remove(gtkblist->timeout); | |
626 gtkblist->timeout = 0; | |
627 } | |
628 | |
4687 | 629 /*************************************************** |
630 * Crap * | |
631 ***************************************************/ | |
632 static GtkItemFactoryEntry blist_menu[] = | |
1929
d51ea669d84e
[gaim-migrate @ 1939]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1918
diff
changeset
|
633 { |
4687 | 634 /* Buddies menu */ |
635 { N_("/_Buddies"), NULL, NULL, 0, "<Branch>" }, | |
4916 | 636 { N_("/Buddies/New _Instant Message..."), "<CTL>I", show_im_dialog, 0, |
4687 | 637 "<StockItem>", GAIM_STOCK_IM }, |
638 { N_("/Buddies/Join a _Chat..."), "<CTL>C", join_chat, 0, | |
639 "<StockItem>", GAIM_STOCK_CHAT }, | |
4834 | 640 { "/Buddies/sep1", NULL, NULL, 0, "<Separator>" }, |
4687 | 641 { N_("/Buddies/Get _User Info..."), "<CTL>J", show_info_dialog, 0, |
642 "<StockItem>", GAIM_STOCK_INFO }, | |
4834 | 643 { "/Buddies/sep2", NULL, NULL, 0, "<Separator>" }, |
4687 | 644 { N_("/Buddies/_Signoff"), "<CTL>D", signoff_all, 0, NULL }, |
645 { N_("/Buddies/_Quit"), "<CTL>Q", do_quit, 0, | |
646 "<StockItem>", GTK_STOCK_QUIT }, | |
1929
d51ea669d84e
[gaim-migrate @ 1939]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1918
diff
changeset
|
647 |
4916 | 648 /* Edit menu */ |
649 { N_("/_Edit"), NULL, NULL, 0, "<Branch>" }, | |
4944 | 650 { N_("/Edit/_Show Offline Buddies"), NULL, gaim_gtk_blist_edit_mode_cb, 1, "<CheckItem>"}, |
4916 | 651 { N_("/Edit/_Add a Buddy..."), NULL, gaim_gtk_blist_add_buddy_cb, 0, "<StockItem>", GTK_STOCK_ADD }, |
652 { N_("/Edit/Add a _Group..."), NULL, show_add_group, 0, NULL}, | |
653 { "/Edit/sep", NULL, NULL, 0, "<Separator>" }, | |
654 { N_("/Edit/A_ccounts"), "<CTL>A", account_editor, 0, NULL }, | |
655 { N_("/Edit/Preferences"), "<CTL>P", show_prefs, 0, | |
656 "<StockItem>", GTK_STOCK_PREFERENCES }, | |
657 { N_("/Edit/Pr_ivacy"), NULL, show_privacy_options, 0, NULL }, | |
658 | |
4687 | 659 /* Tools */ |
660 { N_("/_Tools"), NULL, NULL, 0, "<Branch>" }, | |
661 { N_("/Tools/_Away"), NULL, NULL, 0, "<Branch>" }, | |
662 { N_("/Tools/Buddy _Pounce"), NULL, NULL, 0, "<Branch>" }, | |
4916 | 663 { N_("/Tools/sep1"), NULL, NULL, 0, "<Separator>" }, |
4698 | 664 { N_("/Tools/_File Transfers"), NULL, gaim_show_xfer_dialog, 0, |
4687 | 665 "<StockItem>", GTK_STOCK_REVERT_TO_SAVED }, |
4834 | 666 { "/Tools/sep2", NULL, NULL, 0, "<Separator>" }, |
4687 | 667 { N_("/Tools/P_rotocol Actions"), NULL, NULL, 0, "<Branch>" }, |
4697 | 668 { N_("/Tools/View System _Log"), NULL, gtk_blist_show_systemlog_cb, 0, NULL }, |
3251 | 669 |
4687 | 670 /* Help */ |
671 { N_("/_Help"), NULL, NULL, 0, "<Branch>" }, | |
4776 | 672 { N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, |
4687 | 673 "<StockItem>", GTK_STOCK_HELP }, |
4755 | 674 { N_("/Help/_Debug Window"), NULL, toggle_debug, 0, NULL }, |
4687 | 675 { N_("/Help/_About"), NULL, show_about, 0, NULL }, |
676 | |
677 }; | |
1929
d51ea669d84e
[gaim-migrate @ 1939]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1918
diff
changeset
|
678 |
4687 | 679 /********************************************************* |
680 * Private Utility functions * | |
681 *********************************************************/ | |
682 | |
4724 | 683 static char *gaim_get_tooltip_text(struct buddy *b) |
684 { | |
685 char *text = NULL; | |
686 struct prpl* prpl = find_prpl(b->account->protocol); | |
687 char *statustext = NULL; | |
4867 | 688 char *aliastext = NULL, *nicktext = NULL; |
4724 | 689 char *warning = NULL, *idletime = NULL; |
690 | |
691 if (prpl->tooltip_text) { | |
4815 | 692 const char *end; |
4732 | 693 statustext = prpl->tooltip_text(b); |
4815 | 694 |
695 if(statustext && !g_utf8_validate(statustext, -1, &end)) { | |
696 char *new = g_strndup(statustext, | |
697 g_utf8_pointer_to_offset(statustext, end)); | |
698 g_free(statustext); | |
699 statustext = new; | |
700 } | |
4724 | 701 } |
4732 | 702 |
4724 | 703 if (b->idle) { |
704 int ihrs, imin; | |
705 time_t t; | |
706 time(&t); | |
707 ihrs = (t - b->idle) / 3600; | |
708 imin = ((t - b->idle) / 60) % 60; | |
709 if (ihrs) | |
4744 | 710 idletime = g_strdup_printf(_("%dh%02dm"), ihrs, imin); |
4724 | 711 else |
4744 | 712 idletime = g_strdup_printf(_("%dm"), imin); |
4724 | 713 } |
4732 | 714 |
4945 | 715 if(b->alias && b->alias[0]) |
4867 | 716 aliastext = g_markup_escape_text(b->alias, -1); |
717 | |
718 if(b->server_alias) | |
719 nicktext = g_markup_escape_text(b->server_alias, -1); | |
720 | |
4724 | 721 if (b->evil > 0) |
4744 | 722 warning = g_strdup_printf(_("%d%%"), b->evil); |
4732 | 723 |
4724 | 724 text = g_strdup_printf("<span size='larger' weight='bold'>%s</span>" |
4744 | 725 "%s %s" /* Alias */ |
726 "%s %s" /* Nickname */ | |
727 "%s %s" /* Idle */ | |
728 "%s %s" /* Warning */ | |
4916 | 729 "%s" /* Offline */ |
4741 | 730 "%s%s", /* Status */ |
4724 | 731 b->name, |
4867 | 732 aliastext ? _("\n<b>Alias:</b>") : "", aliastext ? aliastext : "", |
733 nicktext ? _("\n<b>Nickname:</b>") : "", nicktext ? nicktext : "", | |
734 b->idle ? _("\n<b>Idle:</b>") : "", b->idle ? idletime : "", | |
4744 | 735 b->evil ? _("\n<b>Warned:</b>") : "", b->evil ? warning : "", |
4916 | 736 !b->present ? _("\n<b>Status:</b> Offline") : "", |
4724 | 737 statustext ? "\n" : "", statustext ? statustext : ""); |
4737 | 738 if(warning) |
739 g_free(warning); | |
740 if(idletime) | |
741 g_free(idletime); | |
742 if(statustext) | |
743 g_free(statustext); | |
4867 | 744 if(nicktext) |
745 g_free(nicktext); | |
746 if(aliastext) | |
747 g_free(aliastext); | |
4737 | 748 |
4724 | 749 return text; |
750 | |
751 } | |
752 | |
753 static GdkPixbuf *gaim_gtk_blist_get_status_icon(struct buddy *b, GaimStatusIconSize size) | |
4687 | 754 { |
755 GdkPixbuf *status = NULL; | |
756 GdkPixbuf *scale = NULL; | |
757 GdkPixbuf *emblem = NULL; | |
4737 | 758 gchar *filename = NULL; |
4687 | 759 const char *protoname = NULL; |
1929
d51ea669d84e
[gaim-migrate @ 1939]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1918
diff
changeset
|
760 |
4691 | 761 char *se = NULL, *sw = NULL ,*nw = NULL ,*ne = NULL; |
4737 | 762 |
4687 | 763 int scalesize = 30; |
764 | |
765 struct prpl* prpl = find_prpl(b->account->protocol); | |
4916 | 766 |
767 if (!prpl) | |
768 return NULL; | |
769 | |
4687 | 770 if (prpl->list_icon) |
771 protoname = prpl->list_icon(b->account, b); | |
772 if (prpl->list_emblems) | |
773 prpl->list_emblems(b, &se, &sw, &nw, &ne); | |
4916 | 774 |
4724 | 775 if (size == GAIM_STATUS_ICON_SMALL) { |
4687 | 776 scalesize = 15; |
777 sw = nw = ne = NULL; /* So that only the se icon will composite */ | |
1929
d51ea669d84e
[gaim-migrate @ 1939]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1918
diff
changeset
|
778 } |
d51ea669d84e
[gaim-migrate @ 1939]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1918
diff
changeset
|
779 |
4701 | 780 |
4687 | 781 if (b->present == 2) { |
4701 | 782 struct gaim_gtk_blist_node *gtknode; |
4687 | 783 /* If b->present is 2, that means this buddy has just signed on. We use the "login" icon for the |
784 * status, and we set a timeout to change it to a normal icon after 10 seconds. */ | |
785 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "login.png", NULL); | |
786 status = gdk_pixbuf_new_from_file(filename,NULL); | |
787 g_free(filename); | |
4701 | 788 |
789 gtknode = GAIM_GTK_BLIST_NODE((GaimBlistNode*)b); | |
4773 | 790 if (gtknode->timer > 0) |
791 g_source_remove(gtknode->timer); | |
4701 | 792 gtknode->timer = g_timeout_add(10000, (GSourceFunc)gaim_reset_present_icon, b); |
793 | |
4737 | 794 /* "Hey, what's all this crap?" you ask. Status icons will be themeable too, and |
4687 | 795 then it will look up protoname from the theme */ |
796 } else { | |
797 char *image = g_strdup_printf("%s.png", protoname); | |
798 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
799 status = gdk_pixbuf_new_from_file(filename,NULL); | |
800 g_free(image); | |
801 g_free(filename); | |
1929
d51ea669d84e
[gaim-migrate @ 1939]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1918
diff
changeset
|
802 |
4687 | 803 } |
4737 | 804 |
4687 | 805 if (!status) |
806 return NULL; | |
4737 | 807 |
4687 | 808 scale = gdk_pixbuf_scale_simple(status, scalesize, scalesize, GDK_INTERP_BILINEAR); |
4737 | 809 |
810 g_object_unref(G_OBJECT(status)); | |
811 | |
4687 | 812 /* Emblems */ |
4737 | 813 |
4687 | 814 /* Each protocol can specify up to four "emblems" to composite over the base icon. "away", "busy", "mobile user" |
815 * are all examples of states represented by emblems. I'm not even really sure I like this yet. */ | |
4737 | 816 |
4687 | 817 /* XXX Clean this crap up, yo. */ |
818 if (se) { | |
819 char *image = g_strdup_printf("%s.png", se); | |
820 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
821 g_free(image); | |
822 emblem = gdk_pixbuf_new_from_file(filename,NULL); | |
823 g_free(filename); | |
824 if (emblem) { | |
4724 | 825 if (size == GAIM_STATUS_ICON_LARGE) |
4687 | 826 gdk_pixbuf_composite (emblem, |
827 scale, 15, 15, | |
828 15, 15, | |
829 15, 15, | |
830 1, 1, | |
831 GDK_INTERP_BILINEAR, | |
832 255); | |
833 else | |
834 gdk_pixbuf_composite (emblem, | |
835 scale, 0, 0, | |
836 15, 15, | |
837 0, 0, | |
838 1, 1, | |
839 GDK_INTERP_BILINEAR, | |
840 255); | |
4737 | 841 g_object_unref(G_OBJECT(emblem)); |
4687 | 842 } |
843 } | |
844 if (sw) { | |
845 char *image = g_strdup_printf("%s.png", sw); | |
846 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
847 g_free(image); | |
848 emblem = gdk_pixbuf_new_from_file(filename,NULL); | |
849 g_free(filename); | |
850 if (emblem) { | |
4737 | 851 gdk_pixbuf_composite (emblem, |
852 scale, 0, 15, | |
853 15, 15, | |
854 0, 15, | |
855 1, 1, | |
856 GDK_INTERP_BILINEAR, | |
857 255); | |
858 g_object_unref(G_OBJECT(emblem)); | |
4687 | 859 } |
860 } | |
861 if (nw) { | |
862 char *image = g_strdup_printf("%s.png", nw); | |
863 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
864 g_free(image); | |
865 emblem = gdk_pixbuf_new_from_file(filename,NULL); | |
866 g_free(filename); | |
867 if (emblem) { | |
868 gdk_pixbuf_composite (emblem, | |
869 scale, 0, 0, | |
870 15, 15, | |
871 0, 0, | |
872 1, 1, | |
873 GDK_INTERP_BILINEAR, | |
874 255); | |
4737 | 875 g_object_unref(G_OBJECT(emblem)); |
4687 | 876 } |
877 } | |
878 if (ne) { | |
879 char *image = g_strdup_printf("%s.png", ne); | |
880 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
881 g_free(image); | |
882 emblem = gdk_pixbuf_new_from_file(filename,NULL); | |
883 g_free(filename); | |
884 if (emblem) { | |
885 gdk_pixbuf_composite (emblem, | |
886 scale, 15, 0, | |
887 15, 15, | |
888 15, 0, | |
889 1, 1, | |
890 GDK_INTERP_BILINEAR, | |
891 255); | |
4954 | 892 g_object_unref(G_OBJECT(emblem)); |
4687 | 893 } |
4737 | 894 } |
4687 | 895 |
4737 | 896 |
4718 | 897 /* Idle grey buddies affects the whole row. This converts the status icon to greyscale. */ |
4930 | 898 if (!b->present) |
4928 | 899 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.0, FALSE); |
900 else if (b->idle && blist_options & OPT_BLIST_GREY_IDLERS) | |
901 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.25, FALSE); | |
4687 | 902 return scale; |
1 | 903 } |
904 | |
4737 | 905 static GdkPixbuf *gaim_gtk_blist_get_buddy_icon(struct buddy *b) |
1 | 906 { |
4687 | 907 /* This just opens a file from ~/.gaim/icons/screenname. This needs to change to be more gooder. */ |
4737 | 908 char *file; |
909 GdkPixbuf *buf, *ret; | |
910 | |
4687 | 911 if (!(blist_options & OPT_BLIST_SHOW_ICONS)) |
912 return NULL; | |
4737 | 913 |
4757 | 914 if ((file = gaim_buddy_get_setting(b, "buddy_icon")) == NULL) |
915 return NULL; | |
916 | |
4737 | 917 buf = gdk_pixbuf_new_from_file(file, NULL); |
918 g_free(file); | |
919 | |
920 | |
4687 | 921 if (buf) { |
4930 | 922 if (!b->present) |
4928 | 923 gdk_pixbuf_saturate_and_pixelate(buf, buf, 0.0, FALSE); |
924 if (b->idle && blist_options & OPT_BLIST_GREY_IDLERS) | |
925 gdk_pixbuf_saturate_and_pixelate(buf, buf, 0.25, FALSE); | |
926 | |
4737 | 927 ret = gdk_pixbuf_scale_simple(buf,30,30, GDK_INTERP_BILINEAR); |
928 g_object_unref(G_OBJECT(buf)); | |
929 return ret; | |
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
930 } |
4687 | 931 return NULL; |
2986 | 932 } |
933 | |
4810 | 934 static gchar *gaim_gtk_blist_get_name_markup(struct buddy *b, gboolean selected) |
1 | 935 { |
4687 | 936 char *name = gaim_get_buddy_alias(b); |
937 char *esc = g_markup_escape_text(name, strlen(name)), *text = NULL; | |
4722 | 938 struct prpl* prpl = find_prpl(b->account->protocol); |
939 | |
4687 | 940 /* XXX Clean up this crap */ |
4699 | 941 |
4687 | 942 int ihrs, imin; |
4724 | 943 char *idletime = NULL, *warning = NULL, *statustext = NULL; |
4732 | 944 time_t t; |
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
945 |
4687 | 946 if (!(blist_options & OPT_BLIST_SHOW_ICONS)) { |
4929 | 947 if ((b->idle > 0 && blist_options & OPT_BLIST_GREY_IDLERS && !selected) || blist_options & OPT_BLIST_SHOW_OFFLINE) { |
4718 | 948 text = g_strdup_printf("<span color='dim grey'>%s</span>", |
4699 | 949 esc); |
4687 | 950 g_free(esc); |
951 return text; | |
952 } else { | |
953 return esc; | |
954 } | |
1 | 955 } |
956 | |
4687 | 957 time(&t); |
958 ihrs = (t - b->idle) / 3600; | |
959 imin = ((t - b->idle) / 60) % 60; | |
4699 | 960 |
4916 | 961 if (prpl && prpl->status_text) { |
4732 | 962 char *tmp = prpl->status_text(b); |
4815 | 963 const char *end; |
964 | |
965 if(tmp && !g_utf8_validate(tmp, -1, &end)) { | |
966 char *new = g_strndup(tmp, | |
967 g_utf8_pointer_to_offset(tmp, end)); | |
968 g_free(tmp); | |
969 tmp = new; | |
970 } | |
4732 | 971 |
972 if(tmp) { | |
4855 | 973 char buf[32]; |
974 char *c = tmp; | |
975 int length = 0, vis=0; | |
976 gboolean inside = FALSE; | |
4806 | 977 g_strdelimit(tmp, "\n", ' '); |
4852
d1c17e81055e
[gaim-migrate @ 5179]
Christian Hammond <chipx86@chipx86.com>
parents:
4847
diff
changeset
|
978 |
4855 | 979 while(*c && vis < 20) { |
980 if(*c == '&') | |
981 inside = TRUE; | |
4856 | 982 else if(*c == ';') |
983 inside = FALSE; | |
4855 | 984 if(!inside) |
985 vis++; | |
986 length++; | |
987 c++; /* this is fun */ | |
988 } | |
4852
d1c17e81055e
[gaim-migrate @ 5179]
Christian Hammond <chipx86@chipx86.com>
parents:
4847
diff
changeset
|
989 |
4855 | 990 if(vis == 20) |
991 g_snprintf(buf, sizeof(buf), "%%.%ds...", length); | |
992 else | |
993 g_snprintf(buf, sizeof(buf), "%%s "); | |
4852
d1c17e81055e
[gaim-migrate @ 5179]
Christian Hammond <chipx86@chipx86.com>
parents:
4847
diff
changeset
|
994 |
4855 | 995 statustext = g_strdup_printf(buf, tmp); |
4852
d1c17e81055e
[gaim-migrate @ 5179]
Christian Hammond <chipx86@chipx86.com>
parents:
4847
diff
changeset
|
996 |
4732 | 997 g_free(tmp); |
998 } | |
4722 | 999 } |
4732 | 1000 |
4687 | 1001 if (b->idle) { |
1002 if (ihrs) | |
4757 | 1003 idletime = g_strdup_printf(_("Idle (%dh%02dm) "), ihrs, imin); |
4687 | 1004 else |
4757 | 1005 idletime = g_strdup_printf(_("Idle (%dm) "), imin); |
4687 | 1006 } |
4757 | 1007 |
4687 | 1008 if (b->evil > 0) |
4757 | 1009 warning = g_strdup_printf(_("Warned (%d%%) "), b->evil); |
1010 | |
4810 | 1011 if (b->idle && blist_options & OPT_BLIST_GREY_IDLERS && !selected) { |
4916 | 1012 text = g_strdup_printf("<span color='dim grey'>%s</span>\n" |
1013 "<span color='dim grey' size='smaller'>%s%s%s%s</span>", | |
4687 | 1014 esc, |
4722 | 1015 statustext != NULL ? statustext : "", |
1016 idletime != NULL ? idletime : "", | |
4916 | 1017 warning != NULL ? warning : "", |
1018 !b->present ? _("Offline ") : ""); | |
1019 } else if (statustext == NULL && idletime == NULL && warning == NULL && b->present) { | |
1020 text = g_strdup(esc); | |
4797 | 1021 } else { |
4916 | 1022 text = g_strdup_printf("%s\n" |
1023 "<span %s size='smaller'>%s%s%s%s</span>", esc, | |
1024 selected ? "" : "color='dim grey'", | |
1025 statustext != NULL ? statustext : "", | |
1026 idletime != NULL ? idletime : "", | |
1027 warning != NULL ? warning : "", | |
1028 !b->present ? _("Offline ") : ""); | |
4797 | 1029 } |
4722 | 1030 if (idletime) |
4687 | 1031 g_free(idletime); |
4722 | 1032 if (warning) |
4687 | 1033 g_free(warning); |
4722 | 1034 if (statustext) |
1035 g_free(statustext); | |
4737 | 1036 if (esc) |
1037 g_free(esc); | |
4699 | 1038 |
4687 | 1039 return text; |
1040 } | |
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
1041 |
4840 | 1042 static void gaim_gtk_blist_restore_position() |
1043 { | |
1044 /* if the window exists, is hidden, we're saving positions, and the position is sane... */ | |
1045 if(gtkblist && gtkblist->window && | |
1046 !GTK_WIDGET_VISIBLE(gtkblist->window) && | |
1047 blist_options & OPT_BLIST_SAVED_WINDOWS && | |
1048 blist_pos.width != 0) { | |
1049 /* ...check position is on screen... */ | |
1050 if (blist_pos.x >= gdk_screen_width()) | |
1051 blist_pos.x = gdk_screen_width() - 100; | |
1052 else if (blist_pos.x < 0) | |
1053 blist_pos.x = 100; | |
1054 | |
1055 if (blist_pos.y >= gdk_screen_height()) | |
1056 blist_pos.y = gdk_screen_height() - 100; | |
1057 else if (blist_pos.y < 0) | |
1058 blist_pos.y = 100; | |
1059 | |
1060 /* ...and move it back. */ | |
1061 gtk_window_move(GTK_WINDOW(gtkblist->window), blist_pos.x, blist_pos.y); | |
1062 gtk_window_resize(GTK_WINDOW(gtkblist->window), blist_pos.width, blist_pos.height); | |
1063 } | |
1064 } | |
1065 | |
4944 | 1066 static gboolean gaim_gtk_blist_refresh_timer(struct gaim_buddy_list *list) |
1067 { | |
1068 GaimBlistNode *group = list->root; | |
1069 GaimBlistNode *buddy; | |
1070 | |
1071 while (group) { | |
1072 buddy = group->child; | |
1073 while (buddy) { | |
1074 if (((struct buddy *)buddy)->idle) | |
1075 gaim_gtk_blist_update(list, buddy); | |
1076 buddy = buddy->next; | |
1077 } | |
1078 group = group->next; | |
1079 } | |
1080 | |
1081 /* keep on going */ | |
1082 return TRUE; | |
1083 } | |
4840 | 1084 |
4687 | 1085 /********************************************************************************** |
1086 * Public API Functions * | |
1087 **********************************************************************************/ | |
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1088 static void gaim_gtk_blist_new_list(struct gaim_buddy_list *blist) |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1089 { |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1090 blist->ui_data = g_new0(struct gaim_gtk_buddy_list, 1); |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1091 } |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1092 |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1093 static void gaim_gtk_blist_new_node(GaimBlistNode *node) |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1094 { |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1095 node->ui_data = g_new0(struct gaim_gtk_blist_node, 1); |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1096 } |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1097 |
4729 | 1098 void gaim_gtk_blist_update_columns() |
1099 { | |
1100 if (blist_options & OPT_BLIST_SHOW_ICONS) { | |
1101 gtk_tree_view_column_set_visible(gtkblist->buddy_icon_column, TRUE); | |
1102 gtk_tree_view_column_set_visible(gtkblist->idle_column, FALSE); | |
1103 gtk_tree_view_column_set_visible(gtkblist->warning_column, FALSE); | |
1104 } else { | |
1105 gtk_tree_view_column_set_visible(gtkblist->idle_column, blist_options & OPT_BLIST_SHOW_IDLETIME); | |
1106 gtk_tree_view_column_set_visible(gtkblist->warning_column, blist_options & OPT_BLIST_SHOW_WARN); | |
1107 gtk_tree_view_column_set_visible(gtkblist->buddy_icon_column, FALSE); | |
1108 } | |
1109 } | |
1110 | |
4702 | 1111 enum {DRAG_BUDDY, DRAG_ROW}; |
1112 | |
4834 | 1113 static char * |
1114 item_factory_translate_func (const char *path, gpointer func_data) | |
1115 { | |
1116 return _(path); | |
1117 } | |
1118 | |
4687 | 1119 static void gaim_gtk_blist_show(struct gaim_buddy_list *list) |
1120 { | |
1121 GtkItemFactory *ift; | |
1122 GtkCellRenderer *rend; | |
1123 GtkTreeViewColumn *column; | |
1124 GtkWidget *sw; | |
1125 GtkWidget *button; | |
4694 | 1126 GtkSizeGroup *sg; |
4810 | 1127 GtkTreeSelection *selection; |
4781 | 1128 GtkTargetEntry gte[] = {{"GAIM_BLIST_NODE", GTK_TARGET_SAME_APP, DRAG_ROW}, |
4702 | 1129 {"application/x-im-contact", 0, DRAG_BUDDY}}; |
4690 | 1130 |
4745 | 1131 if (gtkblist && gtkblist->window) { |
4687 | 1132 gtk_widget_show(gtkblist->window); |
1133 return; | |
1134 } | |
4690 | 1135 |
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1136 gtkblist = GAIM_GTK_BLIST(list); |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1137 |
4687 | 1138 gtkblist->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
4840 | 1139 gtk_window_set_role(GTK_WINDOW(gtkblist->window), "buddy_list"); |
4947 | 1140 gtk_window_set_title(GTK_WINDOW(gtkblist->window), _("Biatches List")); |
4879
4f5bd9a2da37
[gaim-migrate @ 5209]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
4867
diff
changeset
|
1141 gtk_widget_realize(gtkblist->window); |
4690 | 1142 |
4925 | 1143 gtkblist->vbox = gtk_vbox_new(FALSE, 0); |
4687 | 1144 gtk_container_add(GTK_CONTAINER(gtkblist->window), gtkblist->vbox); |
1 | 1145 |
4840 | 1146 g_signal_connect(G_OBJECT(gtkblist->window), "delete_event", G_CALLBACK(gtk_blist_delete_cb), NULL); |
1147 g_signal_connect(G_OBJECT(gtkblist->window), "configure_event", G_CALLBACK(gtk_blist_configure_cb), NULL); | |
1148 g_signal_connect(G_OBJECT(gtkblist->window), "visibility_notify_event", G_CALLBACK(gtk_blist_visibility_cb), NULL); | |
1149 gtk_widget_add_events(gtkblist->window, GDK_VISIBILITY_NOTIFY_MASK); | |
4698 | 1150 |
4687 | 1151 /******************************* Menu bar *************************************/ |
1152 ift = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<GaimMain>", NULL); | |
4834 | 1153 gtk_item_factory_set_translate_func (ift, |
1154 item_factory_translate_func, | |
1155 NULL, NULL); | |
4687 | 1156 gtk_item_factory_create_items(ift, sizeof(blist_menu) / sizeof(*blist_menu), |
1157 blist_menu, NULL); | |
1158 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtk_item_factory_get_widget(ift, "<GaimMain>"), FALSE, FALSE, 0); | |
1 | 1159 |
4834 | 1160 awaymenu = gtk_item_factory_get_widget(ift, N_("/Tools/Away")); |
4694 | 1161 do_away_menu(); |
1162 | |
4834 | 1163 bpmenu = gtk_item_factory_get_widget(ift, N_("/Tools/Buddy Pounce")); |
4696 | 1164 do_bp_menu(); |
1165 | |
4834 | 1166 protomenu = gtk_item_factory_get_widget(ift, N_("/Tools/Protocol Actions")); |
4696 | 1167 do_proto_menu(); |
1168 | |
4687 | 1169 /****************************** GtkTreeView **********************************/ |
1170 sw = gtk_scrolled_window_new(NULL,NULL); | |
1171 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN); | |
1172 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
1173 | |
4847 | 1174 gtkblist->treemodel = gtk_tree_store_new(BLIST_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, |
4687 | 1175 G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_POINTER); |
4702 | 1176 |
4687 | 1177 gtkblist->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(gtkblist->treemodel)); |
4943 | 1178 gtk_widget_set_size_request(gtkblist->treeview, -1, 200); |
4704 | 1179 |
4810 | 1180 /* Set up selection stuff */ |
1181 | |
1182 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkblist->treeview)); | |
1183 g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(gaim_gtk_blist_selection_changed), NULL); | |
1184 | |
1185 | |
4702 | 1186 /* Set up dnd */ |
1187 gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(gtkblist->treeview), GDK_BUTTON1_MASK, gte, | |
1188 2, GDK_ACTION_COPY); | |
4704 | 1189 gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(gtkblist->treeview), gte, 2, |
4702 | 1190 GDK_ACTION_COPY | GDK_ACTION_MOVE); |
4704 | 1191 g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-data-received", G_CALLBACK(gaim_gtk_blist_drag_data_rcv_cb), NULL); |
1192 g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-data-get", G_CALLBACK(gaim_gtk_blist_drag_data_get_cb), NULL); | |
1193 | |
4724 | 1194 /* Tooltips */ |
1195 g_signal_connect(G_OBJECT(gtkblist->treeview), "motion-notify-event", G_CALLBACK(gaim_gtk_blist_motion_cb), NULL); | |
1196 g_signal_connect(G_OBJECT(gtkblist->treeview), "leave-notify-event", G_CALLBACK(gaim_gtk_blist_leave_cb), NULL); | |
4687 | 1197 |
1198 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(gtkblist->treeview), FALSE); | |
1 | 1199 |
4687 | 1200 rend = gtk_cell_renderer_pixbuf_new(); |
1201 column = gtk_tree_view_column_new_with_attributes("Status", rend, "pixbuf", STATUS_ICON_COLUMN, NULL); | |
1202 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), column); | |
4933 | 1203 g_object_set(rend, "xalign", 0.0, "ypad", 0, NULL); |
4706 | 1204 |
4687 | 1205 rend = gtk_cell_renderer_text_new(); |
1206 column = gtk_tree_view_column_new_with_attributes("Name", rend, "markup", NAME_COLUMN, NULL); | |
1207 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), column); | |
4797 | 1208 g_object_set(rend, "ypad", 0, "yalign", 0.5, NULL); |
4706 | 1209 |
4687 | 1210 rend = gtk_cell_renderer_text_new(); |
4725 | 1211 gtkblist->warning_column = gtk_tree_view_column_new_with_attributes("Warning", rend, "markup", WARNING_COLUMN, NULL); |
1212 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), gtkblist->warning_column); | |
4796 | 1213 g_object_set(rend, "xalign", 1.0, "ypad", 0, NULL); |
4687 | 1214 |
1215 rend = gtk_cell_renderer_text_new(); | |
4725 | 1216 gtkblist->idle_column = gtk_tree_view_column_new_with_attributes("Idle", rend, "markup", IDLE_COLUMN, NULL); |
1217 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), gtkblist->idle_column); | |
4796 | 1218 g_object_set(rend, "xalign", 1.0, "ypad", 0, NULL); |
1 | 1219 |
4687 | 1220 rend = gtk_cell_renderer_pixbuf_new(); |
4725 | 1221 gtkblist->buddy_icon_column = gtk_tree_view_column_new_with_attributes("Buddy Icon", rend, "pixbuf", BUDDY_ICON_COLUMN, NULL); |
4796 | 1222 g_object_set(rend, "xalign", 1.0, "ypad", 0, NULL); |
4725 | 1223 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), gtkblist->buddy_icon_column); |
4718 | 1224 |
4687 | 1225 g_signal_connect(G_OBJECT(gtkblist->treeview), "row-activated", G_CALLBACK(gtk_blist_row_activated_cb), NULL); |
1226 g_signal_connect(G_OBJECT(gtkblist->treeview), "button-press-event", G_CALLBACK(gtk_blist_button_press_cb), NULL); | |
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
1227 |
4687 | 1228 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), sw, TRUE, TRUE, 0); |
1229 gtk_container_add(GTK_CONTAINER(sw), gtkblist->treeview); | |
4725 | 1230 gaim_gtk_blist_update_columns(); |
4934 | 1231 |
4956 | 1232 /* set the Show Offline Buddies option. must be done |
1233 * after the treeview or faceprint gets mad. -Robot101 | |
1234 */ | |
1235 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (ift, N_("/Edit/Show Offline Buddies"))), | |
1236 blist_options & OPT_BLIST_SHOW_OFFLINE); | |
1237 | |
1238 /* OK... let's show this bad boy. */ | |
1239 gaim_gtk_blist_refresh(list); | |
1240 gaim_gtk_blist_restore_position(); | |
1241 gtk_widget_show_all(gtkblist->window); | |
1242 | |
4687 | 1243 /**************************** Button Box **************************************/ |
4956 | 1244 /* add this afterwards so it doesn't force up the width of the window */ |
4694 | 1245 |
1246 sg = gtk_size_group_new(GTK_SIZE_GROUP_BOTH); | |
4687 | 1247 gtkblist->bbox = gtk_hbox_new(TRUE, 0); |
1248 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->bbox, FALSE, FALSE, 0); | |
4956 | 1249 gtk_widget_show(gtkblist->bbox); |
1250 | |
4687 | 1251 button = gaim_pixbuf_button_from_stock(_("IM"), GAIM_STOCK_IM, GAIM_BUTTON_VERTICAL); |
1252 gtk_box_pack_start(GTK_BOX(gtkblist->bbox), button, FALSE, FALSE, 0); | |
1253 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
4694 | 1254 gtk_size_group_add_widget(sg, button); |
4692 | 1255 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_blist_button_im_cb), |
4697 | 1256 gtkblist->treeview); |
4956 | 1257 gtk_widget_show(button); |
1258 | |
4687 | 1259 button = gaim_pixbuf_button_from_stock(_("Get Info"), GAIM_STOCK_INFO, GAIM_BUTTON_VERTICAL); |
1260 gtk_box_pack_start(GTK_BOX(gtkblist->bbox), button, FALSE, FALSE, 0); | |
1261 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
4694 | 1262 gtk_size_group_add_widget(sg, button); |
1263 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_blist_button_info_cb), | |
4697 | 1264 gtkblist->treeview); |
4956 | 1265 gtk_widget_show(button); |
4729 | 1266 |
4687 | 1267 button = gaim_pixbuf_button_from_stock(_("Chat"), GAIM_STOCK_CHAT, GAIM_BUTTON_VERTICAL); |
1268 gtk_box_pack_start(GTK_BOX(gtkblist->bbox), button, FALSE, FALSE, 0); | |
1269 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
4694 | 1270 gtk_size_group_add_widget(sg, button); |
1271 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_blist_button_chat_cb), NULL); | |
4956 | 1272 gtk_widget_show(button); |
4694 | 1273 |
4687 | 1274 button = gaim_pixbuf_button_from_stock(_("Away"), GAIM_STOCK_AWAY, GAIM_BUTTON_VERTICAL); |
1275 gtk_box_pack_start(GTK_BOX(gtkblist->bbox), button, FALSE, FALSE, 0); | |
1276 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
4694 | 1277 gtk_size_group_add_widget(sg, button); |
1278 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_blist_button_away_cb), NULL); | |
4956 | 1279 gtk_widget_show(button); |
4687 | 1280 |
4956 | 1281 /* this will show the right image/label widgets for us */ |
4944 | 1282 gaim_gtk_blist_update_toolbar(); |
1283 | |
4956 | 1284 /* start the refresh timer */ |
4944 | 1285 gtkblist->refresh_timer = g_timeout_add(30000, (GSourceFunc)gaim_gtk_blist_refresh_timer, list); |
4687 | 1286 } |
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
1287 |
4687 | 1288 void gaim_gtk_blist_refresh(struct gaim_buddy_list *list) |
1289 { | |
1290 GaimBlistNode *group = list->root; | |
1291 GaimBlistNode *buddy; | |
4690 | 1292 |
4687 | 1293 while (group) { |
4916 | 1294 buddy = group->child; |
4687 | 1295 gaim_gtk_blist_update(list, group); |
1296 while (buddy) { | |
4699 | 1297 gaim_gtk_blist_update(list, buddy); |
4687 | 1298 buddy = buddy->next; |
1299 } | |
1300 group = group->next; | |
1301 } | |
1302 } | |
1 | 1303 |
4699 | 1304 static gboolean get_iter_from_node_helper(GaimBlistNode *node, GtkTreeIter *iter, GtkTreeIter *root) { |
4867 | 1305 |
4699 | 1306 do { |
1307 GaimBlistNode *n; | |
1308 GtkTreeIter child; | |
1309 | |
1310 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), root, NODE_COLUMN, &n, -1); | |
1311 if(n == node) { | |
1312 *iter = *root; | |
1313 return TRUE; | |
1314 } | |
1315 | |
1316 if(gtk_tree_model_iter_children(GTK_TREE_MODEL(gtkblist->treemodel), &child, root)) { | |
1317 if(get_iter_from_node_helper(node,iter,&child)) | |
1318 return TRUE; | |
1319 } | |
1320 } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(gtkblist->treemodel), root)); | |
1321 | |
1322 return FALSE; | |
1323 } | |
1324 | |
1325 static gboolean get_iter_from_node(GaimBlistNode *node, GtkTreeIter *iter) { | |
1326 GtkTreeIter root; | |
1327 | |
1328 if (!gtkblist) | |
1329 return FALSE; | |
1330 | |
1331 if(!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(gtkblist->treemodel), &root)) | |
1332 return FALSE; | |
1333 | |
1334 return get_iter_from_node_helper(node, iter, &root); | |
1335 } | |
1336 | |
4944 | 1337 /* |
1338 * These state assignments suck. I'm sorry. They're for historical reasons. | |
1339 * Roll on new prefs. -Robot101 | |
1340 * | |
1341 * NO_BUTTON_TEXT && SHOW_BUTTON_XPM - image | |
1342 * !NO_BUTTON_TEXT && !SHOW_BUTTON_XPM - text | |
1343 * !NO_BUTTON_TEXT && SHOW_BUTTON_XPM - text & images | |
1344 * NO_BUTTON_TEXT && !SHOW_BUTTON_XPM - none | |
1345 */ | |
1346 | |
1347 static void gaim_gtk_blist_update_toolbar_icons (GtkWidget *widget, gpointer data) { | |
1348 if (GTK_IS_IMAGE(widget)) { | |
1349 if (blist_options & OPT_BLIST_SHOW_BUTTON_XPM) | |
1350 gtk_widget_show(widget); | |
1351 else | |
1352 gtk_widget_hide(widget); | |
1353 } else if (GTK_IS_LABEL(widget)) { | |
1354 if (blist_options & OPT_BLIST_NO_BUTTON_TEXT) | |
1355 gtk_widget_hide(widget); | |
1356 else | |
1357 gtk_widget_show(widget); | |
1358 } else if (GTK_IS_CONTAINER(widget)) { | |
1359 gtk_container_foreach(GTK_CONTAINER(widget), gaim_gtk_blist_update_toolbar_icons, NULL); | |
1360 } | |
1361 } | |
1362 | |
4697 | 1363 void gaim_gtk_blist_update_toolbar() { |
1364 if (!gtkblist) | |
1365 return; | |
4699 | 1366 |
4944 | 1367 if (blist_options & OPT_BLIST_NO_BUTTON_TEXT && !(blist_options & OPT_BLIST_SHOW_BUTTON_XPM)) |
4697 | 1368 gtk_widget_hide(gtkblist->bbox); |
4944 | 1369 else { |
1370 gtk_container_foreach(GTK_CONTAINER(gtkblist->bbox), gaim_gtk_blist_update_toolbar_icons, NULL); | |
4956 | 1371 gtk_widget_show(gtkblist->bbox); |
4944 | 1372 } |
4697 | 1373 } |
1374 | |
4701 | 1375 static void gaim_gtk_blist_remove(struct gaim_buddy_list *list, GaimBlistNode *node) |
1376 { | |
1377 struct gaim_gtk_blist_node *gtknode; | |
1378 GtkTreeIter iter; | |
1379 | |
1380 if (!node->ui_data) | |
1381 return; | |
1382 | |
1383 gtknode = (struct gaim_gtk_blist_node *)node->ui_data; | |
1384 | |
1385 if (gtknode->timer > 0) { | |
1386 g_source_remove(gtknode->timer); | |
1387 gtknode->timer = 0; | |
1388 } | |
1389 | |
4912 | 1390 /* For some reason, we're called before we have a buddy list sometimes */ |
1391 if(!gtkblist) | |
1392 return; | |
1393 | |
4831 | 1394 if(gtkblist->selected_node == node) |
1395 gtkblist->selected_node = NULL; | |
1396 | |
4701 | 1397 if (get_iter_from_node(node, &iter)) { |
1398 gtk_tree_store_remove(gtkblist->treemodel, &iter); | |
4918
553d96cb9b26
[gaim-migrate @ 5252]
Christian Hammond <chipx86@chipx86.com>
parents:
4916
diff
changeset
|
1399 if(GAIM_BLIST_NODE_IS_BUDDY(node) && |
4954 | 1400 !(blist_options & OPT_BLIST_SHOW_OFFLINE) && |
4918
553d96cb9b26
[gaim-migrate @ 5252]
Christian Hammond <chipx86@chipx86.com>
parents:
4916
diff
changeset
|
1401 gaim_blist_get_group_online_count((struct group *)node->parent) == 0) { |
4701 | 1402 GtkTreeIter groupiter; |
1403 if(get_iter_from_node(node->parent, &groupiter)) | |
1404 gtk_tree_store_remove(gtkblist->treemodel, &groupiter); | |
1405 } | |
1406 } | |
1407 } | |
1408 | |
4810 | 1409 static gboolean do_selection_changed(GaimBlistNode *new_selection) |
1410 { | |
1411 GaimBlistNode *old_selection = gtkblist->selected_node; | |
1412 | |
1413 if(new_selection != gtkblist->selected_node) { | |
1414 gtkblist->selected_node = new_selection; | |
1415 if(new_selection) | |
1416 gaim_gtk_blist_update(NULL, new_selection); | |
1417 if(old_selection) | |
1418 gaim_gtk_blist_update(NULL, old_selection); | |
1419 } | |
1420 | |
1421 return FALSE; | |
1422 } | |
1423 | |
1424 static void gaim_gtk_blist_selection_changed(GtkTreeSelection *selection, gpointer data) | |
1425 { | |
1426 GaimBlistNode *new_selection = NULL; | |
1427 GtkTreeIter iter; | |
1428 | |
1429 if(gtk_tree_selection_get_selected(selection, NULL, &iter)){ | |
1430 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, | |
1431 NODE_COLUMN, &new_selection, -1); | |
1432 } | |
1433 /* we set this up as a timeout, otherwise the blist flickers */ | |
1434 g_timeout_add(0, (GSourceFunc)do_selection_changed, new_selection); | |
1435 } | |
1436 | |
4936 | 1437 static void make_a_group(GaimBlistNode *node, GtkTreeIter *iter) { |
1438 GaimBlistNode *sibling; | |
1439 GtkTreeIter siblingiter; | |
1440 GdkPixbuf *groupicon = gtk_widget_render_icon(gtkblist->treeview, | |
1441 GTK_STOCK_OPEN, GTK_ICON_SIZE_SMALL_TOOLBAR, NULL); | |
1442 char *esc = g_markup_escape_text(((struct group*)node)->name, -1); | |
1443 char *mark = g_strdup_printf("<span weight='bold'>%s</span>", esc); | |
1444 g_free(esc); | |
1445 sibling = node->prev; | |
1446 while (sibling && !get_iter_from_node(sibling, &siblingiter)) { | |
1447 sibling = sibling->prev; | |
1448 } | |
1449 | |
1450 gtk_tree_store_insert_after(gtkblist->treemodel, iter, NULL, | |
1451 sibling ? &siblingiter : NULL); | |
1452 gtk_tree_store_set(gtkblist->treemodel, iter, | |
1453 STATUS_ICON_COLUMN, groupicon, | |
1454 NAME_COLUMN, mark, | |
1455 NODE_COLUMN, node, | |
1456 -1); | |
1457 g_free(mark); | |
1458 g_object_unref(groupicon); | |
1459 } | |
1460 | |
4701 | 1461 |
4687 | 1462 static void gaim_gtk_blist_update(struct gaim_buddy_list *list, GaimBlistNode *node) |
1463 { | |
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1464 struct gaim_gtk_blist_node *gtknode; |
4699 | 1465 GtkTreeIter iter; |
4936 | 1466 GtkTreePath *expand = NULL; |
4699 | 1467 gboolean new_entry = FALSE; |
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
1468 |
4687 | 1469 if (!gtkblist) |
1470 return; | |
4699 | 1471 |
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1472 gtknode = GAIM_GTK_BLIST_NODE(node); |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1473 |
4690 | 1474 |
4699 | 1475 if (!get_iter_from_node(node, &iter)) { /* This is a newly added node */ |
1476 new_entry = TRUE; | |
4687 | 1477 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { |
4929 | 1478 if (((struct buddy*)node)->present || (blist_options & OPT_BLIST_SHOW_OFFLINE && ((struct buddy*)node)->account->gc)) { |
4699 | 1479 GtkTreeIter groupiter; |
1480 GaimBlistNode *oldersibling; | |
1481 GtkTreeIter oldersiblingiter; | |
4690 | 1482 |
4936 | 1483 if(node->parent && |
1484 !get_iter_from_node(node->parent, &groupiter)) { | |
1485 /* This buddy's group has not yet been added. | |
1486 * We do that here */ | |
1487 make_a_group(node->parent, &groupiter); | |
1488 expand = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &groupiter); | |
4687 | 1489 } |
4810 | 1490 |
4699 | 1491 oldersibling = node->prev; |
4867 | 1492 while (oldersibling && !get_iter_from_node(oldersibling, &oldersiblingiter)) { |
4699 | 1493 oldersibling = oldersibling->prev; |
4867 | 1494 } |
4699 | 1495 |
1496 gtk_tree_store_insert_after(gtkblist->treemodel, &iter, &groupiter, oldersibling ? &oldersiblingiter : NULL); | |
4810 | 1497 |
4767 | 1498 if (blist_options & OPT_BLIST_POPUP) |
1499 gtk_window_present(GTK_WINDOW(gtkblist->window)); | |
4699 | 1500 |
1501 } | |
1502 } | |
4936 | 1503 else if (GAIM_BLIST_NODE_IS_GROUP(node) && (blist_options & OPT_BLIST_SHOW_OFFLINE)) { |
1504 make_a_group(node, &iter); | |
1505 expand = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); | |
4916 | 1506 } |
1507 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
4936 | 1508 if ((gaim_blist_get_group_online_count((struct group *)node) == 0) || |
1509 (!gtk_tree_model_iter_has_child(GTK_TREE_MODEL(gtkblist->treemodel), &iter) && !(blist_options & OPT_BLIST_SHOW_OFFLINE))) { | |
4916 | 1510 gtk_tree_store_remove(gtkblist->treemodel, &iter); |
4936 | 1511 } else { |
4916 | 1512 char *esc = g_markup_escape_text(((struct group*)node)->name, -1); |
1513 char *mark = g_strdup_printf("<span weight='bold'>%s</span>", esc); | |
1514 g_free(esc); | |
1515 gtk_tree_store_set(gtkblist->treemodel, &iter, | |
4936 | 1516 NAME_COLUMN, mark, |
1517 -1); | |
4916 | 1518 g_free(mark); |
1519 } | |
4699 | 1520 } |
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1521 |
4929 | 1522 if (GAIM_BLIST_NODE_IS_BUDDY(node) && (((struct buddy*)node)->present || (blist_options & OPT_BLIST_SHOW_OFFLINE && ((struct buddy*)node)->account->gc))) { |
4687 | 1523 GdkPixbuf *status, *avatar; |
1524 char *mark; | |
4697 | 1525 char *warning = NULL, *idle = NULL; |
1526 | |
4810 | 1527 gboolean selected = (gtkblist->selected_node == node); |
1528 | |
1529 status = gaim_gtk_blist_get_status_icon((struct buddy*)node, | |
4724 | 1530 blist_options & OPT_BLIST_SHOW_ICONS ? GAIM_STATUS_ICON_LARGE : GAIM_STATUS_ICON_SMALL); |
4687 | 1531 avatar = gaim_gtk_blist_get_buddy_icon((struct buddy*)node); |
4810 | 1532 mark = gaim_gtk_blist_get_name_markup((struct buddy*)node, selected); |
4697 | 1533 |
4725 | 1534 if (((struct buddy*)node)->idle > 0) { |
4697 | 1535 time_t t; |
1536 int ihrs, imin; | |
1537 time(&t); | |
1538 ihrs = (t - ((struct buddy *)node)->idle) / 3600; | |
1539 imin = ((t - ((struct buddy*)node)->idle) / 60) % 60; | |
4718 | 1540 if(ihrs > 0) |
1541 idle = g_strdup_printf("(%d:%02d)", ihrs, imin); | |
1542 else | |
1543 idle = g_strdup_printf("(%d)", imin); | |
4697 | 1544 } |
1545 | |
4725 | 1546 if (((struct buddy*)node)->evil > 0) |
4699 | 1547 warning = g_strdup_printf("%d%%", ((struct buddy*)node)->evil); |
4810 | 1548 |
4697 | 1549 |
4718 | 1550 if((blist_options & OPT_BLIST_GREY_IDLERS) |
1551 && ((struct buddy *)node)->idle) { | |
4810 | 1552 if(warning && !selected) { |
4718 | 1553 char *w2 = g_strdup_printf("<span color='dim grey'>%s</span>", |
1554 warning); | |
1555 g_free(warning); | |
1556 warning = w2; | |
1557 } | |
1558 | |
4810 | 1559 if(idle && !selected) { |
4718 | 1560 char *i2 = g_strdup_printf("<span color='dim grey'>%s</span>", |
1561 idle); | |
1562 g_free(idle); | |
1563 idle = i2; | |
1564 } | |
1565 } | |
1566 | |
1567 | |
4699 | 1568 gtk_tree_store_set(gtkblist->treemodel, &iter, |
4687 | 1569 STATUS_ICON_COLUMN, status, |
1570 NAME_COLUMN, mark, | |
4697 | 1571 WARNING_COLUMN, warning, |
1572 IDLE_COLUMN, idle, | |
4699 | 1573 BUDDY_ICON_COLUMN, avatar, |
4687 | 1574 NODE_COLUMN, node, |
1575 -1); | |
4699 | 1576 |
4687 | 1577 g_free(mark); |
4697 | 1578 if (idle) |
1579 g_free(idle); | |
1580 if (warning) | |
1581 g_free(warning); | |
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1582 |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1583 if (status != NULL) |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1584 g_object_unref(status); |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1585 |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1586 if (avatar != NULL) |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1587 g_object_unref(avatar); |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1588 |
4701 | 1589 } else if (GAIM_BLIST_NODE_IS_BUDDY(node) && !new_entry) { |
1590 gaim_gtk_blist_remove(list, node); | |
4767 | 1591 if (blist_options & OPT_BLIST_POPUP) |
1592 gtk_window_present(GTK_WINDOW(gtkblist->window)); | |
4781 | 1593 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { |
1594 GaimBlistNode *afsad = node->child; | |
1595 while (afsad) { | |
1596 gaim_gtk_blist_update(list, afsad); | |
1597 afsad = afsad->next; | |
1598 } | |
4936 | 1599 |
4916 | 1600 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(gtkblist->treeview)); |
4687 | 1601 } |
4936 | 1602 |
1603 if(expand) { | |
1604 gtk_tree_view_expand_row(GTK_TREE_VIEW(gtkblist->treeview), expand, TRUE); | |
1605 gtk_tree_path_free(expand); | |
1606 } | |
4687 | 1607 } |
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
1608 |
4687 | 1609 static void gaim_gtk_blist_destroy(struct gaim_buddy_list *list) |
1610 { | |
4770 | 1611 if (!gtkblist) |
1612 return; | |
4944 | 1613 |
4687 | 1614 gtk_widget_destroy(gtkblist->window); |
4745 | 1615 |
4944 | 1616 if (gtkblist->refresh_timer) |
1617 g_source_remove(gtkblist->refresh_timer); | |
1618 if (gtkblist->timeout) | |
1619 g_source_remove(gtkblist->timeout); | |
1620 | |
1621 gtkblist->refresh_timer = 0; | |
1622 gtkblist->timeout = 0; | |
4745 | 1623 gtkblist->window = gtkblist->vbox = gtkblist->treeview = NULL; |
1624 gtkblist->treemodel = NULL; | |
1625 gtkblist->idle_column = NULL; | |
1626 gtkblist->warning_column = gtkblist->buddy_icon_column = NULL; | |
1627 gtkblist->bbox = gtkblist->tipwindow = NULL; | |
1628 protomenu = NULL; | |
1629 awaymenu = NULL; | |
1630 bpmenu = NULL; | |
4687 | 1631 } |
1 | 1632 |
4687 | 1633 static void gaim_gtk_blist_set_visible(struct gaim_buddy_list *list, gboolean show) |
1634 { | |
4840 | 1635 if (!(gtkblist && gtkblist->window)) |
1636 return; | |
1637 | |
4698 | 1638 if (show) { |
4840 | 1639 gaim_gtk_blist_restore_position(); |
4699 | 1640 gtk_window_present(GTK_WINDOW(gtkblist->window)); |
4698 | 1641 } else { |
1642 if (!connections || docklet_count) { | |
1643 #ifdef _WIN32 | |
4711
0c1f3e651d3e
[gaim-migrate @ 5022]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
4706
diff
changeset
|
1644 wgaim_systray_minimize(gtkblist->window); |
4698 | 1645 #endif |
1646 gtk_widget_hide(gtkblist->window); | |
1647 } else { | |
1648 gtk_window_iconify(GTK_WINDOW(gtkblist->window)); | |
1649 } | |
1650 } | |
1651 } | |
1652 | |
1653 void gaim_gtk_blist_docklet_toggle() { | |
1654 /* Useful for the docklet plugin and also for the win32 tray icon*/ | |
1655 /* This is called when one of those is clicked--it will show/hide the | |
1656 buddy list/login window--depending on which is active */ | |
4840 | 1657 if (connections) { |
1658 if (gtkblist && gtkblist->window) { | |
1659 if (GTK_WIDGET_VISIBLE(gtkblist->window)) { | |
1660 gaim_blist_set_visible(GAIM_WINDOW_ICONIFIED(gtkblist->window) || gaim_gtk_blist_obscured); | |
1661 } else { | |
4698 | 1662 #if _WIN32 |
4840 | 1663 wgaim_systray_maximize(gtkblist->window); |
4698 | 1664 #endif |
4840 | 1665 gaim_blist_set_visible(TRUE); |
1666 } | |
1667 } else { | |
1668 /* we're logging in or something... do nothing */ | |
1669 /* or should I make the blist? */ | |
1670 debug_printf("docklet_toggle called with connections but no blist!\n"); | |
4698 | 1671 } |
4840 | 1672 } else if (mainwindow) { |
1673 if (GTK_WIDGET_VISIBLE(mainwindow)) { | |
4698 | 1674 if (GAIM_WINDOW_ICONIFIED(mainwindow)) { |
1675 gtk_window_present(GTK_WINDOW(mainwindow)); | |
1676 } else { | |
1677 #if _WIN32 | |
1678 wgaim_systray_minimize(mainwindow); | |
1679 #endif | |
1680 gtk_widget_hide(mainwindow); | |
1681 } | |
1682 } else { | |
1683 #if _WIN32 | |
1684 wgaim_systray_maximize(mainwindow); | |
1685 #endif | |
4833 | 1686 show_login(); |
4698 | 1687 } |
4840 | 1688 } else { |
1689 show_login(); | |
4698 | 1690 } |
1691 } | |
1692 | |
1693 void gaim_gtk_blist_docklet_add() | |
1694 { | |
1695 docklet_count++; | |
1696 } | |
1697 | |
1698 void gaim_gtk_blist_docklet_remove() | |
1699 { | |
1700 docklet_count--; | |
1701 if (!docklet_count) { | |
4944 | 1702 if (connections) |
4698 | 1703 gaim_blist_set_visible(TRUE); |
4944 | 1704 else if (mainwindow) |
4840 | 1705 gtk_window_present(GTK_WINDOW(mainwindow)); |
4944 | 1706 else |
4840 | 1707 show_login(); |
4698 | 1708 } |
4687 | 1709 } |
1 | 1710 |
4687 | 1711 static struct gaim_blist_ui_ops blist_ui_ops = |
1712 { | |
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1713 gaim_gtk_blist_new_list, |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1714 gaim_gtk_blist_new_node, |
4687 | 1715 gaim_gtk_blist_show, |
1716 gaim_gtk_blist_update, | |
1717 gaim_gtk_blist_remove, | |
1718 gaim_gtk_blist_destroy, | |
1719 gaim_gtk_blist_set_visible | |
1720 }; | |
1 | 1721 |
1722 | |
4687 | 1723 struct gaim_blist_ui_ops *gaim_get_gtk_blist_ui_ops() |
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
1724 { |
4687 | 1725 return &blist_ui_ops; |
1037
1c663beef29d
[gaim-migrate @ 1047]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1036
diff
changeset
|
1726 } |
1c663beef29d
[gaim-migrate @ 1047]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1036
diff
changeset
|
1727 |
3131 | 1728 |
1729 | |
4687 | 1730 /********************************************************************* |
1731 * Public utility functions * | |
1732 *********************************************************************/ | |
1058
4927ce25d8cc
[gaim-migrate @ 1068]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1057
diff
changeset
|
1733 |
4687 | 1734 GdkPixbuf * |
1735 create_prpl_icon(struct gaim_account *account) | |
4553
d03fcb3f4be2
[gaim-migrate @ 4833]
Christian Hammond <chipx86@chipx86.com>
parents:
4525
diff
changeset
|
1736 { |
4687 | 1737 struct prpl *prpl = find_prpl(account->protocol); |
1738 GdkPixbuf *status = NULL; | |
1739 char *filename = NULL; | |
1740 const char *protoname = prpl->list_icon(account, NULL); | |
1741 /* "Hey, what's all this crap?" you ask. Status icons will be themeable too, and | |
1742 then it will look up protoname from the theme */ | |
1743 if (!strcmp(protoname, "aim")) { | |
1744 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "aim.png", NULL); | |
1745 status = gdk_pixbuf_new_from_file(filename,NULL); | |
1746 g_free(filename); | |
1747 } else if (!strcmp(protoname, "yahoo")) { | |
1748 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "yahoo.png", NULL); | |
1749 status = gdk_pixbuf_new_from_file(filename,NULL); | |
1750 g_free(filename); | |
1751 } else if (!strcmp(protoname, "msn")) { | |
1752 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "msn.png", NULL); | |
1753 status = gdk_pixbuf_new_from_file(filename,NULL); | |
1754 g_free(filename); | |
1755 } else if (!strcmp(protoname, "jabber")) { | |
1756 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "jabber.png", NULL); | |
1757 status = gdk_pixbuf_new_from_file(filename,NULL); | |
1758 g_free(filename); | |
1759 } else if (!strcmp(protoname, "icq")) { | |
1760 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "icq.png", NULL); | |
1761 status = gdk_pixbuf_new_from_file(filename,NULL); | |
1762 g_free(filename); | |
1763 } else if (!strcmp(protoname, "gadu-gadu")) { | |
1764 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "gadugadu.png", NULL); | |
1765 status = gdk_pixbuf_new_from_file(filename,NULL); | |
1766 g_free(filename); | |
1767 } else if (!strcmp(protoname, "napster")) { | |
1768 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "napster.png", NULL); | |
1769 status = gdk_pixbuf_new_from_file(filename,NULL); | |
1770 g_free(filename); | |
1771 } else if (!strcmp(protoname, "irc")) { | |
1772 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "irc.png", NULL); | |
1773 status = gdk_pixbuf_new_from_file(filename,NULL); | |
1774 g_free(filename); | |
960
fa681641643d
[gaim-migrate @ 970]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
945
diff
changeset
|
1775 } |
4687 | 1776 return status; |
1 | 1777 } |
4699 | 1778 |