Mercurial > pidgin
annotate src/buddy.c @ 4985:088566495617
[gaim-migrate @ 5320]
Removed a pair of options ("remember buddy list size and position" and
"ignore new messages when away") and made "Show warning levels" and "show
idle times" depend on "show buddy icons".
Also, brought back the old offline.png status emblem.
committer: Tailor Script <tailor@pidgin.im>
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Thu, 03 Apr 2003 17:41:08 +0000 |
parents | b5e52f7e5302 |
children | 1f92610b0772 |
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); |
4970 | 489 gaim_blist_save(); |
4704 | 490 } |
4702 | 491 } |
492 } | |
493 | |
4724 | 494 static void gaim_gtk_blist_paint_tip(GtkWidget *widget, GdkEventExpose *event, struct buddy *b) |
495 { | |
496 GtkStyle *style; | |
497 GdkPixbuf *pixbuf = gaim_gtk_blist_get_status_icon(b, GAIM_STATUS_ICON_LARGE); | |
498 PangoLayout *layout; | |
499 char *tooltiptext = gaim_get_tooltip_text(b); | |
500 | |
501 layout = gtk_widget_create_pango_layout (gtkblist->tipwindow, NULL); | |
502 pango_layout_set_markup(layout, tooltiptext, strlen(tooltiptext)); | |
4732 | 503 pango_layout_set_wrap(layout, PANGO_WRAP_WORD); |
4733 | 504 pango_layout_set_width(layout, 300000); |
4724 | 505 style = gtkblist->tipwindow->style; |
4732 | 506 |
4724 | 507 gtk_paint_flat_box (style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, |
508 NULL, gtkblist->tipwindow, "tooltip", 0, 0, -1, -1); | |
4729 | 509 |
510 #if GTK_CHECK_VERSION(2,2,0) | |
4724 | 511 gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, pixbuf, |
512 0, 0, 4, 4, -1 , -1, GDK_RGB_DITHER_NONE, 0, 0); | |
4729 | 513 #else |
4758 | 514 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 | 515 #endif |
4724 | 516 |
517 gtk_paint_layout (style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, TRUE, | |
518 NULL, gtkblist->tipwindow, "tooltip", 38, 4, layout); | |
519 | |
520 g_object_unref (pixbuf); | |
521 g_object_unref (layout); | |
522 g_free(tooltiptext); | |
523 return; | |
524 } | |
525 | |
526 static gboolean gaim_gtk_blist_tooltip_timeout(GtkWidget *tv) | |
527 { | |
528 GtkTreePath *path; | |
529 GtkTreeIter iter; | |
530 GaimBlistNode *node; | |
531 GValue val = {0}; | |
532 | |
533 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->rect.x, gtkblist->rect.y, &path, NULL, NULL, NULL)) | |
534 return FALSE; | |
535 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); | |
536 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
537 node = g_value_get_pointer(&val); | |
538 | |
539 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
540 int scr_w,scr_h, w, h, x, y; | |
541 PangoLayout *layout; | |
542 struct buddy *buddy = (struct buddy*)node; | |
543 char *tooltiptext = gaim_get_tooltip_text(buddy); | |
544 gtkblist->tipwindow = gtk_window_new(GTK_WINDOW_POPUP); | |
4907
68e2b07ef8d7
[gaim-migrate @ 5241]
Christian Hammond <chipx86@chipx86.com>
parents:
4883
diff
changeset
|
545 gtkblist->tipwindow->parent = tv; |
4724 | 546 gtk_widget_set_app_paintable(gtkblist->tipwindow, TRUE); |
4729 | 547 gtk_window_set_resizable(GTK_WINDOW(gtkblist->tipwindow), FALSE); |
4724 | 548 gtk_widget_set_name(gtkblist->tipwindow, "gtk-tooltips"); |
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 { | |
4978 | 619 if (gtkblist->timeout) { |
620 g_source_remove(gtkblist->timeout); | |
621 gtkblist->timeout = 0; | |
622 } | |
4724 | 623 if (gtkblist->tipwindow) { |
624 gtk_widget_destroy(gtkblist->tipwindow); | |
625 gtkblist->tipwindow = NULL; | |
626 } | |
4978 | 627 } |
4724 | 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>" }, |
4983 | 644 { N_("/Buddies/_Show Offline Buddies"), NULL, gaim_gtk_blist_edit_mode_cb, 1, "<CheckItem>"}, |
645 { N_("/Buddies/_Add a Buddy..."), NULL, gaim_gtk_blist_add_buddy_cb, 0, "<StockItem>", GTK_STOCK_ADD }, | |
646 { N_("/Buddies/Add a _Group..."), NULL, show_add_group, 0, NULL}, | |
647 { "/Buddies/sep3", NULL, NULL, 0, "<Separator>" }, | |
4687 | 648 { N_("/Buddies/_Signoff"), "<CTL>D", signoff_all, 0, NULL }, |
649 { N_("/Buddies/_Quit"), "<CTL>Q", do_quit, 0, | |
650 "<StockItem>", GTK_STOCK_QUIT }, | |
1929
d51ea669d84e
[gaim-migrate @ 1939]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1918
diff
changeset
|
651 |
4687 | 652 /* Tools */ |
653 { N_("/_Tools"), NULL, NULL, 0, "<Branch>" }, | |
654 { N_("/Tools/_Away"), NULL, NULL, 0, "<Branch>" }, | |
655 { N_("/Tools/Buddy _Pounce"), NULL, NULL, 0, "<Branch>" }, | |
4916 | 656 { N_("/Tools/sep1"), NULL, NULL, 0, "<Separator>" }, |
4698 | 657 { N_("/Tools/_File Transfers"), NULL, gaim_show_xfer_dialog, 0, |
4687 | 658 "<StockItem>", GTK_STOCK_REVERT_TO_SAVED }, |
4834 | 659 { "/Tools/sep2", NULL, NULL, 0, "<Separator>" }, |
4687 | 660 { N_("/Tools/P_rotocol Actions"), NULL, NULL, 0, "<Branch>" }, |
4697 | 661 { N_("/Tools/View System _Log"), NULL, gtk_blist_show_systemlog_cb, 0, NULL }, |
4983 | 662 { "/Tools/sep3", NULL, NULL, 0, "<Separator>" }, |
663 { N_("/Tools/A_ccounts"), "<CTL>A", account_editor, 0, NULL }, | |
664 { N_("/Tools/Preferences"), "<CTL>P", show_prefs, 0, | |
665 "<StockItem>", GTK_STOCK_PREFERENCES }, | |
666 { N_("/Tools/Pr_ivacy"), NULL, show_privacy_options, 0, NULL }, | |
3251 | 667 |
4687 | 668 /* Help */ |
669 { N_("/_Help"), NULL, NULL, 0, "<Branch>" }, | |
4776 | 670 { N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, |
4687 | 671 "<StockItem>", GTK_STOCK_HELP }, |
4755 | 672 { N_("/Help/_Debug Window"), NULL, toggle_debug, 0, NULL }, |
4687 | 673 { N_("/Help/_About"), NULL, show_about, 0, NULL }, |
674 | |
675 }; | |
1929
d51ea669d84e
[gaim-migrate @ 1939]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1918
diff
changeset
|
676 |
4687 | 677 /********************************************************* |
678 * Private Utility functions * | |
679 *********************************************************/ | |
680 | |
4724 | 681 static char *gaim_get_tooltip_text(struct buddy *b) |
682 { | |
683 char *text = NULL; | |
684 struct prpl* prpl = find_prpl(b->account->protocol); | |
685 char *statustext = NULL; | |
4867 | 686 char *aliastext = NULL, *nicktext = NULL; |
4724 | 687 char *warning = NULL, *idletime = NULL; |
688 | |
689 if (prpl->tooltip_text) { | |
4815 | 690 const char *end; |
4732 | 691 statustext = prpl->tooltip_text(b); |
4815 | 692 |
693 if(statustext && !g_utf8_validate(statustext, -1, &end)) { | |
694 char *new = g_strndup(statustext, | |
695 g_utf8_pointer_to_offset(statustext, end)); | |
696 g_free(statustext); | |
697 statustext = new; | |
698 } | |
4724 | 699 } |
4732 | 700 |
4724 | 701 if (b->idle) { |
702 int ihrs, imin; | |
703 time_t t; | |
704 time(&t); | |
705 ihrs = (t - b->idle) / 3600; | |
706 imin = ((t - b->idle) / 60) % 60; | |
707 if (ihrs) | |
4744 | 708 idletime = g_strdup_printf(_("%dh%02dm"), ihrs, imin); |
4724 | 709 else |
4744 | 710 idletime = g_strdup_printf(_("%dm"), imin); |
4724 | 711 } |
4732 | 712 |
4945 | 713 if(b->alias && b->alias[0]) |
4867 | 714 aliastext = g_markup_escape_text(b->alias, -1); |
715 | |
716 if(b->server_alias) | |
717 nicktext = g_markup_escape_text(b->server_alias, -1); | |
718 | |
4724 | 719 if (b->evil > 0) |
4744 | 720 warning = g_strdup_printf(_("%d%%"), b->evil); |
4732 | 721 |
4724 | 722 text = g_strdup_printf("<span size='larger' weight='bold'>%s</span>" |
4744 | 723 "%s %s" /* Alias */ |
724 "%s %s" /* Nickname */ | |
725 "%s %s" /* Idle */ | |
726 "%s %s" /* Warning */ | |
4916 | 727 "%s" /* Offline */ |
4968 | 728 "%s%s" /* Status */ |
729 "%s", | |
4724 | 730 b->name, |
4867 | 731 aliastext ? _("\n<b>Alias:</b>") : "", aliastext ? aliastext : "", |
732 nicktext ? _("\n<b>Nickname:</b>") : "", nicktext ? nicktext : "", | |
733 b->idle ? _("\n<b>Idle:</b>") : "", b->idle ? idletime : "", | |
4744 | 734 b->evil ? _("\n<b>Warned:</b>") : "", b->evil ? warning : "", |
4916 | 735 !b->present ? _("\n<b>Status:</b> Offline") : "", |
4968 | 736 statustext ? "\n" : "", statustext ? statustext : "", |
4980 | 737 !g_ascii_strcasecmp(b->name, "robflynn") ? "\n<b>Description:</b> Spooky" : ""); |
4968 | 738 |
4737 | 739 if(warning) |
740 g_free(warning); | |
741 if(idletime) | |
742 g_free(idletime); | |
743 if(statustext) | |
744 g_free(statustext); | |
4867 | 745 if(nicktext) |
746 g_free(nicktext); | |
747 if(aliastext) | |
748 g_free(aliastext); | |
4737 | 749 |
4724 | 750 return text; |
751 | |
752 } | |
753 | |
754 static GdkPixbuf *gaim_gtk_blist_get_status_icon(struct buddy *b, GaimStatusIconSize size) | |
4687 | 755 { |
756 GdkPixbuf *status = NULL; | |
757 GdkPixbuf *scale = NULL; | |
758 GdkPixbuf *emblem = NULL; | |
4737 | 759 gchar *filename = NULL; |
4687 | 760 const char *protoname = NULL; |
1929
d51ea669d84e
[gaim-migrate @ 1939]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1918
diff
changeset
|
761 |
4691 | 762 char *se = NULL, *sw = NULL ,*nw = NULL ,*ne = NULL; |
4737 | 763 |
4687 | 764 int scalesize = 30; |
765 | |
766 struct prpl* prpl = find_prpl(b->account->protocol); | |
4916 | 767 |
768 if (!prpl) | |
769 return NULL; | |
770 | |
4687 | 771 if (prpl->list_icon) |
772 protoname = prpl->list_icon(b->account, b); | |
773 if (prpl->list_emblems) | |
774 prpl->list_emblems(b, &se, &sw, &nw, &ne); | |
4916 | 775 |
4724 | 776 if (size == GAIM_STATUS_ICON_SMALL) { |
4687 | 777 scalesize = 15; |
778 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
|
779 } |
d51ea669d84e
[gaim-migrate @ 1939]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1918
diff
changeset
|
780 |
4701 | 781 |
4687 | 782 if (b->present == 2) { |
4701 | 783 struct gaim_gtk_blist_node *gtknode; |
4687 | 784 /* If b->present is 2, that means this buddy has just signed on. We use the "login" icon for the |
785 * status, and we set a timeout to change it to a normal icon after 10 seconds. */ | |
786 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "login.png", NULL); | |
787 status = gdk_pixbuf_new_from_file(filename,NULL); | |
788 g_free(filename); | |
4701 | 789 |
790 gtknode = GAIM_GTK_BLIST_NODE((GaimBlistNode*)b); | |
4773 | 791 if (gtknode->timer > 0) |
792 g_source_remove(gtknode->timer); | |
4701 | 793 gtknode->timer = g_timeout_add(10000, (GSourceFunc)gaim_reset_present_icon, b); |
794 | |
4737 | 795 /* "Hey, what's all this crap?" you ask. Status icons will be themeable too, and |
4687 | 796 then it will look up protoname from the theme */ |
797 } else { | |
798 char *image = g_strdup_printf("%s.png", protoname); | |
799 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
800 status = gdk_pixbuf_new_from_file(filename,NULL); | |
801 g_free(image); | |
802 g_free(filename); | |
1929
d51ea669d84e
[gaim-migrate @ 1939]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1918
diff
changeset
|
803 |
4687 | 804 } |
4737 | 805 |
4687 | 806 if (!status) |
807 return NULL; | |
4737 | 808 |
4687 | 809 scale = gdk_pixbuf_scale_simple(status, scalesize, scalesize, GDK_INTERP_BILINEAR); |
4737 | 810 |
811 g_object_unref(G_OBJECT(status)); | |
812 | |
4687 | 813 /* Emblems */ |
4737 | 814 |
4687 | 815 /* Each protocol can specify up to four "emblems" to composite over the base icon. "away", "busy", "mobile user" |
816 * are all examples of states represented by emblems. I'm not even really sure I like this yet. */ | |
4737 | 817 |
4687 | 818 /* XXX Clean this crap up, yo. */ |
819 if (se) { | |
820 char *image = g_strdup_printf("%s.png", se); | |
821 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
822 g_free(image); | |
823 emblem = gdk_pixbuf_new_from_file(filename,NULL); | |
824 g_free(filename); | |
825 if (emblem) { | |
4724 | 826 if (size == GAIM_STATUS_ICON_LARGE) |
4687 | 827 gdk_pixbuf_composite (emblem, |
828 scale, 15, 15, | |
829 15, 15, | |
830 15, 15, | |
831 1, 1, | |
832 GDK_INTERP_BILINEAR, | |
833 255); | |
834 else | |
835 gdk_pixbuf_composite (emblem, | |
836 scale, 0, 0, | |
837 15, 15, | |
838 0, 0, | |
839 1, 1, | |
840 GDK_INTERP_BILINEAR, | |
841 255); | |
4737 | 842 g_object_unref(G_OBJECT(emblem)); |
4687 | 843 } |
844 } | |
845 if (sw) { | |
846 char *image = g_strdup_printf("%s.png", sw); | |
847 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
848 g_free(image); | |
849 emblem = gdk_pixbuf_new_from_file(filename,NULL); | |
850 g_free(filename); | |
851 if (emblem) { | |
4737 | 852 gdk_pixbuf_composite (emblem, |
853 scale, 0, 15, | |
854 15, 15, | |
855 0, 15, | |
856 1, 1, | |
857 GDK_INTERP_BILINEAR, | |
858 255); | |
859 g_object_unref(G_OBJECT(emblem)); | |
4687 | 860 } |
861 } | |
862 if (nw) { | |
863 char *image = g_strdup_printf("%s.png", nw); | |
864 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
865 g_free(image); | |
866 emblem = gdk_pixbuf_new_from_file(filename,NULL); | |
867 g_free(filename); | |
868 if (emblem) { | |
869 gdk_pixbuf_composite (emblem, | |
870 scale, 0, 0, | |
871 15, 15, | |
872 0, 0, | |
873 1, 1, | |
874 GDK_INTERP_BILINEAR, | |
875 255); | |
4737 | 876 g_object_unref(G_OBJECT(emblem)); |
4687 | 877 } |
878 } | |
879 if (ne) { | |
880 char *image = g_strdup_printf("%s.png", ne); | |
881 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
882 g_free(image); | |
883 emblem = gdk_pixbuf_new_from_file(filename,NULL); | |
884 g_free(filename); | |
885 if (emblem) { | |
886 gdk_pixbuf_composite (emblem, | |
887 scale, 15, 0, | |
888 15, 15, | |
889 15, 0, | |
890 1, 1, | |
891 GDK_INTERP_BILINEAR, | |
892 255); | |
4954 | 893 g_object_unref(G_OBJECT(emblem)); |
4687 | 894 } |
4737 | 895 } |
4687 | 896 |
4737 | 897 |
4718 | 898 /* Idle grey buddies affects the whole row. This converts the status icon to greyscale. */ |
4930 | 899 if (!b->present) |
4928 | 900 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.0, FALSE); |
901 else if (b->idle && blist_options & OPT_BLIST_GREY_IDLERS) | |
902 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.25, FALSE); | |
4687 | 903 return scale; |
1 | 904 } |
905 | |
4737 | 906 static GdkPixbuf *gaim_gtk_blist_get_buddy_icon(struct buddy *b) |
1 | 907 { |
4687 | 908 /* This just opens a file from ~/.gaim/icons/screenname. This needs to change to be more gooder. */ |
4737 | 909 char *file; |
910 GdkPixbuf *buf, *ret; | |
911 | |
4687 | 912 if (!(blist_options & OPT_BLIST_SHOW_ICONS)) |
913 return NULL; | |
4737 | 914 |
4757 | 915 if ((file = gaim_buddy_get_setting(b, "buddy_icon")) == NULL) |
916 return NULL; | |
917 | |
4737 | 918 buf = gdk_pixbuf_new_from_file(file, NULL); |
919 g_free(file); | |
920 | |
921 | |
4687 | 922 if (buf) { |
4930 | 923 if (!b->present) |
4928 | 924 gdk_pixbuf_saturate_and_pixelate(buf, buf, 0.0, FALSE); |
925 if (b->idle && blist_options & OPT_BLIST_GREY_IDLERS) | |
926 gdk_pixbuf_saturate_and_pixelate(buf, buf, 0.25, FALSE); | |
927 | |
4737 | 928 ret = gdk_pixbuf_scale_simple(buf,30,30, GDK_INTERP_BILINEAR); |
929 g_object_unref(G_OBJECT(buf)); | |
930 return ret; | |
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
931 } |
4687 | 932 return NULL; |
2986 | 933 } |
934 | |
4810 | 935 static gchar *gaim_gtk_blist_get_name_markup(struct buddy *b, gboolean selected) |
1 | 936 { |
4687 | 937 char *name = gaim_get_buddy_alias(b); |
938 char *esc = g_markup_escape_text(name, strlen(name)), *text = NULL; | |
4722 | 939 struct prpl* prpl = find_prpl(b->account->protocol); |
940 | |
4687 | 941 /* XXX Clean up this crap */ |
4699 | 942 |
4687 | 943 int ihrs, imin; |
4724 | 944 char *idletime = NULL, *warning = NULL, *statustext = NULL; |
4732 | 945 time_t t; |
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
946 |
4687 | 947 if (!(blist_options & OPT_BLIST_SHOW_ICONS)) { |
4978 | 948 if ((b->idle > 0 && blist_options & OPT_BLIST_GREY_IDLERS && !selected) || b->present == 0) { |
4718 | 949 text = g_strdup_printf("<span color='dim grey'>%s</span>", |
4699 | 950 esc); |
4687 | 951 g_free(esc); |
952 return text; | |
953 } else { | |
954 return esc; | |
955 } | |
1 | 956 } |
957 | |
4687 | 958 time(&t); |
959 ihrs = (t - b->idle) / 3600; | |
960 imin = ((t - b->idle) / 60) % 60; | |
4699 | 961 |
4916 | 962 if (prpl && prpl->status_text) { |
4732 | 963 char *tmp = prpl->status_text(b); |
4815 | 964 const char *end; |
965 | |
966 if(tmp && !g_utf8_validate(tmp, -1, &end)) { | |
967 char *new = g_strndup(tmp, | |
968 g_utf8_pointer_to_offset(tmp, end)); | |
969 g_free(tmp); | |
970 tmp = new; | |
971 } | |
4732 | 972 |
973 if(tmp) { | |
4855 | 974 char buf[32]; |
975 char *c = tmp; | |
976 int length = 0, vis=0; | |
977 gboolean inside = FALSE; | |
4806 | 978 g_strdelimit(tmp, "\n", ' '); |
4852
d1c17e81055e
[gaim-migrate @ 5179]
Christian Hammond <chipx86@chipx86.com>
parents:
4847
diff
changeset
|
979 |
4855 | 980 while(*c && vis < 20) { |
981 if(*c == '&') | |
982 inside = TRUE; | |
4856 | 983 else if(*c == ';') |
984 inside = FALSE; | |
4855 | 985 if(!inside) |
986 vis++; | |
987 length++; | |
988 c++; /* this is fun */ | |
989 } | |
4852
d1c17e81055e
[gaim-migrate @ 5179]
Christian Hammond <chipx86@chipx86.com>
parents:
4847
diff
changeset
|
990 |
4855 | 991 if(vis == 20) |
992 g_snprintf(buf, sizeof(buf), "%%.%ds...", length); | |
993 else | |
994 g_snprintf(buf, sizeof(buf), "%%s "); | |
4852
d1c17e81055e
[gaim-migrate @ 5179]
Christian Hammond <chipx86@chipx86.com>
parents:
4847
diff
changeset
|
995 |
4855 | 996 statustext = g_strdup_printf(buf, tmp); |
4852
d1c17e81055e
[gaim-migrate @ 5179]
Christian Hammond <chipx86@chipx86.com>
parents:
4847
diff
changeset
|
997 |
4732 | 998 g_free(tmp); |
999 } | |
4722 | 1000 } |
4732 | 1001 |
4687 | 1002 if (b->idle) { |
1003 if (ihrs) | |
4757 | 1004 idletime = g_strdup_printf(_("Idle (%dh%02dm) "), ihrs, imin); |
4687 | 1005 else |
4757 | 1006 idletime = g_strdup_printf(_("Idle (%dm) "), imin); |
4687 | 1007 } |
4757 | 1008 |
4687 | 1009 if (b->evil > 0) |
4757 | 1010 warning = g_strdup_printf(_("Warned (%d%%) "), b->evil); |
1011 | |
4810 | 1012 if (b->idle && blist_options & OPT_BLIST_GREY_IDLERS && !selected) { |
4916 | 1013 text = g_strdup_printf("<span color='dim grey'>%s</span>\n" |
1014 "<span color='dim grey' size='smaller'>%s%s%s%s</span>", | |
4687 | 1015 esc, |
4722 | 1016 statustext != NULL ? statustext : "", |
1017 idletime != NULL ? idletime : "", | |
4916 | 1018 warning != NULL ? warning : "", |
1019 !b->present ? _("Offline ") : ""); | |
1020 } else if (statustext == NULL && idletime == NULL && warning == NULL && b->present) { | |
1021 text = g_strdup(esc); | |
4797 | 1022 } else { |
4916 | 1023 text = g_strdup_printf("%s\n" |
1024 "<span %s size='smaller'>%s%s%s%s</span>", esc, | |
1025 selected ? "" : "color='dim grey'", | |
1026 statustext != NULL ? statustext : "", | |
1027 idletime != NULL ? idletime : "", | |
1028 warning != NULL ? warning : "", | |
1029 !b->present ? _("Offline ") : ""); | |
4797 | 1030 } |
4722 | 1031 if (idletime) |
4687 | 1032 g_free(idletime); |
4722 | 1033 if (warning) |
4687 | 1034 g_free(warning); |
4722 | 1035 if (statustext) |
1036 g_free(statustext); | |
4737 | 1037 if (esc) |
1038 g_free(esc); | |
4699 | 1039 |
4687 | 1040 return text; |
1041 } | |
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
1042 |
4840 | 1043 static void gaim_gtk_blist_restore_position() |
1044 { | |
1045 /* if the window exists, is hidden, we're saving positions, and the position is sane... */ | |
1046 if(gtkblist && gtkblist->window && | |
1047 !GTK_WIDGET_VISIBLE(gtkblist->window) && | |
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; | |
4973 | 1126 GtkTooltips *tooltips; |
4694 | 1127 GtkSizeGroup *sg; |
4810 | 1128 GtkTreeSelection *selection; |
4781 | 1129 GtkTargetEntry gte[] = {{"GAIM_BLIST_NODE", GTK_TARGET_SAME_APP, DRAG_ROW}, |
4702 | 1130 {"application/x-im-contact", 0, DRAG_BUDDY}}; |
4690 | 1131 |
4745 | 1132 if (gtkblist && gtkblist->window) { |
4687 | 1133 gtk_widget_show(gtkblist->window); |
1134 return; | |
1135 } | |
4690 | 1136 |
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1137 gtkblist = GAIM_GTK_BLIST(list); |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1138 |
4687 | 1139 gtkblist->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
4840 | 1140 gtk_window_set_role(GTK_WINDOW(gtkblist->window), "buddy_list"); |
4964 | 1141 gtk_window_set_title(GTK_WINDOW(gtkblist->window), _("Buddy List")); |
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 |
4973 | 1246 tooltips = gtk_tooltips_new(); |
1247 | |
4694 | 1248 sg = gtk_size_group_new(GTK_SIZE_GROUP_BOTH); |
4687 | 1249 gtkblist->bbox = gtk_hbox_new(TRUE, 0); |
1250 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->bbox, FALSE, FALSE, 0); | |
4956 | 1251 gtk_widget_show(gtkblist->bbox); |
1252 | |
4687 | 1253 button = gaim_pixbuf_button_from_stock(_("IM"), GAIM_STOCK_IM, GAIM_BUTTON_VERTICAL); |
1254 gtk_box_pack_start(GTK_BOX(gtkblist->bbox), button, FALSE, FALSE, 0); | |
1255 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
4694 | 1256 gtk_size_group_add_widget(sg, button); |
4692 | 1257 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_blist_button_im_cb), |
4697 | 1258 gtkblist->treeview); |
4973 | 1259 gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), button, _("Send an Instant Message to the selected buddy"), NULL); |
4956 | 1260 gtk_widget_show(button); |
1261 | |
4687 | 1262 button = gaim_pixbuf_button_from_stock(_("Get Info"), GAIM_STOCK_INFO, GAIM_BUTTON_VERTICAL); |
1263 gtk_box_pack_start(GTK_BOX(gtkblist->bbox), button, FALSE, FALSE, 0); | |
1264 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
4694 | 1265 gtk_size_group_add_widget(sg, button); |
1266 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_blist_button_info_cb), | |
4697 | 1267 gtkblist->treeview); |
4973 | 1268 gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), button, _("Get information on the selected buddy"), NULL); |
4956 | 1269 gtk_widget_show(button); |
4729 | 1270 |
4687 | 1271 button = gaim_pixbuf_button_from_stock(_("Chat"), GAIM_STOCK_CHAT, GAIM_BUTTON_VERTICAL); |
1272 gtk_box_pack_start(GTK_BOX(gtkblist->bbox), button, FALSE, FALSE, 0); | |
1273 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
4694 | 1274 gtk_size_group_add_widget(sg, button); |
1275 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_blist_button_chat_cb), NULL); | |
4973 | 1276 gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), button, _("Join a chat room"), NULL); |
4956 | 1277 gtk_widget_show(button); |
4694 | 1278 |
4687 | 1279 button = gaim_pixbuf_button_from_stock(_("Away"), GAIM_STOCK_AWAY, GAIM_BUTTON_VERTICAL); |
1280 gtk_box_pack_start(GTK_BOX(gtkblist->bbox), button, FALSE, FALSE, 0); | |
1281 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
4694 | 1282 gtk_size_group_add_widget(sg, button); |
1283 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_blist_button_away_cb), NULL); | |
4973 | 1284 gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), button, _("Set an away message"), NULL); |
4956 | 1285 gtk_widget_show(button); |
4687 | 1286 |
4980 | 1287 /* we're done setting tooltips */ |
1288 gtk_object_sink(GTK_OBJECT(tooltips)); | |
1289 | |
4956 | 1290 /* this will show the right image/label widgets for us */ |
4944 | 1291 gaim_gtk_blist_update_toolbar(); |
1292 | |
4956 | 1293 /* start the refresh timer */ |
4944 | 1294 gtkblist->refresh_timer = g_timeout_add(30000, (GSourceFunc)gaim_gtk_blist_refresh_timer, list); |
4687 | 1295 } |
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
1296 |
4687 | 1297 void gaim_gtk_blist_refresh(struct gaim_buddy_list *list) |
1298 { | |
1299 GaimBlistNode *group = list->root; | |
1300 GaimBlistNode *buddy; | |
4690 | 1301 |
4687 | 1302 while (group) { |
4916 | 1303 buddy = group->child; |
4687 | 1304 gaim_gtk_blist_update(list, group); |
1305 while (buddy) { | |
4699 | 1306 gaim_gtk_blist_update(list, buddy); |
4687 | 1307 buddy = buddy->next; |
1308 } | |
1309 group = group->next; | |
1310 } | |
1311 } | |
1 | 1312 |
4699 | 1313 static gboolean get_iter_from_node_helper(GaimBlistNode *node, GtkTreeIter *iter, GtkTreeIter *root) { |
4867 | 1314 |
4699 | 1315 do { |
1316 GaimBlistNode *n; | |
1317 GtkTreeIter child; | |
1318 | |
1319 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), root, NODE_COLUMN, &n, -1); | |
1320 if(n == node) { | |
1321 *iter = *root; | |
1322 return TRUE; | |
1323 } | |
1324 | |
1325 if(gtk_tree_model_iter_children(GTK_TREE_MODEL(gtkblist->treemodel), &child, root)) { | |
1326 if(get_iter_from_node_helper(node,iter,&child)) | |
1327 return TRUE; | |
1328 } | |
1329 } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(gtkblist->treemodel), root)); | |
1330 | |
1331 return FALSE; | |
1332 } | |
1333 | |
1334 static gboolean get_iter_from_node(GaimBlistNode *node, GtkTreeIter *iter) { | |
1335 GtkTreeIter root; | |
1336 | |
1337 if (!gtkblist) | |
1338 return FALSE; | |
1339 | |
1340 if(!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(gtkblist->treemodel), &root)) | |
1341 return FALSE; | |
1342 | |
1343 return get_iter_from_node_helper(node, iter, &root); | |
1344 } | |
1345 | |
4944 | 1346 /* |
1347 * These state assignments suck. I'm sorry. They're for historical reasons. | |
1348 * Roll on new prefs. -Robot101 | |
1349 * | |
1350 * NO_BUTTON_TEXT && SHOW_BUTTON_XPM - image | |
1351 * !NO_BUTTON_TEXT && !SHOW_BUTTON_XPM - text | |
1352 * !NO_BUTTON_TEXT && SHOW_BUTTON_XPM - text & images | |
1353 * NO_BUTTON_TEXT && !SHOW_BUTTON_XPM - none | |
1354 */ | |
1355 | |
1356 static void gaim_gtk_blist_update_toolbar_icons (GtkWidget *widget, gpointer data) { | |
1357 if (GTK_IS_IMAGE(widget)) { | |
1358 if (blist_options & OPT_BLIST_SHOW_BUTTON_XPM) | |
1359 gtk_widget_show(widget); | |
1360 else | |
1361 gtk_widget_hide(widget); | |
1362 } else if (GTK_IS_LABEL(widget)) { | |
1363 if (blist_options & OPT_BLIST_NO_BUTTON_TEXT) | |
1364 gtk_widget_hide(widget); | |
1365 else | |
1366 gtk_widget_show(widget); | |
1367 } else if (GTK_IS_CONTAINER(widget)) { | |
1368 gtk_container_foreach(GTK_CONTAINER(widget), gaim_gtk_blist_update_toolbar_icons, NULL); | |
1369 } | |
1370 } | |
1371 | |
4697 | 1372 void gaim_gtk_blist_update_toolbar() { |
1373 if (!gtkblist) | |
1374 return; | |
4699 | 1375 |
4944 | 1376 if (blist_options & OPT_BLIST_NO_BUTTON_TEXT && !(blist_options & OPT_BLIST_SHOW_BUTTON_XPM)) |
4697 | 1377 gtk_widget_hide(gtkblist->bbox); |
4944 | 1378 else { |
1379 gtk_container_foreach(GTK_CONTAINER(gtkblist->bbox), gaim_gtk_blist_update_toolbar_icons, NULL); | |
4956 | 1380 gtk_widget_show(gtkblist->bbox); |
4944 | 1381 } |
4697 | 1382 } |
1383 | |
4701 | 1384 static void gaim_gtk_blist_remove(struct gaim_buddy_list *list, GaimBlistNode *node) |
1385 { | |
1386 struct gaim_gtk_blist_node *gtknode; | |
1387 GtkTreeIter iter; | |
1388 | |
1389 if (!node->ui_data) | |
1390 return; | |
1391 | |
1392 gtknode = (struct gaim_gtk_blist_node *)node->ui_data; | |
1393 | |
1394 if (gtknode->timer > 0) { | |
1395 g_source_remove(gtknode->timer); | |
1396 gtknode->timer = 0; | |
1397 } | |
1398 | |
4912 | 1399 /* For some reason, we're called before we have a buddy list sometimes */ |
1400 if(!gtkblist) | |
1401 return; | |
1402 | |
4831 | 1403 if(gtkblist->selected_node == node) |
1404 gtkblist->selected_node = NULL; | |
1405 | |
4701 | 1406 if (get_iter_from_node(node, &iter)) { |
1407 gtk_tree_store_remove(gtkblist->treemodel, &iter); | |
4918
553d96cb9b26
[gaim-migrate @ 5252]
Christian Hammond <chipx86@chipx86.com>
parents:
4916
diff
changeset
|
1408 if(GAIM_BLIST_NODE_IS_BUDDY(node) && |
4954 | 1409 !(blist_options & OPT_BLIST_SHOW_OFFLINE) && |
4918
553d96cb9b26
[gaim-migrate @ 5252]
Christian Hammond <chipx86@chipx86.com>
parents:
4916
diff
changeset
|
1410 gaim_blist_get_group_online_count((struct group *)node->parent) == 0) { |
4701 | 1411 GtkTreeIter groupiter; |
1412 if(get_iter_from_node(node->parent, &groupiter)) | |
1413 gtk_tree_store_remove(gtkblist->treemodel, &groupiter); | |
1414 } | |
1415 } | |
1416 } | |
1417 | |
4810 | 1418 static gboolean do_selection_changed(GaimBlistNode *new_selection) |
1419 { | |
1420 GaimBlistNode *old_selection = gtkblist->selected_node; | |
1421 | |
1422 if(new_selection != gtkblist->selected_node) { | |
1423 gtkblist->selected_node = new_selection; | |
1424 if(new_selection) | |
1425 gaim_gtk_blist_update(NULL, new_selection); | |
1426 if(old_selection) | |
1427 gaim_gtk_blist_update(NULL, old_selection); | |
1428 } | |
1429 | |
1430 return FALSE; | |
1431 } | |
1432 | |
1433 static void gaim_gtk_blist_selection_changed(GtkTreeSelection *selection, gpointer data) | |
1434 { | |
1435 GaimBlistNode *new_selection = NULL; | |
1436 GtkTreeIter iter; | |
1437 | |
1438 if(gtk_tree_selection_get_selected(selection, NULL, &iter)){ | |
1439 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, | |
1440 NODE_COLUMN, &new_selection, -1); | |
1441 } | |
1442 /* we set this up as a timeout, otherwise the blist flickers */ | |
1443 g_timeout_add(0, (GSourceFunc)do_selection_changed, new_selection); | |
1444 } | |
1445 | |
4936 | 1446 static void make_a_group(GaimBlistNode *node, GtkTreeIter *iter) { |
1447 GaimBlistNode *sibling; | |
1448 GtkTreeIter siblingiter; | |
1449 GdkPixbuf *groupicon = gtk_widget_render_icon(gtkblist->treeview, | |
1450 GTK_STOCK_OPEN, GTK_ICON_SIZE_SMALL_TOOLBAR, NULL); | |
4980 | 1451 struct group *group = (struct group *)node; |
1452 char *esc = g_markup_escape_text(group->name, -1); | |
1453 char *mark; | |
1454 | |
1455 if(blist_options & OPT_BLIST_SHOW_GRPNUM) | |
1456 mark = g_strdup_printf("<span weight='bold'>%s</span> (%d/%d)", esc, gaim_blist_get_group_online_count(group), gaim_blist_get_group_size(group, FALSE)); | |
1457 else | |
1458 mark = g_strdup_printf("<span weight='bold'>%s</span>", esc); | |
1459 | |
4936 | 1460 g_free(esc); |
4980 | 1461 |
4936 | 1462 sibling = node->prev; |
1463 while (sibling && !get_iter_from_node(sibling, &siblingiter)) { | |
1464 sibling = sibling->prev; | |
1465 } | |
1466 | |
1467 gtk_tree_store_insert_after(gtkblist->treemodel, iter, NULL, | |
1468 sibling ? &siblingiter : NULL); | |
1469 gtk_tree_store_set(gtkblist->treemodel, iter, | |
1470 STATUS_ICON_COLUMN, groupicon, | |
1471 NAME_COLUMN, mark, | |
1472 NODE_COLUMN, node, | |
1473 -1); | |
1474 g_free(mark); | |
1475 g_object_unref(groupicon); | |
1476 } | |
1477 | |
4701 | 1478 |
4687 | 1479 static void gaim_gtk_blist_update(struct gaim_buddy_list *list, GaimBlistNode *node) |
1480 { | |
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1481 struct gaim_gtk_blist_node *gtknode; |
4699 | 1482 GtkTreeIter iter; |
4936 | 1483 GtkTreePath *expand = NULL; |
4699 | 1484 gboolean new_entry = FALSE; |
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
1485 |
4687 | 1486 if (!gtkblist) |
1487 return; | |
4699 | 1488 |
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1489 gtknode = GAIM_GTK_BLIST_NODE(node); |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1490 |
4690 | 1491 |
4699 | 1492 if (!get_iter_from_node(node, &iter)) { /* This is a newly added node */ |
1493 new_entry = TRUE; | |
4687 | 1494 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { |
4929 | 1495 if (((struct buddy*)node)->present || (blist_options & OPT_BLIST_SHOW_OFFLINE && ((struct buddy*)node)->account->gc)) { |
4699 | 1496 GtkTreeIter groupiter; |
1497 GaimBlistNode *oldersibling; | |
1498 GtkTreeIter oldersiblingiter; | |
4690 | 1499 |
4936 | 1500 if(node->parent && |
1501 !get_iter_from_node(node->parent, &groupiter)) { | |
1502 /* This buddy's group has not yet been added. | |
1503 * We do that here */ | |
1504 make_a_group(node->parent, &groupiter); | |
1505 expand = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &groupiter); | |
4687 | 1506 } |
4810 | 1507 |
4699 | 1508 oldersibling = node->prev; |
4867 | 1509 while (oldersibling && !get_iter_from_node(oldersibling, &oldersiblingiter)) { |
4699 | 1510 oldersibling = oldersibling->prev; |
4867 | 1511 } |
4699 | 1512 |
1513 gtk_tree_store_insert_after(gtkblist->treemodel, &iter, &groupiter, oldersibling ? &oldersiblingiter : NULL); | |
4810 | 1514 |
4767 | 1515 if (blist_options & OPT_BLIST_POPUP) |
1516 gtk_window_present(GTK_WINDOW(gtkblist->window)); | |
4699 | 1517 |
1518 } | |
1519 } | |
4936 | 1520 else if (GAIM_BLIST_NODE_IS_GROUP(node) && (blist_options & OPT_BLIST_SHOW_OFFLINE)) { |
1521 make_a_group(node, &iter); | |
1522 expand = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); | |
4916 | 1523 } |
1524 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
4936 | 1525 if ((gaim_blist_get_group_online_count((struct group *)node) == 0) || |
1526 (!gtk_tree_model_iter_has_child(GTK_TREE_MODEL(gtkblist->treemodel), &iter) && !(blist_options & OPT_BLIST_SHOW_OFFLINE))) { | |
4916 | 1527 gtk_tree_store_remove(gtkblist->treemodel, &iter); |
4936 | 1528 } else { |
4980 | 1529 struct group *group = (struct group *)node; |
1530 char *esc = g_markup_escape_text(group->name, -1); | |
1531 char *mark; | |
1532 | |
1533 if(blist_options & OPT_BLIST_SHOW_GRPNUM) | |
1534 mark = g_strdup_printf("<span weight='bold'>%s</span> (%d/%d)", esc, gaim_blist_get_group_online_count(group), gaim_blist_get_group_size(group, FALSE)); | |
1535 else | |
1536 mark = g_strdup_printf("<span weight='bold'>%s</span>", esc); | |
1537 | |
4916 | 1538 g_free(esc); |
1539 gtk_tree_store_set(gtkblist->treemodel, &iter, | |
4936 | 1540 NAME_COLUMN, mark, |
1541 -1); | |
4916 | 1542 g_free(mark); |
1543 } | |
4699 | 1544 } |
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1545 |
4929 | 1546 if (GAIM_BLIST_NODE_IS_BUDDY(node) && (((struct buddy*)node)->present || (blist_options & OPT_BLIST_SHOW_OFFLINE && ((struct buddy*)node)->account->gc))) { |
4687 | 1547 GdkPixbuf *status, *avatar; |
1548 char *mark; | |
4697 | 1549 char *warning = NULL, *idle = NULL; |
1550 | |
4810 | 1551 gboolean selected = (gtkblist->selected_node == node); |
1552 | |
1553 status = gaim_gtk_blist_get_status_icon((struct buddy*)node, | |
4724 | 1554 blist_options & OPT_BLIST_SHOW_ICONS ? GAIM_STATUS_ICON_LARGE : GAIM_STATUS_ICON_SMALL); |
4687 | 1555 avatar = gaim_gtk_blist_get_buddy_icon((struct buddy*)node); |
4810 | 1556 mark = gaim_gtk_blist_get_name_markup((struct buddy*)node, selected); |
4697 | 1557 |
4725 | 1558 if (((struct buddy*)node)->idle > 0) { |
4697 | 1559 time_t t; |
1560 int ihrs, imin; | |
1561 time(&t); | |
1562 ihrs = (t - ((struct buddy *)node)->idle) / 3600; | |
1563 imin = ((t - ((struct buddy*)node)->idle) / 60) % 60; | |
4718 | 1564 if(ihrs > 0) |
1565 idle = g_strdup_printf("(%d:%02d)", ihrs, imin); | |
1566 else | |
1567 idle = g_strdup_printf("(%d)", imin); | |
4697 | 1568 } |
1569 | |
4725 | 1570 if (((struct buddy*)node)->evil > 0) |
4699 | 1571 warning = g_strdup_printf("%d%%", ((struct buddy*)node)->evil); |
4810 | 1572 |
4697 | 1573 |
4718 | 1574 if((blist_options & OPT_BLIST_GREY_IDLERS) |
1575 && ((struct buddy *)node)->idle) { | |
4810 | 1576 if(warning && !selected) { |
4718 | 1577 char *w2 = g_strdup_printf("<span color='dim grey'>%s</span>", |
1578 warning); | |
1579 g_free(warning); | |
1580 warning = w2; | |
1581 } | |
1582 | |
4810 | 1583 if(idle && !selected) { |
4718 | 1584 char *i2 = g_strdup_printf("<span color='dim grey'>%s</span>", |
1585 idle); | |
1586 g_free(idle); | |
1587 idle = i2; | |
1588 } | |
1589 } | |
1590 | |
1591 | |
4699 | 1592 gtk_tree_store_set(gtkblist->treemodel, &iter, |
4687 | 1593 STATUS_ICON_COLUMN, status, |
1594 NAME_COLUMN, mark, | |
4697 | 1595 WARNING_COLUMN, warning, |
1596 IDLE_COLUMN, idle, | |
4699 | 1597 BUDDY_ICON_COLUMN, avatar, |
4687 | 1598 NODE_COLUMN, node, |
1599 -1); | |
4699 | 1600 |
4687 | 1601 g_free(mark); |
4697 | 1602 if (idle) |
1603 g_free(idle); | |
1604 if (warning) | |
1605 g_free(warning); | |
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1606 |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1607 if (status != NULL) |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1608 g_object_unref(status); |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1609 |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1610 if (avatar != NULL) |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1611 g_object_unref(avatar); |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1612 |
4701 | 1613 } else if (GAIM_BLIST_NODE_IS_BUDDY(node) && !new_entry) { |
1614 gaim_gtk_blist_remove(list, node); | |
4767 | 1615 if (blist_options & OPT_BLIST_POPUP) |
1616 gtk_window_present(GTK_WINDOW(gtkblist->window)); | |
4687 | 1617 } |
4980 | 1618 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(gtkblist->treeview)); |
4936 | 1619 |
4974 | 1620 |
4936 | 1621 if(expand) { |
1622 gtk_tree_view_expand_row(GTK_TREE_VIEW(gtkblist->treeview), expand, TRUE); | |
1623 gtk_tree_path_free(expand); | |
1624 } | |
4980 | 1625 |
1626 if(GAIM_BLIST_NODE_IS_BUDDY(node)) | |
1627 gaim_gtk_blist_update(list, node->parent); | |
4687 | 1628 } |
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
1629 |
4687 | 1630 static void gaim_gtk_blist_destroy(struct gaim_buddy_list *list) |
1631 { | |
4770 | 1632 if (!gtkblist) |
1633 return; | |
4944 | 1634 |
4687 | 1635 gtk_widget_destroy(gtkblist->window); |
4745 | 1636 |
4944 | 1637 if (gtkblist->refresh_timer) |
1638 g_source_remove(gtkblist->refresh_timer); | |
1639 if (gtkblist->timeout) | |
1640 g_source_remove(gtkblist->timeout); | |
1641 | |
1642 gtkblist->refresh_timer = 0; | |
1643 gtkblist->timeout = 0; | |
4745 | 1644 gtkblist->window = gtkblist->vbox = gtkblist->treeview = NULL; |
1645 gtkblist->treemodel = NULL; | |
1646 gtkblist->idle_column = NULL; | |
1647 gtkblist->warning_column = gtkblist->buddy_icon_column = NULL; | |
1648 gtkblist->bbox = gtkblist->tipwindow = NULL; | |
1649 protomenu = NULL; | |
1650 awaymenu = NULL; | |
1651 bpmenu = NULL; | |
4687 | 1652 } |
1 | 1653 |
4687 | 1654 static void gaim_gtk_blist_set_visible(struct gaim_buddy_list *list, gboolean show) |
1655 { | |
4840 | 1656 if (!(gtkblist && gtkblist->window)) |
1657 return; | |
1658 | |
4698 | 1659 if (show) { |
4840 | 1660 gaim_gtk_blist_restore_position(); |
4699 | 1661 gtk_window_present(GTK_WINDOW(gtkblist->window)); |
4698 | 1662 } else { |
1663 if (!connections || docklet_count) { | |
1664 #ifdef _WIN32 | |
4711
0c1f3e651d3e
[gaim-migrate @ 5022]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
4706
diff
changeset
|
1665 wgaim_systray_minimize(gtkblist->window); |
4698 | 1666 #endif |
1667 gtk_widget_hide(gtkblist->window); | |
1668 } else { | |
1669 gtk_window_iconify(GTK_WINDOW(gtkblist->window)); | |
1670 } | |
1671 } | |
1672 } | |
1673 | |
1674 void gaim_gtk_blist_docklet_toggle() { | |
1675 /* Useful for the docklet plugin and also for the win32 tray icon*/ | |
1676 /* This is called when one of those is clicked--it will show/hide the | |
1677 buddy list/login window--depending on which is active */ | |
4840 | 1678 if (connections) { |
1679 if (gtkblist && gtkblist->window) { | |
1680 if (GTK_WIDGET_VISIBLE(gtkblist->window)) { | |
1681 gaim_blist_set_visible(GAIM_WINDOW_ICONIFIED(gtkblist->window) || gaim_gtk_blist_obscured); | |
1682 } else { | |
4698 | 1683 #if _WIN32 |
4840 | 1684 wgaim_systray_maximize(gtkblist->window); |
4698 | 1685 #endif |
4840 | 1686 gaim_blist_set_visible(TRUE); |
1687 } | |
1688 } else { | |
1689 /* we're logging in or something... do nothing */ | |
1690 /* or should I make the blist? */ | |
1691 debug_printf("docklet_toggle called with connections but no blist!\n"); | |
4698 | 1692 } |
4840 | 1693 } else if (mainwindow) { |
1694 if (GTK_WIDGET_VISIBLE(mainwindow)) { | |
4698 | 1695 if (GAIM_WINDOW_ICONIFIED(mainwindow)) { |
1696 gtk_window_present(GTK_WINDOW(mainwindow)); | |
1697 } else { | |
1698 #if _WIN32 | |
1699 wgaim_systray_minimize(mainwindow); | |
1700 #endif | |
1701 gtk_widget_hide(mainwindow); | |
1702 } | |
1703 } else { | |
1704 #if _WIN32 | |
1705 wgaim_systray_maximize(mainwindow); | |
1706 #endif | |
4833 | 1707 show_login(); |
4698 | 1708 } |
4840 | 1709 } else { |
1710 show_login(); | |
4698 | 1711 } |
1712 } | |
1713 | |
1714 void gaim_gtk_blist_docklet_add() | |
1715 { | |
1716 docklet_count++; | |
1717 } | |
1718 | |
1719 void gaim_gtk_blist_docklet_remove() | |
1720 { | |
1721 docklet_count--; | |
1722 if (!docklet_count) { | |
4944 | 1723 if (connections) |
4698 | 1724 gaim_blist_set_visible(TRUE); |
4944 | 1725 else if (mainwindow) |
4840 | 1726 gtk_window_present(GTK_WINDOW(mainwindow)); |
4944 | 1727 else |
4840 | 1728 show_login(); |
4698 | 1729 } |
4687 | 1730 } |
1 | 1731 |
4687 | 1732 static struct gaim_blist_ui_ops blist_ui_ops = |
1733 { | |
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1734 gaim_gtk_blist_new_list, |
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1735 gaim_gtk_blist_new_node, |
4687 | 1736 gaim_gtk_blist_show, |
1737 gaim_gtk_blist_update, | |
1738 gaim_gtk_blist_remove, | |
1739 gaim_gtk_blist_destroy, | |
1740 gaim_gtk_blist_set_visible | |
1741 }; | |
1 | 1742 |
1743 | |
4687 | 1744 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
|
1745 { |
4687 | 1746 return &blist_ui_ops; |
1037
1c663beef29d
[gaim-migrate @ 1047]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1036
diff
changeset
|
1747 } |
1c663beef29d
[gaim-migrate @ 1047]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1036
diff
changeset
|
1748 |
3131 | 1749 |
1750 | |
4687 | 1751 /********************************************************************* |
1752 * Public utility functions * | |
1753 *********************************************************************/ | |
1058
4927ce25d8cc
[gaim-migrate @ 1068]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1057
diff
changeset
|
1754 |
4687 | 1755 GdkPixbuf * |
1756 create_prpl_icon(struct gaim_account *account) | |
4553
d03fcb3f4be2
[gaim-migrate @ 4833]
Christian Hammond <chipx86@chipx86.com>
parents:
4525
diff
changeset
|
1757 { |
4687 | 1758 struct prpl *prpl = find_prpl(account->protocol); |
1759 GdkPixbuf *status = NULL; | |
1760 char *filename = NULL; | |
1761 const char *protoname = prpl->list_icon(account, NULL); | |
1762 /* "Hey, what's all this crap?" you ask. Status icons will be themeable too, and | |
1763 then it will look up protoname from the theme */ | |
1764 if (!strcmp(protoname, "aim")) { | |
1765 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "aim.png", NULL); | |
1766 status = gdk_pixbuf_new_from_file(filename,NULL); | |
1767 g_free(filename); | |
1768 } else if (!strcmp(protoname, "yahoo")) { | |
1769 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "yahoo.png", NULL); | |
1770 status = gdk_pixbuf_new_from_file(filename,NULL); | |
1771 g_free(filename); | |
1772 } else if (!strcmp(protoname, "msn")) { | |
1773 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "msn.png", NULL); | |
1774 status = gdk_pixbuf_new_from_file(filename,NULL); | |
1775 g_free(filename); | |
1776 } else if (!strcmp(protoname, "jabber")) { | |
1777 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "jabber.png", NULL); | |
1778 status = gdk_pixbuf_new_from_file(filename,NULL); | |
1779 g_free(filename); | |
1780 } else if (!strcmp(protoname, "icq")) { | |
1781 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "icq.png", NULL); | |
1782 status = gdk_pixbuf_new_from_file(filename,NULL); | |
1783 g_free(filename); | |
1784 } else if (!strcmp(protoname, "gadu-gadu")) { | |
1785 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "gadugadu.png", NULL); | |
1786 status = gdk_pixbuf_new_from_file(filename,NULL); | |
1787 g_free(filename); | |
1788 } else if (!strcmp(protoname, "napster")) { | |
1789 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "napster.png", NULL); | |
1790 status = gdk_pixbuf_new_from_file(filename,NULL); | |
1791 g_free(filename); | |
1792 } else if (!strcmp(protoname, "irc")) { | |
1793 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "irc.png", NULL); | |
1794 status = gdk_pixbuf_new_from_file(filename,NULL); | |
1795 g_free(filename); | |
960
fa681641643d
[gaim-migrate @ 970]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
945
diff
changeset
|
1796 } |
4687 | 1797 return status; |
1 | 1798 } |
4699 | 1799 |