Mercurial > pidgin
annotate src/buddy.c @ 4952:b7dfce780963
[gaim-migrate @ 5286]
AOL has started requesting hashes again. This means they'll *probably* start
blocking again soon. The hash server we put up last time isn't working right
because we claim to be a different version of AIM now, so I hard-coded the values
in oscar.c and we'll have to keep updating that until we get it fixed. Stable Gaim
and TOC are unaffected. You should really update this so that OSCAR will work.
committer: Tailor Script <tailor@pidgin.im>
| author | Sean Egan <seanegan@gmail.com> |
|---|---|
| date | Tue, 01 Apr 2003 20:47:50 +0000 |
| parents | 24c9a23df63b |
| children | decdf19454ab |
| 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 | |
| 319 /* Protocol specific options */ | |
| 320 prpl = find_prpl(((struct buddy*)node)->account->protocol); | |
| 321 | |
| 322 if(prpl && prpl->get_info) { | |
| 323 menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Get Info")); | |
| 324 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_info_cb), node); | |
| 325 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
| 326 } | |
| 4732 | 327 |
| 4916 | 328 menuitem = gtk_image_menu_item_new_with_mnemonic(_("_IM")); |
| 329 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_im_cb), node); | |
| 330 image = gtk_image_new_from_stock(GAIM_STOCK_IM, GTK_ICON_SIZE_MENU); | |
| 331 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image); | |
| 332 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
| 333 | |
| 334 menuitem = gtk_image_menu_item_new_with_mnemonic(_("Add Buddy _Pounce")); | |
| 335 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_bp_cb), node); | |
| 336 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
| 337 | |
| 338 menuitem = gtk_image_menu_item_new_with_mnemonic(_("View _Log")); | |
| 339 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_showlog_cb), node); | |
| 340 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
| 341 | |
| 342 if (prpl) { | |
| 343 list = prpl->buddy_menu(((struct buddy*)node)->account->gc, ((struct buddy*)node)->name); | |
| 344 while (list) { | |
| 345 struct proto_buddy_menu *pbm = list->data; | |
| 346 menuitem = gtk_menu_item_new_with_mnemonic(pbm->label); | |
| 347 g_object_set_data(G_OBJECT(menuitem), "gaimcallback", pbm); | |
| 348 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gaim_proto_menu_cb), node); | |
| 349 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
| 350 list = list->next; | |
| 351 } | |
| 352 } | |
| 353 | |
| 354 gaim_separator(menu); | |
| 355 | |
| 356 menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Alias")); | |
| 357 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_alias_cb), node); | |
| 358 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
| 359 | |
| 360 menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Remove")); | |
| 361 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gaim_gtk_blist_remove_cb), node); | |
| 362 image = gtk_image_new_from_stock(GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU); | |
| 363 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image); | |
| 4732 | 364 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); |
| 365 } | |
| 4916 | 366 |
| 4687 | 367 gtk_widget_show_all(menu); |
| 368 | |
| 369 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, event->time); | |
| 1 | 370 |
| 4702 | 371 #if (1) /* This code only exists because GTK doesn't work. If we return FALSE here, as would be normal |
| 372 * the event propoagates down and somehow gets interpreted as the start of a drag event. */ | |
| 373 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv)); | |
| 374 gtk_tree_selection_select_path(sel, path); | |
| 4721 | 375 gtk_tree_path_free(path); |
| 4702 | 376 return TRUE; |
| 377 #endif | |
| 1 | 378 } |
| 379 | |
| 4944 | 380 static void gaim_gtk_blist_edit_mode_cb(gpointer callback_data, guint callback_action, |
| 4936 | 381 GtkWidget *checkitem) { |
| 4916 | 382 GdkCursor *cursor = gdk_cursor_new(GDK_WATCH); |
| 383 gdk_window_set_cursor(gtkblist->window->window, cursor); | |
| 384 while (gtk_events_pending()) | |
| 385 gtk_main_iteration(); | |
| 4936 | 386 if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(checkitem))) |
| 387 blist_options |= OPT_BLIST_SHOW_OFFLINE; | |
| 388 else | |
| 389 blist_options &= ~OPT_BLIST_SHOW_OFFLINE; | |
| 4929 | 390 save_prefs(); |
| 4916 | 391 gdk_cursor_unref(cursor); |
| 392 cursor = gdk_cursor_new(GDK_LEFT_PTR); | |
| 393 gdk_window_set_cursor(gtkblist->window->window, cursor); | |
| 394 gdk_cursor_unref(cursor); | |
| 395 gaim_gtk_blist_refresh(gaim_get_blist()); | |
| 396 } | |
|
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4349
diff
changeset
|
397 |
| 4944 | 398 /* This is called 10 seconds after the buddy logs in. It removes the "logged in" icon and replaces it with |
| 399 * the normal status icon. Make sure they didn't sign off in the mean-time though. */ | |
| 1 | 400 |
| 4944 | 401 static gboolean gaim_reset_present_icon (GaimBlistNode *b) |
| 402 { | |
| 403 if (((struct buddy *)b)->present == 2) { | |
| 404 ((struct buddy *)b)->present = 1; | |
| 405 gaim_gtk_blist_update(NULL, b); | |
| 4697 | 406 } |
| 4944 | 407 |
| 408 return FALSE; | |
| 4697 | 409 } |
| 1 | 410 |
| 4702 | 411 static void gaim_gtk_blist_drag_data_get_cb (GtkWidget *widget, |
| 412 GdkDragContext *dc, | |
| 413 GtkSelectionData *data, | |
| 414 guint info, | |
| 415 guint time, | |
| 416 gpointer *null) | |
| 417 { | |
| 4781 | 418 if (data->target == gdk_atom_intern("GAIM_BLIST_NODE", FALSE)) { |
| 4702 | 419 GtkTreeRowReference *ref = g_object_get_data(G_OBJECT(dc), "gtk-tree-view-source-row"); |
| 420 GtkTreePath *sourcerow = gtk_tree_row_reference_get_path(ref); | |
| 421 GtkTreeIter iter; | |
| 422 GaimBlistNode *node = NULL; | |
| 423 GValue val = {0}; | |
| 424 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, sourcerow); | |
| 425 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
| 426 node = g_value_get_pointer(&val); | |
| 4781 | 427 gtk_selection_data_set (data, |
| 428 gdk_atom_intern ("GAIM_BLIST_NODE", FALSE), | |
| 429 8, /* bits */ | |
| 430 (void*)&node, | |
| 431 sizeof (node)); | |
| 432 | |
| 4721 | 433 gtk_tree_path_free(sourcerow); |
| 4702 | 434 } |
| 4781 | 435 |
| 4702 | 436 } |
| 437 | |
| 438 static void gaim_gtk_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, | |
| 439 GtkSelectionData *sd, guint info, guint t) | |
| 440 { | |
| 4781 | 441 if (sd->target == gdk_atom_intern("GAIM_BLIST_NODE", FALSE) && sd->data) { |
| 442 GaimBlistNode *n = NULL; | |
| 4702 | 443 GtkTreePath *path = NULL; |
| 4704 | 444 GtkTreeViewDropPosition position; |
| 4781 | 445 memcpy(&n, sd->data, sizeof(n)); |
| 4704 | 446 if(gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget), x, y, &path, &position)) { |
| 447 /* if we're here, I think it means the drop is ok */ | |
| 4770 | 448 GtkTreeIter iter; |
| 449 GaimBlistNode *node; | |
| 450 GValue val = {0}; | |
| 451 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); | |
| 452 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
| 453 node = g_value_get_pointer(&val); | |
| 4781 | 454 |
| 455 if (GAIM_BLIST_NODE_IS_BUDDY(n)) { | |
| 456 struct buddy *b = (struct buddy*)n; | |
| 457 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
| 4795 | 458 switch(position) { |
| 459 case GTK_TREE_VIEW_DROP_AFTER: | |
| 460 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: | |
| 461 gaim_blist_add_buddy(b, (struct group*)node->parent, node); | |
| 462 break; | |
| 463 case GTK_TREE_VIEW_DROP_BEFORE: | |
| 464 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: | |
| 465 gaim_blist_add_buddy(b, (struct group*)node->parent, node->prev); | |
| 466 break; | |
| 4781 | 467 } |
| 468 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
| 469 gaim_blist_add_buddy(b, (struct group*)node, NULL); | |
| 4795 | 470 } |
| 4781 | 471 } else if (GAIM_BLIST_NODE_IS_GROUP(n)) { |
| 472 struct group *g = (struct group*)n; | |
| 473 if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
| 474 switch (position) { | |
| 475 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: | |
| 476 case GTK_TREE_VIEW_DROP_AFTER: | |
| 477 gaim_blist_add_group(g, node); | |
| 478 break; | |
| 479 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: | |
| 480 case GTK_TREE_VIEW_DROP_BEFORE: | |
| 481 gaim_blist_add_group(g, node->prev); | |
| 482 break; | |
| 483 } | |
| 484 | |
| 4770 | 485 } |
| 4781 | 486 |
| 4777 | 487 } |
| 4781 | 488 |
| 4721 | 489 gtk_tree_path_free(path); |
| 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"); |
|
4883
3c3bafae42e8
[gaim-migrate @ 5213]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
4879
diff
changeset
|
549 gtk_widget_realize(gtkblist->tipwindow); |
| 4724 | 550 g_signal_connect(G_OBJECT(gtkblist->tipwindow), "expose_event", |
| 551 G_CALLBACK(gaim_gtk_blist_paint_tip), buddy); | |
| 552 gtk_widget_ensure_style (gtkblist->tipwindow); | |
| 553 | |
| 554 layout = gtk_widget_create_pango_layout (gtkblist->tipwindow, NULL); | |
| 4733 | 555 pango_layout_set_wrap(layout, PANGO_WRAP_WORD); |
| 556 pango_layout_set_width(layout, 300000); | |
| 4724 | 557 pango_layout_set_markup(layout, tooltiptext, strlen(tooltiptext)); |
| 558 scr_w = gdk_screen_width(); | |
| 559 scr_h = gdk_screen_height(); | |
| 560 pango_layout_get_size (layout, &w, &h); | |
| 561 w = PANGO_PIXELS(w) + 8; | |
| 562 h = PANGO_PIXELS(h) + 8; | |
| 563 | |
| 564 /* 38 is the size of a large status icon plus 4 pixels padding on each side. | |
| 565 I should #define this or something */ | |
| 566 w = w + 38; | |
| 567 h = MAX(h, 38); | |
| 568 | |
| 569 gdk_window_get_pointer(NULL, &x, &y, NULL); | |
| 570 if (GTK_WIDGET_NO_WINDOW(gtkblist->window)) | |
| 571 y+=gtkblist->window->allocation.y; | |
| 572 | |
| 573 x -= ((w >> 1) + 4); | |
| 574 | |
| 575 if ((x + w) > scr_w) | |
| 576 x -= (x + w) - scr_w; | |
| 577 else if (x < 0) | |
| 578 x = 0; | |
| 579 | |
| 580 if ((y + h + 4) > scr_h) | |
| 581 y = y - h; | |
| 582 else | |
| 583 y = y + 6; | |
| 584 g_object_unref (layout); | |
| 585 g_free(tooltiptext); | |
| 586 gtk_widget_set_size_request(gtkblist->tipwindow, w, h); | |
| 4729 | 587 gtk_window_move(GTK_WINDOW(gtkblist->tipwindow), x, y); |
| 4724 | 588 gtk_widget_show(gtkblist->tipwindow); |
| 589 } | |
| 4729 | 590 |
| 4724 | 591 gtk_tree_path_free(path); |
| 592 return FALSE; | |
| 593 } | |
| 594 | |
| 4730 | 595 static gboolean gaim_gtk_blist_motion_cb (GtkWidget *tv, GdkEventMotion *event, gpointer null) |
| 4724 | 596 { |
| 597 GtkTreePath *path; | |
| 598 if (gtkblist->timeout) { | |
| 599 if ((event->y > gtkblist->rect.y) && ((event->y - gtkblist->rect.height) < gtkblist->rect.y)) | |
| 4732 | 600 return FALSE; |
| 4724 | 601 /* We've left the cell. Remove the timeout and create a new one below */ |
| 602 if (gtkblist->tipwindow) { | |
| 603 gtk_widget_destroy(gtkblist->tipwindow); | |
| 604 gtkblist->tipwindow = NULL; | |
| 605 } | |
| 606 | |
| 607 g_source_remove(gtkblist->timeout); | |
| 608 } | |
| 609 | |
| 610 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), event->x, event->y, &path, NULL, NULL, NULL); | |
| 611 gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, >kblist->rect); | |
| 612 if (path) | |
| 613 gtk_tree_path_free(path); | |
| 614 gtkblist->timeout = g_timeout_add(500, (GSourceFunc)gaim_gtk_blist_tooltip_timeout, tv); | |
| 4730 | 615 return FALSE; |
| 4724 | 616 } |
| 617 | |
| 618 static void gaim_gtk_blist_leave_cb (GtkWidget *w, GdkEventCrossing *e, gpointer n) | |
| 619 { | |
| 620 if (gtkblist->timeout == 0) | |
| 621 return; | |
| 622 if (gtkblist->tipwindow) { | |
| 623 gtk_widget_destroy(gtkblist->tipwindow); | |
| 624 gtkblist->tipwindow = NULL; | |
| 625 } | |
| 626 g_source_remove(gtkblist->timeout); | |
| 627 gtkblist->timeout = 0; | |
| 628 } | |
| 629 | |
| 4687 | 630 /*************************************************** |
| 631 * Crap * | |
| 632 ***************************************************/ | |
| 633 static GtkItemFactoryEntry blist_menu[] = | |
|
1929
d51ea669d84e
[gaim-migrate @ 1939]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1918
diff
changeset
|
634 { |
| 4687 | 635 /* Buddies menu */ |
| 636 { N_("/_Buddies"), NULL, NULL, 0, "<Branch>" }, | |
| 4916 | 637 { N_("/Buddies/New _Instant Message..."), "<CTL>I", show_im_dialog, 0, |
| 4687 | 638 "<StockItem>", GAIM_STOCK_IM }, |
| 639 { N_("/Buddies/Join a _Chat..."), "<CTL>C", join_chat, 0, | |
| 640 "<StockItem>", GAIM_STOCK_CHAT }, | |
| 4834 | 641 { "/Buddies/sep1", NULL, NULL, 0, "<Separator>" }, |
| 4687 | 642 { N_("/Buddies/Get _User Info..."), "<CTL>J", show_info_dialog, 0, |
| 643 "<StockItem>", GAIM_STOCK_INFO }, | |
| 4834 | 644 { "/Buddies/sep2", NULL, NULL, 0, "<Separator>" }, |
| 4687 | 645 { N_("/Buddies/_Signoff"), "<CTL>D", signoff_all, 0, NULL }, |
| 646 { N_("/Buddies/_Quit"), "<CTL>Q", do_quit, 0, | |
| 647 "<StockItem>", GTK_STOCK_QUIT }, | |
|
1929
d51ea669d84e
[gaim-migrate @ 1939]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1918
diff
changeset
|
648 |
| 4916 | 649 /* Edit menu */ |
| 650 { N_("/_Edit"), NULL, NULL, 0, "<Branch>" }, | |
| 4944 | 651 { N_("/Edit/_Show Offline Buddies"), NULL, gaim_gtk_blist_edit_mode_cb, 1, "<CheckItem>"}, |
| 4916 | 652 { N_("/Edit/_Add a Buddy..."), NULL, gaim_gtk_blist_add_buddy_cb, 0, "<StockItem>", GTK_STOCK_ADD }, |
| 653 { N_("/Edit/Add a _Group..."), NULL, show_add_group, 0, NULL}, | |
| 654 { "/Edit/sep", NULL, NULL, 0, "<Separator>" }, | |
| 655 { N_("/Edit/A_ccounts"), "<CTL>A", account_editor, 0, NULL }, | |
| 656 { N_("/Edit/Preferences"), "<CTL>P", show_prefs, 0, | |
| 657 "<StockItem>", GTK_STOCK_PREFERENCES }, | |
| 658 { N_("/Edit/Pr_ivacy"), NULL, show_privacy_options, 0, NULL }, | |
| 659 | |
| 4687 | 660 /* Tools */ |
| 661 { N_("/_Tools"), NULL, NULL, 0, "<Branch>" }, | |
| 662 { N_("/Tools/_Away"), NULL, NULL, 0, "<Branch>" }, | |
| 663 { N_("/Tools/Buddy _Pounce"), NULL, NULL, 0, "<Branch>" }, | |
| 4916 | 664 { N_("/Tools/sep1"), NULL, NULL, 0, "<Separator>" }, |
| 4698 | 665 { N_("/Tools/_File Transfers"), NULL, gaim_show_xfer_dialog, 0, |
| 4687 | 666 "<StockItem>", GTK_STOCK_REVERT_TO_SAVED }, |
| 4834 | 667 { "/Tools/sep2", NULL, NULL, 0, "<Separator>" }, |
| 4687 | 668 { N_("/Tools/P_rotocol Actions"), NULL, NULL, 0, "<Branch>" }, |
| 4697 | 669 { N_("/Tools/View System _Log"), NULL, gtk_blist_show_systemlog_cb, 0, NULL }, |
| 3251 | 670 |
| 4687 | 671 /* Help */ |
| 672 { N_("/_Help"), NULL, NULL, 0, "<Branch>" }, | |
| 4776 | 673 { N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, |
| 4687 | 674 "<StockItem>", GTK_STOCK_HELP }, |
| 4755 | 675 { N_("/Help/_Debug Window"), NULL, toggle_debug, 0, NULL }, |
| 4687 | 676 { N_("/Help/_About"), NULL, show_about, 0, NULL }, |
| 677 | |
| 678 }; | |
|
1929
d51ea669d84e
[gaim-migrate @ 1939]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1918
diff
changeset
|
679 |
| 4687 | 680 /********************************************************* |
| 681 * Private Utility functions * | |
| 682 *********************************************************/ | |
| 683 | |
| 4724 | 684 static char *gaim_get_tooltip_text(struct buddy *b) |
| 685 { | |
| 686 char *text = NULL; | |
| 687 struct prpl* prpl = find_prpl(b->account->protocol); | |
| 688 char *statustext = NULL; | |
| 4867 | 689 char *aliastext = NULL, *nicktext = NULL; |
| 4724 | 690 char *warning = NULL, *idletime = NULL; |
| 691 | |
| 692 if (prpl->tooltip_text) { | |
| 4815 | 693 const char *end; |
| 4732 | 694 statustext = prpl->tooltip_text(b); |
| 4815 | 695 |
| 696 if(statustext && !g_utf8_validate(statustext, -1, &end)) { | |
| 697 char *new = g_strndup(statustext, | |
| 698 g_utf8_pointer_to_offset(statustext, end)); | |
| 699 g_free(statustext); | |
| 700 statustext = new; | |
| 701 } | |
| 4724 | 702 } |
| 4732 | 703 |
| 4724 | 704 if (b->idle) { |
| 705 int ihrs, imin; | |
| 706 time_t t; | |
| 707 time(&t); | |
| 708 ihrs = (t - b->idle) / 3600; | |
| 709 imin = ((t - b->idle) / 60) % 60; | |
| 710 if (ihrs) | |
| 4744 | 711 idletime = g_strdup_printf(_("%dh%02dm"), ihrs, imin); |
| 4724 | 712 else |
| 4744 | 713 idletime = g_strdup_printf(_("%dm"), imin); |
| 4724 | 714 } |
| 4732 | 715 |
| 4945 | 716 if(b->alias && b->alias[0]) |
| 4867 | 717 aliastext = g_markup_escape_text(b->alias, -1); |
| 718 | |
| 719 if(b->server_alias) | |
| 720 nicktext = g_markup_escape_text(b->server_alias, -1); | |
| 721 | |
| 4724 | 722 if (b->evil > 0) |
| 4744 | 723 warning = g_strdup_printf(_("%d%%"), b->evil); |
| 4732 | 724 |
| 4724 | 725 text = g_strdup_printf("<span size='larger' weight='bold'>%s</span>" |
| 4744 | 726 "%s %s" /* Alias */ |
| 727 "%s %s" /* Nickname */ | |
| 728 "%s %s" /* Idle */ | |
| 729 "%s %s" /* Warning */ | |
| 4916 | 730 "%s" /* Offline */ |
| 4741 | 731 "%s%s", /* Status */ |
| 4724 | 732 b->name, |
| 4867 | 733 aliastext ? _("\n<b>Alias:</b>") : "", aliastext ? aliastext : "", |
| 734 nicktext ? _("\n<b>Nickname:</b>") : "", nicktext ? nicktext : "", | |
| 735 b->idle ? _("\n<b>Idle:</b>") : "", b->idle ? idletime : "", | |
| 4744 | 736 b->evil ? _("\n<b>Warned:</b>") : "", b->evil ? warning : "", |
| 4916 | 737 !b->present ? _("\n<b>Status:</b> Offline") : "", |
| 4724 | 738 statustext ? "\n" : "", statustext ? statustext : ""); |
| 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); | |
| 893 } | |
| 4737 | 894 } |
| 4687 | 895 |
| 4737 | 896 |
| 4718 | 897 /* Idle grey buddies affects the whole row. This converts the status icon to greyscale. */ |
| 4930 | 898 if (!b->present) |
| 4928 | 899 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.0, FALSE); |
| 900 else if (b->idle && blist_options & OPT_BLIST_GREY_IDLERS) | |
| 901 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.25, FALSE); | |
| 4687 | 902 return scale; |
| 1 | 903 } |
| 904 | |
| 4737 | 905 static GdkPixbuf *gaim_gtk_blist_get_buddy_icon(struct buddy *b) |
| 1 | 906 { |
| 4687 | 907 /* This just opens a file from ~/.gaim/icons/screenname. This needs to change to be more gooder. */ |
| 4737 | 908 char *file; |
| 909 GdkPixbuf *buf, *ret; | |
| 910 | |
| 4687 | 911 if (!(blist_options & OPT_BLIST_SHOW_ICONS)) |
| 912 return NULL; | |
| 4737 | 913 |
| 4757 | 914 if ((file = gaim_buddy_get_setting(b, "buddy_icon")) == NULL) |
| 915 return NULL; | |
| 916 | |
| 4737 | 917 buf = gdk_pixbuf_new_from_file(file, NULL); |
| 918 g_free(file); | |
| 919 | |
| 920 | |
| 4687 | 921 if (buf) { |
| 4930 | 922 if (!b->present) |
| 4928 | 923 gdk_pixbuf_saturate_and_pixelate(buf, buf, 0.0, FALSE); |
| 924 if (b->idle && blist_options & OPT_BLIST_GREY_IDLERS) | |
| 925 gdk_pixbuf_saturate_and_pixelate(buf, buf, 0.25, FALSE); | |
| 926 | |
| 4737 | 927 ret = gdk_pixbuf_scale_simple(buf,30,30, GDK_INTERP_BILINEAR); |
| 928 g_object_unref(G_OBJECT(buf)); | |
| 929 return ret; | |
|
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
930 } |
| 4687 | 931 return NULL; |
| 2986 | 932 } |
| 933 | |
| 4810 | 934 static gchar *gaim_gtk_blist_get_name_markup(struct buddy *b, gboolean selected) |
| 1 | 935 { |
| 4687 | 936 char *name = gaim_get_buddy_alias(b); |
| 937 char *esc = g_markup_escape_text(name, strlen(name)), *text = NULL; | |
| 4722 | 938 struct prpl* prpl = find_prpl(b->account->protocol); |
| 939 | |
| 4687 | 940 /* XXX Clean up this crap */ |
| 4699 | 941 |
| 4687 | 942 int ihrs, imin; |
| 4724 | 943 char *idletime = NULL, *warning = NULL, *statustext = NULL; |
| 4732 | 944 time_t t; |
|
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
945 |
| 4687 | 946 if (!(blist_options & OPT_BLIST_SHOW_ICONS)) { |
| 4929 | 947 if ((b->idle > 0 && blist_options & OPT_BLIST_GREY_IDLERS && !selected) || blist_options & OPT_BLIST_SHOW_OFFLINE) { |
| 4718 | 948 text = g_strdup_printf("<span color='dim grey'>%s</span>", |
| 4699 | 949 esc); |
| 4687 | 950 g_free(esc); |
| 951 return text; | |
| 952 } else { | |
| 953 return esc; | |
| 954 } | |
| 1 | 955 } |
| 956 | |
| 4687 | 957 time(&t); |
| 958 ihrs = (t - b->idle) / 3600; | |
| 959 imin = ((t - b->idle) / 60) % 60; | |
| 4699 | 960 |
| 4916 | 961 if (prpl && prpl->status_text) { |
| 4732 | 962 char *tmp = prpl->status_text(b); |
| 4815 | 963 const char *end; |
| 964 | |
| 965 if(tmp && !g_utf8_validate(tmp, -1, &end)) { | |
| 966 char *new = g_strndup(tmp, | |
| 967 g_utf8_pointer_to_offset(tmp, end)); | |
| 968 g_free(tmp); | |
| 969 tmp = new; | |
| 970 } | |
| 4732 | 971 |
| 972 if(tmp) { | |
| 4855 | 973 char buf[32]; |
| 974 char *c = tmp; | |
| 975 int length = 0, vis=0; | |
| 976 gboolean inside = FALSE; | |
| 4806 | 977 g_strdelimit(tmp, "\n", ' '); |
|
4852
d1c17e81055e
[gaim-migrate @ 5179]
Christian Hammond <chipx86@chipx86.com>
parents:
4847
diff
changeset
|
978 |
| 4855 | 979 while(*c && vis < 20) { |
| 980 if(*c == '&') | |
| 981 inside = TRUE; | |
| 4856 | 982 else if(*c == ';') |
| 983 inside = FALSE; | |
| 4855 | 984 if(!inside) |
| 985 vis++; | |
| 986 length++; | |
| 987 c++; /* this is fun */ | |
| 988 } | |
|
4852
d1c17e81055e
[gaim-migrate @ 5179]
Christian Hammond <chipx86@chipx86.com>
parents:
4847
diff
changeset
|
989 |
| 4855 | 990 if(vis == 20) |
| 991 g_snprintf(buf, sizeof(buf), "%%.%ds...", length); | |
| 992 else | |
| 993 g_snprintf(buf, sizeof(buf), "%%s "); | |
|
4852
d1c17e81055e
[gaim-migrate @ 5179]
Christian Hammond <chipx86@chipx86.com>
parents:
4847
diff
changeset
|
994 |
| 4855 | 995 statustext = g_strdup_printf(buf, tmp); |
|
4852
d1c17e81055e
[gaim-migrate @ 5179]
Christian Hammond <chipx86@chipx86.com>
parents:
4847
diff
changeset
|
996 |
| 4732 | 997 g_free(tmp); |
| 998 } | |
| 4722 | 999 } |
| 4732 | 1000 |
| 4687 | 1001 if (b->idle) { |
| 1002 if (ihrs) | |
| 4757 | 1003 idletime = g_strdup_printf(_("Idle (%dh%02dm) "), ihrs, imin); |
| 4687 | 1004 else |
| 4757 | 1005 idletime = g_strdup_printf(_("Idle (%dm) "), imin); |
| 4687 | 1006 } |
| 4757 | 1007 |
| 4687 | 1008 if (b->evil > 0) |
| 4757 | 1009 warning = g_strdup_printf(_("Warned (%d%%) "), b->evil); |
| 1010 | |
| 4810 | 1011 if (b->idle && blist_options & OPT_BLIST_GREY_IDLERS && !selected) { |
| 4916 | 1012 text = g_strdup_printf("<span color='dim grey'>%s</span>\n" |
| 1013 "<span color='dim grey' size='smaller'>%s%s%s%s</span>", | |
| 4687 | 1014 esc, |
| 4722 | 1015 statustext != NULL ? statustext : "", |
| 1016 idletime != NULL ? idletime : "", | |
| 4916 | 1017 warning != NULL ? warning : "", |
| 1018 !b->present ? _("Offline ") : ""); | |
| 1019 } else if (statustext == NULL && idletime == NULL && warning == NULL && b->present) { | |
| 1020 text = g_strdup(esc); | |
| 4797 | 1021 } else { |
| 4916 | 1022 text = g_strdup_printf("%s\n" |
| 1023 "<span %s size='smaller'>%s%s%s%s</span>", esc, | |
| 1024 selected ? "" : "color='dim grey'", | |
| 1025 statustext != NULL ? statustext : "", | |
| 1026 idletime != NULL ? idletime : "", | |
| 1027 warning != NULL ? warning : "", | |
| 1028 !b->present ? _("Offline ") : ""); | |
| 4797 | 1029 } |
| 4722 | 1030 if (idletime) |
| 4687 | 1031 g_free(idletime); |
| 4722 | 1032 if (warning) |
| 4687 | 1033 g_free(warning); |
| 4722 | 1034 if (statustext) |
| 1035 g_free(statustext); | |
| 4737 | 1036 if (esc) |
| 1037 g_free(esc); | |
| 4699 | 1038 |
| 4687 | 1039 return text; |
| 1040 } | |
|
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
1041 |
| 4840 | 1042 static void gaim_gtk_blist_restore_position() |
| 1043 { | |
| 1044 /* if the window exists, is hidden, we're saving positions, and the position is sane... */ | |
| 1045 if(gtkblist && gtkblist->window && | |
| 1046 !GTK_WIDGET_VISIBLE(gtkblist->window) && | |
| 1047 blist_options & OPT_BLIST_SAVED_WINDOWS && | |
| 1048 blist_pos.width != 0) { | |
| 1049 /* ...check position is on screen... */ | |
| 1050 if (blist_pos.x >= gdk_screen_width()) | |
| 1051 blist_pos.x = gdk_screen_width() - 100; | |
| 1052 else if (blist_pos.x < 0) | |
| 1053 blist_pos.x = 100; | |
| 1054 | |
| 1055 if (blist_pos.y >= gdk_screen_height()) | |
| 1056 blist_pos.y = gdk_screen_height() - 100; | |
| 1057 else if (blist_pos.y < 0) | |
| 1058 blist_pos.y = 100; | |
| 1059 | |
| 1060 /* ...and move it back. */ | |
| 1061 gtk_window_move(GTK_WINDOW(gtkblist->window), blist_pos.x, blist_pos.y); | |
| 1062 gtk_window_resize(GTK_WINDOW(gtkblist->window), blist_pos.width, blist_pos.height); | |
| 1063 } | |
| 1064 } | |
| 1065 | |
| 4944 | 1066 static gboolean gaim_gtk_blist_refresh_timer(struct gaim_buddy_list *list) |
| 1067 { | |
| 1068 GaimBlistNode *group = list->root; | |
| 1069 GaimBlistNode *buddy; | |
| 1070 | |
| 1071 while (group) { | |
| 1072 buddy = group->child; | |
| 1073 while (buddy) { | |
| 1074 if (((struct buddy *)buddy)->idle) | |
| 1075 gaim_gtk_blist_update(list, buddy); | |
| 1076 buddy = buddy->next; | |
| 1077 } | |
| 1078 group = group->next; | |
| 1079 } | |
| 1080 | |
| 1081 /* keep on going */ | |
| 1082 return TRUE; | |
| 1083 } | |
| 4840 | 1084 |
| 4687 | 1085 /********************************************************************************** |
| 1086 * Public API Functions * | |
| 1087 **********************************************************************************/ | |
|
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1088 static void gaim_gtk_blist_new_list(struct gaim_buddy_list *blist) |
|
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1089 { |
|
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1090 blist->ui_data = g_new0(struct gaim_gtk_buddy_list, 1); |
|
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1091 } |
|
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1092 |
|
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1093 static void gaim_gtk_blist_new_node(GaimBlistNode *node) |
|
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1094 { |
|
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1095 node->ui_data = g_new0(struct gaim_gtk_blist_node, 1); |
|
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1096 } |
|
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1097 |
| 4729 | 1098 void gaim_gtk_blist_update_columns() |
| 1099 { | |
| 1100 if (blist_options & OPT_BLIST_SHOW_ICONS) { | |
| 1101 gtk_tree_view_column_set_visible(gtkblist->buddy_icon_column, TRUE); | |
| 1102 gtk_tree_view_column_set_visible(gtkblist->idle_column, FALSE); | |
| 1103 gtk_tree_view_column_set_visible(gtkblist->warning_column, FALSE); | |
| 1104 } else { | |
| 1105 gtk_tree_view_column_set_visible(gtkblist->idle_column, blist_options & OPT_BLIST_SHOW_IDLETIME); | |
| 1106 gtk_tree_view_column_set_visible(gtkblist->warning_column, blist_options & OPT_BLIST_SHOW_WARN); | |
| 1107 gtk_tree_view_column_set_visible(gtkblist->buddy_icon_column, FALSE); | |
| 1108 } | |
| 1109 } | |
| 1110 | |
| 4702 | 1111 enum {DRAG_BUDDY, DRAG_ROW}; |
| 1112 | |
| 4834 | 1113 static char * |
| 1114 item_factory_translate_func (const char *path, gpointer func_data) | |
| 1115 { | |
| 1116 return _(path); | |
| 1117 } | |
| 1118 | |
| 4687 | 1119 static void gaim_gtk_blist_show(struct gaim_buddy_list *list) |
| 1120 { | |
| 1121 GtkItemFactory *ift; | |
| 1122 GtkCellRenderer *rend; | |
| 1123 GtkTreeViewColumn *column; | |
| 1124 GtkWidget *sw; | |
| 1125 GtkWidget *button; | |
| 4694 | 1126 GtkSizeGroup *sg; |
| 4810 | 1127 GtkTreeSelection *selection; |
| 4781 | 1128 GtkTargetEntry gte[] = {{"GAIM_BLIST_NODE", GTK_TARGET_SAME_APP, DRAG_ROW}, |
| 4702 | 1129 {"application/x-im-contact", 0, DRAG_BUDDY}}; |
| 4690 | 1130 |
| 4745 | 1131 if (gtkblist && gtkblist->window) { |
| 4687 | 1132 gtk_widget_show(gtkblist->window); |
| 1133 return; | |
| 1134 } | |
| 4690 | 1135 |
|
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1136 gtkblist = GAIM_GTK_BLIST(list); |
|
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1137 |
| 4687 | 1138 gtkblist->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
| 4840 | 1139 gtk_window_set_role(GTK_WINDOW(gtkblist->window), "buddy_list"); |
| 4947 | 1140 gtk_window_set_title(GTK_WINDOW(gtkblist->window), _("Biatches List")); |
|
4879
4f5bd9a2da37
[gaim-migrate @ 5209]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
4867
diff
changeset
|
1141 gtk_widget_realize(gtkblist->window); |
| 4690 | 1142 |
| 4925 | 1143 gtkblist->vbox = gtk_vbox_new(FALSE, 0); |
| 4687 | 1144 gtk_container_add(GTK_CONTAINER(gtkblist->window), gtkblist->vbox); |
| 1 | 1145 |
| 4840 | 1146 g_signal_connect(G_OBJECT(gtkblist->window), "delete_event", G_CALLBACK(gtk_blist_delete_cb), NULL); |
| 1147 g_signal_connect(G_OBJECT(gtkblist->window), "configure_event", G_CALLBACK(gtk_blist_configure_cb), NULL); | |
| 1148 g_signal_connect(G_OBJECT(gtkblist->window), "visibility_notify_event", G_CALLBACK(gtk_blist_visibility_cb), NULL); | |
| 1149 gtk_widget_add_events(gtkblist->window, GDK_VISIBILITY_NOTIFY_MASK); | |
| 4698 | 1150 |
| 4687 | 1151 /******************************* Menu bar *************************************/ |
| 1152 ift = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<GaimMain>", NULL); | |
| 4834 | 1153 gtk_item_factory_set_translate_func (ift, |
| 1154 item_factory_translate_func, | |
| 1155 NULL, NULL); | |
| 4687 | 1156 gtk_item_factory_create_items(ift, sizeof(blist_menu) / sizeof(*blist_menu), |
| 1157 blist_menu, NULL); | |
| 1158 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtk_item_factory_get_widget(ift, "<GaimMain>"), FALSE, FALSE, 0); | |
| 1 | 1159 |
| 4834 | 1160 awaymenu = gtk_item_factory_get_widget(ift, N_("/Tools/Away")); |
| 4694 | 1161 do_away_menu(); |
| 1162 | |
| 4834 | 1163 bpmenu = gtk_item_factory_get_widget(ift, N_("/Tools/Buddy Pounce")); |
| 4696 | 1164 do_bp_menu(); |
| 1165 | |
| 4834 | 1166 protomenu = gtk_item_factory_get_widget(ift, N_("/Tools/Protocol Actions")); |
| 4696 | 1167 do_proto_menu(); |
| 1168 | |
| 4687 | 1169 /****************************** GtkTreeView **********************************/ |
| 1170 sw = gtk_scrolled_window_new(NULL,NULL); | |
| 1171 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN); | |
| 1172 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
| 1173 | |
| 4847 | 1174 gtkblist->treemodel = gtk_tree_store_new(BLIST_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, |
| 4687 | 1175 G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_POINTER); |
| 4702 | 1176 |
| 4687 | 1177 gtkblist->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(gtkblist->treemodel)); |
| 4943 | 1178 gtk_widget_set_size_request(gtkblist->treeview, -1, 200); |
| 4704 | 1179 |
| 4810 | 1180 /* Set up selection stuff */ |
| 1181 | |
| 1182 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkblist->treeview)); | |
| 1183 g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(gaim_gtk_blist_selection_changed), NULL); | |
| 1184 | |
| 1185 | |
| 4702 | 1186 /* Set up dnd */ |
| 1187 gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(gtkblist->treeview), GDK_BUTTON1_MASK, gte, | |
| 1188 2, GDK_ACTION_COPY); | |
| 4704 | 1189 gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(gtkblist->treeview), gte, 2, |
| 4702 | 1190 GDK_ACTION_COPY | GDK_ACTION_MOVE); |
| 4704 | 1191 g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-data-received", G_CALLBACK(gaim_gtk_blist_drag_data_rcv_cb), NULL); |
| 1192 g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-data-get", G_CALLBACK(gaim_gtk_blist_drag_data_get_cb), NULL); | |
| 1193 | |
| 4724 | 1194 /* Tooltips */ |
| 1195 g_signal_connect(G_OBJECT(gtkblist->treeview), "motion-notify-event", G_CALLBACK(gaim_gtk_blist_motion_cb), NULL); | |
| 1196 g_signal_connect(G_OBJECT(gtkblist->treeview), "leave-notify-event", G_CALLBACK(gaim_gtk_blist_leave_cb), NULL); | |
| 4687 | 1197 |
| 1198 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(gtkblist->treeview), FALSE); | |
| 1 | 1199 |
| 4687 | 1200 rend = gtk_cell_renderer_pixbuf_new(); |
| 1201 column = gtk_tree_view_column_new_with_attributes("Status", rend, "pixbuf", STATUS_ICON_COLUMN, NULL); | |
| 1202 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), column); | |
| 4933 | 1203 g_object_set(rend, "xalign", 0.0, "ypad", 0, NULL); |
| 4706 | 1204 |
| 4687 | 1205 rend = gtk_cell_renderer_text_new(); |
| 1206 column = gtk_tree_view_column_new_with_attributes("Name", rend, "markup", NAME_COLUMN, NULL); | |
| 1207 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), column); | |
| 4797 | 1208 g_object_set(rend, "ypad", 0, "yalign", 0.5, NULL); |
| 4706 | 1209 |
| 4687 | 1210 rend = gtk_cell_renderer_text_new(); |
| 4725 | 1211 gtkblist->warning_column = gtk_tree_view_column_new_with_attributes("Warning", rend, "markup", WARNING_COLUMN, NULL); |
| 1212 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), gtkblist->warning_column); | |
| 4796 | 1213 g_object_set(rend, "xalign", 1.0, "ypad", 0, NULL); |
| 4687 | 1214 |
| 1215 rend = gtk_cell_renderer_text_new(); | |
| 4725 | 1216 gtkblist->idle_column = gtk_tree_view_column_new_with_attributes("Idle", rend, "markup", IDLE_COLUMN, NULL); |
| 1217 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), gtkblist->idle_column); | |
| 4796 | 1218 g_object_set(rend, "xalign", 1.0, "ypad", 0, NULL); |
| 1 | 1219 |
| 4687 | 1220 rend = gtk_cell_renderer_pixbuf_new(); |
| 4725 | 1221 gtkblist->buddy_icon_column = gtk_tree_view_column_new_with_attributes("Buddy Icon", rend, "pixbuf", BUDDY_ICON_COLUMN, NULL); |
| 4796 | 1222 g_object_set(rend, "xalign", 1.0, "ypad", 0, NULL); |
| 4725 | 1223 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), gtkblist->buddy_icon_column); |
| 4718 | 1224 |
| 4687 | 1225 g_signal_connect(G_OBJECT(gtkblist->treeview), "row-activated", G_CALLBACK(gtk_blist_row_activated_cb), NULL); |
| 1226 g_signal_connect(G_OBJECT(gtkblist->treeview), "button-press-event", G_CALLBACK(gtk_blist_button_press_cb), NULL); | |
|
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
1227 |
| 4687 | 1228 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), sw, TRUE, TRUE, 0); |
| 1229 gtk_container_add(GTK_CONTAINER(sw), gtkblist->treeview); | |
| 4725 | 1230 gaim_gtk_blist_update_columns(); |
| 4934 | 1231 |
| 4687 | 1232 /**************************** Button Box **************************************/ |
| 4694 | 1233 |
| 1234 sg = gtk_size_group_new(GTK_SIZE_GROUP_BOTH); | |
| 4687 | 1235 gtkblist->bbox = gtk_hbox_new(TRUE, 0); |
| 1236 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->bbox, FALSE, FALSE, 0); | |
| 1237 button = gaim_pixbuf_button_from_stock(_("IM"), GAIM_STOCK_IM, GAIM_BUTTON_VERTICAL); | |
| 1238 gtk_box_pack_start(GTK_BOX(gtkblist->bbox), button, FALSE, FALSE, 0); | |
| 1239 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
| 4694 | 1240 gtk_size_group_add_widget(sg, button); |
| 4692 | 1241 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_blist_button_im_cb), |
| 4697 | 1242 gtkblist->treeview); |
| 1243 | |
| 4687 | 1244 button = gaim_pixbuf_button_from_stock(_("Get Info"), GAIM_STOCK_INFO, GAIM_BUTTON_VERTICAL); |
| 1245 gtk_box_pack_start(GTK_BOX(gtkblist->bbox), button, FALSE, FALSE, 0); | |
| 1246 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
| 4694 | 1247 gtk_size_group_add_widget(sg, button); |
| 1248 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_blist_button_info_cb), | |
| 4697 | 1249 gtkblist->treeview); |
| 4729 | 1250 |
| 4687 | 1251 button = gaim_pixbuf_button_from_stock(_("Chat"), GAIM_STOCK_CHAT, GAIM_BUTTON_VERTICAL); |
| 1252 gtk_box_pack_start(GTK_BOX(gtkblist->bbox), button, FALSE, FALSE, 0); | |
| 1253 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
| 4694 | 1254 gtk_size_group_add_widget(sg, button); |
| 1255 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_blist_button_chat_cb), NULL); | |
| 1256 | |
| 4687 | 1257 button = gaim_pixbuf_button_from_stock(_("Away"), GAIM_STOCK_AWAY, GAIM_BUTTON_VERTICAL); |
| 1258 gtk_box_pack_start(GTK_BOX(gtkblist->bbox), button, FALSE, FALSE, 0); | |
| 1259 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
| 4694 | 1260 gtk_size_group_add_widget(sg, button); |
| 1261 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_blist_button_away_cb), NULL); | |
| 4687 | 1262 |
| 4944 | 1263 gaim_gtk_blist_update_toolbar(); |
| 1264 | |
| 4936 | 1265 /* set the Show Offline Buddies option */ |
| 1266 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (ift, N_("/Edit/Show Offline Buddies"))), | |
| 1267 blist_options & OPT_BLIST_SHOW_OFFLINE); | |
| 1268 | |
| 1269 /* OK... let's show this bad boy. */ | |
| 1270 gaim_gtk_blist_restore_position(); | |
| 1271 gtk_widget_show_all(gtkblist->window); | |
| 1272 | |
| 4944 | 1273 gaim_gtk_blist_refresh(list); |
| 1274 gtkblist->refresh_timer = g_timeout_add(30000, (GSourceFunc)gaim_gtk_blist_refresh_timer, list); | |
| 4687 | 1275 } |
|
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
1276 |
| 4687 | 1277 void gaim_gtk_blist_refresh(struct gaim_buddy_list *list) |
| 1278 { | |
| 1279 GaimBlistNode *group = list->root; | |
| 1280 GaimBlistNode *buddy; | |
| 4690 | 1281 |
| 4687 | 1282 while (group) { |
| 4916 | 1283 buddy = group->child; |
| 4687 | 1284 gaim_gtk_blist_update(list, group); |
| 1285 while (buddy) { | |
| 4699 | 1286 gaim_gtk_blist_update(list, buddy); |
| 4687 | 1287 buddy = buddy->next; |
| 1288 } | |
| 1289 group = group->next; | |
| 1290 } | |
| 1291 } | |
| 1 | 1292 |
| 4699 | 1293 static gboolean get_iter_from_node_helper(GaimBlistNode *node, GtkTreeIter *iter, GtkTreeIter *root) { |
| 4867 | 1294 |
| 4699 | 1295 do { |
| 1296 GaimBlistNode *n; | |
| 1297 GtkTreeIter child; | |
| 1298 | |
| 1299 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), root, NODE_COLUMN, &n, -1); | |
| 1300 if(n == node) { | |
| 1301 *iter = *root; | |
| 1302 return TRUE; | |
| 1303 } | |
| 1304 | |
| 1305 if(gtk_tree_model_iter_children(GTK_TREE_MODEL(gtkblist->treemodel), &child, root)) { | |
| 1306 if(get_iter_from_node_helper(node,iter,&child)) | |
| 1307 return TRUE; | |
| 1308 } | |
| 1309 } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(gtkblist->treemodel), root)); | |
| 1310 | |
| 1311 return FALSE; | |
| 1312 } | |
| 1313 | |
| 1314 static gboolean get_iter_from_node(GaimBlistNode *node, GtkTreeIter *iter) { | |
| 1315 GtkTreeIter root; | |
| 1316 | |
| 1317 if (!gtkblist) | |
| 1318 return FALSE; | |
| 1319 | |
| 1320 if(!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(gtkblist->treemodel), &root)) | |
| 1321 return FALSE; | |
| 1322 | |
| 1323 return get_iter_from_node_helper(node, iter, &root); | |
| 1324 } | |
| 1325 | |
| 4944 | 1326 /* |
| 1327 * These state assignments suck. I'm sorry. They're for historical reasons. | |
| 1328 * Roll on new prefs. -Robot101 | |
| 1329 * | |
| 1330 * NO_BUTTON_TEXT && SHOW_BUTTON_XPM - image | |
| 1331 * !NO_BUTTON_TEXT && !SHOW_BUTTON_XPM - text | |
| 1332 * !NO_BUTTON_TEXT && SHOW_BUTTON_XPM - text & images | |
| 1333 * NO_BUTTON_TEXT && !SHOW_BUTTON_XPM - none | |
| 1334 */ | |
| 1335 | |
| 1336 static void gaim_gtk_blist_update_toolbar_icons (GtkWidget *widget, gpointer data) { | |
| 1337 if (GTK_IS_IMAGE(widget)) { | |
| 1338 if (blist_options & OPT_BLIST_SHOW_BUTTON_XPM) | |
| 1339 gtk_widget_show(widget); | |
| 1340 else | |
| 1341 gtk_widget_hide(widget); | |
| 1342 } else if (GTK_IS_LABEL(widget)) { | |
| 1343 if (blist_options & OPT_BLIST_NO_BUTTON_TEXT) | |
| 1344 gtk_widget_hide(widget); | |
| 1345 else | |
| 1346 gtk_widget_show(widget); | |
| 1347 } else if (GTK_IS_CONTAINER(widget)) { | |
| 1348 gtk_container_foreach(GTK_CONTAINER(widget), gaim_gtk_blist_update_toolbar_icons, NULL); | |
| 1349 } | |
| 1350 } | |
| 1351 | |
| 4697 | 1352 void gaim_gtk_blist_update_toolbar() { |
| 1353 if (!gtkblist) | |
| 1354 return; | |
| 4699 | 1355 |
| 4944 | 1356 if (blist_options & OPT_BLIST_NO_BUTTON_TEXT && !(blist_options & OPT_BLIST_SHOW_BUTTON_XPM)) |
| 4697 | 1357 gtk_widget_hide(gtkblist->bbox); |
| 4944 | 1358 else { |
| 4697 | 1359 gtk_widget_show_all(gtkblist->bbox); |
| 4944 | 1360 gtk_container_foreach(GTK_CONTAINER(gtkblist->bbox), gaim_gtk_blist_update_toolbar_icons, NULL); |
| 1361 } | |
| 4697 | 1362 } |
| 1363 | |
| 4701 | 1364 static void gaim_gtk_blist_remove(struct gaim_buddy_list *list, GaimBlistNode *node) |
| 1365 { | |
| 1366 struct gaim_gtk_blist_node *gtknode; | |
| 1367 GtkTreeIter iter; | |
| 1368 | |
| 1369 if (!node->ui_data) | |
| 1370 return; | |
| 1371 | |
| 1372 gtknode = (struct gaim_gtk_blist_node *)node->ui_data; | |
| 1373 | |
| 1374 if (gtknode->timer > 0) { | |
| 1375 g_source_remove(gtknode->timer); | |
| 1376 gtknode->timer = 0; | |
| 1377 } | |
| 1378 | |
| 4912 | 1379 /* For some reason, we're called before we have a buddy list sometimes */ |
| 1380 if(!gtkblist) | |
| 1381 return; | |
| 1382 | |
| 4831 | 1383 if(gtkblist->selected_node == node) |
| 1384 gtkblist->selected_node = NULL; | |
| 1385 | |
| 4701 | 1386 if (get_iter_from_node(node, &iter)) { |
| 1387 gtk_tree_store_remove(gtkblist->treemodel, &iter); | |
|
4918
553d96cb9b26
[gaim-migrate @ 5252]
Christian Hammond <chipx86@chipx86.com>
parents:
4916
diff
changeset
|
1388 if(GAIM_BLIST_NODE_IS_BUDDY(node) && |
| 4929 | 1389 !blist_options & OPT_BLIST_SHOW_OFFLINE && |
|
4918
553d96cb9b26
[gaim-migrate @ 5252]
Christian Hammond <chipx86@chipx86.com>
parents:
4916
diff
changeset
|
1390 gaim_blist_get_group_online_count((struct group *)node->parent) == 0) { |
| 4701 | 1391 GtkTreeIter groupiter; |
| 1392 if(get_iter_from_node(node->parent, &groupiter)) | |
| 1393 gtk_tree_store_remove(gtkblist->treemodel, &groupiter); | |
| 1394 } | |
| 1395 } | |
| 1396 } | |
| 1397 | |
| 4810 | 1398 static gboolean do_selection_changed(GaimBlistNode *new_selection) |
| 1399 { | |
| 1400 GaimBlistNode *old_selection = gtkblist->selected_node; | |
| 1401 | |
| 1402 if(new_selection != gtkblist->selected_node) { | |
| 1403 gtkblist->selected_node = new_selection; | |
| 1404 if(new_selection) | |
| 1405 gaim_gtk_blist_update(NULL, new_selection); | |
| 1406 if(old_selection) | |
| 1407 gaim_gtk_blist_update(NULL, old_selection); | |
| 1408 } | |
| 1409 | |
| 1410 return FALSE; | |
| 1411 } | |
| 1412 | |
| 1413 static void gaim_gtk_blist_selection_changed(GtkTreeSelection *selection, gpointer data) | |
| 1414 { | |
| 1415 GaimBlistNode *new_selection = NULL; | |
| 1416 GtkTreeIter iter; | |
| 1417 | |
| 1418 if(gtk_tree_selection_get_selected(selection, NULL, &iter)){ | |
| 1419 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, | |
| 1420 NODE_COLUMN, &new_selection, -1); | |
| 1421 } | |
| 1422 /* we set this up as a timeout, otherwise the blist flickers */ | |
| 1423 g_timeout_add(0, (GSourceFunc)do_selection_changed, new_selection); | |
| 1424 } | |
| 1425 | |
| 4936 | 1426 static void make_a_group(GaimBlistNode *node, GtkTreeIter *iter) { |
| 1427 GaimBlistNode *sibling; | |
| 1428 GtkTreeIter siblingiter; | |
| 1429 GdkPixbuf *groupicon = gtk_widget_render_icon(gtkblist->treeview, | |
| 1430 GTK_STOCK_OPEN, GTK_ICON_SIZE_SMALL_TOOLBAR, NULL); | |
| 1431 char *esc = g_markup_escape_text(((struct group*)node)->name, -1); | |
| 1432 char *mark = g_strdup_printf("<span weight='bold'>%s</span>", esc); | |
| 1433 g_free(esc); | |
| 1434 sibling = node->prev; | |
| 1435 while (sibling && !get_iter_from_node(sibling, &siblingiter)) { | |
| 1436 sibling = sibling->prev; | |
| 1437 } | |
| 1438 | |
| 1439 gtk_tree_store_insert_after(gtkblist->treemodel, iter, NULL, | |
| 1440 sibling ? &siblingiter : NULL); | |
| 1441 gtk_tree_store_set(gtkblist->treemodel, iter, | |
| 1442 STATUS_ICON_COLUMN, groupicon, | |
| 1443 NAME_COLUMN, mark, | |
| 1444 NODE_COLUMN, node, | |
| 1445 -1); | |
| 1446 g_free(mark); | |
| 1447 g_object_unref(groupicon); | |
| 1448 } | |
| 1449 | |
| 4701 | 1450 |
| 4687 | 1451 static void gaim_gtk_blist_update(struct gaim_buddy_list *list, GaimBlistNode *node) |
| 1452 { | |
|
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1453 struct gaim_gtk_blist_node *gtknode; |
| 4699 | 1454 GtkTreeIter iter; |
| 4936 | 1455 GtkTreePath *expand = NULL; |
| 4699 | 1456 gboolean new_entry = FALSE; |
|
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
1457 |
| 4687 | 1458 if (!gtkblist) |
| 1459 return; | |
| 4699 | 1460 |
|
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1461 gtknode = GAIM_GTK_BLIST_NODE(node); |
|
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1462 |
| 4690 | 1463 |
| 4699 | 1464 if (!get_iter_from_node(node, &iter)) { /* This is a newly added node */ |
| 1465 new_entry = TRUE; | |
| 4687 | 1466 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { |
| 4929 | 1467 if (((struct buddy*)node)->present || (blist_options & OPT_BLIST_SHOW_OFFLINE && ((struct buddy*)node)->account->gc)) { |
| 4699 | 1468 GtkTreeIter groupiter; |
| 1469 GaimBlistNode *oldersibling; | |
| 1470 GtkTreeIter oldersiblingiter; | |
| 4690 | 1471 |
| 4936 | 1472 if(node->parent && |
| 1473 !get_iter_from_node(node->parent, &groupiter)) { | |
| 1474 /* This buddy's group has not yet been added. | |
| 1475 * We do that here */ | |
| 1476 make_a_group(node->parent, &groupiter); | |
| 1477 expand = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &groupiter); | |
| 4687 | 1478 } |
| 4810 | 1479 |
| 4699 | 1480 oldersibling = node->prev; |
| 4867 | 1481 while (oldersibling && !get_iter_from_node(oldersibling, &oldersiblingiter)) { |
| 4699 | 1482 oldersibling = oldersibling->prev; |
| 4867 | 1483 } |
| 4699 | 1484 |
| 1485 gtk_tree_store_insert_after(gtkblist->treemodel, &iter, &groupiter, oldersibling ? &oldersiblingiter : NULL); | |
| 4810 | 1486 |
| 4767 | 1487 if (blist_options & OPT_BLIST_POPUP) |
| 1488 gtk_window_present(GTK_WINDOW(gtkblist->window)); | |
| 4699 | 1489 |
| 1490 } | |
| 1491 } | |
| 4936 | 1492 else if (GAIM_BLIST_NODE_IS_GROUP(node) && (blist_options & OPT_BLIST_SHOW_OFFLINE)) { |
| 1493 make_a_group(node, &iter); | |
| 1494 expand = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); | |
| 4916 | 1495 } |
| 1496 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
| 4936 | 1497 if ((gaim_blist_get_group_online_count((struct group *)node) == 0) || |
| 1498 (!gtk_tree_model_iter_has_child(GTK_TREE_MODEL(gtkblist->treemodel), &iter) && !(blist_options & OPT_BLIST_SHOW_OFFLINE))) { | |
| 4916 | 1499 gtk_tree_store_remove(gtkblist->treemodel, &iter); |
| 4936 | 1500 } else { |
| 4916 | 1501 char *esc = g_markup_escape_text(((struct group*)node)->name, -1); |
| 1502 char *mark = g_strdup_printf("<span weight='bold'>%s</span>", esc); | |
| 1503 g_free(esc); | |
| 1504 gtk_tree_store_set(gtkblist->treemodel, &iter, | |
| 4936 | 1505 NAME_COLUMN, mark, |
| 1506 -1); | |
| 4916 | 1507 g_free(mark); |
| 1508 } | |
| 4699 | 1509 } |
|
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1510 |
| 4929 | 1511 if (GAIM_BLIST_NODE_IS_BUDDY(node) && (((struct buddy*)node)->present || (blist_options & OPT_BLIST_SHOW_OFFLINE && ((struct buddy*)node)->account->gc))) { |
| 4687 | 1512 GdkPixbuf *status, *avatar; |
| 1513 char *mark; | |
| 4697 | 1514 char *warning = NULL, *idle = NULL; |
| 1515 | |
| 4810 | 1516 gboolean selected = (gtkblist->selected_node == node); |
| 1517 | |
| 1518 status = gaim_gtk_blist_get_status_icon((struct buddy*)node, | |
| 4724 | 1519 blist_options & OPT_BLIST_SHOW_ICONS ? GAIM_STATUS_ICON_LARGE : GAIM_STATUS_ICON_SMALL); |
| 4687 | 1520 avatar = gaim_gtk_blist_get_buddy_icon((struct buddy*)node); |
| 4810 | 1521 mark = gaim_gtk_blist_get_name_markup((struct buddy*)node, selected); |
| 4697 | 1522 |
| 4725 | 1523 if (((struct buddy*)node)->idle > 0) { |
| 4697 | 1524 time_t t; |
| 1525 int ihrs, imin; | |
| 1526 time(&t); | |
| 1527 ihrs = (t - ((struct buddy *)node)->idle) / 3600; | |
| 1528 imin = ((t - ((struct buddy*)node)->idle) / 60) % 60; | |
| 4718 | 1529 if(ihrs > 0) |
| 1530 idle = g_strdup_printf("(%d:%02d)", ihrs, imin); | |
| 1531 else | |
| 1532 idle = g_strdup_printf("(%d)", imin); | |
| 4697 | 1533 } |
| 1534 | |
| 4725 | 1535 if (((struct buddy*)node)->evil > 0) |
| 4699 | 1536 warning = g_strdup_printf("%d%%", ((struct buddy*)node)->evil); |
| 4810 | 1537 |
| 4697 | 1538 |
| 4718 | 1539 if((blist_options & OPT_BLIST_GREY_IDLERS) |
| 1540 && ((struct buddy *)node)->idle) { | |
| 4810 | 1541 if(warning && !selected) { |
| 4718 | 1542 char *w2 = g_strdup_printf("<span color='dim grey'>%s</span>", |
| 1543 warning); | |
| 1544 g_free(warning); | |
| 1545 warning = w2; | |
| 1546 } | |
| 1547 | |
| 4810 | 1548 if(idle && !selected) { |
| 4718 | 1549 char *i2 = g_strdup_printf("<span color='dim grey'>%s</span>", |
| 1550 idle); | |
| 1551 g_free(idle); | |
| 1552 idle = i2; | |
| 1553 } | |
| 1554 } | |
| 1555 | |
| 1556 | |
| 4699 | 1557 gtk_tree_store_set(gtkblist->treemodel, &iter, |
| 4687 | 1558 STATUS_ICON_COLUMN, status, |
| 1559 NAME_COLUMN, mark, | |
| 4697 | 1560 WARNING_COLUMN, warning, |
| 1561 IDLE_COLUMN, idle, | |
| 4699 | 1562 BUDDY_ICON_COLUMN, avatar, |
| 4687 | 1563 NODE_COLUMN, node, |
| 1564 -1); | |
| 4699 | 1565 |
| 4687 | 1566 g_free(mark); |
| 4697 | 1567 if (idle) |
| 1568 g_free(idle); | |
| 1569 if (warning) | |
| 1570 g_free(warning); | |
|
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1571 |
|
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1572 if (status != NULL) |
|
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1573 g_object_unref(status); |
|
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1574 |
|
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1575 if (avatar != NULL) |
|
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1576 g_object_unref(avatar); |
|
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1577 |
| 4701 | 1578 } else if (GAIM_BLIST_NODE_IS_BUDDY(node) && !new_entry) { |
| 1579 gaim_gtk_blist_remove(list, node); | |
| 4767 | 1580 if (blist_options & OPT_BLIST_POPUP) |
| 1581 gtk_window_present(GTK_WINDOW(gtkblist->window)); | |
| 4781 | 1582 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { |
| 1583 GaimBlistNode *afsad = node->child; | |
| 1584 while (afsad) { | |
| 1585 gaim_gtk_blist_update(list, afsad); | |
| 1586 afsad = afsad->next; | |
| 1587 } | |
| 4936 | 1588 |
| 4916 | 1589 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(gtkblist->treeview)); |
| 4687 | 1590 } |
| 4936 | 1591 |
| 1592 if(expand) { | |
| 1593 gtk_tree_view_expand_row(GTK_TREE_VIEW(gtkblist->treeview), expand, TRUE); | |
| 1594 gtk_tree_path_free(expand); | |
| 1595 } | |
| 4687 | 1596 } |
|
2372
2927c2c26fe6
[gaim-migrate @ 2385]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2334
diff
changeset
|
1597 |
| 4687 | 1598 static void gaim_gtk_blist_destroy(struct gaim_buddy_list *list) |
| 1599 { | |
| 4770 | 1600 if (!gtkblist) |
| 1601 return; | |
| 4944 | 1602 |
| 4687 | 1603 gtk_widget_destroy(gtkblist->window); |
| 4745 | 1604 |
| 4944 | 1605 if (gtkblist->refresh_timer) |
| 1606 g_source_remove(gtkblist->refresh_timer); | |
| 1607 if (gtkblist->timeout) | |
| 1608 g_source_remove(gtkblist->timeout); | |
| 1609 | |
| 1610 gtkblist->refresh_timer = 0; | |
| 1611 gtkblist->timeout = 0; | |
| 4745 | 1612 gtkblist->window = gtkblist->vbox = gtkblist->treeview = NULL; |
| 1613 gtkblist->treemodel = NULL; | |
| 1614 gtkblist->idle_column = NULL; | |
| 1615 gtkblist->warning_column = gtkblist->buddy_icon_column = NULL; | |
| 1616 gtkblist->bbox = gtkblist->tipwindow = NULL; | |
| 1617 protomenu = NULL; | |
| 1618 awaymenu = NULL; | |
| 1619 bpmenu = NULL; | |
| 4687 | 1620 } |
| 1 | 1621 |
| 4687 | 1622 static void gaim_gtk_blist_set_visible(struct gaim_buddy_list *list, gboolean show) |
| 1623 { | |
| 4840 | 1624 if (!(gtkblist && gtkblist->window)) |
| 1625 return; | |
| 1626 | |
| 4698 | 1627 if (show) { |
| 4840 | 1628 gaim_gtk_blist_restore_position(); |
| 4699 | 1629 gtk_window_present(GTK_WINDOW(gtkblist->window)); |
| 4698 | 1630 } else { |
| 1631 if (!connections || docklet_count) { | |
| 1632 #ifdef _WIN32 | |
|
4711
0c1f3e651d3e
[gaim-migrate @ 5022]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
4706
diff
changeset
|
1633 wgaim_systray_minimize(gtkblist->window); |
| 4698 | 1634 #endif |
| 1635 gtk_widget_hide(gtkblist->window); | |
| 1636 } else { | |
| 1637 gtk_window_iconify(GTK_WINDOW(gtkblist->window)); | |
| 1638 } | |
| 1639 } | |
| 1640 } | |
| 1641 | |
| 1642 void gaim_gtk_blist_docklet_toggle() { | |
| 1643 /* Useful for the docklet plugin and also for the win32 tray icon*/ | |
| 1644 /* This is called when one of those is clicked--it will show/hide the | |
| 1645 buddy list/login window--depending on which is active */ | |
| 4840 | 1646 if (connections) { |
| 1647 if (gtkblist && gtkblist->window) { | |
| 1648 if (GTK_WIDGET_VISIBLE(gtkblist->window)) { | |
| 1649 gaim_blist_set_visible(GAIM_WINDOW_ICONIFIED(gtkblist->window) || gaim_gtk_blist_obscured); | |
| 1650 } else { | |
| 4698 | 1651 #if _WIN32 |
| 4840 | 1652 wgaim_systray_maximize(gtkblist->window); |
| 4698 | 1653 #endif |
| 4840 | 1654 gaim_blist_set_visible(TRUE); |
| 1655 } | |
| 1656 } else { | |
| 1657 /* we're logging in or something... do nothing */ | |
| 1658 /* or should I make the blist? */ | |
| 1659 debug_printf("docklet_toggle called with connections but no blist!\n"); | |
| 4698 | 1660 } |
| 4840 | 1661 } else if (mainwindow) { |
| 1662 if (GTK_WIDGET_VISIBLE(mainwindow)) { | |
| 4698 | 1663 if (GAIM_WINDOW_ICONIFIED(mainwindow)) { |
| 1664 gtk_window_present(GTK_WINDOW(mainwindow)); | |
| 1665 } else { | |
| 1666 #if _WIN32 | |
| 1667 wgaim_systray_minimize(mainwindow); | |
| 1668 #endif | |
| 1669 gtk_widget_hide(mainwindow); | |
| 1670 } | |
| 1671 } else { | |
| 1672 #if _WIN32 | |
| 1673 wgaim_systray_maximize(mainwindow); | |
| 1674 #endif | |
| 4833 | 1675 show_login(); |
| 4698 | 1676 } |
| 4840 | 1677 } else { |
| 1678 show_login(); | |
| 4698 | 1679 } |
| 1680 } | |
| 1681 | |
| 1682 void gaim_gtk_blist_docklet_add() | |
| 1683 { | |
| 1684 docklet_count++; | |
| 1685 } | |
| 1686 | |
| 1687 void gaim_gtk_blist_docklet_remove() | |
| 1688 { | |
| 1689 docklet_count--; | |
| 1690 if (!docklet_count) { | |
| 4944 | 1691 if (connections) |
| 4698 | 1692 gaim_blist_set_visible(TRUE); |
| 4944 | 1693 else if (mainwindow) |
| 4840 | 1694 gtk_window_present(GTK_WINDOW(mainwindow)); |
| 4944 | 1695 else |
| 4840 | 1696 show_login(); |
| 4698 | 1697 } |
| 4687 | 1698 } |
| 1 | 1699 |
| 4687 | 1700 static struct gaim_blist_ui_ops blist_ui_ops = |
| 1701 { | |
|
4695
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1702 gaim_gtk_blist_new_list, |
|
4bdd9a5fd026
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1703 gaim_gtk_blist_new_node, |
| 4687 | 1704 gaim_gtk_blist_show, |
| 1705 gaim_gtk_blist_update, | |
| 1706 gaim_gtk_blist_remove, | |
| 1707 gaim_gtk_blist_destroy, | |
| 1708 gaim_gtk_blist_set_visible | |
| 1709 }; | |
| 1 | 1710 |
| 1711 | |
| 4687 | 1712 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
|
1713 { |
| 4687 | 1714 return &blist_ui_ops; |
|
1037
1c663beef29d
[gaim-migrate @ 1047]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1036
diff
changeset
|
1715 } |
|
1c663beef29d
[gaim-migrate @ 1047]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1036
diff
changeset
|
1716 |
| 3131 | 1717 |
| 1718 | |
| 4687 | 1719 /********************************************************************* |
| 1720 * Public utility functions * | |
| 1721 *********************************************************************/ | |
|
1058
4927ce25d8cc
[gaim-migrate @ 1068]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1057
diff
changeset
|
1722 |
| 4687 | 1723 GdkPixbuf * |
| 1724 create_prpl_icon(struct gaim_account *account) | |
|
4553
d03fcb3f4be2
[gaim-migrate @ 4833]
Christian Hammond <chipx86@chipx86.com>
parents:
4525
diff
changeset
|
1725 { |
| 4687 | 1726 struct prpl *prpl = find_prpl(account->protocol); |
| 1727 GdkPixbuf *status = NULL; | |
| 1728 char *filename = NULL; | |
| 1729 const char *protoname = prpl->list_icon(account, NULL); | |
| 1730 /* "Hey, what's all this crap?" you ask. Status icons will be themeable too, and | |
| 1731 then it will look up protoname from the theme */ | |
| 1732 if (!strcmp(protoname, "aim")) { | |
| 1733 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "aim.png", NULL); | |
| 1734 status = gdk_pixbuf_new_from_file(filename,NULL); | |
| 1735 g_free(filename); | |
| 1736 } else if (!strcmp(protoname, "yahoo")) { | |
| 1737 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "yahoo.png", NULL); | |
| 1738 status = gdk_pixbuf_new_from_file(filename,NULL); | |
| 1739 g_free(filename); | |
| 1740 } else if (!strcmp(protoname, "msn")) { | |
| 1741 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "msn.png", NULL); | |
| 1742 status = gdk_pixbuf_new_from_file(filename,NULL); | |
| 1743 g_free(filename); | |
| 1744 } else if (!strcmp(protoname, "jabber")) { | |
| 1745 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "jabber.png", NULL); | |
| 1746 status = gdk_pixbuf_new_from_file(filename,NULL); | |
| 1747 g_free(filename); | |
| 1748 } else if (!strcmp(protoname, "icq")) { | |
| 1749 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "icq.png", NULL); | |
| 1750 status = gdk_pixbuf_new_from_file(filename,NULL); | |
| 1751 g_free(filename); | |
| 1752 } else if (!strcmp(protoname, "gadu-gadu")) { | |
| 1753 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "gadugadu.png", NULL); | |
| 1754 status = gdk_pixbuf_new_from_file(filename,NULL); | |
| 1755 g_free(filename); | |
| 1756 } else if (!strcmp(protoname, "napster")) { | |
| 1757 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "napster.png", NULL); | |
| 1758 status = gdk_pixbuf_new_from_file(filename,NULL); | |
| 1759 g_free(filename); | |
| 1760 } else if (!strcmp(protoname, "irc")) { | |
| 1761 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "irc.png", NULL); | |
| 1762 status = gdk_pixbuf_new_from_file(filename,NULL); | |
| 1763 g_free(filename); | |
|
960
fa681641643d
[gaim-migrate @ 970]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
945
diff
changeset
|
1764 } |
| 4687 | 1765 return status; |
| 1 | 1766 } |
| 4699 | 1767 |
