Mercurial > pidgin
annotate plugins/gevolution/gevolution.c @ 8999:8f838ae3e710
[gaim-migrate @ 9774]
" This patch renames the existing received-*-msg signals
to receiving-*msg to fit the naming of other signals
where a pointer to the message is passed (writing,
sending, displaying)
It adds new received-*-msg signals which are emitted
after the receiving signals, in line with the other
conversation signals (wrote, sent, displayed)
This is necessary to allow plugins which depend on the
final received message to work alongside plugins which
may modify the message.
One known example of this is festival-gaim alongside
gaim-encryption - festival-gaim would try to "speak"
the encrypted text:
http://sf.net/tracker/?func=detail&aid=943216&group_id=89763&atid=591320
I've tested this with gaim-encryption and festival-gaim
(locally modified so gaim-encryption uses the receiving
signal and festival uses the received signal)
All in-tree users of received-*-msg are updated to use
receiving-*-msg if they do modify the message, the
conversation-signals documentation is updated, the
signals-test.c & signal-test.tcl plugins are also updated." --Stu Tomlinson
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Fri, 21 May 2004 14:33:32 +0000 |
parents | 294ae6548d4e |
children | 826013efffcb |
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 | |
202 menu_item_activate_cb(GtkWidget *item, GaimBuddy *buddy) | |
203 { | |
204 gevo_associate_buddy_dialog_new(buddy); | |
205 } | |
206 | |
207 static void | |
208 drawing_menu_cb(GtkWidget *menu, GaimBuddy *buddy) | |
209 { | |
210 GtkWidget *item; | |
211 | |
212 if (gevo_prpl_is_supported(buddy->account, buddy)) | |
213 { | |
214 item = gtk_menu_item_new_with_label(_("Add to Address Book")); | |
215 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
216 | |
217 g_signal_connect(G_OBJECT(item), "activate", | |
218 G_CALLBACK(menu_item_activate_cb), buddy); | |
219 } | |
220 } | |
221 | |
222 static gboolean | |
223 load_timeout(gpointer data) | |
224 { | |
225 GaimPlugin *plugin = (GaimPlugin *)data; | |
8127
96ee7b21c1ae
[gaim-migrate @ 8832]
Christian Hammond <chipx86@chipx86.com>
parents:
8089
diff
changeset
|
226 EBookQuery *query; |
8089 | 227 |
228 timer = 0; | |
229 | |
230 if (!gevo_load_addressbook(&book, NULL)) | |
231 return FALSE; | |
232 | |
8127
96ee7b21c1ae
[gaim-migrate @ 8832]
Christian Hammond <chipx86@chipx86.com>
parents:
8089
diff
changeset
|
233 query = e_book_query_any_field_contains(""); |
96ee7b21c1ae
[gaim-migrate @ 8832]
Christian Hammond <chipx86@chipx86.com>
parents:
8089
diff
changeset
|
234 |
96ee7b21c1ae
[gaim-migrate @ 8832]
Christian Hammond <chipx86@chipx86.com>
parents:
8089
diff
changeset
|
235 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
|
236 got_book_view_cb, NULL); |
96ee7b21c1ae
[gaim-migrate @ 8832]
Christian Hammond <chipx86@chipx86.com>
parents:
8089
diff
changeset
|
237 |
96ee7b21c1ae
[gaim-migrate @ 8832]
Christian Hammond <chipx86@chipx86.com>
parents:
8089
diff
changeset
|
238 e_book_query_unref(query); |
8089 | 239 |
240 gaim_signal_connect(GAIM_GTK_BLIST(gaim_get_blist()), "drawing-menu", | |
241 plugin, GAIM_CALLBACK(drawing_menu_cb), NULL); | |
242 | |
243 return FALSE; | |
244 } | |
245 | |
246 static gboolean | |
247 plugin_load(GaimPlugin *plugin) | |
248 { | |
249 if (!bonobo_init_full(NULL, NULL, bonobo_activation_orb_get(), | |
250 CORBA_OBJECT_NIL, CORBA_OBJECT_NIL)) | |
251 { | |
252 gaim_debug_error("evolution", "Unable to initialize bonobo.\n"); | |
253 return FALSE; | |
254 } | |
255 | |
256 bonobo_activate(); | |
257 | |
258 backup_blist_ui_ops = gaim_blist_get_ui_ops(); | |
259 | |
260 blist_ui_ops = g_memdup(backup_blist_ui_ops, sizeof(GaimBlistUiOps)); | |
261 blist_ui_ops->request_add_buddy = request_add_buddy; | |
262 | |
263 gaim_blist_set_ui_ops(blist_ui_ops); | |
264 | |
265 gaim_signal_connect(gaim_connections_get_handle(), "signed-on", | |
266 plugin, GAIM_CALLBACK(signed_on_cb), NULL); | |
267 | |
268 timer = g_timeout_add(1, load_timeout, plugin); | |
269 | |
270 return TRUE; | |
271 } | |
272 | |
273 static gboolean | |
274 plugin_unload(GaimPlugin *plugin) | |
275 { | |
276 gaim_blist_set_ui_ops(backup_blist_ui_ops); | |
277 | |
278 g_free(blist_ui_ops); | |
279 | |
280 backup_blist_ui_ops = NULL; | |
281 blist_ui_ops = NULL; | |
282 | |
283 if (book_view != NULL) | |
284 { | |
285 e_book_view_stop(book_view); | |
286 g_object_unref(book_view); | |
287 book_view = NULL; | |
288 } | |
289 | |
290 if (book != NULL) | |
291 { | |
292 g_object_unref(book); | |
293 book = NULL; | |
294 } | |
295 | |
296 bonobo_debug_shutdown(); | |
297 | |
298 return TRUE; | |
299 } | |
300 | |
301 static void | |
302 plugin_destroy(GaimPlugin *plugin) | |
303 { | |
304 } | |
305 | |
306 static void | |
307 autoadd_toggled_cb(GtkCellRendererToggle *renderer, gchar *path_str, | |
308 gpointer data) | |
309 { | |
310 GaimAccount *account; | |
311 GtkTreeModel *model = (GtkTreeModel *)data; | |
312 GtkTreeIter iter; | |
313 gboolean autoadd; | |
314 | |
315 gtk_tree_model_get_iter_from_string(model, &iter, path_str); | |
316 gtk_tree_model_get(model, &iter, | |
317 COLUMN_DATA, &account, | |
318 COLUMN_AUTOADD, &autoadd, | |
319 -1); | |
320 | |
321 gaim_account_set_bool(account, "gevo-autoadd", !autoadd); | |
322 | |
323 gtk_list_store_set(GTK_LIST_STORE(model), &iter, | |
324 COLUMN_AUTOADD, !autoadd, | |
325 -1); | |
326 } | |
327 | |
328 static GtkWidget * | |
329 get_config_frame(GaimPlugin *plugin) | |
330 { | |
331 GtkWidget *ret; | |
332 GtkWidget *vbox; | |
333 GtkWidget *label; | |
334 GtkWidget *sw; | |
335 GtkWidget *treeview; | |
336 GtkTreeViewColumn *column; | |
337 GtkCellRenderer *renderer; | |
338 GdkPixbuf *pixbuf, *scale = NULL; | |
339 GtkListStore *model; | |
340 GList *l; | |
341 | |
342 /* Outside container */ | |
343 ret = gtk_vbox_new(FALSE, 18); | |
344 gtk_container_set_border_width(GTK_CONTAINER(ret), 12); | |
345 | |
346 /* Configuration frame */ | |
347 vbox = gaim_gtk_make_frame(ret, _("Evolution Integration Configuration")); | |
348 | |
349 /* Label */ | |
350 label = gtk_label_new(_("Select all accounts that buddies should be " | |
351 "auto-added to.")); | |
352 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
353 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); | |
354 gtk_widget_show(label); | |
355 | |
356 /* Scrolled window */ | |
357 sw = gtk_scrolled_window_new(0, 0); | |
358 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), | |
359 GTK_POLICY_AUTOMATIC, | |
360 GTK_POLICY_ALWAYS); | |
361 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), | |
362 GTK_SHADOW_IN); | |
363 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); | |
364 gtk_widget_set_size_request(sw, 300, 300); | |
365 gtk_widget_show(sw); | |
366 | |
367 /* Create the list model for the treeview. */ | |
368 model = gtk_list_store_new(NUM_COLUMNS, | |
369 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, | |
370 G_TYPE_STRING, G_TYPE_POINTER); | |
371 | |
372 /* Setup the treeview */ | |
373 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model)); | |
374 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); | |
375 gtk_container_add(GTK_CONTAINER(sw), treeview); | |
376 gtk_widget_show(treeview); | |
377 | |
378 /* Setup the column */ | |
379 column = gtk_tree_view_column_new(); | |
380 gtk_tree_view_column_set_title(column, _("Account")); | |
381 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeview), column, -1); | |
382 | |
383 /* Checkbox */ | |
384 renderer = gtk_cell_renderer_toggle_new(); | |
385 | |
386 g_signal_connect(G_OBJECT(renderer), "toggled", | |
387 G_CALLBACK(autoadd_toggled_cb), model); | |
388 | |
389 gtk_tree_view_column_pack_start(column, renderer, FALSE); | |
390 gtk_tree_view_column_add_attribute(column, renderer, | |
391 "active", COLUMN_AUTOADD); | |
392 | |
393 /* Icon */ | |
394 renderer = gtk_cell_renderer_pixbuf_new(); | |
395 gtk_tree_view_column_pack_start(column, renderer, FALSE); | |
396 gtk_tree_view_column_add_attribute(column, renderer, | |
397 "pixbuf", COLUMN_ICON); | |
398 | |
399 /* Screenname */ | |
400 renderer = gtk_cell_renderer_text_new(); | |
401 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
402 gtk_tree_view_column_add_attribute(column, renderer, | |
403 "text", COLUMN_SCREENNAME); | |
404 | |
405 | |
406 /* Populate */ | |
407 for (l = gaim_accounts_get_all(); l != NULL; l = l->next) | |
408 { | |
409 GaimAccount *account = (GaimAccount *)l->data; | |
410 GtkTreeIter iter; | |
411 | |
412 gaim_debug_info("evolution", "Adding account\n"); | |
413 | |
414 gtk_list_store_append(model, &iter); | |
415 | |
416 pixbuf = create_prpl_icon(account); | |
417 | |
418 if (pixbuf != NULL) | |
419 { | |
420 scale = gdk_pixbuf_scale_simple(pixbuf, 16, 16, | |
421 GDK_INTERP_BILINEAR); | |
422 | |
423 if (!gaim_account_is_connected(account)) | |
424 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.0, FALSE); | |
425 } | |
426 | |
427 gtk_list_store_set(model, &iter, | |
428 COLUMN_AUTOADD, | |
429 gaim_account_get_bool(account, "gevo-autoadd", | |
430 FALSE), | |
431 COLUMN_ICON, scale, | |
432 COLUMN_SCREENNAME, | |
433 gaim_account_get_username(account), | |
434 COLUMN_DATA, account, | |
435 -1); | |
436 | |
437 if (pixbuf != NULL) g_object_unref(G_OBJECT(pixbuf)); | |
438 if (scale != NULL) g_object_unref(G_OBJECT(scale)); | |
439 } | |
440 | |
441 gtk_widget_show_all(ret); | |
442 | |
443 return ret; | |
444 } | |
445 | |
446 static GaimGtkPluginUiInfo ui_info = | |
447 { | |
448 get_config_frame | |
449 }; | |
450 | |
451 static GaimPluginInfo info = | |
452 { | |
8749
d7b8eb1f0a18
[gaim-migrate @ 9504]
Christian Hammond <chipx86@chipx86.com>
parents:
8127
diff
changeset
|
453 GAIM_PLUGIN_API_VERSION, /**< api_version */ |
8089 | 454 GAIM_PLUGIN_STANDARD, /**< type */ |
455 GAIM_GTK_PLUGIN_TYPE, /**< ui_requirement */ | |
456 0, /**< flags */ | |
457 NULL, /**< dependencies */ | |
458 GAIM_PRIORITY_DEFAULT, /**< priority */ | |
459 | |
460 GEVOLUTION_PLUGIN_ID, /**< id */ | |
461 N_("Evolution Integration"), /**< name */ | |
462 VERSION, /**< version */ | |
463 /** summary */ | |
464 N_("Provides integration with Ximian Evolution."), | |
465 /** description */ | |
466 N_("Provides integration with Ximian Evolution."), | |
467 "Christian Hammond <chipx86@gnupdate.org>", /**< author */ | |
468 GAIM_WEBSITE, /**< homepage */ | |
469 | |
470 plugin_load, /**< load */ | |
471 plugin_unload, /**< unload */ | |
472 plugin_destroy, /**< destroy */ | |
473 | |
474 &ui_info, /**< ui_info */ | |
8993 | 475 NULL, /**< extra_info */ |
476 NULL, | |
477 NULL | |
8089 | 478 }; |
479 | |
480 static void | |
481 init_plugin(GaimPlugin *plugin) | |
482 { | |
483 /* TODO: Change to core-remote when possible. */ | |
484 /* info.dependencies = g_list_append(info.dependencies, "gtk-remote"); */ | |
485 | |
486 /* | |
487 * I'm going to rant a little bit here... | |
488 * | |
489 * For some reason, when we init bonobo from inside a plugin, it will | |
490 * segfault when destroyed. The backtraces are within gmodule somewhere. | |
491 * There's not much I can do, and I'm not sure where the bug lies. | |
492 * However, plugins are only destroyed when Gaim is shutting down. After | |
493 * destroying the plugins, gaim ends, and anything else is of course | |
494 * freed. That includes this, if we make the module resident, which | |
495 * prevents us from being able to actually unload it. | |
496 * | |
497 * So, in conclusion, this is an evil hack, but it doesn't harm anything | |
498 * and it works. | |
499 */ | |
500 g_module_make_resident(plugin->handle); | |
501 } | |
502 | |
503 GAIM_INIT_PLUGIN(gevolution, init_plugin, info) |