Mercurial > pidgin
annotate plugins/gevolution/gevolution.c @ 9772:5f7c81eeebd2
[gaim-migrate @ 10640]
Another ft patch from Dave West. This one makes transfers appear in the
ft dialog earlier. I'm a bit concerned that transfers might not be
removed correctly when canceled early on. Or that they won't show up
with the right status between the time they're initiated and the time
the file actually begins being transferred.
committer: Tailor Script <tailor@pidgin.im>
| author | Mark Doliner <mark@kingant.net> |
|---|---|
| date | Wed, 18 Aug 2004 04:22:31 +0000 |
| parents | a5ec9e73f46d |
| children | a09ffb82aef1 |
| rev | line source |
|---|---|
| 8089 | 1 /* |
| 2 * Evolution integration plugin for Gaim | |
| 3 * | |
| 4 * Copyright (C) 2003 Christian Hammond. | |
| 5 * | |
| 6 * This program is free software; you can redistribute it and/or | |
| 7 * modify it under the terms of the GNU General Public License as | |
| 8 * published by the Free Software Foundation; either version 2 of the | |
| 9 * License, or (at your option) any later version. | |
| 10 * | |
| 11 * This program is distributed in the hope that it will be useful, but | |
| 12 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 14 * 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 | |
| 19 * 02111-1307, USA. | |
| 20 */ | |
| 21 #include "internal.h" | |
| 22 #include "gtkinternal.h" | |
| 23 #include "gtkblist.h" | |
| 24 | |
| 25 #include "connection.h" | |
| 26 #include "debug.h" | |
| 27 #include "prefs.h" | |
| 28 #include "signals.h" | |
| 29 | |
| 30 #include "gtkconv.h" | |
| 31 #include "gtkplugin.h" | |
| 32 #include "gtkutils.h" | |
| 33 | |
| 34 #include "gevolution.h" | |
| 35 | |
| 36 #include <libedata-book/Evolution-DataServer-Addressbook.h> | |
| 37 | |
| 38 #include <libebook/e-book-listener.h> | |
| 39 #include <libedata-book/e-data-book-factory.h> | |
| 40 #include <bonobo/bonobo-main.h> | |
| 41 | |
| 42 #define GEVOLUTION_PLUGIN_ID "gtk-x11-gevolution" | |
| 43 | |
| 44 #define E_DATA_BOOK_FACTORY_OAF_ID \ | |
| 45 "OAFIID:GNOME_Evolution_DataServer_BookFactory" | |
| 46 | |
| 47 enum | |
| 48 { | |
| 49 COLUMN_AUTOADD, | |
| 50 COLUMN_ICON, | |
| 51 COLUMN_SCREENNAME, | |
| 52 COLUMN_DATA, | |
| 53 NUM_COLUMNS | |
| 54 }; | |
| 55 | |
| 56 static GaimBlistUiOps *backup_blist_ui_ops = NULL; | |
| 57 static GaimBlistUiOps *blist_ui_ops = NULL; | |
| 58 static EBook *book = NULL; | |
| 59 static gulong timer = 0; | |
| 60 static gulong book_view_tag = 0; | |
| 61 static EBookView *book_view = NULL; | |
| 62 | |
| 63 static void | |
| 64 update_ims_from_contact(EContact *contact, const char *name, | |
| 65 const char *prpl_id, EContactField field) | |
| 66 { | |
| 67 GList *ims = e_contact_get(contact, field); | |
| 68 GList *l, *l2; | |
| 69 | |
| 70 if (ims == NULL) | |
| 71 return; | |
| 72 | |
| 73 for (l = gaim_connections_get_all(); l != NULL; l = l->next) | |
| 74 { | |
| 75 GaimConnection *gc = (GaimConnection *)l->data; | |
| 76 GaimAccount *account = gaim_connection_get_account(gc); | |
| 77 | |
| 78 if (strcmp(gaim_account_get_protocol_id(account), prpl_id)) | |
| 79 continue; | |
| 80 | |
| 81 if (!gaim_account_get_bool(account, "gevo-autoadd", FALSE)) | |
| 82 continue; | |
| 83 | |
| 84 for (l2 = ims; l2 != NULL; l2 = l2->next) | |
| 85 { | |
| 86 if (gaim_find_buddy(account, l2->data) != NULL) | |
| 87 continue; | |
| 88 | |
| 89 gevo_add_buddy(account, _("Buddies"), l2->data, name); | |
| 90 } | |
| 91 } | |
| 92 | |
| 93 g_list_foreach(ims, (GFunc)g_free, NULL); | |
| 94 g_list_free(ims); | |
| 95 } | |
| 96 | |
| 97 static void | |
| 98 update_buddies_from_contact(EContact *contact) | |
| 99 { | |
| 100 const char *name; | |
| 101 | |
| 102 name = e_contact_get_const(contact, E_CONTACT_FULL_NAME); | |
| 103 | |
| 104 update_ims_from_contact(contact, name, "prpl-oscar", E_CONTACT_IM_AIM); | |
| 105 update_ims_from_contact(contact, name, "prpl-jabber", E_CONTACT_IM_JABBER); | |
| 106 update_ims_from_contact(contact, name, "prpl-yahoo", E_CONTACT_IM_YAHOO); | |
| 107 update_ims_from_contact(contact, name, "prpl-msn", E_CONTACT_IM_MSN); | |
| 108 update_ims_from_contact(contact, name, "prpl-oscar", E_CONTACT_IM_ICQ); | |
| 109 } | |
| 110 | |
| 111 static void | |
| 112 contacts_changed_cb(EBookView *book_view, const GList *contacts) | |
| 113 { | |
| 114 const GList *l; | |
| 115 | |
| 116 if (gaim_connections_get_all() == NULL) | |
| 117 return; | |
| 118 | |
| 119 for (l = contacts; l != NULL; l = l->next) | |
| 120 { | |
| 121 EContact *contact = (EContact *)l->data; | |
| 122 | |
| 123 update_buddies_from_contact(contact); | |
| 124 } | |
| 125 } | |
| 126 | |
| 127 static void | |
| 128 request_add_buddy(GaimAccount *account, const char *username, | |
| 129 const char *group, const char *alias) | |
| 130 { | |
| 131 if (book == NULL) | |
| 132 { | |
| 133 backup_blist_ui_ops->request_add_buddy(account, username, group, | |
| 134 alias); | |
| 135 } | |
| 136 else | |
| 137 { | |
| 138 gevo_add_buddy_dialog_show(account, username, group, alias); | |
| 139 } | |
| 140 } | |
| 141 | |
| 142 static void | |
| 143 got_book_view_cb(EBook *book, EBookStatus status, EBookView *view, | |
| 144 gpointer user_data) | |
| 145 { | |
| 146 book_view_tag = 0; | |
| 147 | |
| 148 if (status != E_BOOK_ERROR_OK) | |
| 149 { | |
| 150 gaim_debug_error("evolution", "Unable to retrieve book view! :(\n"); | |
| 151 | |
| 152 return; | |
| 153 } | |
| 154 | |
| 155 book_view = view; | |
| 156 | |
| 157 g_object_ref(book_view); | |
| 158 | |
| 159 g_signal_connect(G_OBJECT(book_view), "contacts_changed", | |
| 160 G_CALLBACK(contacts_changed_cb), book); | |
| 161 | |
| 162 g_signal_connect(G_OBJECT(book_view), "contacts_added", | |
| 163 G_CALLBACK(contacts_changed_cb), book); | |
| 164 | |
| 165 e_book_view_start(view); | |
| 166 } | |
| 167 | |
| 168 static void | |
| 169 signed_on_cb(GaimConnection *gc) | |
| 170 { | |
| 171 EBookQuery *query; | |
| 172 gboolean status; | |
| 173 GList *contacts; | |
| 174 GList *l; | |
| 175 | |
| 176 if (book == NULL) | |
| 177 return; | |
| 178 | |
| 179 query = e_book_query_any_field_contains(""); | |
| 180 | |
| 181 status = e_book_get_contacts(book, query, &contacts, NULL); | |
| 182 | |
| 183 e_book_query_unref(query); | |
| 184 | |
| 185 if (!status) | |
| 186 return; | |
| 187 | |
| 188 for (l = contacts; l != NULL; l = l->next) | |
| 189 { | |
| 190 EContact *contact = E_CONTACT(l->data); | |
| 191 | |
| 192 update_buddies_from_contact(contact); | |
| 193 | |
| 194 g_object_unref(contact); | |
| 195 } | |
| 196 | |
| 197 g_list_free(contacts); | |
| 198 } | |
| 199 | |
| 200 static void | |
|
9055
a243d688c93c
[gaim-migrate @ 9831]
Christian Hammond <chipx86@chipx86.com>
parents:
9051
diff
changeset
|
201 menu_item_activate_cb(GaimBlistNode *node, gpointer user_data) |
| 8089 | 202 { |
| 9051 | 203 GaimBuddy *buddy = (GaimBuddy *)node; |
| 8089 | 204 gevo_associate_buddy_dialog_new(buddy); |
| 205 } | |
| 206 | |
| 207 static void | |
| 9051 | 208 blist_node_extended_menu_cb(GaimBlistNode *node, GList **menu) |
| 8089 | 209 { |
| 9051 | 210 GaimBlistNodeAction *act; |
| 211 GaimBuddy *buddy; | |
| 8089 | 212 |
| 9051 | 213 if (!GAIM_BLIST_NODE_IS_BUDDY(node)) |
| 214 return; | |
| 215 | |
| 216 buddy = (GaimBuddy *)node; | |
| 217 | |
| 8089 | 218 if (gevo_prpl_is_supported(buddy->account, buddy)) |
| 219 { | |
| 9051 | 220 act = gaim_blist_node_action_new(_("Add to Address Book"), |
| 221 menu_item_activate_cb, NULL); | |
| 222 *menu = g_list_append(*menu, act); | |
| 8089 | 223 } |
| 224 } | |
| 225 | |
| 226 static gboolean | |
| 227 load_timeout(gpointer data) | |
| 228 { | |
| 229 GaimPlugin *plugin = (GaimPlugin *)data; | |
|
8127
96ee7b21c1ae
[gaim-migrate @ 8832]
Christian Hammond <chipx86@chipx86.com>
parents:
8089
diff
changeset
|
230 EBookQuery *query; |
| 8089 | 231 |
| 232 timer = 0; | |
| 233 | |
| 234 if (!gevo_load_addressbook(&book, NULL)) | |
| 235 return FALSE; | |
| 236 | |
|
8127
96ee7b21c1ae
[gaim-migrate @ 8832]
Christian Hammond <chipx86@chipx86.com>
parents:
8089
diff
changeset
|
237 query = e_book_query_any_field_contains(""); |
|
96ee7b21c1ae
[gaim-migrate @ 8832]
Christian Hammond <chipx86@chipx86.com>
parents:
8089
diff
changeset
|
238 |
|
96ee7b21c1ae
[gaim-migrate @ 8832]
Christian Hammond <chipx86@chipx86.com>
parents:
8089
diff
changeset
|
239 book_view_tag = e_book_async_get_book_view(book, query, NULL, -1, |
|
96ee7b21c1ae
[gaim-migrate @ 8832]
Christian Hammond <chipx86@chipx86.com>
parents:
8089
diff
changeset
|
240 got_book_view_cb, NULL); |
|
96ee7b21c1ae
[gaim-migrate @ 8832]
Christian Hammond <chipx86@chipx86.com>
parents:
8089
diff
changeset
|
241 |
|
96ee7b21c1ae
[gaim-migrate @ 8832]
Christian Hammond <chipx86@chipx86.com>
parents:
8089
diff
changeset
|
242 e_book_query_unref(query); |
| 8089 | 243 |
| 9051 | 244 gaim_signal_connect(gaim_blist_get_handle(), "blist-node-extended-menu", |
| 245 plugin, GAIM_CALLBACK(blist_node_extended_menu_cb), NULL); | |
| 8089 | 246 |
| 247 return FALSE; | |
| 248 } | |
| 249 | |
| 250 static gboolean | |
| 251 plugin_load(GaimPlugin *plugin) | |
| 252 { | |
| 253 if (!bonobo_init_full(NULL, NULL, bonobo_activation_orb_get(), | |
| 254 CORBA_OBJECT_NIL, CORBA_OBJECT_NIL)) | |
| 255 { | |
| 256 gaim_debug_error("evolution", "Unable to initialize bonobo.\n"); | |
| 257 return FALSE; | |
| 258 } | |
| 259 | |
| 260 bonobo_activate(); | |
| 261 | |
| 262 backup_blist_ui_ops = gaim_blist_get_ui_ops(); | |
| 263 | |
| 264 blist_ui_ops = g_memdup(backup_blist_ui_ops, sizeof(GaimBlistUiOps)); | |
| 265 blist_ui_ops->request_add_buddy = request_add_buddy; | |
| 266 | |
| 267 gaim_blist_set_ui_ops(blist_ui_ops); | |
| 268 | |
| 269 gaim_signal_connect(gaim_connections_get_handle(), "signed-on", | |
| 270 plugin, GAIM_CALLBACK(signed_on_cb), NULL); | |
| 271 | |
| 272 timer = g_timeout_add(1, load_timeout, plugin); | |
| 273 | |
| 274 return TRUE; | |
| 275 } | |
| 276 | |
| 277 static gboolean | |
| 278 plugin_unload(GaimPlugin *plugin) | |
| 279 { | |
| 280 gaim_blist_set_ui_ops(backup_blist_ui_ops); | |
| 281 | |
| 282 g_free(blist_ui_ops); | |
| 283 | |
| 284 backup_blist_ui_ops = NULL; | |
| 285 blist_ui_ops = NULL; | |
| 286 | |
| 287 if (book_view != NULL) | |
| 288 { | |
| 289 e_book_view_stop(book_view); | |
| 290 g_object_unref(book_view); | |
| 291 book_view = NULL; | |
| 292 } | |
| 293 | |
| 294 if (book != NULL) | |
| 295 { | |
| 296 g_object_unref(book); | |
| 297 book = NULL; | |
| 298 } | |
| 299 | |
| 300 bonobo_debug_shutdown(); | |
| 301 | |
| 302 return TRUE; | |
| 303 } | |
| 304 | |
| 305 static void | |
| 306 plugin_destroy(GaimPlugin *plugin) | |
| 307 { | |
| 308 } | |
| 309 | |
| 310 static void | |
| 311 autoadd_toggled_cb(GtkCellRendererToggle *renderer, gchar *path_str, | |
| 312 gpointer data) | |
| 313 { | |
| 314 GaimAccount *account; | |
| 315 GtkTreeModel *model = (GtkTreeModel *)data; | |
| 316 GtkTreeIter iter; | |
| 317 gboolean autoadd; | |
| 318 | |
| 319 gtk_tree_model_get_iter_from_string(model, &iter, path_str); | |
| 320 gtk_tree_model_get(model, &iter, | |
| 321 COLUMN_DATA, &account, | |
| 322 COLUMN_AUTOADD, &autoadd, | |
| 323 -1); | |
| 324 | |
| 325 gaim_account_set_bool(account, "gevo-autoadd", !autoadd); | |
| 326 | |
| 327 gtk_list_store_set(GTK_LIST_STORE(model), &iter, | |
| 328 COLUMN_AUTOADD, !autoadd, | |
| 329 -1); | |
| 330 } | |
| 331 | |
| 332 static GtkWidget * | |
| 333 get_config_frame(GaimPlugin *plugin) | |
| 334 { | |
| 335 GtkWidget *ret; | |
| 336 GtkWidget *vbox; | |
| 337 GtkWidget *label; | |
| 338 GtkWidget *sw; | |
| 339 GtkWidget *treeview; | |
| 340 GtkTreeViewColumn *column; | |
| 341 GtkCellRenderer *renderer; | |
| 342 GdkPixbuf *pixbuf, *scale = NULL; | |
| 343 GtkListStore *model; | |
| 344 GList *l; | |
| 345 | |
| 346 /* Outside container */ | |
| 347 ret = gtk_vbox_new(FALSE, 18); | |
| 348 gtk_container_set_border_width(GTK_CONTAINER(ret), 12); | |
| 349 | |
| 350 /* Configuration frame */ | |
| 351 vbox = gaim_gtk_make_frame(ret, _("Evolution Integration Configuration")); | |
| 352 | |
| 353 /* Label */ | |
| 354 label = gtk_label_new(_("Select all accounts that buddies should be " | |
| 355 "auto-added to.")); | |
| 356 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
| 357 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); | |
| 358 gtk_widget_show(label); | |
| 359 | |
| 360 /* Scrolled window */ | |
| 361 sw = gtk_scrolled_window_new(0, 0); | |
| 362 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), | |
| 363 GTK_POLICY_AUTOMATIC, | |
| 364 GTK_POLICY_ALWAYS); | |
| 365 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), | |
| 366 GTK_SHADOW_IN); | |
| 367 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); | |
| 368 gtk_widget_set_size_request(sw, 300, 300); | |
| 369 gtk_widget_show(sw); | |
| 370 | |
| 371 /* Create the list model for the treeview. */ | |
| 372 model = gtk_list_store_new(NUM_COLUMNS, | |
| 373 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, | |
| 374 G_TYPE_STRING, G_TYPE_POINTER); | |
| 375 | |
| 376 /* Setup the treeview */ | |
| 377 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model)); | |
| 378 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); | |
| 379 gtk_container_add(GTK_CONTAINER(sw), treeview); | |
| 380 gtk_widget_show(treeview); | |
| 381 | |
| 382 /* Setup the column */ | |
| 383 column = gtk_tree_view_column_new(); | |
| 384 gtk_tree_view_column_set_title(column, _("Account")); | |
| 385 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeview), column, -1); | |
| 386 | |
| 387 /* Checkbox */ | |
| 388 renderer = gtk_cell_renderer_toggle_new(); | |
| 389 | |
| 390 g_signal_connect(G_OBJECT(renderer), "toggled", | |
| 391 G_CALLBACK(autoadd_toggled_cb), model); | |
| 392 | |
| 393 gtk_tree_view_column_pack_start(column, renderer, FALSE); | |
| 394 gtk_tree_view_column_add_attribute(column, renderer, | |
| 395 "active", COLUMN_AUTOADD); | |
| 396 | |
| 397 /* Icon */ | |
| 398 renderer = gtk_cell_renderer_pixbuf_new(); | |
| 399 gtk_tree_view_column_pack_start(column, renderer, FALSE); | |
| 400 gtk_tree_view_column_add_attribute(column, renderer, | |
| 401 "pixbuf", COLUMN_ICON); | |
| 402 | |
| 403 /* Screenname */ | |
| 404 renderer = gtk_cell_renderer_text_new(); | |
| 405 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
| 406 gtk_tree_view_column_add_attribute(column, renderer, | |
| 407 "text", COLUMN_SCREENNAME); | |
| 408 | |
| 409 | |
| 410 /* Populate */ | |
| 411 for (l = gaim_accounts_get_all(); l != NULL; l = l->next) | |
| 412 { | |
| 413 GaimAccount *account = (GaimAccount *)l->data; | |
| 414 GtkTreeIter iter; | |
| 415 | |
| 416 gaim_debug_info("evolution", "Adding account\n"); | |
| 417 | |
| 418 gtk_list_store_append(model, &iter); | |
| 419 | |
| 420 pixbuf = create_prpl_icon(account); | |
| 421 | |
| 422 if (pixbuf != NULL) | |
| 423 { | |
| 424 scale = gdk_pixbuf_scale_simple(pixbuf, 16, 16, | |
| 425 GDK_INTERP_BILINEAR); | |
| 426 | |
| 427 if (!gaim_account_is_connected(account)) | |
| 428 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.0, FALSE); | |
| 429 } | |
| 430 | |
| 431 gtk_list_store_set(model, &iter, | |
| 432 COLUMN_AUTOADD, | |
| 433 gaim_account_get_bool(account, "gevo-autoadd", | |
| 434 FALSE), | |
| 435 COLUMN_ICON, scale, | |
| 436 COLUMN_SCREENNAME, | |
| 437 gaim_account_get_username(account), | |
| 438 COLUMN_DATA, account, | |
| 439 -1); | |
| 440 | |
| 441 if (pixbuf != NULL) g_object_unref(G_OBJECT(pixbuf)); | |
| 442 if (scale != NULL) g_object_unref(G_OBJECT(scale)); | |
| 443 } | |
| 444 | |
| 445 gtk_widget_show_all(ret); | |
| 446 | |
| 447 return ret; | |
| 448 } | |
| 449 | |
| 450 static GaimGtkPluginUiInfo ui_info = | |
| 451 { | |
| 452 get_config_frame | |
| 453 }; | |
| 454 | |
| 455 static GaimPluginInfo info = | |
| 456 { | |
|
8749
d7b8eb1f0a18
[gaim-migrate @ 9504]
Christian Hammond <chipx86@chipx86.com>
parents:
8127
diff
changeset
|
457 GAIM_PLUGIN_API_VERSION, /**< api_version */ |
| 8089 | 458 GAIM_PLUGIN_STANDARD, /**< type */ |
| 459 GAIM_GTK_PLUGIN_TYPE, /**< ui_requirement */ | |
| 460 0, /**< flags */ | |
| 461 NULL, /**< dependencies */ | |
| 462 GAIM_PRIORITY_DEFAULT, /**< priority */ | |
| 463 | |
| 464 GEVOLUTION_PLUGIN_ID, /**< id */ | |
| 465 N_("Evolution Integration"), /**< name */ | |
| 466 VERSION, /**< version */ | |
| 467 /** summary */ | |
| 468 N_("Provides integration with Ximian Evolution."), | |
| 469 /** description */ | |
| 470 N_("Provides integration with Ximian Evolution."), | |
| 471 "Christian Hammond <chipx86@gnupdate.org>", /**< author */ | |
| 472 GAIM_WEBSITE, /**< homepage */ | |
| 473 | |
| 474 plugin_load, /**< load */ | |
| 475 plugin_unload, /**< unload */ | |
| 476 plugin_destroy, /**< destroy */ | |
| 477 | |
| 478 &ui_info, /**< ui_info */ | |
| 8993 | 479 NULL, /**< extra_info */ |
| 480 NULL, | |
| 481 NULL | |
| 8089 | 482 }; |
| 483 | |
| 484 static void | |
| 485 init_plugin(GaimPlugin *plugin) | |
| 486 { | |
| 487 /* TODO: Change to core-remote when possible. */ | |
| 488 /* info.dependencies = g_list_append(info.dependencies, "gtk-remote"); */ | |
| 489 | |
| 490 /* | |
| 491 * I'm going to rant a little bit here... | |
| 492 * | |
| 493 * For some reason, when we init bonobo from inside a plugin, it will | |
| 494 * segfault when destroyed. The backtraces are within gmodule somewhere. | |
| 495 * There's not much I can do, and I'm not sure where the bug lies. | |
| 496 * However, plugins are only destroyed when Gaim is shutting down. After | |
| 497 * destroying the plugins, gaim ends, and anything else is of course | |
| 498 * freed. That includes this, if we make the module resident, which | |
| 499 * prevents us from being able to actually unload it. | |
| 500 * | |
| 501 * So, in conclusion, this is an evil hack, but it doesn't harm anything | |
| 502 * and it works. | |
| 503 */ | |
| 504 g_module_make_resident(plugin->handle); | |
| 505 } | |
| 506 | |
| 507 GAIM_INIT_PLUGIN(gevolution, init_plugin, info) |
