evolution-3.6.4/modules/addressbook/e-book-shell-backend.c

No issues found

  1 /*
  2  * e-book-shell-backend.c
  3  *
  4  * This program is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU Lesser General Public
  6  * License as published by the Free Software Foundation; either
  7  * version 2 of the License, or (at your option) version 3.
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  * Lesser General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU Lesser General Public
 15  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 16  *
 17  *
 18  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 19  *
 20  */
 21 
 22 #ifdef HAVE_CONFIG_H
 23 #include <config.h>
 24 #endif
 25 
 26 #include "e-book-shell-backend.h"
 27 
 28 #include <string.h>
 29 #include <glib/gi18n.h>
 30 #include <libebook/libebook.h>
 31 #include <libedataserverui/libedataserverui.h>
 32 
 33 #include "e-util/e-import.h"
 34 #include "shell/e-shell.h"
 35 #include "shell/e-shell-window.h"
 36 #include "widgets/misc/e-book-source-config.h"
 37 #include "widgets/misc/e-preferences-window.h"
 38 #include "widgets/misc/e-source-config-dialog.h"
 39 
 40 #include "addressbook/gui/widgets/eab-gui-util.h"
 41 #include "addressbook/gui/widgets/e-addressbook-view.h"
 42 #include "addressbook/gui/contact-editor/e-contact-editor.h"
 43 #include "addressbook/gui/contact-editor/e-contact-quick-add.h"
 44 #include "addressbook/gui/contact-list-editor/e-contact-list-editor.h"
 45 #include "addressbook/importers/evolution-addressbook-importers.h"
 46 
 47 #include "autocompletion-config.h"
 48 
 49 #include "e-book-shell-content.h"
 50 #include "e-book-shell-migrate.h"
 51 #include "e-book-shell-settings.h"
 52 #include "e-book-shell-view.h"
 53 
 54 #ifdef ENABLE_SMIME
 55 #include "smime/gui/component.h"
 56 #include "smime/gui/certificate-manager.h"
 57 #endif
 58 
 59 #define E_BOOK_SHELL_BACKEND_GET_PRIVATE(obj) \
 60 	(G_TYPE_INSTANCE_GET_PRIVATE \
 61 	((obj), E_TYPE_BOOK_SHELL_BACKEND, EBookShellBackendPrivate))
 62 
 63 struct _EBookShellBackendPrivate {
 64 	gint placeholder;
 65 };
 66 
 67 G_DEFINE_DYNAMIC_TYPE (
 68 	EBookShellBackend,
 69 	e_book_shell_backend,
 70 	E_TYPE_SHELL_BACKEND)
 71 
 72 static void
 73 book_shell_backend_init_importers (void)
 74 {
 75 	EImportClass *import_class;
 76 	EImportImporter *importer;
 77 
 78 	import_class = g_type_class_ref (e_import_get_type ());
 79 
 80 	importer = evolution_ldif_importer_peek ();
 81 	e_import_class_add_importer (import_class, importer, NULL, NULL);
 82 
 83 	importer = evolution_vcard_importer_peek ();
 84 	e_import_class_add_importer (import_class, importer, NULL, NULL);
 85 
 86 	importer = evolution_csv_outlook_importer_peek ();
 87 	e_import_class_add_importer (import_class, importer, NULL, NULL);
 88 
 89 	importer = evolution_csv_mozilla_importer_peek ();
 90 	e_import_class_add_importer (import_class, importer, NULL, NULL);
 91 
 92 	importer = evolution_csv_evolution_importer_peek ();
 93 	e_import_class_add_importer (import_class, importer, NULL, NULL);
 94 }
 95 
 96 static void
 97 book_shell_backend_new_contact_cb (GObject *source_object,
 98                                    GAsyncResult *result,
 99                                    gpointer user_data)
100 {
101 	ESource *source = E_SOURCE (source_object);
102 	EShell *shell = user_data;
103 	EClient *client = NULL;
104 	EContact *contact;
105 	EABEditor *editor;
106 	GError *error = NULL;
107 
108 	e_client_utils_open_new_finish (source, result, &client, &error);
109 
110 	/* XXX Handle errors better. */
111 	if (error != NULL) {
112 		g_warn_if_fail (client == NULL);
113 		g_warning (
114 			"%s: Failed to open book: %s",
115 			G_STRFUNC, error->message);
116 		g_error_free (error);
117 		goto exit;
118 	}
119 
120 	g_return_if_fail (E_IS_CLIENT (client));
121 
122 	contact = e_contact_new ();
123 
124 	editor = e_contact_editor_new (
125 		shell, E_BOOK_CLIENT (client), contact, TRUE, TRUE);
126 
127 	eab_editor_show (editor);
128 
129 	g_object_unref (contact);
130 	g_object_unref (client);
131 
132 exit:
133 	g_object_unref (shell);
134 }
135 
136 static void
137 book_shell_backend_new_contact_list_cb (GObject *source_object,
138                                         GAsyncResult *result,
139                                         gpointer user_data)
140 {
141 	ESource *source = E_SOURCE (source_object);
142 	EShell *shell = user_data;
143 	EClient *client = NULL;
144 	EContact *contact;
145 	EABEditor *editor;
146 	GError *error = NULL;
147 
148 	e_client_utils_open_new_finish (source, result, &client, &error);
149 
150 	/* XXX Handle errors better. */
151 	if (error != NULL) {
152 		g_warn_if_fail (client == NULL);
153 		g_warning (
154 			"%s: Failed to open book: %s",
155 			G_STRFUNC, error->message);
156 		g_error_free (error);
157 		goto exit;
158 	}
159 
160 	g_return_if_fail (E_IS_CLIENT (client));
161 
162 	contact = e_contact_new ();
163 
164 	editor = e_contact_list_editor_new (
165 		shell, E_BOOK_CLIENT (client), contact, TRUE, TRUE);
166 
167 	eab_editor_show (editor);
168 
169 	g_object_unref (contact);
170 	g_object_unref (client);
171 
172 exit:
173 	g_object_unref (shell);
174 }
175 
176 static void
177 action_contact_new_cb (GtkAction *action,
178                        EShellWindow *shell_window)
179 {
180 	EShell *shell;
181 	ESource *source = NULL;
182 	ESourceRegistry *registry;
183 	const gchar *action_name;
184 
185 	/* This callback is used for both contacts and contact lists. */
186 
187 	shell = e_shell_window_get_shell (shell_window);
188 
189 	if (g_strcmp0 (e_shell_window_get_active_view (shell_window), "addressbook") == 0) {
190 		EShellView *shell_view = e_shell_window_get_shell_view (shell_window, "addressbook");
191 
192 		if (shell_view && E_IS_BOOK_SHELL_VIEW (shell_view)) {
193 			EBookShellContent *book_shell_content;
194 			EAddressbookView *view;
195 			EAddressbookModel *model;
196 			EBookClient *book_client;
197 
198 			book_shell_content = NULL;
199 			g_object_get (G_OBJECT (shell_view), "shell-content", &book_shell_content, NULL);
200 			g_return_if_fail (book_shell_content != NULL);
201 
202 			view = e_book_shell_content_get_current_view (book_shell_content);
203 			g_return_if_fail (view != NULL);
204 
205 			model = e_addressbook_view_get_model (view);
206 			book_client = e_addressbook_model_get_client (model);
207 			g_return_if_fail (book_client != NULL);
208 
209 			source = g_object_ref (e_client_get_source (E_CLIENT (book_client)));
210 
211 			g_object_unref (book_shell_content);
212 		}
213 	}
214 
215 	if (!source) {
216 		registry = e_shell_get_registry (shell);
217 		source = e_source_registry_ref_default_address_book (registry);
218 	}
219 
220 	/* Use a callback function appropriate for the action. */
221 	action_name = gtk_action_get_name (action);
222 	if (strcmp (action_name, "contact-new") == 0)
223 		e_client_utils_open_new (
224 			source, E_CLIENT_SOURCE_TYPE_CONTACTS, FALSE, NULL,
225 			book_shell_backend_new_contact_cb,
226 			g_object_ref (shell));
227 	if (strcmp (action_name, "contact-new-list") == 0)
228 		e_client_utils_open_new (
229 			source, E_CLIENT_SOURCE_TYPE_CONTACTS, FALSE, NULL,
230 			book_shell_backend_new_contact_list_cb,
231 			g_object_ref (shell));
232 
233 	g_object_unref (source);
234 }
235 
236 static void
237 action_address_book_new_cb (GtkAction *action,
238                             EShellWindow *shell_window)
239 {
240 	EShell *shell;
241 	ESourceRegistry *registry;
242 	GtkWidget *config;
243 	GtkWidget *dialog;
244 	const gchar *icon_name;
245 
246 	shell = e_shell_window_get_shell (shell_window);
247 
248 	registry = e_shell_get_registry (shell);
249 	config = e_book_source_config_new (registry, NULL);
250 
251 	dialog = e_source_config_dialog_new (E_SOURCE_CONFIG (config));
252 
253 	gtk_window_set_transient_for (
254 		GTK_WINDOW (dialog), GTK_WINDOW (shell_window));
255 
256 	icon_name = gtk_action_get_icon_name (action);
257 	gtk_window_set_icon_name (GTK_WINDOW (dialog), icon_name);
258 
259 	gtk_window_set_title (GTK_WINDOW (dialog), _("New Address Book"));
260 
261 	gtk_widget_show (dialog);
262 }
263 
264 static GtkActionEntry item_entries[] = {
265 
266 	{ "contact-new",
267 	  "contact-new",
268 	  NC_("New", "_Contact"),
269 	  "<Shift><Control>c",
270 	  N_("Create a new contact"),
271 	  G_CALLBACK (action_contact_new_cb) },
272 
273 	{ "contact-new-list",
274 	  "stock_contact-list",
275 	  NC_("New", "Contact _List"),
276 	  "<Shift><Control>l",
277 	  N_("Create a new contact list"),
278 	  G_CALLBACK (action_contact_new_cb) }
279 };
280 
281 static GtkActionEntry source_entries[] = {
282 
283 	{ "address-book-new",
284 	  "address-book-new",
285 	  NC_("New", "Address _Book"),
286 	  NULL,
287 	  N_("Create a new address book"),
288 	  G_CALLBACK (action_address_book_new_cb) }
289 };
290 
291 static gboolean
292 book_shell_backend_init_preferences (EShell *shell)
293 {
294 	GtkWidget *preferences_window;
295 
296 	/* This is a main loop idle callback. */
297 
298 	preferences_window = e_shell_get_preferences_window (shell);
299 
300 	e_preferences_window_add_page (
301 		E_PREFERENCES_WINDOW (preferences_window),
302 		"contacts",
303 		"preferences-autocompletion",
304 		_("Contacts"),
305 		"index#contacts",
306 		autocompletion_config_new,
307 		200);
308 
309 #ifdef ENABLE_SMIME
310 	preferences_window = e_shell_get_preferences_window (shell);
311 	e_preferences_window_add_page (
312 		E_PREFERENCES_WINDOW (preferences_window),
313 		"certificates",
314 		"preferences-certificates",
315 		_("Certificates"),
316 		"mail-encryption-s-mime-manage",
317 		e_cert_manager_config_new,
318 		700);
319 #endif
320 
321 	return FALSE;
322 }
323 
324 static void
325 book_shell_backend_quick_add_email_cb (EShell *shell,
326                                        const gchar *email)
327 {
328 	ESourceRegistry *registry;
329 
330 	/* XXX This is an ugly hack but it's the only way I could think
331 	 *     of to integrate this feature with other shell modules. */
332 
333 	registry = e_shell_get_registry (shell);
334 	e_contact_quick_add_email (registry, email, NULL, NULL);
335 }
336 
337 static void
338 book_shell_backend_quick_add_vcard_cb (EShell *shell,
339                                        const gchar *vcard)
340 {
341 	ESourceRegistry *registry;
342 
343 	/* XXX This is an ugly hack but it's the only way I could think
344 	 *     of to integrate this feature with other shell modules. */
345 
346 	registry = e_shell_get_registry (shell);
347 	e_contact_quick_add_vcard (registry, vcard, NULL, NULL);
348 }
349 
350 static gboolean
351 book_shell_backend_handle_uri_cb (EShellBackend *shell_backend,
352                                   const gchar *uri)
353 {
354 	SoupURI *soup_uri;
355 	const gchar *cp;
356 	gchar *source_uid = NULL;
357 	gchar *contact_uid = NULL;
358 
359 	if (!g_str_has_prefix (uri, "contacts:"))
360 		return FALSE;
361 
362 	soup_uri = soup_uri_new (uri);
363 
364 	if (soup_uri == NULL)
365 		return FALSE;
366 
367 	cp = soup_uri_get_query (soup_uri);
368 
369 	if (cp == NULL) {
370 		soup_uri_free (soup_uri);
371 		return FALSE;
372 	}
373 
374 	while (*cp != '\0') {
375 		gchar *header;
376 		gchar *content;
377 		gsize length;
378 		gsize content_length;
379 
380 		length = strcspn (cp, "=&");
381 
382 		/* If it's malformed, give up. */
383 		if (cp[length] != '=')
384 			break;
385 
386 		header = (gchar *) cp;
387 		header[length] = '\0';
388 		cp += length + 1;
389 
390 		content_length = strcspn (cp, "&");
391 		content = g_strndup (cp, content_length);
392 
393 		if (g_ascii_strcasecmp (header, "source-uid") == 0)
394 			source_uid = g_strdup (content);
395 
396 		if (g_ascii_strcasecmp (header, "contact-uid") == 0)
397 			contact_uid = g_strdup (content);
398 
399 		g_free (content);
400 
401 		cp += content_length;
402 		if (*cp == '&') {
403 			cp++;
404 			if (strcmp (cp, "amp;"))
405 				cp += 4;
406 		}
407 	}
408 
409 	/* FIXME */
410 	/*addressbook_view_edit_contact (view, source_uid, contact_uid);*/
411 
412 	g_free (source_uid);
413 	g_free (contact_uid);
414 
415 	soup_uri_free (soup_uri);
416 
417 	return TRUE;
418 }
419 
420 static void
421 book_shell_backend_window_added_cb (EShellBackend *shell_backend,
422                                     GtkWindow *window)
423 {
424 	const gchar *backend_name;
425 
426 	if (!E_IS_SHELL_WINDOW (window))
427 		return;
428 
429 	backend_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name;
430 
431 	e_shell_window_register_new_item_actions (
432 		E_SHELL_WINDOW (window), backend_name,
433 		item_entries, G_N_ELEMENTS (item_entries));
434 
435 	e_shell_window_register_new_source_actions (
436 		E_SHELL_WINDOW (window), backend_name,
437 		source_entries, G_N_ELEMENTS (source_entries));
438 }
439 
440 static void
441 book_shell_backend_constructed (GObject *object)
442 {
443 	EShell *shell;
444 	EShellBackend *shell_backend;
445 
446 	shell_backend = E_SHELL_BACKEND (object);
447 	shell = e_shell_backend_get_shell (shell_backend);
448 
449 	/* XXX Why is this here?  Address books aren't the only
450 	 *     things that use S/MIME.  Maybe put it in EShell? */
451 #ifdef ENABLE_SMIME
452 	smime_component_init ();
453 #endif
454 
455 	book_shell_backend_init_importers ();
456 
457 	g_signal_connect (
458 		shell, "event::contact-quick-add-email",
459 		G_CALLBACK (book_shell_backend_quick_add_email_cb), NULL);
460 
461 	g_signal_connect_swapped (
462 		shell, "event::contact-quick-add-vcard",
463 		G_CALLBACK (book_shell_backend_quick_add_vcard_cb), NULL);
464 
465 	g_signal_connect_swapped (
466 		shell, "handle-uri",
467 		G_CALLBACK (book_shell_backend_handle_uri_cb),
468 		shell_backend);
469 
470 	g_signal_connect_swapped (
471 		shell, "window-added",
472 		G_CALLBACK (book_shell_backend_window_added_cb),
473 		shell_backend);
474 
475 	e_book_shell_backend_init_settings (shell);
476 
477 	/* Initialize preferences after the main loop starts so
478 	 * that all EPlugins and EPluginHooks are loaded first. */
479 	g_idle_add ((GSourceFunc) book_shell_backend_init_preferences, shell);
480 
481 	/* Chain up to parent's constructed() method. */
482 	G_OBJECT_CLASS (e_book_shell_backend_parent_class)->constructed (object);
483 }
484 
485 static void
486 e_book_shell_backend_class_init (EBookShellBackendClass *class)
487 {
488 	GObjectClass *object_class;
489 	EShellBackendClass *shell_backend_class;
490 
491 	g_type_class_add_private (class, sizeof (EBookShellBackendPrivate));
492 
493 	object_class = G_OBJECT_CLASS (class);
494 	object_class->constructed = book_shell_backend_constructed;
495 
496 	shell_backend_class = E_SHELL_BACKEND_CLASS (class);
497 	shell_backend_class->shell_view_type = E_TYPE_BOOK_SHELL_VIEW;
498 	shell_backend_class->name = "addressbook";
499 	shell_backend_class->aliases = "contacts";
500 	shell_backend_class->schemes = "";
501 	shell_backend_class->sort_order = 300;
502 	shell_backend_class->preferences_page = "contacts";
503 	shell_backend_class->start = NULL;
504 	shell_backend_class->migrate = e_book_shell_backend_migrate;
505 }
506 
507 static void
508 e_book_shell_backend_class_finalize (EBookShellBackendClass *class)
509 {
510 }
511 
512 static void
513 e_book_shell_backend_init (EBookShellBackend *book_shell_backend)
514 {
515 	book_shell_backend->priv =
516 		E_BOOK_SHELL_BACKEND_GET_PRIVATE (book_shell_backend);
517 }
518 
519 void
520 e_book_shell_backend_type_register (GTypeModule *type_module)
521 {
522 	/* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
523 	 *     function, so we have to wrap it with a public function in
524 	 *     order to register types from a separate compilation unit. */
525 	e_book_shell_backend_register_type (type_module);
526 }