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