Fri, 14 Mar 2003 16:01:08 +0000
[gaim-migrate @ 5092]
This fixes the crash from signing on then signing off again in less
than 10 seconds. It also fixes the "you have signed on too many
times, wait 10 minutes then try again" crash.
It's like butter.
| 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
6f7d28b0f98d
[gaim-migrate @ 359]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
342
diff
changeset
|
22 | #ifdef HAVE_CONFIG_H |
|
2090
bab8b7e309db
[gaim-migrate @ 2100]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
2048
diff
changeset
|
23 | #include <config.h> |
|
349
6f7d28b0f98d
[gaim-migrate @ 359]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
342
diff
changeset
|
24 | #endif |
|
391
677e4414a83f
[gaim-migrate @ 401]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
350
diff
changeset
|
25 | #ifdef GAIM_PLUGINS |
| 3630 | 26 | #ifndef _WIN32 |
|
391
677e4414a83f
[gaim-migrate @ 401]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
350
diff
changeset
|
27 | #include <dlfcn.h> |
| 3630 | 28 | #endif |
|
391
677e4414a83f
[gaim-migrate @ 401]
Eric Warmenhoven <warmenhoven@yahoo.com>
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
e73eeec6323c
[gaim-migrate @ 1243]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
1230
diff
changeset
|
41 | #include <unistd.h> |
| 3630 | 42 | #include <gdk/gdkx.h> |
| 43 | #endif | |
| 1 | 44 | |
| 1634 | 45 | #include <gdk/gdkkeysyms.h> |
| 1 | 46 | #include <gtk/gtk.h> |
|
1030
b9fa9eadc0a4
[gaim-migrate @ 1040]
Eric Warmenhoven <warmenhoven@yahoo.com>
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
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
57 | static struct gaim_gtk_buddy_list *gtkblist = NULL; |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
58 | |
| 4698 | 59 | /* Docklet nonsense */ |
| 60 | static gboolean gaim_gtk_blist_obscured = FALSE; | |
| 61 | ||
| 4687 | 62 | static void gaim_gtk_blist_update(struct gaim_buddy_list *list, GaimBlistNode *node); |
| 4724 | 63 | static char *gaim_get_tooltip_text(struct buddy *b); |
| 64 | static GdkPixbuf *gaim_gtk_blist_get_status_icon(struct buddy *b, GaimStatusIconSize size); | |
|
2372
c24942700dfd
[gaim-migrate @ 2385]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
2334
diff
changeset
|
65 | |
| 4687 | 66 | /*************************************************** |
| 67 | * Callbacks * | |
| 68 | ***************************************************/ | |
| 3869 | 69 | |
| 4698 | 70 | static void gaim_gtk_blist_destroy_cb() |
| 71 | { | |
| 72 | if (docklet_count) | |
| 73 | gaim_blist_set_visible(FALSE); | |
| 74 | else | |
| 75 | do_quit(); | |
| 76 | } | |
| 77 | ||
| 4732 | 78 | static void gtk_blist_menu_info_cb(GtkWidget *w, struct buddy *b) |
| 79 | { | |
| 80 | serv_get_info(b->account->gc, b->name); | |
| 81 | } | |
| 82 | ||
| 4697 | 83 | static void gtk_blist_menu_im_cb(GtkWidget *w, struct buddy *b) |
| 84 | { | |
| 85 | gaim_conversation_new(GAIM_CONV_IM, b->account, b->name); | |
| 86 | } | |
| 87 | ||
| 88 | static void gtk_blist_menu_alias_cb(GtkWidget *w, struct buddy *b) | |
| 89 | { | |
| 90 | alias_dialog_bud(b); | |
| 91 | } | |
| 92 | ||
| 93 | static void gtk_blist_menu_bp_cb(GtkWidget *w, struct buddy *b) | |
| 94 | { | |
| 95 | show_new_bp(b->name, b->account->gc, b->idle, | |
| 96 | b->uc & UC_UNAVAILABLE, NULL); | |
| 97 | } | |
| 98 | ||
| 99 | static void gtk_blist_menu_showlog_cb(GtkWidget *w, struct buddy *b) | |
| 100 | { | |
| 101 | show_log(b->name); | |
| 102 | } | |
| 103 | ||
| 104 | static void gtk_blist_show_systemlog_cb() | |
| 105 | { | |
| 106 | show_log(NULL); | |
| 107 | } | |
| 108 | ||
| 4692 | 109 | static void gtk_blist_button_im_cb(GtkWidget *w, GtkTreeView *tv) |
| 110 | { | |
| 111 | GtkTreeIter iter; | |
| 112 | GtkTreeModel *model = gtk_tree_view_get_model(tv); | |
| 113 | GtkTreeSelection *sel = gtk_tree_view_get_selection(tv); | |
| 114 | ||
| 115 | if(gtk_tree_selection_get_selected(sel, &model, &iter)){ | |
| 116 | GaimBlistNode *node; | |
| 117 | ||
| 118 | gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); | |
| 119 | if (GAIM_BLIST_NODE_IS_BUDDY(node)) | |
| 120 | gaim_conversation_new(GAIM_CONV_IM, ((struct buddy*)node)->account, ((struct buddy*)node)->name); | |
| 121 | } | |
| 4694 | 122 | } |
| 4692 | 123 | |
| 4694 | 124 | static void gtk_blist_button_info_cb(GtkWidget *w, GtkTreeView *tv) |
| 125 | { | |
| 126 | GtkTreeIter iter; | |
| 127 | GtkTreeModel *model = gtk_tree_view_get_model(tv); | |
| 128 | GtkTreeSelection *sel = gtk_tree_view_get_selection(tv); | |
| 4692 | 129 | |
| 4694 | 130 | if(gtk_tree_selection_get_selected(sel, &model, &iter)){ |
| 131 | GaimBlistNode *node; | |
| 132 | ||
| 133 | gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); | |
| 134 | if (GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
| 135 | serv_get_info(((struct buddy*)node)->account->gc, ((struct buddy*)node)->name); | |
| 136 | return; | |
| 137 | } | |
| 138 | } | |
| 139 | show_info_dialog(); | |
| 140 | } | |
| 141 | ||
| 142 | static void gtk_blist_button_chat_cb(GtkWidget *w, gpointer data) | |
| 143 | { | |
| 144 | /* FIXME: someday, we can check to see if we've selected a chat node */ | |
| 145 | join_chat(); | |
| 146 | } | |
| 147 | ||
| 148 | static void gtk_blist_button_away_cb(GtkWidget *w, gpointer data) | |
| 149 | { | |
| 150 | gtk_menu_popup(GTK_MENU(awaymenu), NULL, NULL, NULL, NULL, 1, GDK_CURRENT_TIME); | |
| 4692 | 151 | } |
| 152 | ||
| 4687 | 153 | static void gtk_blist_row_activated_cb(GtkTreeView *tv, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data) { |
| 154 | GaimBlistNode *node; | |
| 155 | GtkTreeIter iter; | |
| 156 | GValue val = { 0, }; | |
| 3154 | 157 | |
| 4687 | 158 | gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); |
| 159 | ||
| 160 | gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
| 161 | node = g_value_get_pointer(&val); | |
| 162 | ||
| 163 | if (GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
| 164 | gaim_conversation_new(GAIM_CONV_IM, ((struct buddy*)node)->account, ((struct buddy*)node)->name); | |
| 4697 | 165 | } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { |
| 166 | if (gtk_tree_view_row_expanded(tv, path)) | |
| 167 | gtk_tree_view_collapse_row(tv, path); | |
| 168 | else | |
| 169 | gtk_tree_view_expand_row(tv,path,FALSE); | |
| 1 | 170 | } |
| 171 | } | |
| 172 | ||
| 4687 | 173 | static void gaim_proto_menu_cb(GtkMenuItem *item, struct buddy *b) |
| 1 | 174 | { |
| 4687 | 175 | struct proto_buddy_menu *pbm = g_object_get_data(G_OBJECT(item), "gaimcallback"); |
| 176 | if (pbm->callback) | |
| 177 | pbm->callback(pbm->gc, b->name); | |
|
1396
c038bcdcc1e9
[gaim-migrate @ 1406]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
1392
diff
changeset
|
178 | } |
| 1 | 179 | |
| 4687 | 180 | static gboolean gtk_blist_button_press_cb(GtkWidget *tv, GdkEventButton *event, gpointer null) |
|
1391
e6e7f3bf1e81
[gaim-migrate @ 1401]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
1376
diff
changeset
|
181 | { |
| 4687 | 182 | GtkTreePath *path; |
| 183 | GaimBlistNode *node; | |
| 184 | GValue val = { 0, }; | |
| 185 | GtkTreeIter iter; | |
| 186 | GtkWidget *menu, *menuitem; | |
| 187 | GtkWidget *image; | |
| 4702 | 188 | GtkTreeSelection *sel; |
| 4687 | 189 | GList *list; |
| 190 | struct prpl *prpl; | |
|
1391
e6e7f3bf1e81
[gaim-migrate @ 1401]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
1376
diff
changeset
|
191 | |
| 4687 | 192 | if (event->button != 3) |
| 193 | return FALSE; | |
| 4718 | 194 | |
| 4687 | 195 | /* Here we figure out which node was clicked */ |
| 196 | if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), event->x, event->y, &path, NULL, NULL, NULL)) | |
| 197 | return FALSE; | |
| 198 | gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); | |
| 199 | gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
| 200 | node = g_value_get_pointer(&val); | |
| 4718 | 201 | |
| 4721 | 202 | if (!GAIM_BLIST_NODE_IS_BUDDY(node)) { |
| 203 | gtk_tree_path_free(path); | |
| 4687 | 204 | return FALSE; |
| 4721 | 205 | } |
| 4718 | 206 | |
| 4687 | 207 | menu = gtk_menu_new(); |
|
3251
360fb695996d
[gaim-migrate @ 3269]
Jim Seymour <jseymour@users.sourceforge.net>
parents:
3204
diff
changeset
|
208 | |
| 4687 | 209 | /* Protocol specific options */ |
| 210 | prpl = find_prpl(((struct buddy*)node)->account->protocol); | |
| 4732 | 211 | |
| 212 | if(prpl && prpl->get_info) { | |
| 213 | menuitem = gtk_image_menu_item_new_with_mnemonic("_Get Info"); | |
| 214 | g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_info_cb), node); | |
| 215 | gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
| 216 | } | |
| 217 | ||
| 218 | menuitem = gtk_image_menu_item_new_with_mnemonic("_IM"); | |
| 219 | g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_im_cb), node); | |
| 220 | image = gtk_image_new_from_stock(GAIM_STOCK_IM, GTK_ICON_SIZE_MENU); | |
| 221 | gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image); | |
| 222 | gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
| 223 | ||
| 224 | menuitem = gtk_image_menu_item_new_with_mnemonic("_Alias"); | |
| 225 | g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_alias_cb), node); | |
| 226 | gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
| 227 | ||
| 228 | menuitem = gtk_image_menu_item_new_with_mnemonic("Add Buddy _Pounce"); | |
| 229 | g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_bp_cb), node); | |
| 230 | gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
| 231 | ||
| 232 | menuitem = gtk_image_menu_item_new_with_mnemonic("View _Log"); | |
| 233 | g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_showlog_cb), node); | |
| 234 | gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
| 235 | ||
| 4687 | 236 | if (prpl) { |
| 237 | list = prpl->buddy_menu(((struct buddy*)node)->account->gc, ((struct buddy*)node)->name); | |
| 238 | while (list) { | |
| 239 | struct proto_buddy_menu *pbm = list->data; | |
| 240 | menuitem = gtk_menu_item_new_with_mnemonic(pbm->label); | |
| 241 | g_object_set_data(G_OBJECT(menuitem), "gaimcallback", pbm); | |
| 242 | g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gaim_proto_menu_cb), node); | |
| 243 | gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
| 244 | list = list->next; | |
|
3313
a2e08cbb143a
[gaim-migrate @ 3331]
Jim Seymour <jseymour@users.sourceforge.net>
parents:
3279
diff
changeset
|
245 | } |
|
3251
360fb695996d
[gaim-migrate @ 3269]
Jim Seymour <jseymour@users.sourceforge.net>
parents:
3204
diff
changeset
|
246 | } |
| 1 | 247 | |
| 4687 | 248 | gtk_widget_show_all(menu); |
| 249 | ||
| 250 | gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, event->time); | |
| 1 | 251 | |
| 4702 | 252 | #if (1) /* This code only exists because GTK doesn't work. If we return FALSE here, as would be normal |
| 253 | * the event propoagates down and somehow gets interpreted as the start of a drag event. */ | |
| 254 | sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv)); | |
| 255 | gtk_tree_selection_select_path(sel, path); | |
| 4721 | 256 | gtk_tree_path_free(path); |
| 4702 | 257 | return TRUE; |
| 258 | #endif | |
| 1 | 259 | } |
| 260 | ||
| 4687 | 261 | static void gaim_gtk_blist_reordered_cb(GtkTreeModel *model, |
| 262 | GtkTreePath *path, | |
| 263 | GtkTreeIter *iter, | |
| 264 | gint *neworder, | |
| 265 | gpointer null) | |
|
3111
4e5c19f42fbe
[gaim-migrate @ 3125]
Christian Hammond <chipx86@chipx86.com>
parents:
3104
diff
changeset
|
266 | { |
| 4687 | 267 | debug_printf("This doesn't work because GTK is broken\n"); |
| 1 | 268 | |
| 269 | } | |
| 270 | ||
| 4687 | 271 | /* This is called 10 seconds after the buddy logs in. It removes the "logged in" icon and replaces it with |
| 272 | * the normal status icon */ | |
|
1072
44ae81f8ea2e
[gaim-migrate @ 1082]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
1070
diff
changeset
|
273 | |
| 4687 | 274 | static gboolean gaim_reset_present_icon(GaimBlistNode *b) |
| 275 | { | |
| 276 | ((struct buddy*)b)->present = 1; | |
| 277 | gaim_gtk_blist_update(NULL, b); | |
| 278 | return FALSE; | |
|
577
0e317d0cfc2c
[gaim-migrate @ 587]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
544
diff
changeset
|
279 | } |
|
0e317d0cfc2c
[gaim-migrate @ 587]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
544
diff
changeset
|
280 | |
| 4687 | 281 | static void gaim_gtk_blist_add_buddy_cb() |
| 935 | 282 | { |
| 4690 | 283 | GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkblist->treeview)); |
| 4687 | 284 | GtkTreeIter iter; |
| 285 | GaimBlistNode *node; | |
|
4359
cf899ee07d1d
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4349
diff
changeset
|
286 | |
| 4692 | 287 | if(gtk_tree_selection_get_selected(sel, NULL, &iter)){ |
| 288 | gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); | |
| 4691 | 289 | if (GAIM_BLIST_NODE_IS_BUDDY(node)) |
| 290 | show_add_buddy(NULL, NULL, ((struct group*)node->parent)->name, NULL); | |
| 291 | else if (GAIM_BLIST_NODE_IS_GROUP(node)) | |
| 292 | show_add_buddy(NULL, NULL, ((struct group*)node)->name, NULL); | |
| 293 | } | |
| 4697 | 294 | else { |
| 4692 | 295 | show_add_buddy(NULL, NULL, NULL, NULL); |
| 296 | } | |
| 1 | 297 | } |
| 298 | ||
| 4697 | 299 | static void gaim_gtk_blist_update_toolbar_icons (GtkWidget *widget, gpointer data) { |
| 300 | if (GTK_IS_IMAGE(widget)) { | |
| 301 | if (blist_options & OPT_BLIST_SHOW_BUTTON_XPM) | |
| 302 | gtk_widget_show(widget); | |
| 303 | else | |
| 304 | gtk_widget_hide(widget); | |
| 305 | } else if (GTK_IS_CONTAINER(widget)) { | |
| 306 | gtk_container_foreach(GTK_CONTAINER(widget), gaim_gtk_blist_update_toolbar_icons, NULL); | |
| 307 | } | |
| 308 | } | |
| 1 | 309 | |
| 4702 | 310 | static void gaim_gtk_blist_drag_data_get_cb (GtkWidget *widget, |
| 311 | GdkDragContext *dc, | |
| 312 | GtkSelectionData *data, | |
| 313 | guint info, | |
| 314 | guint time, | |
| 315 | gpointer *null) | |
| 316 | { | |
| 317 | if (data->target == gdk_atom_intern("GAIM_BUDDY", FALSE)) { | |
| 318 | GtkTreeRowReference *ref = g_object_get_data(G_OBJECT(dc), "gtk-tree-view-source-row"); | |
| 319 | GtkTreePath *sourcerow = gtk_tree_row_reference_get_path(ref); | |
| 320 | GtkTreeIter iter; | |
| 321 | GaimBlistNode *node = NULL; | |
| 322 | GValue val = {0}; | |
| 323 | gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, sourcerow); | |
| 324 | gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
| 325 | node = g_value_get_pointer(&val); | |
| 326 | if (GAIM_BLIST_NODE_IS_BUDDY(node)) | |
| 327 | gtk_selection_data_set (data, | |
| 328 | gdk_atom_intern ("GAIM_BUDDY", FALSE), | |
| 329 | 8, /* bits */ | |
| 330 | (void*)&node, | |
| 331 | sizeof (node)); | |
| 4721 | 332 | |
| 333 | gtk_tree_path_free(sourcerow); | |
| 4702 | 334 | } |
| 4721 | 335 | |
| 4702 | 336 | } |
| 337 | ||
| 338 | static void gaim_gtk_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, | |
| 339 | GtkSelectionData *sd, guint info, guint t) | |
| 340 | { | |
| 341 | if (sd->target == gdk_atom_intern("GAIM_BUDDY", FALSE)) { | |
| 342 | struct buddy *b = NULL; | |
| 343 | GtkTreePath *path = NULL; | |
| 4704 | 344 | GtkTreeViewDropPosition position; |
| 4702 | 345 | memcpy(&b, sd->data, sizeof(b)); |
| 4704 | 346 | if(gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget), x, y, &path, &position)) { |
| 347 | /* if we're here, I think it means the drop is ok */ | |
| 4770 | 348 | GtkTreeIter iter; |
| 349 | GaimBlistNode *node; | |
| 350 | GValue val = {0}; | |
| 351 | gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); | |
| 352 | gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
| 353 | node = g_value_get_pointer(&val); | |
| 354 | if (GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
| 355 | if (position == GTK_TREE_VIEW_DROP_AFTER) { | |
| 356 | gaim_blist_add_buddy(b, node->parent, node); | |
| 357 | } else if (position == GTK_TREE_VIEW_DROP_BEFORE) { | |
| 358 | gaim_blist_add_buddy(b, node->parent, node->prev); | |
| 359 | } | |
| 360 | } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
| 361 | gaim_blist_add_buddy(b, node, NULL); | |
| 362 | } | |
| 4721 | 363 | gtk_tree_path_free(path); |
| 4704 | 364 | } |
| 4702 | 365 | } |
| 366 | } | |
| 367 | ||
| 4724 | 368 | static void gaim_gtk_blist_paint_tip(GtkWidget *widget, GdkEventExpose *event, struct buddy *b) |
| 369 | { | |
| 370 | GtkStyle *style; | |
| 371 | GdkPixbuf *pixbuf = gaim_gtk_blist_get_status_icon(b, GAIM_STATUS_ICON_LARGE); | |
| 372 | PangoLayout *layout; | |
| 373 | char *tooltiptext = gaim_get_tooltip_text(b); | |
| 374 | ||
| 375 | layout = gtk_widget_create_pango_layout (gtkblist->tipwindow, NULL); | |
| 376 | pango_layout_set_markup(layout, tooltiptext, strlen(tooltiptext)); | |
| 4732 | 377 | pango_layout_set_wrap(layout, PANGO_WRAP_WORD); |
| 4733 | 378 | pango_layout_set_width(layout, 300000); |
| 4724 | 379 | style = gtkblist->tipwindow->style; |
| 4732 | 380 | |
| 4724 | 381 | gtk_paint_flat_box (style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, |
| 382 | NULL, gtkblist->tipwindow, "tooltip", 0, 0, -1, -1); | |
| 4729 | 383 | |
| 384 | #if GTK_CHECK_VERSION(2,2,0) | |
| 4724 | 385 | gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, pixbuf, |
| 386 | 0, 0, 4, 4, -1 , -1, GDK_RGB_DITHER_NONE, 0, 0); | |
| 4729 | 387 | #else |
| 4758 | 388 | 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 | 389 | #endif |
| 4724 | 390 | |
| 391 | gtk_paint_layout (style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, TRUE, | |
| 392 | NULL, gtkblist->tipwindow, "tooltip", 38, 4, layout); | |
| 393 | ||
| 394 | g_object_unref (pixbuf); | |
| 395 | g_object_unref (layout); | |
| 396 | g_free(tooltiptext); | |
| 397 | return; | |
| 398 | } | |
| 399 | ||
| 400 | static gboolean gaim_gtk_blist_tooltip_timeout(GtkWidget *tv) | |
| 401 | { | |
| 402 | GtkTreePath *path; | |
| 403 | GtkTreeIter iter; | |
| 404 | GaimBlistNode *node; | |
| 405 | GValue val = {0}; | |
| 406 | ||
| 407 | if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->rect.x, gtkblist->rect.y, &path, NULL, NULL, NULL)) | |
| 408 | return FALSE; | |
| 409 | gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); | |
| 410 | gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
| 411 | node = g_value_get_pointer(&val); | |
| 412 | ||
| 413 | if (GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
| 414 | int scr_w,scr_h, w, h, x, y; | |
| 415 | PangoLayout *layout; | |
| 416 | struct buddy *buddy = (struct buddy*)node; | |
| 417 | char *tooltiptext = gaim_get_tooltip_text(buddy); | |
| 418 | gtkblist->tipwindow = gtk_window_new(GTK_WINDOW_POPUP); | |
| 419 | gtk_widget_set_app_paintable(gtkblist->tipwindow, TRUE); | |
| 4729 | 420 | gtk_window_set_resizable(GTK_WINDOW(gtkblist->tipwindow), FALSE); |
| 4724 | 421 | gtk_widget_set_name(gtkblist->tipwindow, "gtk-tooltips"); |
| 422 | g_signal_connect(G_OBJECT(gtkblist->tipwindow), "expose_event", | |
| 423 | G_CALLBACK(gaim_gtk_blist_paint_tip), buddy); | |
| 424 | gtk_widget_ensure_style (gtkblist->tipwindow); | |
| 425 | ||
| 426 | layout = gtk_widget_create_pango_layout (gtkblist->tipwindow, NULL); | |
| 4733 | 427 | pango_layout_set_wrap(layout, PANGO_WRAP_WORD); |
| 428 | pango_layout_set_width(layout, 300000); | |
| 4724 | 429 | pango_layout_set_markup(layout, tooltiptext, strlen(tooltiptext)); |
| 430 | scr_w = gdk_screen_width(); | |
| 431 | scr_h = gdk_screen_height(); | |
| 432 | pango_layout_get_size (layout, &w, &h); | |
| 433 | w = PANGO_PIXELS(w) + 8; | |
| 434 | h = PANGO_PIXELS(h) + 8; | |
| 435 | ||
| 436 | /* 38 is the size of a large status icon plus 4 pixels padding on each side. | |
| 437 | I should #define this or something */ | |
| 438 | w = w + 38; | |
| 439 | h = MAX(h, 38); | |
| 440 | ||
| 441 | gdk_window_get_pointer(NULL, &x, &y, NULL); | |
| 442 | if (GTK_WIDGET_NO_WINDOW(gtkblist->window)) | |
| 443 | y+=gtkblist->window->allocation.y; | |
| 444 | ||
| 445 | x -= ((w >> 1) + 4); | |
| 446 | ||
| 447 | if ((x + w) > scr_w) | |
| 448 | x -= (x + w) - scr_w; | |
| 449 | else if (x < 0) | |
| 450 | x = 0; | |
| 451 | ||
| 452 | if ((y + h + 4) > scr_h) | |
| 453 | y = y - h; | |
| 454 | else | |
| 455 | y = y + 6; | |
| 456 | g_object_unref (layout); | |
| 457 | g_free(tooltiptext); | |
| 458 | gtk_widget_set_size_request(gtkblist->tipwindow, w, h); | |
| 4729 | 459 | gtk_window_move(GTK_WINDOW(gtkblist->tipwindow), x, y); |
| 4724 | 460 | gtk_widget_show(gtkblist->tipwindow); |
| 461 | } | |
| 4729 | 462 | |
| 4724 | 463 | gtk_tree_path_free(path); |
| 464 | return FALSE; | |
| 465 | } | |
| 466 | ||
| 4730 | 467 | static gboolean gaim_gtk_blist_motion_cb (GtkWidget *tv, GdkEventMotion *event, gpointer null) |
| 4724 | 468 | { |
| 469 | GtkTreePath *path; | |
| 470 | ||
| 471 | if (gtkblist->timeout) { | |
| 472 | if ((event->y > gtkblist->rect.y) && ((event->y - gtkblist->rect.height) < gtkblist->rect.y)) | |
| 4732 | 473 | return FALSE; |
| 4724 | 474 | /* We've left the cell. Remove the timeout and create a new one below */ |
| 475 | if (gtkblist->tipwindow) { | |
| 476 | gtk_widget_destroy(gtkblist->tipwindow); | |
| 477 | gtkblist->tipwindow = NULL; | |
| 478 | } | |
| 479 | ||
| 480 | g_source_remove(gtkblist->timeout); | |
| 481 | } | |
| 482 | ||
| 483 | gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), event->x, event->y, &path, NULL, NULL, NULL); | |
| 484 | gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, >kblist->rect); | |
| 485 | if (path) | |
| 486 | gtk_tree_path_free(path); | |
| 487 | gtkblist->timeout = g_timeout_add(500, (GSourceFunc)gaim_gtk_blist_tooltip_timeout, tv); | |
| 4730 | 488 | return FALSE; |
| 4724 | 489 | } |
| 490 | ||
| 491 | static void gaim_gtk_blist_leave_cb (GtkWidget *w, GdkEventCrossing *e, gpointer n) | |
| 492 | { | |
| 493 | if (gtkblist->timeout == 0) | |
| 494 | return; | |
| 495 | if (gtkblist->tipwindow) { | |
| 496 | gtk_widget_destroy(gtkblist->tipwindow); | |
| 497 | gtkblist->tipwindow = NULL; | |
| 498 | } | |
| 499 | g_source_remove(gtkblist->timeout); | |
| 500 | gtkblist->timeout = 0; | |
| 501 | } | |
| 502 | ||
| 4687 | 503 | /*************************************************** |
| 504 | * Crap * | |
| 505 | ***************************************************/ | |
| 506 | static GtkItemFactoryEntry blist_menu[] = | |
| 1929 | 507 | { |
| 4687 | 508 | /* Buddies menu */ |
| 509 | { N_("/_Buddies"), NULL, NULL, 0, "<Branch>" }, | |
| 510 | { N_("/Buddies/_Add A Buddy..."), "<CTL>B", gaim_gtk_blist_add_buddy_cb, 0, | |
| 511 | "<StockItem>", GTK_STOCK_ADD }, | |
| 512 | { N_("/Buddies/New _Instant Message..."), "<CTL>I", show_im_dialog, 0, | |
| 513 | "<StockItem>", GAIM_STOCK_IM }, | |
| 514 | { N_("/Buddies/Join a _Chat..."), "<CTL>C", join_chat, 0, | |
| 515 | "<StockItem>", GAIM_STOCK_CHAT }, | |
| 516 | { N_("/Buddies/sep1"), NULL, NULL, 0, "<Separator>" }, | |
| 517 | { N_("/Buddies/Get _User Info..."), "<CTL>J", show_info_dialog, 0, | |
| 518 | "<StockItem>", GAIM_STOCK_INFO }, | |
| 519 | { N_("/Buddies/sep2"), NULL, NULL, 0, "<Separator>" }, | |
| 520 | { N_("/Buddies/_Signoff"), "<CTL>D", signoff_all, 0, NULL }, | |
| 521 | { N_("/Buddies/_Quit"), "<CTL>Q", do_quit, 0, | |
| 522 | "<StockItem>", GTK_STOCK_QUIT }, | |
| 1929 | 523 | |
| 4687 | 524 | /* Tools */ |
| 525 | { N_("/_Tools"), NULL, NULL, 0, "<Branch>" }, | |
| 526 | { N_("/Tools/_Away"), NULL, NULL, 0, "<Branch>" }, | |
| 527 | { N_("/Tools/Buddy _Pounce"), NULL, NULL, 0, "<Branch>" }, | |
| 528 | { N_("/Tools/sep1"), NULL, NULL, 0, "<Separator>" }, | |
| 529 | { N_("/Tools/A_ccounts"), "<CTL>A", account_editor, 0, NULL }, | |
| 4694 | 530 | { N_("/Tools/Preferences"), "<CTL>P", show_prefs, 0, |
| 4687 | 531 | "<StockItem>", GTK_STOCK_PREFERENCES }, |
| 4698 | 532 | { N_("/Tools/_File Transfers"), NULL, gaim_show_xfer_dialog, 0, |
| 4687 | 533 | "<StockItem>", GTK_STOCK_REVERT_TO_SAVED }, |
| 534 | { N_("/Tools/sep2"), NULL, NULL, 0, "<Separator>" }, | |
| 535 | { N_("/Tools/P_rotocol Actions"), NULL, NULL, 0, "<Branch>" }, | |
| 536 | { N_("/Tools/Pr_ivacy"), NULL, show_privacy_options, 0, NULL }, | |
| 4697 | 537 | { N_("/Tools/View System _Log"), NULL, gtk_blist_show_systemlog_cb, 0, NULL }, |
|
3251
360fb695996d
[gaim-migrate @ 3269]
Jim Seymour <jseymour@users.sourceforge.net>
parents:
3204
diff
changeset
|
538 | |
| 4687 | 539 | /* Help */ |
| 540 | { N_("/_Help"), NULL, NULL, 0, "<Branch>" }, | |
| 541 | { N_("/Help/Online _Help"), "F1", NULL, 0, | |
| 542 | "<StockItem>", GTK_STOCK_HELP }, | |
|
4755
64ee7fb9cdba
[gaim-migrate @ 5072]
Mark Doliner <markdoliner@pidgin.im>
parents:
4745
diff
changeset
|
543 | { N_("/Help/_Debug Window"), NULL, toggle_debug, 0, NULL }, |
| 4687 | 544 | { N_("/Help/_About"), NULL, show_about, 0, NULL }, |
| 545 | ||
| 546 | }; | |
| 1929 | 547 | |
| 4687 | 548 | /********************************************************* |
| 549 | * Private Utility functions * | |
| 550 | *********************************************************/ | |
| 551 | ||
| 4724 | 552 | static char *gaim_get_tooltip_text(struct buddy *b) |
| 553 | { | |
| 554 | char *text = NULL; | |
| 555 | struct prpl* prpl = find_prpl(b->account->protocol); | |
| 556 | char *statustext = NULL; | |
| 557 | char *warning = NULL, *idletime = NULL; | |
| 558 | ||
| 559 | if (prpl->tooltip_text) { | |
| 4732 | 560 | statustext = prpl->tooltip_text(b); |
| 4724 | 561 | } |
| 4732 | 562 | |
| 4724 | 563 | if (b->idle) { |
| 564 | int ihrs, imin; | |
| 565 | time_t t; | |
| 566 | time(&t); | |
| 567 | ihrs = (t - b->idle) / 3600; | |
| 568 | imin = ((t - b->idle) / 60) % 60; | |
| 569 | if (ihrs) | |
| 4744 | 570 | idletime = g_strdup_printf(_("%dh%02dm"), ihrs, imin); |
| 4724 | 571 | else |
| 4744 | 572 | idletime = g_strdup_printf(_("%dm"), imin); |
| 4724 | 573 | } |
| 4732 | 574 | |
| 4724 | 575 | if (b->evil > 0) |
| 4744 | 576 | warning = g_strdup_printf(_("%d%%"), b->evil); |
| 4732 | 577 | |
| 4724 | 578 | text = g_strdup_printf("<span size='larger' weight='bold'>%s</span>" |
| 4744 | 579 | "%s %s" /* Alias */ |
| 580 | "%s %s" /* Nickname */ | |
| 581 | "%s %s" /* Idle */ | |
| 582 | "%s %s" /* Warning */ | |
| 4741 | 583 | "%s%s", /* Status */ |
| 4724 | 584 | b->name, |
| 4744 | 585 | b->alias && b->alias[0] ? _("\n<b>Alias:</b>") : "", b->alias ? b->alias : "", |
| 586 | b->server_alias ? _("\n<b>Nickname:</b>") : "", b->server_alias ? b->server_alias : "", | |
| 587 | b->idle ? _("\n<b>Idle:</b>") : "", b->idle ? idletime : "", | |
| 588 | b->evil ? _("\n<b>Warned:</b>") : "", b->evil ? warning : "", | |
| 4724 | 589 | statustext ? "\n" : "", statustext ? statustext : ""); |
| 4737 | 590 | if(warning) |
| 591 | g_free(warning); | |
| 592 | if(idletime) | |
| 593 | g_free(idletime); | |
| 594 | if(statustext) | |
| 595 | g_free(statustext); | |
| 596 | ||
| 4724 | 597 | return text; |
| 598 | ||
| 599 | } | |
| 600 | ||
| 601 | static GdkPixbuf *gaim_gtk_blist_get_status_icon(struct buddy *b, GaimStatusIconSize size) | |
| 4687 | 602 | { |
| 603 | GdkPixbuf *status = NULL; | |
| 604 | GdkPixbuf *scale = NULL; | |
| 605 | GdkPixbuf *emblem = NULL; | |
| 4737 | 606 | gchar *filename = NULL; |
| 4687 | 607 | const char *protoname = NULL; |
| 1929 | 608 | |
| 4691 | 609 | char *se = NULL, *sw = NULL ,*nw = NULL ,*ne = NULL; |
| 4737 | 610 | |
| 4687 | 611 | int scalesize = 30; |
| 612 | ||
| 613 | struct prpl* prpl = find_prpl(b->account->protocol); | |
| 614 | if (prpl->list_icon) | |
| 615 | protoname = prpl->list_icon(b->account, b); | |
| 616 | if (prpl->list_emblems) | |
| 617 | prpl->list_emblems(b, &se, &sw, &nw, &ne); | |
| 4737 | 618 | |
| 4724 | 619 | if (size == GAIM_STATUS_ICON_SMALL) { |
| 4687 | 620 | scalesize = 15; |
| 621 | sw = nw = ne = NULL; /* So that only the se icon will composite */ | |
| 1929 | 622 | } |
| 623 | ||
| 4701 | 624 | |
| 4687 | 625 | if (b->present == 2) { |
| 4701 | 626 | struct gaim_gtk_blist_node *gtknode; |
| 4687 | 627 | /* If b->present is 2, that means this buddy has just signed on. We use the "login" icon for the |
| 628 | * status, and we set a timeout to change it to a normal icon after 10 seconds. */ | |
| 629 | filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "login.png", NULL); | |
| 630 | status = gdk_pixbuf_new_from_file(filename,NULL); | |
| 631 | g_free(filename); | |
| 4701 | 632 | |
| 633 | gtknode = GAIM_GTK_BLIST_NODE((GaimBlistNode*)b); | |
|
4773
1cc75c5e16b0
[gaim-migrate @ 5092]
Mark Doliner <markdoliner@pidgin.im>
parents:
4770
diff
changeset
|
634 | if (gtknode->timer > 0) |
|
1cc75c5e16b0
[gaim-migrate @ 5092]
Mark Doliner <markdoliner@pidgin.im>
parents:
4770
diff
changeset
|
635 | g_source_remove(gtknode->timer); |
| 4701 | 636 | gtknode->timer = g_timeout_add(10000, (GSourceFunc)gaim_reset_present_icon, b); |
| 637 | ||
| 4737 | 638 | /* "Hey, what's all this crap?" you ask. Status icons will be themeable too, and |
| 4687 | 639 | then it will look up protoname from the theme */ |
| 640 | } else { | |
| 641 | char *image = g_strdup_printf("%s.png", protoname); | |
| 642 | filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
| 643 | status = gdk_pixbuf_new_from_file(filename,NULL); | |
| 644 | g_free(image); | |
| 645 | g_free(filename); | |
| 1929 | 646 | |
| 4687 | 647 | } |
| 4737 | 648 | |
| 4687 | 649 | if (!status) |
| 650 | return NULL; | |
| 4737 | 651 | |
| 4687 | 652 | scale = gdk_pixbuf_scale_simple(status, scalesize, scalesize, GDK_INTERP_BILINEAR); |
| 4737 | 653 | |
| 654 | g_object_unref(G_OBJECT(status)); | |
| 655 | ||
| 4687 | 656 | /* Emblems */ |
| 4737 | 657 | |
| 4687 | 658 | /* Each protocol can specify up to four "emblems" to composite over the base icon. "away", "busy", "mobile user" |
| 659 | * are all examples of states represented by emblems. I'm not even really sure I like this yet. */ | |
| 4737 | 660 | |
| 4687 | 661 | /* XXX Clean this crap up, yo. */ |
| 662 | if (se) { | |
| 663 | char *image = g_strdup_printf("%s.png", se); | |
| 664 | filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
| 665 | g_free(image); | |
| 666 | emblem = gdk_pixbuf_new_from_file(filename,NULL); | |
| 667 | g_free(filename); | |
| 668 | if (emblem) { | |
| 4724 | 669 | if (size == GAIM_STATUS_ICON_LARGE) |
| 4687 | 670 | gdk_pixbuf_composite (emblem, |
| 671 | scale, 15, 15, | |
| 672 | 15, 15, | |
| 673 | 15, 15, | |
| 674 | 1, 1, | |
| 675 | GDK_INTERP_BILINEAR, | |
| 676 | 255); | |
| 677 | else | |
| 678 | gdk_pixbuf_composite (emblem, | |
| 679 | scale, 0, 0, | |
| 680 | 15, 15, | |
| 681 | 0, 0, | |
| 682 | 1, 1, | |
| 683 | GDK_INTERP_BILINEAR, | |
| 684 | 255); | |
| 4737 | 685 | g_object_unref(G_OBJECT(emblem)); |
| 4687 | 686 | } |
| 687 | } | |
| 688 | if (sw) { | |
| 689 | char *image = g_strdup_printf("%s.png", sw); | |
| 690 | filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
| 691 | g_free(image); | |
| 692 | emblem = gdk_pixbuf_new_from_file(filename,NULL); | |
| 693 | g_free(filename); | |
| 694 | if (emblem) { | |
| 4737 | 695 | gdk_pixbuf_composite (emblem, |
| 696 | scale, 0, 15, | |
| 697 | 15, 15, | |
| 698 | 0, 15, | |
| 699 | 1, 1, | |
| 700 | GDK_INTERP_BILINEAR, | |
| 701 | 255); | |
| 702 | g_object_unref(G_OBJECT(emblem)); | |
| 4687 | 703 | } |
| 704 | } | |
| 705 | if (nw) { | |
| 706 | char *image = g_strdup_printf("%s.png", nw); | |
| 707 | filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
| 708 | g_free(image); | |
| 709 | emblem = gdk_pixbuf_new_from_file(filename,NULL); | |
| 710 | g_free(filename); | |
| 711 | if (emblem) { | |
| 712 | gdk_pixbuf_composite (emblem, | |
| 713 | scale, 0, 0, | |
| 714 | 15, 15, | |
| 715 | 0, 0, | |
| 716 | 1, 1, | |
| 717 | GDK_INTERP_BILINEAR, | |
| 718 | 255); | |
| 4737 | 719 | g_object_unref(G_OBJECT(emblem)); |
| 4687 | 720 | } |
| 721 | } | |
| 722 | if (ne) { | |
| 723 | char *image = g_strdup_printf("%s.png", ne); | |
| 724 | filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
| 725 | g_free(image); | |
| 726 | emblem = gdk_pixbuf_new_from_file(filename,NULL); | |
| 727 | g_free(filename); | |
| 728 | if (emblem) { | |
| 729 | gdk_pixbuf_composite (emblem, | |
| 730 | scale, 15, 0, | |
| 731 | 15, 15, | |
| 732 | 15, 0, | |
| 733 | 1, 1, | |
| 734 | GDK_INTERP_BILINEAR, | |
| 735 | 255); | |
| 736 | } | |
| 4737 | 737 | } |
| 4687 | 738 | |
| 4737 | 739 | |
| 4718 | 740 | /* Idle grey buddies affects the whole row. This converts the status icon to greyscale. */ |
| 4699 | 741 | if (b->idle && blist_options & OPT_BLIST_GREY_IDLERS) |
| 4687 | 742 | gdk_pixbuf_saturate_and_pixelate(scale, scale, 0, FALSE); |
| 743 | return scale; | |
| 1 | 744 | } |
| 745 | ||
| 4737 | 746 | static GdkPixbuf *gaim_gtk_blist_get_buddy_icon(struct buddy *b) |
| 1 | 747 | { |
| 4687 | 748 | /* This just opens a file from ~/.gaim/icons/screenname. This needs to change to be more gooder. */ |
| 4737 | 749 | char *file; |
| 750 | GdkPixbuf *buf, *ret; | |
| 751 | ||
| 4687 | 752 | if (!(blist_options & OPT_BLIST_SHOW_ICONS)) |
| 753 | return NULL; | |
| 4737 | 754 | |
| 4757 | 755 | if ((file = gaim_buddy_get_setting(b, "buddy_icon")) == NULL) |
| 756 | return NULL; | |
| 757 | ||
| 4737 | 758 | buf = gdk_pixbuf_new_from_file(file, NULL); |
| 759 | g_free(file); | |
| 760 | ||
| 761 | ||
| 4687 | 762 | if (buf) { |
| 4699 | 763 | if (b->idle && blist_options & OPT_BLIST_GREY_IDLERS) { |
| 4687 | 764 | gdk_pixbuf_saturate_and_pixelate(buf, buf, 0, FALSE); |
|
2372
c24942700dfd
[gaim-migrate @ 2385]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
2334
diff
changeset
|
765 | } |
| 4737 | 766 | ret = gdk_pixbuf_scale_simple(buf,30,30, GDK_INTERP_BILINEAR); |
| 767 | g_object_unref(G_OBJECT(buf)); | |
| 768 | return ret; | |
|
2372
c24942700dfd
[gaim-migrate @ 2385]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
2334
diff
changeset
|
769 | } |
| 4687 | 770 | return NULL; |
| 2986 | 771 | } |
| 772 | ||
| 4687 | 773 | static gchar *gaim_gtk_blist_get_name_markup(struct buddy *b) |
| 1 | 774 | { |
| 4687 | 775 | char *name = gaim_get_buddy_alias(b); |
| 776 | char *esc = g_markup_escape_text(name, strlen(name)), *text = NULL; | |
| 4722 | 777 | struct prpl* prpl = find_prpl(b->account->protocol); |
| 778 | ||
| 4687 | 779 | /* XXX Clean up this crap */ |
| 4699 | 780 | |
| 4687 | 781 | int ihrs, imin; |
| 4724 | 782 | char *idletime = NULL, *warning = NULL, *statustext = NULL; |
| 4732 | 783 | time_t t; |
|
2372
c24942700dfd
[gaim-migrate @ 2385]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
2334
diff
changeset
|
784 | |
| 4687 | 785 | if (!(blist_options & OPT_BLIST_SHOW_ICONS)) { |
| 4699 | 786 | if (b->idle > 0 && blist_options & OPT_BLIST_GREY_IDLERS) { |
| 4718 | 787 | text = g_strdup_printf("<span color='dim grey'>%s</span>", |
| 4699 | 788 | esc); |
| 4687 | 789 | g_free(esc); |
| 790 | return text; | |
| 791 | } else { | |
| 792 | return esc; | |
| 793 | } | |
| 1 | 794 | } |
| 795 | ||
| 4687 | 796 | time(&t); |
| 797 | ihrs = (t - b->idle) / 3600; | |
| 798 | imin = ((t - b->idle) / 60) % 60; | |
| 4699 | 799 | |
| 4722 | 800 | if (prpl->status_text) { |
| 4732 | 801 | char *tmp = prpl->status_text(b); |
| 802 | ||
| 803 | if(tmp) { | |
| 804 | if(strlen(tmp) > 20) | |
| 4757 | 805 | statustext = g_strdup_printf("%.20s... ", tmp); |
| 4732 | 806 | else |
| 4757 | 807 | statustext = g_strdup_printf("%s ", tmp); |
| 4732 | 808 | g_free(tmp); |
| 809 | } | |
| 4722 | 810 | } |
| 4732 | 811 | |
| 4687 | 812 | if (b->idle) { |
| 813 | if (ihrs) | |
| 4757 | 814 | idletime = g_strdup_printf(_("Idle (%dh%02dm) "), ihrs, imin); |
| 4687 | 815 | else |
| 4757 | 816 | idletime = g_strdup_printf(_("Idle (%dm) "), imin); |
| 4687 | 817 | } |
| 4757 | 818 | |
| 4687 | 819 | if (b->evil > 0) |
| 4757 | 820 | warning = g_strdup_printf(_("Warned (%d%%) "), b->evil); |
| 821 | ||
| 4699 | 822 | if (b->idle && blist_options & OPT_BLIST_GREY_IDLERS) |
| 4757 | 823 | text = g_strdup_printf("<span color='dim grey'>%s</span>\n<span color='dim grey' size='smaller'>%s%s%s</span>", |
| 4687 | 824 | esc, |
| 4722 | 825 | statustext != NULL ? statustext : "", |
| 826 | idletime != NULL ? idletime : "", | |
| 827 | warning != NULL ? warning : ""); | |
| 4687 | 828 | else |
| 4757 | 829 | text = g_strdup_printf("%s\n<span color='dim grey' size='smaller'>%s%s%s</span>", esc, |
| 4722 | 830 | statustext != NULL ? statustext : "", |
| 831 | idletime != NULL ? idletime : "", | |
| 832 | warning != NULL ? warning : ""); | |
| 833 | if (idletime) | |
| 4687 | 834 | g_free(idletime); |
| 4722 | 835 | if (warning) |
| 4687 | 836 | g_free(warning); |
| 4722 | 837 | if (statustext) |
| 838 | g_free(statustext); | |
| 4737 | 839 | if (esc) |
| 840 | g_free(esc); | |
| 4699 | 841 | |
| 4687 | 842 | return text; |
| 843 | } | |
|
2372
c24942700dfd
[gaim-migrate @ 2385]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
2334
diff
changeset
|
844 | |
| 4687 | 845 | /********************************************************************************** |
| 846 | * Public API Functions * | |
| 847 | **********************************************************************************/ | |
|
4695
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
848 | static void gaim_gtk_blist_new_list(struct gaim_buddy_list *blist) |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
849 | { |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
850 | blist->ui_data = g_new0(struct gaim_gtk_buddy_list, 1); |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
851 | } |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
852 | |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
853 | static void gaim_gtk_blist_new_node(GaimBlistNode *node) |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
854 | { |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
855 | node->ui_data = g_new0(struct gaim_gtk_blist_node, 1); |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
856 | } |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
857 | |
| 4729 | 858 | void gaim_gtk_blist_update_columns() |
| 859 | { | |
| 860 | if (blist_options & OPT_BLIST_SHOW_ICONS) { | |
| 861 | gtk_tree_view_column_set_visible(gtkblist->buddy_icon_column, TRUE); | |
| 862 | gtk_tree_view_column_set_visible(gtkblist->idle_column, FALSE); | |
| 863 | gtk_tree_view_column_set_visible(gtkblist->warning_column, FALSE); | |
| 864 | } else { | |
| 865 | gtk_tree_view_column_set_visible(gtkblist->idle_column, blist_options & OPT_BLIST_SHOW_IDLETIME); | |
| 866 | gtk_tree_view_column_set_visible(gtkblist->warning_column, blist_options & OPT_BLIST_SHOW_WARN); | |
| 867 | gtk_tree_view_column_set_visible(gtkblist->buddy_icon_column, FALSE); | |
| 868 | } | |
| 869 | } | |
| 870 | ||
| 4702 | 871 | enum {DRAG_BUDDY, DRAG_ROW}; |
| 872 | ||
| 4687 | 873 | static void gaim_gtk_blist_show(struct gaim_buddy_list *list) |
| 874 | { | |
| 875 | GtkItemFactory *ift; | |
| 876 | GtkCellRenderer *rend; | |
| 877 | GtkTreeViewColumn *column; | |
| 878 | GtkWidget *sw; | |
| 879 | GtkWidget *button; | |
| 4694 | 880 | GtkSizeGroup *sg; |
| 4729 | 881 | GtkTargetEntry gte[] = {{"GAIM_BUDDY", GTK_TARGET_SAME_APP, DRAG_ROW}, |
| 4702 | 882 | {"application/x-im-contact", 0, DRAG_BUDDY}}; |
| 4690 | 883 | |
| 4745 | 884 | if (gtkblist && gtkblist->window) { |
| 4687 | 885 | gtk_widget_show(gtkblist->window); |
| 886 | return; | |
| 887 | } | |
| 4690 | 888 | |
|
4695
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
889 | gtkblist = GAIM_GTK_BLIST(list); |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
890 | |
| 4687 | 891 | gtkblist->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
| 892 | gtk_window_set_title(GTK_WINDOW(gtkblist->window), _("Buddy List")); | |
| 4690 | 893 | |
| 4687 | 894 | gtkblist->vbox = gtk_vbox_new(FALSE, 6); |
| 895 | gtk_container_add(GTK_CONTAINER(gtkblist->window), gtkblist->vbox); | |
| 1 | 896 | |
| 4698 | 897 | g_signal_connect(G_OBJECT(gtkblist->window), "delete_event", G_CALLBACK(gaim_gtk_blist_destroy_cb), NULL); |
| 898 | ||
| 4687 | 899 | /******************************* Menu bar *************************************/ |
| 900 | ift = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<GaimMain>", NULL); | |
| 901 | gtk_item_factory_create_items(ift, sizeof(blist_menu) / sizeof(*blist_menu), | |
| 902 | blist_menu, NULL); | |
| 903 | gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtk_item_factory_get_widget(ift, "<GaimMain>"), FALSE, FALSE, 0); | |
| 1 | 904 | |
| 4694 | 905 | awaymenu = gtk_item_factory_get_widget(ift, "/Tools/Away"); |
| 906 | do_away_menu(); | |
| 907 | ||
| 4696 | 908 | bpmenu = gtk_item_factory_get_widget(ift, "/Tools/Buddy Pounce"); |
| 909 | do_bp_menu(); | |
| 910 | ||
| 911 | protomenu = gtk_item_factory_get_widget(ift, "/Tools/Protocol Actions"); | |
| 912 | do_proto_menu(); | |
| 913 | ||
| 4687 | 914 | /****************************** GtkTreeView **********************************/ |
| 915 | sw = gtk_scrolled_window_new(NULL,NULL); | |
| 916 | gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN); | |
| 917 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
| 4690 | 918 | gtk_widget_set_size_request(sw, 200, 200); |
| 4687 | 919 | |
| 4729 | 920 | gtkblist->treemodel = gtk_tree_store_new(BLIST_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, |
| 4687 | 921 | G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_POINTER); |
| 4702 | 922 | |
| 4687 | 923 | gtkblist->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(gtkblist->treemodel)); |
| 4704 | 924 | |
| 4702 | 925 | /* Set up dnd */ |
| 926 | gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(gtkblist->treeview), GDK_BUTTON1_MASK, gte, | |
| 927 | 2, GDK_ACTION_COPY); | |
| 4704 | 928 | gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(gtkblist->treeview), gte, 2, |
| 4702 | 929 | GDK_ACTION_COPY | GDK_ACTION_MOVE); |
| 4704 | 930 | g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-data-received", G_CALLBACK(gaim_gtk_blist_drag_data_rcv_cb), NULL); |
| 931 | g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-data-get", G_CALLBACK(gaim_gtk_blist_drag_data_get_cb), NULL); | |
| 932 | ||
| 4724 | 933 | /* Tooltips */ |
| 934 | g_signal_connect(G_OBJECT(gtkblist->treeview), "motion-notify-event", G_CALLBACK(gaim_gtk_blist_motion_cb), NULL); | |
| 935 | g_signal_connect(G_OBJECT(gtkblist->treeview), "leave-notify-event", G_CALLBACK(gaim_gtk_blist_leave_cb), NULL); | |
| 4687 | 936 | |
| 937 | gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(gtkblist->treeview), FALSE); | |
| 1 | 938 | |
| 4687 | 939 | rend = gtk_cell_renderer_pixbuf_new(); |
| 940 | column = gtk_tree_view_column_new_with_attributes("Status", rend, "pixbuf", STATUS_ICON_COLUMN, NULL); | |
| 941 | gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), column); | |
| 4716 | 942 | g_object_set(rend, "ypad", 0.0, NULL); |
| 4706 | 943 | |
| 4687 | 944 | rend = gtk_cell_renderer_text_new(); |
| 945 | column = gtk_tree_view_column_new_with_attributes("Name", rend, "markup", NAME_COLUMN, NULL); | |
| 946 | gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), column); | |
| 4706 | 947 | g_object_set(rend, "ypad", 0.0, NULL); |
| 948 | ||
| 4687 | 949 | rend = gtk_cell_renderer_text_new(); |
| 4725 | 950 | gtkblist->warning_column = gtk_tree_view_column_new_with_attributes("Warning", rend, "markup", WARNING_COLUMN, NULL); |
| 951 | gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), gtkblist->warning_column); | |
| 4716 | 952 | g_object_set(rend, "xalign", 1.0, "ypad", 0.0, NULL); |
| 4687 | 953 | |
| 954 | rend = gtk_cell_renderer_text_new(); | |
| 4725 | 955 | gtkblist->idle_column = gtk_tree_view_column_new_with_attributes("Idle", rend, "markup", IDLE_COLUMN, NULL); |
| 956 | gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), gtkblist->idle_column); | |
| 4716 | 957 | g_object_set(rend, "xalign", 1.0, "ypad", 0.0, NULL); |
| 1 | 958 | |
| 4687 | 959 | rend = gtk_cell_renderer_pixbuf_new(); |
| 4725 | 960 | gtkblist->buddy_icon_column = gtk_tree_view_column_new_with_attributes("Buddy Icon", rend, "pixbuf", BUDDY_ICON_COLUMN, NULL); |
| 4706 | 961 | g_object_set(rend, "xalign", 1.0, "ypad", 0.0, NULL); |
| 4725 | 962 | gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), gtkblist->buddy_icon_column); |
| 4718 | 963 | |
| 4687 | 964 | g_signal_connect(G_OBJECT(gtkblist->treeview), "row-activated", G_CALLBACK(gtk_blist_row_activated_cb), NULL); |
| 965 | g_signal_connect(G_OBJECT(gtkblist->treeview), "button-press-event", G_CALLBACK(gtk_blist_button_press_cb), NULL); | |
|
2372
c24942700dfd
[gaim-migrate @ 2385]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
2334
diff
changeset
|
966 | |
| 4687 | 967 | gtk_box_pack_start(GTK_BOX(gtkblist->vbox), sw, TRUE, TRUE, 0); |
| 968 | gtk_container_add(GTK_CONTAINER(sw), gtkblist->treeview); | |
| 4725 | 969 | gaim_gtk_blist_update_columns(); |
| 4687 | 970 | /**************************** Button Box **************************************/ |
| 4694 | 971 | |
| 972 | sg = gtk_size_group_new(GTK_SIZE_GROUP_BOTH); | |
| 4687 | 973 | gtkblist->bbox = gtk_hbox_new(TRUE, 0); |
| 974 | gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->bbox, FALSE, FALSE, 0); | |
| 975 | button = gaim_pixbuf_button_from_stock(_("IM"), GAIM_STOCK_IM, GAIM_BUTTON_VERTICAL); | |
| 976 | gtk_box_pack_start(GTK_BOX(gtkblist->bbox), button, FALSE, FALSE, 0); | |
| 977 | gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
| 4694 | 978 | gtk_size_group_add_widget(sg, button); |
| 4692 | 979 | g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_blist_button_im_cb), |
| 4697 | 980 | gtkblist->treeview); |
| 981 | ||
| 4687 | 982 | button = gaim_pixbuf_button_from_stock(_("Get Info"), GAIM_STOCK_INFO, GAIM_BUTTON_VERTICAL); |
| 983 | gtk_box_pack_start(GTK_BOX(gtkblist->bbox), button, FALSE, FALSE, 0); | |
| 984 | gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
| 4694 | 985 | gtk_size_group_add_widget(sg, button); |
| 986 | g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_blist_button_info_cb), | |
| 4697 | 987 | gtkblist->treeview); |
| 4729 | 988 | |
| 4687 | 989 | button = gaim_pixbuf_button_from_stock(_("Chat"), GAIM_STOCK_CHAT, GAIM_BUTTON_VERTICAL); |
| 990 | gtk_box_pack_start(GTK_BOX(gtkblist->bbox), button, FALSE, FALSE, 0); | |
| 991 | gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
| 4694 | 992 | gtk_size_group_add_widget(sg, button); |
| 993 | g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_blist_button_chat_cb), NULL); | |
| 994 | ||
| 4687 | 995 | button = gaim_pixbuf_button_from_stock(_("Away"), GAIM_STOCK_AWAY, GAIM_BUTTON_VERTICAL); |
| 996 | gtk_box_pack_start(GTK_BOX(gtkblist->bbox), button, FALSE, FALSE, 0); | |
| 997 | gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
| 4694 | 998 | gtk_size_group_add_widget(sg, button); |
| 999 | g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_blist_button_away_cb), NULL); | |
| 4687 | 1000 | |
| 1001 | /* OK... let's show this bad boy. */ | |
| 1002 | gaim_gtk_blist_refresh(list); | |
| 1003 | gtk_widget_show_all(gtkblist->window); | |
| 4729 | 1004 | |
| 4697 | 1005 | gaim_gtk_blist_update_toolbar(); |
| 1006 | ||
| 4687 | 1007 | } |
|
2372
c24942700dfd
[gaim-migrate @ 2385]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
2334
diff
changeset
|
1008 | |
| 4687 | 1009 | void gaim_gtk_blist_refresh(struct gaim_buddy_list *list) |
| 1010 | { | |
| 1011 | GaimBlistNode *group = list->root; | |
| 1012 | GaimBlistNode *buddy; | |
| 4690 | 1013 | |
| 4687 | 1014 | while (group) { |
| 1015 | gaim_gtk_blist_update(list, group); | |
| 1016 | buddy = group->child; | |
| 1017 | while (buddy) { | |
| 4699 | 1018 | gaim_gtk_blist_update(list, buddy); |
| 4687 | 1019 | buddy = buddy->next; |
| 1020 | } | |
| 1021 | group = group->next; | |
| 1022 | } | |
| 1023 | } | |
| 1 | 1024 | |
| 4699 | 1025 | static gboolean get_iter_from_node_helper(GaimBlistNode *node, GtkTreeIter *iter, GtkTreeIter *root) { |
| 1026 | do { | |
| 1027 | GaimBlistNode *n; | |
| 1028 | GtkTreeIter child; | |
| 1029 | ||
| 1030 | gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), root, NODE_COLUMN, &n, -1); | |
| 1031 | if(n == node) { | |
| 1032 | *iter = *root; | |
| 1033 | return TRUE; | |
| 1034 | } | |
| 1035 | ||
| 1036 | if(gtk_tree_model_iter_children(GTK_TREE_MODEL(gtkblist->treemodel), &child, root)) { | |
| 1037 | if(get_iter_from_node_helper(node,iter,&child)) | |
| 1038 | return TRUE; | |
| 1039 | } | |
| 1040 | } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(gtkblist->treemodel), root)); | |
| 1041 | ||
| 1042 | return FALSE; | |
| 1043 | } | |
| 1044 | ||
| 1045 | static gboolean get_iter_from_node(GaimBlistNode *node, GtkTreeIter *iter) { | |
| 1046 | GtkTreeIter root; | |
| 1047 | ||
| 1048 | if (!gtkblist) | |
| 1049 | return FALSE; | |
| 1050 | ||
| 1051 | if(!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(gtkblist->treemodel), &root)) | |
| 1052 | return FALSE; | |
| 1053 | ||
| 1054 | return get_iter_from_node_helper(node, iter, &root); | |
| 1055 | } | |
| 1056 | ||
| 4697 | 1057 | void gaim_gtk_blist_update_toolbar() { |
| 1058 | if (!gtkblist) | |
| 1059 | return; | |
| 4699 | 1060 | |
| 4697 | 1061 | gtk_container_foreach(GTK_CONTAINER(gtkblist->bbox), gaim_gtk_blist_update_toolbar_icons, NULL); |
| 4699 | 1062 | |
| 4697 | 1063 | if (blist_options & OPT_BLIST_NO_BUTTONS) |
| 1064 | gtk_widget_hide(gtkblist->bbox); | |
| 1065 | else | |
| 1066 | gtk_widget_show_all(gtkblist->bbox); | |
| 1067 | } | |
| 1068 | ||
| 4701 | 1069 | static void gaim_gtk_blist_remove(struct gaim_buddy_list *list, GaimBlistNode *node) |
| 1070 | { | |
| 1071 | struct gaim_gtk_blist_node *gtknode; | |
| 1072 | GtkTreeIter iter; | |
| 1073 | ||
| 1074 | if (!node->ui_data) | |
| 1075 | return; | |
| 1076 | ||
| 1077 | gtknode = (struct gaim_gtk_blist_node *)node->ui_data; | |
| 1078 | ||
| 1079 | if (gtknode->timer > 0) { | |
| 1080 | g_source_remove(gtknode->timer); | |
| 1081 | gtknode->timer = 0; | |
| 1082 | } | |
| 1083 | ||
| 1084 | if (get_iter_from_node(node, &iter)) { | |
| 1085 | gtk_tree_store_remove(gtkblist->treemodel, &iter); | |
| 1086 | if(GAIM_BLIST_NODE_IS_BUDDY(node) && gaim_blist_get_group_online_count((struct group *)node->parent) == 0) { | |
| 1087 | GtkTreeIter groupiter; | |
| 1088 | if(get_iter_from_node(node->parent, &groupiter)) | |
| 1089 | gtk_tree_store_remove(gtkblist->treemodel, &groupiter); | |
| 1090 | } | |
| 1091 | } | |
| 1092 | } | |
| 1093 | ||
| 1094 | ||
| 4687 | 1095 | static void gaim_gtk_blist_update(struct gaim_buddy_list *list, GaimBlistNode *node) |
| 1096 | { | |
|
4695
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1097 | struct gaim_gtk_blist_node *gtknode; |
| 4699 | 1098 | GtkTreeIter iter; |
| 4687 | 1099 | gboolean expand = FALSE; |
| 4699 | 1100 | gboolean new_entry = FALSE; |
|
2372
c24942700dfd
[gaim-migrate @ 2385]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
2334
diff
changeset
|
1101 | |
| 4687 | 1102 | if (!gtkblist) |
| 1103 | return; | |
| 4699 | 1104 | |
|
4695
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1105 | gtknode = GAIM_GTK_BLIST_NODE(node); |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1106 | |
| 4690 | 1107 | |
| 4699 | 1108 | if (!get_iter_from_node(node, &iter)) { /* This is a newly added node */ |
| 1109 | new_entry = TRUE; | |
| 4687 | 1110 | if (GAIM_BLIST_NODE_IS_BUDDY(node)) { |
| 1111 | if (((struct buddy*)node)->present) { | |
| 4699 | 1112 | GtkTreeIter groupiter; |
| 1113 | GaimBlistNode *oldersibling; | |
| 1114 | GtkTreeIter oldersiblingiter; | |
| 4690 | 1115 | |
| 4699 | 1116 | if(node->parent && !get_iter_from_node(node->parent, &groupiter)) { |
| 1117 | /* This buddy's group has not yet been added. We do that here */ | |
| 4757 | 1118 | GdkPixbuf *groupicon = gtk_widget_render_icon(gtkblist->treeview, |
| 1119 | GTK_STOCK_OPEN, GTK_ICON_SIZE_SMALL_TOOLBAR, NULL); | |
| 4687 | 1120 | char *mark = g_strdup_printf("<span weight='bold'>%s</span>", ((struct group*)node->parent)->name); |
| 4699 | 1121 | oldersibling = node->parent->prev; |
|
2372
c24942700dfd
[gaim-migrate @ 2385]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
2334
diff
changeset
|
1122 | |
| 4687 | 1123 | /* We traverse backwards through the buddy list to find the node in the tree to insert it after */ |
| 4699 | 1124 | while (oldersibling && !get_iter_from_node(oldersibling, &oldersiblingiter)) |
| 1125 | oldersibling = oldersibling->prev; | |
| 4690 | 1126 | |
| 4687 | 1127 | /* This is where we create the node and add it. */ |
| 4699 | 1128 | gtk_tree_store_insert_after(gtkblist->treemodel, &groupiter, NULL, oldersibling ? &oldersiblingiter : NULL); |
| 1129 | gtk_tree_store_set(gtkblist->treemodel, &groupiter, | |
| 4757 | 1130 | STATUS_ICON_COLUMN, groupicon, |
| 4687 | 1131 | NAME_COLUMN, mark, |
| 1132 | NODE_COLUMN, node->parent, | |
| 1133 | -1); | |
|
4695
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1134 | |
| 4737 | 1135 | g_free(mark); |
| 4757 | 1136 | g_object_unref(G_OBJECT(groupicon)); |
| 4737 | 1137 | |
| 4687 | 1138 | expand = TRUE; |
| 1139 | } | |
| 4767 | 1140 | |
| 4699 | 1141 | oldersibling = node->prev; |
| 1142 | while (oldersibling && !get_iter_from_node(oldersibling, &oldersiblingiter)) | |
| 1143 | oldersibling = oldersibling->prev; | |
| 1144 | ||
| 1145 | gtk_tree_store_insert_after(gtkblist->treemodel, &iter, &groupiter, oldersibling ? &oldersiblingiter : NULL); | |
| 4767 | 1146 | |
| 1147 | if (blist_options & OPT_BLIST_POPUP) | |
| 1148 | gtk_window_present(GTK_WINDOW(gtkblist->window)); | |
| 4699 | 1149 | |
| 4687 | 1150 | if (expand) { /* expand was set to true if this is the first element added to a group. In such case |
| 1151 | * we expand the group node */ | |
| 4699 | 1152 | GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &groupiter); |
| 1153 | gtk_tree_view_expand_row(GTK_TREE_VIEW(gtkblist->treeview), path, TRUE); | |
| 4721 | 1154 | gtk_tree_path_free(path); |
| 4687 | 1155 | } |
| 4699 | 1156 | } |
| 1157 | } | |
| 1158 | } | |
|
4695
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1159 | |
| 4687 | 1160 | if (GAIM_BLIST_NODE_IS_BUDDY(node) && ((struct buddy*)node)->present) { |
| 1161 | GdkPixbuf *status, *avatar; | |
| 1162 | char *mark; | |
| 4697 | 1163 | char *warning = NULL, *idle = NULL; |
| 1164 | ||
| 4724 | 1165 | status = gaim_gtk_blist_get_status_icon((struct buddy*)node, |
| 1166 | blist_options & OPT_BLIST_SHOW_ICONS ? GAIM_STATUS_ICON_LARGE : GAIM_STATUS_ICON_SMALL); | |
| 4687 | 1167 | avatar = gaim_gtk_blist_get_buddy_icon((struct buddy*)node); |
| 1168 | mark = gaim_gtk_blist_get_name_markup((struct buddy*)node); | |
| 4697 | 1169 | |
| 4725 | 1170 | if (((struct buddy*)node)->idle > 0) { |
| 4697 | 1171 | time_t t; |
| 1172 | int ihrs, imin; | |
| 1173 | time(&t); | |
| 1174 | ihrs = (t - ((struct buddy *)node)->idle) / 3600; | |
| 1175 | imin = ((t - ((struct buddy*)node)->idle) / 60) % 60; | |
| 4718 | 1176 | if(ihrs > 0) |
| 1177 | idle = g_strdup_printf("(%d:%02d)", ihrs, imin); | |
| 1178 | else | |
| 1179 | idle = g_strdup_printf("(%d)", imin); | |
| 4697 | 1180 | } |
| 1181 | ||
| 4725 | 1182 | if (((struct buddy*)node)->evil > 0) |
| 4699 | 1183 | warning = g_strdup_printf("%d%%", ((struct buddy*)node)->evil); |
| 4725 | 1184 | |
| 4697 | 1185 | |
| 4718 | 1186 | if((blist_options & OPT_BLIST_GREY_IDLERS) |
| 1187 | && ((struct buddy *)node)->idle) { | |
| 1188 | if(warning) { | |
| 1189 | char *w2 = g_strdup_printf("<span color='dim grey'>%s</span>", | |
| 1190 | warning); | |
| 1191 | g_free(warning); | |
| 1192 | warning = w2; | |
| 1193 | } | |
| 1194 | ||
| 1195 | if(idle) { | |
| 1196 | char *i2 = g_strdup_printf("<span color='dim grey'>%s</span>", | |
| 1197 | idle); | |
| 1198 | g_free(idle); | |
| 1199 | idle = i2; | |
| 1200 | } | |
| 1201 | } | |
| 1202 | ||
| 1203 | ||
| 4699 | 1204 | gtk_tree_store_set(gtkblist->treemodel, &iter, |
| 4687 | 1205 | STATUS_ICON_COLUMN, status, |
| 1206 | NAME_COLUMN, mark, | |
| 4697 | 1207 | WARNING_COLUMN, warning, |
| 1208 | IDLE_COLUMN, idle, | |
| 4699 | 1209 | BUDDY_ICON_COLUMN, avatar, |
| 4687 | 1210 | NODE_COLUMN, node, |
| 1211 | -1); | |
| 4699 | 1212 | |
| 4687 | 1213 | g_free(mark); |
| 4697 | 1214 | if (idle) |
| 1215 | g_free(idle); | |
| 1216 | if (warning) | |
| 1217 | g_free(warning); | |
|
4695
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1218 | |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1219 | if (status != NULL) |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1220 | g_object_unref(status); |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1221 | |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1222 | if (avatar != NULL) |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1223 | g_object_unref(avatar); |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1224 | |
| 4701 | 1225 | } else if (GAIM_BLIST_NODE_IS_BUDDY(node) && !new_entry) { |
| 1226 | gaim_gtk_blist_remove(list, node); | |
| 4767 | 1227 | if (blist_options & OPT_BLIST_POPUP) |
| 1228 | gtk_window_present(GTK_WINDOW(gtkblist->window)); | |
| 4687 | 1229 | } |
| 1230 | } | |
|
2372
c24942700dfd
[gaim-migrate @ 2385]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
2334
diff
changeset
|
1231 | |
| 4687 | 1232 | static void gaim_gtk_blist_destroy(struct gaim_buddy_list *list) |
| 1233 | { | |
| 4770 | 1234 | if (!gtkblist) |
| 1235 | return; | |
| 4687 | 1236 | gtk_widget_destroy(gtkblist->window); |
| 4745 | 1237 | |
| 1238 | gtkblist->window = gtkblist->vbox = gtkblist->treeview = NULL; | |
| 1239 | gtkblist->treemodel = NULL; | |
| 1240 | gtkblist->idle_column = NULL; | |
| 1241 | gtkblist->warning_column = gtkblist->buddy_icon_column = NULL; | |
| 1242 | gtkblist->bbox = gtkblist->tipwindow = NULL; | |
| 1243 | protomenu = NULL; | |
| 1244 | awaymenu = NULL; | |
| 1245 | bpmenu = NULL; | |
| 1246 | ||
| 1247 | gtkblist->timeout = 0; | |
| 4687 | 1248 | } |
| 1 | 1249 | |
| 4687 | 1250 | static void gaim_gtk_blist_set_visible(struct gaim_buddy_list *list, gboolean show) |
| 1251 | { | |
| 4698 | 1252 | if (show) { |
| 4699 | 1253 | gtk_window_present(GTK_WINDOW(gtkblist->window)); |
| 4698 | 1254 | } else { |
| 1255 | if (!connections || docklet_count) { | |
| 1256 | #ifdef _WIN32 | |
|
4711
27aa515e4246
[gaim-migrate @ 5022]
Herman Bloggs <herman@bluedigits.com>
parents:
4706
diff
changeset
|
1257 | wgaim_systray_minimize(gtkblist->window); |
| 4698 | 1258 | #endif |
| 1259 | gtk_widget_hide(gtkblist->window); | |
| 1260 | } else { | |
| 1261 | gtk_window_iconify(GTK_WINDOW(gtkblist->window)); | |
| 1262 | } | |
| 1263 | } | |
| 1264 | } | |
| 1265 | ||
| 1266 | void gaim_gtk_blist_docklet_toggle() { | |
| 1267 | /* Useful for the docklet plugin and also for the win32 tray icon*/ | |
| 1268 | /* This is called when one of those is clicked--it will show/hide the | |
| 1269 | buddy list/login window--depending on which is active */ | |
| 1270 | if (connections && gtkblist) { | |
| 1271 | if (GTK_WIDGET_VISIBLE(gtkblist->window)) { | |
| 1272 | gaim_blist_set_visible(GAIM_WINDOW_ICONIFIED(gtkblist->window) || gaim_gtk_blist_obscured); | |
| 1273 | } else { | |
| 1274 | #if _WIN32 | |
|
4711
27aa515e4246
[gaim-migrate @ 5022]
Herman Bloggs <herman@bluedigits.com>
parents:
4706
diff
changeset
|
1275 | wgaim_systray_maximize(gtkblist->window); |
| 4698 | 1276 | #endif |
| 1277 | gaim_blist_set_visible(TRUE); | |
| 1278 | } | |
| 1279 | } else if (connections) { | |
| 1280 | /* we're logging in or something... do nothing */ | |
| 1281 | debug_printf("docklet_toggle called with connections but no blist!\n"); | |
| 1282 | } else { | |
| 1283 | if (GTK_WIDGET_VISIBLE(mainwindow)) { | |
| 1284 | if (GAIM_WINDOW_ICONIFIED(mainwindow)) { | |
| 1285 | gtk_window_present(GTK_WINDOW(mainwindow)); | |
| 1286 | } else { | |
| 1287 | #if _WIN32 | |
| 1288 | wgaim_systray_minimize(mainwindow); | |
| 1289 | #endif | |
| 1290 | gtk_widget_hide(mainwindow); | |
| 1291 | } | |
| 1292 | } else { | |
| 1293 | #if _WIN32 | |
| 1294 | wgaim_systray_maximize(mainwindow); | |
| 1295 | #endif | |
| 1296 | gtk_window_present(GTK_WINDOW(mainwindow)); | |
| 1297 | } | |
| 1298 | } | |
| 1299 | } | |
| 1300 | ||
| 1301 | void gaim_gtk_blist_docklet_add() | |
| 1302 | { | |
| 1303 | docklet_count++; | |
| 1304 | } | |
| 1305 | ||
| 1306 | void gaim_gtk_blist_docklet_remove() | |
| 1307 | { | |
| 1308 | docklet_count--; | |
| 1309 | if (!docklet_count) { | |
| 1310 | if (connections) { | |
| 1311 | gaim_blist_set_visible(TRUE); | |
| 4745 | 1312 | } else if(gtkblist && gtkblist->window) { |
| 4698 | 1313 | gtk_window_present(GTK_WINDOW(gtkblist->window)); |
| 1314 | } | |
| 1315 | } | |
| 4687 | 1316 | } |
| 1 | 1317 | |
| 4687 | 1318 | static struct gaim_blist_ui_ops blist_ui_ops = |
| 1319 | { | |
|
4695
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1320 | gaim_gtk_blist_new_list, |
|
82df59fb9931
[gaim-migrate @ 5006]
Christian Hammond <chipx86@chipx86.com>
parents:
4694
diff
changeset
|
1321 | gaim_gtk_blist_new_node, |
| 4687 | 1322 | gaim_gtk_blist_show, |
| 1323 | gaim_gtk_blist_update, | |
| 1324 | gaim_gtk_blist_remove, | |
| 1325 | gaim_gtk_blist_destroy, | |
| 1326 | gaim_gtk_blist_set_visible | |
| 1327 | }; | |
| 1 | 1328 | |
| 1329 | ||
| 4687 | 1330 | struct gaim_blist_ui_ops *gaim_get_gtk_blist_ui_ops() |
|
2372
c24942700dfd
[gaim-migrate @ 2385]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
2334
diff
changeset
|
1331 | { |
| 4687 | 1332 | return &blist_ui_ops; |
|
1037
b73eadf592b1
[gaim-migrate @ 1047]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
1036
diff
changeset
|
1333 | } |
|
b73eadf592b1
[gaim-migrate @ 1047]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
1036
diff
changeset
|
1334 | |
| 3131 | 1335 | |
| 1336 | ||
| 4687 | 1337 | /********************************************************************* |
| 1338 | * Public utility functions * | |
| 1339 | *********************************************************************/ | |
|
1058
e878d758cff6
[gaim-migrate @ 1068]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
1057
diff
changeset
|
1340 | |
| 4687 | 1341 | GdkPixbuf * |
| 1342 | create_prpl_icon(struct gaim_account *account) | |
|
4553
3c1735b36327
[gaim-migrate @ 4833]
Christian Hammond <chipx86@chipx86.com>
parents:
4525
diff
changeset
|
1343 | { |
| 4687 | 1344 | struct prpl *prpl = find_prpl(account->protocol); |
| 1345 | GdkPixbuf *status = NULL; | |
| 1346 | char *filename = NULL; | |
| 1347 | const char *protoname = prpl->list_icon(account, NULL); | |
| 1348 | /* "Hey, what's all this crap?" you ask. Status icons will be themeable too, and | |
| 1349 | then it will look up protoname from the theme */ | |
| 1350 | if (!strcmp(protoname, "aim")) { | |
| 1351 | filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "aim.png", NULL); | |
| 1352 | status = gdk_pixbuf_new_from_file(filename,NULL); | |
| 1353 | g_free(filename); | |
| 1354 | } else if (!strcmp(protoname, "yahoo")) { | |
| 1355 | filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "yahoo.png", NULL); | |
| 1356 | status = gdk_pixbuf_new_from_file(filename,NULL); | |
| 1357 | g_free(filename); | |
| 1358 | } else if (!strcmp(protoname, "msn")) { | |
| 1359 | filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "msn.png", NULL); | |
| 1360 | status = gdk_pixbuf_new_from_file(filename,NULL); | |
| 1361 | g_free(filename); | |
| 1362 | } else if (!strcmp(protoname, "jabber")) { | |
| 1363 | filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "jabber.png", NULL); | |
| 1364 | status = gdk_pixbuf_new_from_file(filename,NULL); | |
| 1365 | g_free(filename); | |
| 1366 | } else if (!strcmp(protoname, "icq")) { | |
| 1367 | filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "icq.png", NULL); | |
| 1368 | status = gdk_pixbuf_new_from_file(filename,NULL); | |
| 1369 | g_free(filename); | |
| 1370 | } else if (!strcmp(protoname, "gadu-gadu")) { | |
| 1371 | filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "gadugadu.png", NULL); | |
| 1372 | status = gdk_pixbuf_new_from_file(filename,NULL); | |
| 1373 | g_free(filename); | |
| 1374 | } else if (!strcmp(protoname, "napster")) { | |
| 1375 | filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "napster.png", NULL); | |
| 1376 | status = gdk_pixbuf_new_from_file(filename,NULL); | |
| 1377 | g_free(filename); | |
| 1378 | } else if (!strcmp(protoname, "irc")) { | |
| 1379 | filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "irc.png", NULL); | |
| 1380 | status = gdk_pixbuf_new_from_file(filename,NULL); | |
| 1381 | g_free(filename); | |
|
960
c4012584334f
[gaim-migrate @ 970]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
945
diff
changeset
|
1382 | } |
| 4687 | 1383 | return status; |
| 1 | 1384 | } |
| 4699 | 1385 |