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