comparison plugins/gevolution/assoc-buddy.c @ 8089:35db601609e3

[gaim-migrate @ 8788] Gaim-Evolution Buddy List-Addressbook syncronocity by our very own Chip X. Eightysix. committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Tue, 13 Jan 2004 01:45:32 +0000
parents
children d7b8eb1f0a18
comparison
equal deleted inserted replaced
8088:a86784e3b98c 8089:35db601609e3
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 "gtkinternal.h"
22 #include "gtkblist.h"
23 #include "gtkutils.h"
24 #include "gtkimhtml.h"
25 #include "gaim-disclosure.h"
26
27 #include "debug.h"
28
29 #include "gevolution.h"
30
31 #include <stdlib.h>
32 #include <bonobo/bonobo-main.h>
33 #include <libebook/e-book.h>
34 #include <libebook/e-book-async.h>
35 #include <libedataserver/e-source-list.h>
36
37 enum
38 {
39 COLUMN_NAME,
40 COLUMN_DATA,
41 NUM_COLUMNS
42 };
43
44 static gint
45 delete_win_cb(GtkWidget *w, GdkEvent *event, GevoAssociateBuddyDialog *dialog)
46 {
47 GList *l;
48
49 gtk_widget_destroy(dialog->win);
50
51 g_list_foreach(dialog->contacts, (GFunc)g_free, NULL);
52
53 if (dialog->contacts != NULL)
54 g_list_free(dialog->contacts);
55
56 g_object_unref(dialog->book);
57
58 g_free(dialog);
59
60 return 0;
61 }
62
63 static void
64 populate_address_books(GevoAssociateBuddyDialog *dialog)
65 {
66 GtkWidget *item;
67 GtkWidget *menu;
68 #if notyet
69 ESourceList *addressbooks;
70 GList *groups, *g;
71 #endif
72
73 menu =
74 gtk_option_menu_get_menu(GTK_OPTION_MENU(dialog->addressbooks_menu));
75
76 item = gtk_menu_item_new_with_label(_("Local Addressbook"));
77 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
78 gtk_widget_show(item);
79
80 #if notyet
81 if (!e_book_get_addressbooks(&addressbooks, NULL))
82 {
83 gaim_debug_error("evolution",
84 "Unable to fetch list of address books.\n");
85
86 item = gtk_menu_item_new_with_label(_("None"));
87 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
88 gtk_widget_show(item);
89
90 return;
91 }
92
93 groups = e_source_list_peek_groups(list);
94
95 if (groups == NULL)
96 {
97 item = gtk_menu_item_new_with_label(_("None"));
98 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
99 gtk_widget_show(item);
100
101 return;
102 }
103
104 for (g = groups; g != NULL; g = g->next)
105 {
106 GList *sources, *s;
107
108 sources = e_source_group_peek_sources(g->data);
109
110 for (p = sources; p != NULL; p = p->next)
111 {
112 ESource *source = E_SOURCE(p->data);
113
114 item = gtk_menu_item_new_with_label(e_source_peek_name(source));
115 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
116 gtk_widget_show(item);
117 }
118 }
119 #endif
120 }
121
122 static void
123 search_changed_cb(GtkEntry *entry, GevoAssociateBuddyDialog *dialog)
124 {
125 const char *text = gtk_entry_get_text(entry);
126 GList *l;
127
128 gtk_list_store_clear(dialog->model);
129
130 for (l = dialog->contacts; l != NULL; l = l->next)
131 {
132 EContact *contact = E_CONTACT(l->data);
133 const char *name;
134 GtkTreeIter iter;
135
136 name = e_contact_get_const(contact, E_CONTACT_FULL_NAME);
137
138 if (text != NULL && *text != '\0' && name != NULL &&
139 g_ascii_strncasecmp(name, text, strlen(text)))
140 {
141 continue;
142 }
143
144 gtk_list_store_append(dialog->model, &iter);
145
146 gtk_list_store_set(dialog->model, &iter,
147 COLUMN_NAME, name,
148 COLUMN_DATA, contact,
149 -1);
150 }
151 }
152
153 static void
154 clear_cb(GtkWidget *w, GevoAssociateBuddyDialog *dialog)
155 {
156 static gboolean lock = FALSE;
157
158 if (lock)
159 return;
160
161 lock = TRUE;
162 gtk_entry_set_text(GTK_ENTRY(dialog->search_field), "");
163 lock = FALSE;
164 }
165
166 static void
167 selected_cb(GtkTreeSelection *sel, GevoAssociateBuddyDialog *dialog)
168 {
169 gtk_widget_set_sensitive(dialog->assoc_button, TRUE);
170 }
171
172 static void
173 add_columns(GevoAssociateBuddyDialog *dialog)
174 {
175 GtkCellRenderer *renderer;
176 GtkTreeViewColumn *column;
177
178 /* Name column */
179 column = gtk_tree_view_column_new();
180 gtk_tree_view_column_set_title(column, _("Name"));
181 gtk_tree_view_insert_column(GTK_TREE_VIEW(dialog->treeview), column, -1);
182 gtk_tree_view_column_set_sort_column_id(column, COLUMN_NAME);
183
184 renderer = gtk_cell_renderer_text_new();
185 gtk_tree_view_column_pack_start(column, renderer, TRUE);
186 gtk_tree_view_column_add_attribute(column, renderer,
187 "text", COLUMN_NAME);
188 }
189
190 static void
191 populate_treeview(GevoAssociateBuddyDialog *dialog)
192 {
193 EBookQuery *query;
194 EBook *book;
195 const char *prpl_id;
196 gboolean status;
197 GList *cards, *c;
198
199 if (!gevo_load_addressbook(&book, NULL))
200 {
201 gaim_debug_error("evolution",
202 "Error retrieving default addressbook\n");
203
204 return;
205 }
206
207 query = e_book_query_field_exists(E_CONTACT_FULL_NAME);
208
209 if (query == NULL)
210 {
211 gaim_debug_error("evolution", "Error in creating query\n");
212
213 g_object_unref(book);
214
215 return;
216 }
217
218 status = e_book_get_contacts(book, query, &cards, NULL);
219
220 e_book_query_unref(query);
221
222 if (!status)
223 {
224 gaim_debug_error("evolution", "Error %d in getting card list\n",
225 status);
226
227 g_object_unref(book);
228
229 return;
230 }
231
232 prpl_id = gaim_account_get_protocol_id(dialog->buddy->account);
233
234 for (c = cards; c != NULL; c = c->next)
235 {
236 EContact *contact = E_CONTACT(c->data);
237 const char *name;
238 GtkTreeIter iter;
239 EContactField protocol_field = 0;
240
241 name = e_contact_get_const(contact, E_CONTACT_FULL_NAME);
242
243 gtk_list_store_append(dialog->model, &iter);
244
245 gtk_list_store_set(dialog->model, &iter,
246 COLUMN_NAME, name,
247 COLUMN_DATA, contact,
248 -1);
249
250 /* See if this user has the buddy in its list. */
251 protocol_field = gevo_prpl_get_field(dialog->buddy->account,
252 dialog->buddy);
253
254 if (protocol_field > 0)
255 {
256 GList *ims, *l;
257
258 ims = e_contact_get(contact, protocol_field);
259
260 for (l = ims; l != NULL; l = l->next)
261 {
262 if (!strcmp(l->data, dialog->buddy->name))
263 {
264 GtkTreeSelection *selection;
265
266 /* This is it. Select it. */
267 selection = gtk_tree_view_get_selection(
268 GTK_TREE_VIEW(dialog->treeview));
269
270 gtk_tree_selection_select_iter(selection, &iter);
271 break;
272 }
273 }
274 }
275 }
276
277 dialog->contacts = cards;
278 dialog->book = book;
279 }
280
281 static void
282 new_person_cb(GtkWidget *w, GevoAssociateBuddyDialog *dialog)
283 {
284 gevo_new_person_dialog_show(NULL, dialog->buddy->account,
285 dialog->buddy->name, NULL, dialog->buddy,
286 TRUE);
287
288 delete_win_cb(NULL, NULL, dialog);
289 }
290
291 static void
292 cancel_cb(GtkWidget *w, GevoAssociateBuddyDialog *dialog)
293 {
294 delete_win_cb(NULL, NULL, dialog);
295 }
296
297 static void
298 assoc_buddy_cb(GtkWidget *w, GevoAssociateBuddyDialog *dialog)
299 {
300 GtkTreeSelection *selection;
301 GtkTreeIter iter;
302 GList *list, *new_list = NULL, *l;
303 const char *fullname;
304 EContactField protocol_field;
305 EContact *contact;
306
307 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview));
308
309 gtk_tree_selection_get_selected(selection, NULL, &iter);
310
311 gtk_tree_model_get(GTK_TREE_MODEL(dialog->model), &iter,
312 COLUMN_NAME, &fullname,
313 COLUMN_DATA, &contact,
314 -1);
315
316 protocol_field = gevo_prpl_get_field(dialog->buddy->account, dialog->buddy);
317
318 if (protocol_field == 0)
319 return; /* XXX */
320
321 list = e_contact_get(contact, protocol_field);
322
323 /* Make a copy of the list */
324 for (l = list; l != NULL; l = l->next)
325 new_list = g_list_append(new_list, g_strdup((char *)l->data));
326
327 new_list = g_list_append(new_list, dialog->buddy->name);
328
329 e_contact_set(contact, protocol_field, new_list);
330
331 /* Free the list. */
332 g_list_foreach(new_list, (GFunc)g_free, NULL);
333 g_list_free(new_list);
334
335 delete_win_cb(NULL, NULL, dialog);
336 }
337
338 GevoAssociateBuddyDialog *
339 gevo_associate_buddy_dialog_new(GaimBuddy *buddy)
340 {
341 GevoAssociateBuddyDialog *dialog;
342 GtkWidget *button;
343 GtkWidget *sw;
344 GtkWidget *label;
345 GtkWidget *vbox;
346 GtkWidget *hbox;
347 GtkWidget *bbox;
348 GtkWidget *menu;
349 GtkWidget *sep;
350 GtkWidget *disclosure;
351 GtkTreeSelection *selection;
352
353 g_return_val_if_fail(buddy != NULL, NULL);
354
355 dialog = g_new0(GevoAssociateBuddyDialog, 1);
356
357 dialog->buddy = buddy;
358
359 dialog->win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
360 gtk_window_set_role(GTK_WINDOW(dialog->win), "assoc_buddy");
361 gtk_container_set_border_width(GTK_CONTAINER(dialog->win), 12);
362
363 g_signal_connect(G_OBJECT(dialog->win), "delete_event",
364 G_CALLBACK(delete_win_cb), dialog);
365
366 /* Setup the vbox */
367 vbox = gtk_vbox_new(FALSE, 12);
368 gtk_container_add(GTK_CONTAINER(dialog->win), vbox);
369 gtk_widget_show(vbox);
370
371 /* Add the label. */
372 label = gtk_label_new(_("Select a person from your address book to "
373 "add this buddy to, or create a new person."));
374 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
375 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
376 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0);
377 gtk_widget_show(label);
378
379 /* Add the search hbox */
380 hbox = gtk_hbox_new(FALSE, 6);
381 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
382 gtk_widget_show(hbox);
383
384 /* "Search" */
385 label = gtk_label_new(_("Search"));
386 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
387 gtk_widget_show(label);
388
389 /* Addressbooks */
390 dialog->addressbooks_menu = gtk_option_menu_new();
391 menu = gtk_menu_new();
392 gtk_option_menu_set_menu(GTK_OPTION_MENU(dialog->addressbooks_menu), menu);
393
394 populate_address_books(dialog);
395
396 gtk_option_menu_set_history(GTK_OPTION_MENU(dialog->addressbooks_menu), 0);
397
398 gtk_box_pack_start(GTK_BOX(hbox), dialog->addressbooks_menu,
399 FALSE, FALSE, 0);
400 gtk_widget_show(dialog->addressbooks_menu);
401
402 /* Search field */
403 dialog->search_field = gtk_entry_new();
404 gtk_box_pack_start(GTK_BOX(hbox), dialog->search_field, TRUE, TRUE, 0);
405 gtk_widget_show(dialog->search_field);
406
407 g_signal_connect(G_OBJECT(dialog->search_field), "changed",
408 G_CALLBACK(search_changed_cb), dialog);
409
410 /* Clear button */
411 button = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
412 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
413 gtk_widget_show(button);
414
415 g_signal_connect(G_OBJECT(button), "clicked",
416 G_CALLBACK(clear_cb), dialog);
417
418 /* Scrolled Window */
419 sw = gtk_scrolled_window_new(0, 0);
420 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
421 GTK_POLICY_AUTOMATIC,
422 GTK_POLICY_ALWAYS);
423 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
424 GTK_SHADOW_IN);
425 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
426 gtk_widget_show(sw);
427
428 /* Create the list model for the treeview. */
429 dialog->model = gtk_list_store_new(NUM_COLUMNS,
430 G_TYPE_STRING, G_TYPE_POINTER);
431
432 /* Now for the treeview */
433 dialog->treeview =
434 gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model));
435 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(dialog->treeview), TRUE);
436 gtk_container_add(GTK_CONTAINER(sw), dialog->treeview);
437 gtk_widget_show(dialog->treeview);
438
439 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview));
440
441 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
442
443 g_signal_connect(G_OBJECT(selection), "changed",
444 G_CALLBACK(selected_cb), dialog);
445
446 add_columns(dialog);
447
448 populate_treeview(dialog);
449
450 /* Add the disclosure */
451 disclosure = gaim_disclosure_new(_("Show user details"),
452 _("Hide user details"));
453 gtk_box_pack_start(GTK_BOX(vbox), disclosure, FALSE, FALSE, 0);
454 gtk_widget_show(disclosure);
455
456 /*
457 * User details
458 */
459
460 /* Scrolled Window */
461 sw = gtk_scrolled_window_new(0, 0);
462 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
463 GTK_POLICY_NEVER,
464 GTK_POLICY_ALWAYS);
465 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
466 GTK_SHADOW_IN);
467 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
468 gaim_disclosure_set_container(GAIM_DISCLOSURE(disclosure), sw);
469
470 /* Textview */
471 dialog->imhtml = gtk_imhtml_new(NULL, NULL);
472 gtk_container_add(GTK_CONTAINER(sw), dialog->imhtml);
473 gtk_widget_show(dialog->imhtml);
474
475 /* Separator. */
476 sep = gtk_hseparator_new();
477 gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, 0);
478 gtk_widget_show(sep);
479
480 /* Button box */
481 bbox = gtk_hbutton_box_new();
482 gtk_box_set_spacing(GTK_BOX(bbox), 6);
483 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
484 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, TRUE, 0);
485 gtk_widget_show(bbox);
486
487 /* "New Person" button */
488 button = gaim_pixbuf_button_from_stock(_("New Person"), GTK_STOCK_NEW,
489 GAIM_BUTTON_HORIZONTAL);
490 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
491 gtk_widget_show(button);
492
493 g_signal_connect(G_OBJECT(button), "clicked",
494 G_CALLBACK(new_person_cb), dialog);
495
496 /* "Cancel" button */
497 button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
498 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
499 gtk_widget_show(button);
500
501 g_signal_connect(G_OBJECT(button), "clicked",
502 G_CALLBACK(cancel_cb), dialog);
503
504 /* "Associate Buddy" button */
505 button = gaim_pixbuf_button_from_stock(_("_Associate Buddy"),
506 GTK_STOCK_APPLY,
507 GAIM_BUTTON_HORIZONTAL);
508 dialog->assoc_button = button;
509 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
510 gtk_widget_set_sensitive(button, FALSE);
511 gtk_widget_show(button);
512
513 g_signal_connect(G_OBJECT(button), "clicked",
514 G_CALLBACK(assoc_buddy_cb), dialog);
515
516 /* Show it. */
517 gtk_widget_show(dialog->win);
518
519 return dialog;
520 }