Mercurial > pidgin
annotate plugins/gevolution/gevolution.c @ 10234:d672afd04dcd
[gaim-migrate @ 11369]
"text replacement cosmetic change," patch 705648 from
Craig Slusher. This was submitted on 2003-03-18 and
it still basically applies. Neat.
"This just changes the way that the plugin reacts to the
'Add' button being clicked. After the replacement is
placed into the list, the text boxes are cleared and
the 'You type:' box gains focus"
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Mon, 22 Nov 2004 05:36:09 +0000 |
parents | ff4be2d1401d |
children | 54ac161a876e |
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" | |
9821 | 22 #include "gtkgaim.h" |
8089 | 23 |
24 #include "connection.h" | |
25 #include "debug.h" | |
26 #include "prefs.h" | |
27 #include "signals.h" | |
9954 | 28 #include "version.h" |
8089 | 29 |
9821 | 30 #include "gtkblist.h" |
8089 | 31 #include "gtkconv.h" |
32 #include "gtkplugin.h" | |
33 #include "gtkutils.h" | |
34 | |
35 #include "gevolution.h" | |
36 | |
37 #include <libedata-book/Evolution-DataServer-Addressbook.h> | |
38 | |
39 #include <libebook/e-book-listener.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 | |
10081
ff4be2d1401d
[gaim-migrate @ 11071]
Christian Hammond <chipx86@chipx86.com>
parents:
10055
diff
changeset
|
235 if (!gevo_load_addressbook(NULL, &book, NULL)) |
8089 | 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 bonobo_activate(); | |
255 | |
256 backup_blist_ui_ops = gaim_blist_get_ui_ops(); | |
257 | |
258 blist_ui_ops = g_memdup(backup_blist_ui_ops, sizeof(GaimBlistUiOps)); | |
259 blist_ui_ops->request_add_buddy = request_add_buddy; | |
260 | |
261 gaim_blist_set_ui_ops(blist_ui_ops); | |
262 | |
263 gaim_signal_connect(gaim_connections_get_handle(), "signed-on", | |
264 plugin, GAIM_CALLBACK(signed_on_cb), NULL); | |
265 | |
266 timer = g_timeout_add(1, load_timeout, plugin); | |
267 | |
268 return TRUE; | |
269 } | |
270 | |
271 static gboolean | |
272 plugin_unload(GaimPlugin *plugin) | |
273 { | |
274 gaim_blist_set_ui_ops(backup_blist_ui_ops); | |
275 | |
276 g_free(blist_ui_ops); | |
277 | |
278 backup_blist_ui_ops = NULL; | |
279 blist_ui_ops = NULL; | |
280 | |
281 if (book_view != NULL) | |
282 { | |
283 e_book_view_stop(book_view); | |
284 g_object_unref(book_view); | |
285 book_view = NULL; | |
286 } | |
287 | |
288 if (book != NULL) | |
289 { | |
290 g_object_unref(book); | |
291 book = NULL; | |
292 } | |
293 | |
294 return TRUE; | |
295 } | |
296 | |
297 static void | |
298 plugin_destroy(GaimPlugin *plugin) | |
299 { | |
10055
0436734708fa
[gaim-migrate @ 11020]
Christian Hammond <chipx86@chipx86.com>
parents:
9954
diff
changeset
|
300 bonobo_debug_shutdown(); |
8089 | 301 } |
302 | |
303 static void | |
304 autoadd_toggled_cb(GtkCellRendererToggle *renderer, gchar *path_str, | |
305 gpointer data) | |
306 { | |
307 GaimAccount *account; | |
308 GtkTreeModel *model = (GtkTreeModel *)data; | |
309 GtkTreeIter iter; | |
310 gboolean autoadd; | |
311 | |
312 gtk_tree_model_get_iter_from_string(model, &iter, path_str); | |
313 gtk_tree_model_get(model, &iter, | |
314 COLUMN_DATA, &account, | |
315 COLUMN_AUTOADD, &autoadd, | |
316 -1); | |
317 | |
318 gaim_account_set_bool(account, "gevo-autoadd", !autoadd); | |
319 | |
320 gtk_list_store_set(GTK_LIST_STORE(model), &iter, | |
321 COLUMN_AUTOADD, !autoadd, | |
322 -1); | |
323 } | |
324 | |
325 static GtkWidget * | |
326 get_config_frame(GaimPlugin *plugin) | |
327 { | |
328 GtkWidget *ret; | |
329 GtkWidget *vbox; | |
330 GtkWidget *label; | |
331 GtkWidget *sw; | |
332 GtkWidget *treeview; | |
333 GtkTreeViewColumn *column; | |
334 GtkCellRenderer *renderer; | |
335 GdkPixbuf *pixbuf, *scale = NULL; | |
336 GtkListStore *model; | |
337 GList *l; | |
338 | |
339 /* Outside container */ | |
340 ret = gtk_vbox_new(FALSE, 18); | |
341 gtk_container_set_border_width(GTK_CONTAINER(ret), 12); | |
342 | |
343 /* Configuration frame */ | |
344 vbox = gaim_gtk_make_frame(ret, _("Evolution Integration Configuration")); | |
345 | |
346 /* Label */ | |
347 label = gtk_label_new(_("Select all accounts that buddies should be " | |
348 "auto-added to.")); | |
349 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
350 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); | |
351 gtk_widget_show(label); | |
352 | |
353 /* Scrolled window */ | |
354 sw = gtk_scrolled_window_new(0, 0); | |
355 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), | |
356 GTK_POLICY_AUTOMATIC, | |
357 GTK_POLICY_ALWAYS); | |
358 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), | |
359 GTK_SHADOW_IN); | |
360 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); | |
361 gtk_widget_set_size_request(sw, 300, 300); | |
362 gtk_widget_show(sw); | |
363 | |
364 /* Create the list model for the treeview. */ | |
365 model = gtk_list_store_new(NUM_COLUMNS, | |
366 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, | |
367 G_TYPE_STRING, G_TYPE_POINTER); | |
368 | |
369 /* Setup the treeview */ | |
370 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model)); | |
371 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); | |
372 gtk_container_add(GTK_CONTAINER(sw), treeview); | |
373 gtk_widget_show(treeview); | |
374 | |
375 /* Setup the column */ | |
376 column = gtk_tree_view_column_new(); | |
377 gtk_tree_view_column_set_title(column, _("Account")); | |
378 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeview), column, -1); | |
379 | |
380 /* Checkbox */ | |
381 renderer = gtk_cell_renderer_toggle_new(); | |
382 | |
383 g_signal_connect(G_OBJECT(renderer), "toggled", | |
384 G_CALLBACK(autoadd_toggled_cb), model); | |
385 | |
386 gtk_tree_view_column_pack_start(column, renderer, FALSE); | |
387 gtk_tree_view_column_add_attribute(column, renderer, | |
388 "active", COLUMN_AUTOADD); | |
389 | |
390 /* Icon */ | |
391 renderer = gtk_cell_renderer_pixbuf_new(); | |
392 gtk_tree_view_column_pack_start(column, renderer, FALSE); | |
393 gtk_tree_view_column_add_attribute(column, renderer, | |
394 "pixbuf", COLUMN_ICON); | |
395 | |
396 /* Screenname */ | |
397 renderer = gtk_cell_renderer_text_new(); | |
398 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
399 gtk_tree_view_column_add_attribute(column, renderer, | |
400 "text", COLUMN_SCREENNAME); | |
401 | |
402 | |
403 /* Populate */ | |
404 for (l = gaim_accounts_get_all(); l != NULL; l = l->next) | |
405 { | |
406 GaimAccount *account = (GaimAccount *)l->data; | |
407 GtkTreeIter iter; | |
408 | |
409 gaim_debug_info("evolution", "Adding account\n"); | |
410 | |
411 gtk_list_store_append(model, &iter); | |
412 | |
413 pixbuf = create_prpl_icon(account); | |
414 | |
415 if (pixbuf != NULL) | |
416 { | |
417 scale = gdk_pixbuf_scale_simple(pixbuf, 16, 16, | |
418 GDK_INTERP_BILINEAR); | |
419 | |
420 if (!gaim_account_is_connected(account)) | |
421 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.0, FALSE); | |
422 } | |
423 | |
424 gtk_list_store_set(model, &iter, | |
425 COLUMN_AUTOADD, | |
426 gaim_account_get_bool(account, "gevo-autoadd", | |
427 FALSE), | |
428 COLUMN_ICON, scale, | |
429 COLUMN_SCREENNAME, | |
430 gaim_account_get_username(account), | |
431 COLUMN_DATA, account, | |
432 -1); | |
433 | |
434 if (pixbuf != NULL) g_object_unref(G_OBJECT(pixbuf)); | |
435 if (scale != NULL) g_object_unref(G_OBJECT(scale)); | |
436 } | |
437 | |
438 gtk_widget_show_all(ret); | |
439 | |
440 return ret; | |
441 } | |
442 | |
443 static GaimGtkPluginUiInfo ui_info = | |
444 { | |
445 get_config_frame | |
446 }; | |
447 | |
448 static GaimPluginInfo info = | |
449 { | |
9954 | 450 GAIM_PLUGIN_MAGIC, |
451 GAIM_MAJOR_VERSION, | |
452 GAIM_MINOR_VERSION, | |
8089 | 453 GAIM_PLUGIN_STANDARD, /**< type */ |
454 GAIM_GTK_PLUGIN_TYPE, /**< ui_requirement */ | |
455 0, /**< flags */ | |
456 NULL, /**< dependencies */ | |
457 GAIM_PRIORITY_DEFAULT, /**< priority */ | |
458 | |
459 GEVOLUTION_PLUGIN_ID, /**< id */ | |
460 N_("Evolution Integration"), /**< name */ | |
461 VERSION, /**< version */ | |
462 /** summary */ | |
463 N_("Provides integration with Ximian Evolution."), | |
464 /** description */ | |
465 N_("Provides integration with Ximian Evolution."), | |
466 "Christian Hammond <chipx86@gnupdate.org>", /**< author */ | |
467 GAIM_WEBSITE, /**< homepage */ | |
468 | |
469 plugin_load, /**< load */ | |
470 plugin_unload, /**< unload */ | |
471 plugin_destroy, /**< destroy */ | |
472 | |
473 &ui_info, /**< ui_info */ | |
8993 | 474 NULL, /**< extra_info */ |
475 NULL, | |
476 NULL | |
8089 | 477 }; |
478 | |
479 static void | |
480 init_plugin(GaimPlugin *plugin) | |
481 { | |
482 /* TODO: Change to core-remote when possible. */ | |
483 /* info.dependencies = g_list_append(info.dependencies, "gtk-remote"); */ | |
484 | |
485 /* | |
486 * I'm going to rant a little bit here... | |
487 * | |
488 * For some reason, when we init bonobo from inside a plugin, it will | |
489 * segfault when destroyed. The backtraces are within gmodule somewhere. | |
490 * There's not much I can do, and I'm not sure where the bug lies. | |
491 * However, plugins are only destroyed when Gaim is shutting down. After | |
492 * destroying the plugins, gaim ends, and anything else is of course | |
493 * freed. That includes this, if we make the module resident, which | |
494 * prevents us from being able to actually unload it. | |
495 * | |
496 * So, in conclusion, this is an evil hack, but it doesn't harm anything | |
497 * and it works. | |
498 */ | |
499 g_module_make_resident(plugin->handle); | |
10055
0436734708fa
[gaim-migrate @ 11020]
Christian Hammond <chipx86@chipx86.com>
parents:
9954
diff
changeset
|
500 |
0436734708fa
[gaim-migrate @ 11020]
Christian Hammond <chipx86@chipx86.com>
parents:
9954
diff
changeset
|
501 if (!bonobo_init_full(NULL, NULL, bonobo_activation_orb_get(), |
0436734708fa
[gaim-migrate @ 11020]
Christian Hammond <chipx86@chipx86.com>
parents:
9954
diff
changeset
|
502 CORBA_OBJECT_NIL, CORBA_OBJECT_NIL)) |
0436734708fa
[gaim-migrate @ 11020]
Christian Hammond <chipx86@chipx86.com>
parents:
9954
diff
changeset
|
503 { |
0436734708fa
[gaim-migrate @ 11020]
Christian Hammond <chipx86@chipx86.com>
parents:
9954
diff
changeset
|
504 gaim_debug_error("evolution", "Unable to initialize bonobo.\n"); |
0436734708fa
[gaim-migrate @ 11020]
Christian Hammond <chipx86@chipx86.com>
parents:
9954
diff
changeset
|
505 } |
8089 | 506 } |
507 | |
508 GAIM_INIT_PLUGIN(gevolution, init_plugin, info) |