1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
4 * Nat Friedman (nat@ximian.com)
6 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
11 #include <glib/gi18n-lib.h>
13 #include <libedataserver/e-data-server-util.h>
15 #include "e-data-book-view.h"
16 #include "e-data-book.h"
17 #include "e-book-backend.h"
19 #define EDB_OPENING_ERROR e_data_book_create_error (E_DATA_BOOK_STATUS_BUSY, _("Cannot process, book backend is opening"))
20 #define EDB_NOT_OPENED_ERROR e_data_book_create_error (E_DATA_BOOK_STATUS_NOT_OPENED, NULL)
22 #define E_BOOK_BACKEND_GET_PRIVATE(obj) \
23 (G_TYPE_INSTANCE_GET_PRIVATE \
24 ((obj), E_TYPE_BOOK_BACKEND, EBookBackendPrivate))
26 struct _EBookBackendPrivate {
27 GMutex *clients_mutex;
30 gboolean opening, opened, readonly, removed, online;
44 G_DEFINE_TYPE (EBookBackend, e_book_backend, E_TYPE_BACKEND)
47 book_backend_set_default_cache_dir (EBookBackend *backend)
50 const gchar *user_cache_dir;
54 user_cache_dir = e_get_user_cache_dir ();
55 source = e_backend_get_source (E_BACKEND (backend));
57 /* Mangle the URI to not contain invalid characters. */
58 mangled_uri = g_strdelimit (e_source_get_uri (source), ":/", '_');
60 filename = g_build_filename (
61 user_cache_dir, "addressbook", mangled_uri, NULL);
62 e_book_backend_set_cache_dir (backend, filename);
69 book_backend_get_backend_property (EBookBackend *backend,
72 GCancellable *cancellable,
73 const gchar *prop_name)
75 g_return_if_fail (backend != NULL);
76 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
77 g_return_if_fail (book != NULL);
78 g_return_if_fail (prop_name != NULL);
80 if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_OPENED)) {
81 e_data_book_respond_get_backend_property (book, opid, NULL, e_book_backend_is_opened (backend) ? "TRUE" : "FALSE");
82 } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_OPENING)) {
83 e_data_book_respond_get_backend_property (book, opid, NULL, e_book_backend_is_opening (backend) ? "TRUE" : "FALSE");
84 } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_ONLINE)) {
85 e_data_book_respond_get_backend_property (book, opid, NULL, e_backend_get_online (E_BACKEND (backend)) ? "TRUE" : "FALSE");
86 } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_READONLY)) {
87 e_data_book_respond_get_backend_property (book, opid, NULL, e_book_backend_is_readonly (backend) ? "TRUE" : "FALSE");
88 } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CACHE_DIR)) {
89 e_data_book_respond_get_backend_property (book, opid, NULL, e_book_backend_get_cache_dir (backend));
91 e_data_book_respond_get_backend_property (book, opid, e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_NOT_SUPPORTED, _("Unknown book property '%s'"), prop_name), NULL);
96 book_backend_set_backend_property (EBookBackend *backend,
99 GCancellable *cancellable,
100 const gchar *prop_name,
101 const gchar *prop_value)
103 g_return_if_fail (backend != NULL);
104 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
105 g_return_if_fail (book != NULL);
106 g_return_if_fail (prop_name != NULL);
108 e_data_book_respond_set_backend_property (book, opid, e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_NOT_SUPPORTED, _("Cannot change value of book property '%s'"), prop_name));
112 book_backend_set_property (GObject *object,
117 switch (property_id) {
119 e_book_backend_set_cache_dir (
120 E_BOOK_BACKEND (object),
121 g_value_get_string (value));
125 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
129 book_backend_get_property (GObject *object,
134 switch (property_id) {
137 value, e_book_backend_get_cache_dir (
138 E_BOOK_BACKEND (object)));
142 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
146 book_backend_dispose (GObject *object)
148 EBookBackendPrivate *priv;
150 priv = E_BOOK_BACKEND_GET_PRIVATE (object);
152 if (priv->views != NULL) {
153 g_slist_free (priv->views);
157 /* Chain up to parent's dispose() method. */
158 G_OBJECT_CLASS (e_book_backend_parent_class)->dispose (object);
162 book_backend_finalize (GObject *object)
164 EBookBackendPrivate *priv;
166 priv = E_BOOK_BACKEND_GET_PRIVATE (object);
168 g_slist_free (priv->clients);
170 g_mutex_free (priv->clients_mutex);
171 g_mutex_free (priv->views_mutex);
173 g_free (priv->cache_dir);
175 /* Chain up to parent's finalize() method. */
176 G_OBJECT_CLASS (e_book_backend_parent_class)->finalize (object);
180 view_notify_update (EDataBookView *view,
183 e_data_book_view_notify_update (view, contact);
189 book_backend_notify_update (EBookBackend *backend,
190 const EContact *contact)
192 e_book_backend_foreach_view (backend, view_notify_update, (gpointer) contact);
196 e_book_backend_class_init (EBookBackendClass *class)
198 GObjectClass *object_class;
200 g_type_class_add_private (class, sizeof (EBookBackendPrivate));
202 object_class = G_OBJECT_CLASS (class);
203 object_class->set_property = book_backend_set_property;
204 object_class->get_property = book_backend_get_property;
205 object_class->dispose = book_backend_dispose;
206 object_class->finalize = book_backend_finalize;
208 class->get_backend_property = book_backend_get_backend_property;
209 class->set_backend_property = book_backend_set_backend_property;
210 class->notify_update = book_backend_notify_update;
212 g_object_class_install_property (
215 g_param_spec_string (
218 "The backend's cache directory",
221 G_PARAM_STATIC_STRINGS));
225 e_book_backend_init (EBookBackend *backend)
227 backend->priv = E_BOOK_BACKEND_GET_PRIVATE (backend);
229 backend->priv->clients = NULL;
230 backend->priv->clients_mutex = g_mutex_new ();
232 backend->priv->views = NULL;
233 backend->priv->views_mutex = g_mutex_new ();
237 * e_book_backend_get_cache_dir:
238 * @backend: an #EBookBackend
240 * Returns the cache directory for the given backend.
242 * Returns: the cache directory for the backend
247 e_book_backend_get_cache_dir (EBookBackend *backend)
249 g_return_val_if_fail (E_IS_BOOK_BACKEND (backend), NULL);
251 return backend->priv->cache_dir;
255 * e_book_backend_set_cache_dir:
256 * @backend: an #EBookBackend
257 * @cache_dir: a local cache directory
259 * Sets the cache directory for the given backend.
261 * Note that #EBookBackend is initialized with a usable default based on
262 * the #ESource given to e_book_backend_open(). Backends should
263 * not override the default without good reason.
268 e_book_backend_set_cache_dir (EBookBackend *backend,
269 const gchar *cache_dir)
271 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
272 g_return_if_fail (cache_dir != NULL);
274 g_free (backend->priv->cache_dir);
275 backend->priv->cache_dir = g_strdup (cache_dir);
277 g_object_notify (G_OBJECT (backend), "cache-dir");
281 * e_book_backend_open:
282 * @backend: an #EBookBackend
283 * @book: an #EDataBook
284 * @opid: the ID to use for this operation
285 * @cancellable: a #GCancellable for the operation
286 * @only_if_exists: %TRUE to prevent the creation of a new book
288 * Executes an 'open' request specified by @opid on @book
289 * using @backend. This call might be finished
290 * with e_data_book_respond_open() or e_book_backend_respond_opened(),
291 * though the overall opening phase finishes only after call
292 * of e_book_backend_notify_opened() after which call the backend
293 * is either fully opened (including authentication against (remote)
294 * server/storage) or an error was encountered during this opening phase.
295 * 'opened' and 'opening' properties are updated automatically.
296 * The backend refuses all other operations until the opening phase is finished.
298 * The e_book_backend_notify_opened() is called either from this function
299 * or from e_book_backend_authenticate_user(), or after necessary steps
300 * initiated by these two functions.
302 * The opening phase usually works like this:
303 * 1) client requests open for the backend
304 * 2) server receives this request and calls e_book_backend_open() - the opening phase begun
305 * 3) either the backend is opened during this call, and notifies client
306 * with e_book_backend_notify_opened() about that. This is usually
307 * for local backends; their opening phase is finished
308 * 4) or the backend requires authentication, thus it notifies client
309 * about that with e_book_backend_notify_auth_required() and is
310 * waiting for credentials, which will be received from client
311 * by e_book_backend_authenticate_user() call. Backend's opening
312 * phase is still running in this case, thus it doesn't call
313 * e_book_backend_notify_opened() within e_book_backend_open() call.
314 * 5) when backend receives credentials in e_book_backend_authenticate_user()
315 * then it tries to authenticate against a server/storage with them
316 * and only after it knows result of the authentication, whether user
317 * was or wasn't authenticated, it notifies client with the result
318 * by e_book_backend_notify_opened() and it's opening phase is
319 * finished now. If there was no error returned then the backend is
320 * considered opened, otherwise it's considered closed. Use AuthenticationFailed
321 * error when the given credentials were rejected by the server/store, which
322 * will result in a re-prompt on the client side, otherwise use AuthenticationRequired
323 * if there was anything wrong with the given credentials. Set error's
324 * message to a reason for a re-prompt, it'll be shown to a user.
325 * 6) client checks error returned from e_book_backend_notify_opened() and
326 * reprompts for a password if it was AuthenticationFailed. Otherwise
327 * considers backend opened based on the error presence (no error means success).
329 * In any case, the call of e_book_backend_open() should be always finished
330 * with e_data_book_respond_open(), which has no influence on the opening phase,
331 * or alternatively with e_book_backend_respond_opened(). Never use authentication
332 * errors in e_data_book_respond_open() to notify the client the authentication is
333 * required, there is e_book_backend_notify_auth_required() for this.
336 e_book_backend_open (EBookBackend *backend,
339 GCancellable *cancellable,
340 gboolean only_if_exists)
342 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
343 g_return_if_fail (E_IS_DATA_BOOK (book));
345 g_mutex_lock (backend->priv->clients_mutex);
347 if (e_book_backend_is_opened (backend)) {
348 g_mutex_unlock (backend->priv->clients_mutex);
350 e_data_book_report_readonly (book, backend->priv->readonly);
351 e_data_book_report_online (book, backend->priv->online);
353 e_book_backend_respond_opened (backend, book, opid, NULL);
354 } else if (e_book_backend_is_opening (backend)) {
355 g_mutex_unlock (backend->priv->clients_mutex);
357 e_data_book_respond_open (book, opid, EDB_OPENING_ERROR);
359 backend->priv->opening = TRUE;
360 g_mutex_unlock (backend->priv->clients_mutex);
362 /* Subclasses may need to call e_book_backend_get_cache_dir() in
363 * their open() methods, so get the "cache-dir" property
364 * initialized before we call the method. */
365 book_backend_set_default_cache_dir (backend);
367 g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->open != NULL);
369 (* E_BOOK_BACKEND_GET_CLASS (backend)->open) (backend, book, opid, cancellable, only_if_exists);
374 * e_book_backend_remove:
375 * @backend: an #EBookBackend
376 * @book: an #EDataBook
377 * @cancellable: a #GCancellable for the operation
378 * @opid: the ID to use for this operation
380 * Executes a 'remove' request to remove all of @backend's data,
381 * specified by @opid on @book.
382 * This might be finished with e_data_book_respond_remove().
385 e_book_backend_remove (EBookBackend *backend,
388 GCancellable *cancellable)
390 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
391 g_return_if_fail (E_IS_DATA_BOOK (book));
392 g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->remove);
394 if (e_book_backend_is_opening (backend))
395 e_data_book_respond_remove (book, opid, EDB_OPENING_ERROR);
397 (* E_BOOK_BACKEND_GET_CLASS (backend)->remove) (backend, book, opid, cancellable);
401 * e_book_backend_refresh:
402 * @backend: an #EBookBackend
403 * @book: an #EDataBook
404 * @opid: the ID to use for this operation
405 * @cancellable: a #GCancellable for the operation
407 * Refreshes the address book being accessed by the given backend.
408 * This might be finished with e_data_book_respond_refresh(),
409 * and it might be called as soon as possible; it doesn't mean
410 * that the refreshing is done after calling that, the backend
411 * is only notifying client whether it started the refresh process
417 e_book_backend_refresh (EBookBackend *backend,
420 GCancellable *cancellable)
422 g_return_if_fail (backend != NULL);
423 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
425 if (e_book_backend_is_opening (backend))
426 e_data_book_respond_refresh (book, opid, EDB_OPENING_ERROR);
427 else if (!E_BOOK_BACKEND_GET_CLASS (backend)->refresh)
428 e_data_book_respond_refresh (book, opid, e_data_book_create_error (E_DATA_BOOK_STATUS_NOT_SUPPORTED, NULL));
429 else if (!e_book_backend_is_opened (backend))
430 e_data_book_respond_refresh (book, opid, EDB_NOT_OPENED_ERROR);
432 (* E_BOOK_BACKEND_GET_CLASS (backend)->refresh) (backend, book, opid, cancellable);
436 * e_book_backend_create_contacts
437 * @backend: an #EBookBackend
438 * @book: an #EDataBook
439 * @opid: the ID to use for this operation
440 * @cancellable: a #GCancellable for the operation
441 * @vcards: a #GSList of vCards to add
443 * Executes a 'create contacts' request specified by @opid on @book
445 * This might be finished with e_data_book_respond_create_contacts().
450 e_book_backend_create_contacts (EBookBackend *backend,
453 GCancellable *cancellable,
454 const GSList *vcards)
456 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
457 g_return_if_fail (E_IS_DATA_BOOK (book));
458 g_return_if_fail (vcards);
459 g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->create_contacts);
461 if (e_book_backend_is_opening (backend))
462 e_data_book_respond_create_contacts (book, opid, EDB_OPENING_ERROR, NULL);
463 else if (!e_book_backend_is_opened (backend))
464 e_data_book_respond_create_contacts (book, opid, EDB_NOT_OPENED_ERROR, NULL);
466 (* E_BOOK_BACKEND_GET_CLASS (backend)->create_contacts) (backend, book, opid, cancellable, vcards);
470 * e_book_backend_remove_contacts:
471 * @backend: an #EBookBackend
472 * @book: an #EDataBook
473 * @opid: the ID to use for this operation
474 * @cancellable: a #GCancellable for the operation
475 * @id_list: list of string IDs to remove
477 * Executes a 'remove contacts' request specified by @opid on @book
479 * This might be finished with e_data_book_respond_remove_contacts().
482 e_book_backend_remove_contacts (EBookBackend *backend,
485 GCancellable *cancellable,
486 const GSList *id_list)
488 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
489 g_return_if_fail (E_IS_DATA_BOOK (book));
490 g_return_if_fail (id_list);
491 g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->remove_contacts);
493 if (e_book_backend_is_opening (backend))
494 e_data_book_respond_remove_contacts (book, opid, EDB_OPENING_ERROR, NULL);
495 else if (!e_book_backend_is_opened (backend))
496 e_data_book_respond_remove_contacts (book, opid, EDB_NOT_OPENED_ERROR, NULL);
498 (* E_BOOK_BACKEND_GET_CLASS (backend)->remove_contacts) (backend, book, opid, cancellable, id_list);
502 * e_book_backend_modify_contacts:
503 * @backend: an #EBookBackend
504 * @book: an #EDataBook
505 * @opid: the ID to use for this operation
506 * @cancellable: a #GCancellable for the operation
507 * @vcards: the VCards to update
509 * Executes a 'modify contacts' request specified by @opid on @book
511 * This might be finished with e_data_book_respond_modify_contacts().
516 e_book_backend_modify_contacts (EBookBackend *backend,
519 GCancellable *cancellable,
520 const GSList *vcards)
522 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
523 g_return_if_fail (E_IS_DATA_BOOK (book));
524 g_return_if_fail (vcards);
525 g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->modify_contacts);
527 if (e_book_backend_is_opening (backend))
528 e_data_book_respond_modify_contacts (book, opid, EDB_OPENING_ERROR, NULL);
529 else if (!e_book_backend_is_opened (backend))
530 e_data_book_respond_modify_contacts (book, opid, EDB_NOT_OPENED_ERROR, NULL);
532 (* E_BOOK_BACKEND_GET_CLASS (backend)->modify_contacts) (backend, book, opid, cancellable, vcards);
536 * e_book_backend_get_contact:
537 * @backend: an #EBookBackend
538 * @book: an #EDataBook
539 * @opid: the ID to use for this operation
540 * @cancellable: a #GCancellable for the operation
541 * @id: the ID of the contact to get
543 * Executes a 'get contact' request specified by @opid on @book
545 * This might be finished with e_data_book_respond_get_contact().
548 e_book_backend_get_contact (EBookBackend *backend,
551 GCancellable *cancellable,
554 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
555 g_return_if_fail (E_IS_DATA_BOOK (book));
556 g_return_if_fail (id);
557 g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->get_contact);
559 if (e_book_backend_is_opening (backend))
560 e_data_book_respond_get_contact (book, opid, EDB_OPENING_ERROR, NULL);
561 else if (!e_book_backend_is_opened (backend))
562 e_data_book_respond_get_contact (book, opid, EDB_NOT_OPENED_ERROR, NULL);
564 (* E_BOOK_BACKEND_GET_CLASS (backend)->get_contact) (backend, book, opid, cancellable, id);
568 * e_book_backend_get_contact_list:
569 * @backend: an #EBookBackend
570 * @book: an #EDataBook
571 * @opid: the ID to use for this operation
572 * @cancellable: a #GCancellable for the operation
573 * @query: the s-expression to match
575 * Executes a 'get contact list' request specified by @opid on @book
577 * This might be finished with e_data_book_respond_get_contact_list().
580 e_book_backend_get_contact_list (EBookBackend *backend,
583 GCancellable *cancellable,
586 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
587 g_return_if_fail (E_IS_DATA_BOOK (book));
588 g_return_if_fail (query);
589 g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->get_contact_list);
591 if (e_book_backend_is_opening (backend))
592 e_data_book_respond_get_contact_list (book, opid, EDB_OPENING_ERROR, NULL);
593 else if (!e_book_backend_is_opened (backend))
594 e_data_book_respond_get_contact_list (book, opid, EDB_NOT_OPENED_ERROR, NULL);
596 (* E_BOOK_BACKEND_GET_CLASS (backend)->get_contact_list) (backend, book, opid, cancellable, query);
600 * e_book_backend_get_contact_list_uids:
601 * @backend: an #EBookBackend
602 * @book: an #EDataBook
603 * @opid: the ID to use for this operation
604 * @cancellable: a #GCancellable for the operation
605 * @query: the s-expression to match
607 * Executes a 'get contact list uids' request specified by @opid on @book
609 * This might be finished with e_data_book_respond_get_contact_list_uids().
614 e_book_backend_get_contact_list_uids (EBookBackend *backend,
617 GCancellable *cancellable,
620 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
621 g_return_if_fail (E_IS_DATA_BOOK (book));
622 g_return_if_fail (query);
623 g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->get_contact_list_uids);
625 if (e_book_backend_is_opening (backend))
626 e_data_book_respond_get_contact_list_uids (book, opid, EDB_OPENING_ERROR, NULL);
627 else if (!e_book_backend_is_opened (backend))
628 e_data_book_respond_get_contact_list_uids (book, opid, EDB_NOT_OPENED_ERROR, NULL);
630 (* E_BOOK_BACKEND_GET_CLASS (backend)->get_contact_list_uids) (backend, book, opid, cancellable, query);
634 * e_book_backend_start_book_view:
635 * @backend: an #EBookBackend
636 * @view: the #EDataBookView to start
638 * Starts running the query specified by @view, emitting signals for
642 e_book_backend_start_book_view (EBookBackend *backend,
645 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
646 g_return_if_fail (E_IS_DATA_BOOK_VIEW (view));
647 g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->start_book_view);
649 (* E_BOOK_BACKEND_GET_CLASS (backend)->start_book_view) (backend, view);
653 * e_book_backend_stop_book_view:
654 * @backend: an #EBookBackend
655 * @view: the #EDataBookView to stop
657 * Stops running the query specified by @view, emitting no more signals.
660 e_book_backend_stop_book_view (EBookBackend *backend,
663 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
664 g_return_if_fail (E_IS_DATA_BOOK_VIEW (view));
665 g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->stop_book_view);
667 (* E_BOOK_BACKEND_GET_CLASS (backend)->stop_book_view) (backend, view);
671 * e_book_backend_authenticate_user:
672 * @backend: an #EBookBackend
673 * @cancellable: a #GCancellable for the operation
674 * @credentials: #ECredentials to use for authentication
676 * Notifies @backend about @credentials provided by user to use
677 * for authentication. This notification is usually called during
678 * opening phase as a response to e_book_backend_notify_auth_required()
679 * on the client side and it results in setting property 'opening' to %TRUE
680 * unless the backend is already opened. This function finishes opening
681 * phase, thus it should be finished with e_book_backend_notify_opened().
683 * See information at e_book_backend_open() for more details
684 * how the opening phase works.
687 e_book_backend_authenticate_user (EBookBackend *backend,
688 GCancellable *cancellable,
689 ECredentials *credentials)
691 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
692 g_return_if_fail (credentials != NULL);
693 g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->authenticate_user);
695 if (backend->priv->opened)
696 backend->priv->opening = TRUE;
698 (* E_BOOK_BACKEND_GET_CLASS (backend)->authenticate_user) (backend, cancellable, credentials);
702 * e_book_backend_add_book_view:
703 * @backend: an #EBookBackend
704 * @view: an #EDataBookView
706 * Adds @view to @backend for querying.
709 e_book_backend_add_book_view (EBookBackend *backend,
712 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
714 g_mutex_lock (backend->priv->views_mutex);
716 e_data_book_view_ref (view);
717 backend->priv->views = g_slist_append (backend->priv->views, view);
719 g_mutex_unlock (backend->priv->views_mutex);
723 * e_book_backend_remove_book_view:
724 * @backend: an #EBookBackend
725 * @view: an #EDataBookView
727 * Removes @view from @backend.
730 e_book_backend_remove_book_view (EBookBackend *backend,
733 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
735 g_mutex_lock (backend->priv->views_mutex);
737 backend->priv->views = g_slist_remove (backend->priv->views, view);
738 e_data_book_view_unref (view);
740 g_mutex_unlock (backend->priv->views_mutex);
744 * e_book_backend_add_client:
745 * @backend: An addressbook backend.
746 * @book: the corba object representing the client connection.
748 * Adds a client to an addressbook backend.
750 * Returns: TRUE on success, FALSE on failure to add the client.
753 e_book_backend_add_client (EBookBackend *backend,
756 g_return_val_if_fail (E_IS_BOOK_BACKEND (backend), FALSE);
757 g_return_val_if_fail (E_IS_DATA_BOOK (book), FALSE);
759 g_mutex_lock (backend->priv->clients_mutex);
760 backend->priv->clients = g_slist_prepend (backend->priv->clients, book);
761 g_mutex_unlock (backend->priv->clients_mutex);
767 * e_book_backend_remove_client:
768 * @backend: an #EBookBackend
769 * @book: an #EDataBook to remove
771 * Removes @book from the list of @backend's clients.
774 e_book_backend_remove_client (EBookBackend *backend,
777 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
778 g_return_if_fail (E_IS_DATA_BOOK (book));
780 /* Make sure the backend stays alive while holding the mutex. */
781 g_object_ref (backend);
784 g_mutex_lock (backend->priv->clients_mutex);
785 backend->priv->clients = g_slist_remove (backend->priv->clients, book);
787 if (backend->priv->clients == NULL)
788 backend->priv->opening = FALSE;
790 g_mutex_unlock (backend->priv->clients_mutex);
792 g_object_unref (backend);
796 * e_book_backend_foreach_view:
797 * @backend: an #EBookBackend
798 * @callback: callback to call
799 * @user_data: user_data passed into the @callback
801 * Calls @callback for each known book view of this @backend.
802 * @callback returns %FALSE to stop further processing.
807 e_book_backend_foreach_view (EBookBackend *backend,
808 gboolean (*callback) (EDataBookView *view,
814 gboolean stop = FALSE;
816 g_return_if_fail (backend != NULL);
817 g_return_if_fail (callback != NULL);
819 g_mutex_lock (backend->priv->views_mutex);
821 for (views = backend->priv->views; views && !stop; views = views->next) {
822 view = E_DATA_BOOK_VIEW (views->data);
823 stop = !callback (view, user_data);
826 g_mutex_unlock (backend->priv->views_mutex);
830 * e_book_backend_get_book_backend_property:
831 * @backend: an #EBookBackend
832 * @book: an #EDataBook
833 * @opid: the ID to use for this operation
834 * @cancellable: a #GCancellable for the operation
835 * @prop_name: property name to get value of; cannot be NULL
837 * Calls the get_backend_property method on the given backend.
838 * This might be finished with e_data_book_respond_get_backend_property().
839 * Default implementation takes care of common properties and returns
840 * an 'unsupported' error for any unknown properties. The subclass may
841 * always call this default implementation for properties which fetching
842 * it doesn't overwrite.
847 e_book_backend_get_backend_property (EBookBackend *backend,
850 GCancellable *cancellable,
851 const gchar *prop_name)
853 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
854 g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->get_backend_property);
856 E_BOOK_BACKEND_GET_CLASS (backend)->get_backend_property (backend, book, opid, cancellable, prop_name);
860 * e_book_backend_set_backend_property:
861 * @backend: an #EBookBackend
862 * @book: an #EDataBook
863 * @opid: the ID to use for this operation
864 * @cancellable: a #GCancellable for the operation
865 * @prop_name: property name to change; cannot be NULL
866 * @prop_value: value to set to @prop_name; cannot be NULL
868 * Calls the set_backend_property method on the given backend.
869 * This might be finished with e_data_book_respond_set_backend_property().
870 * Default implementation simply returns an 'unsupported' error.
871 * The subclass may always call this default implementation for properties
872 * which fetching it doesn't overwrite.
877 e_book_backend_set_backend_property (EBookBackend *backend,
880 GCancellable *cancellable,
881 const gchar *prop_name,
882 const gchar *prop_value)
884 g_return_if_fail (backend != NULL);
885 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
886 g_return_if_fail (prop_name != NULL);
887 g_return_if_fail (prop_value != NULL);
888 g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->set_backend_property != NULL);
890 E_BOOK_BACKEND_GET_CLASS (backend)->set_backend_property (backend, book, opid, cancellable, prop_name, prop_value);
894 * e_book_backend_is_opened:
895 * @backend: an #EBookBackend
897 * Checks if @backend's storage has been opened (and
898 * authenticated, if necessary) and the backend itself
899 * is ready for accessing. This property is changed automatically
900 * within call of e_book_backend_notify_opened().
902 * Returns: %TRUE if fully opened, %FALSE otherwise.
907 e_book_backend_is_opened (EBookBackend *backend)
909 g_return_val_if_fail (E_IS_BOOK_BACKEND (backend), FALSE);
911 return backend->priv->opened;
915 * e_book_backend_is_opening:
916 * @backend: an #EBookBackend
918 * Checks if @backend is processing its opening phase, which
919 * includes everything since the e_book_backend_open() call,
920 * through authentication, up to e_book_backend_notify_opened().
921 * This property is managed automatically and the backend deny
922 * every operation except of cancel and authenticate_user while
923 * it is being opening.
925 * Returns: %TRUE if opening phase is in the effect, %FALSE otherwise.
930 e_book_backend_is_opening (EBookBackend *backend)
932 g_return_val_if_fail (E_IS_BOOK_BACKEND (backend), FALSE);
934 return backend->priv->opening;
938 * e_book_backend_is_readonly:
939 * @backend: an #EBookBackend
941 * Checks if we can write to @backend.
943 * Returns: %TRUE if writeable, %FALSE if not.
948 e_book_backend_is_readonly (EBookBackend *backend)
950 g_return_val_if_fail (E_IS_BOOK_BACKEND (backend), FALSE);
952 return backend->priv->readonly;
956 * e_book_backend_is_removed:
957 * @backend: an #EBookBackend
959 * Checks if @backend has been removed from its physical storage.
961 * Returns: %TRUE if @backend has been removed, %FALSE otherwise.
964 e_book_backend_is_removed (EBookBackend *backend)
966 g_return_val_if_fail (E_IS_BOOK_BACKEND (backend), FALSE);
968 return backend->priv->removed;
972 * e_book_backend_set_is_removed:
973 * @backend: an #EBookBackend
974 * @is_removed: A flag indicating whether the backend's storage was removed
976 * Sets the flag indicating whether @backend was removed to @is_removed.
977 * Meant to be used by backend implementations.
980 e_book_backend_set_is_removed (EBookBackend *backend,
983 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
985 backend->priv->removed = is_removed;
989 * e_book_backend_sync:
990 * @backend: an #EBookbackend
992 * Write all pending data to disk. This is only required under special
993 * circumstances (for example before a live backup) and should not be used in
999 e_book_backend_sync (EBookBackend *backend)
1001 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
1003 g_object_ref (backend);
1005 if (E_BOOK_BACKEND_GET_CLASS (backend)->sync)
1006 (* E_BOOK_BACKEND_GET_CLASS (backend)->sync) (backend);
1008 g_object_unref (backend);
1012 * e_book_backend_notify_update:
1013 * @backend: an #EBookBackend
1014 * @contact: a new or modified contact
1016 * Notifies all of @backend's book views about the new or modified
1017 * contacts @contact.
1019 * e_data_book_respond_create_contacts() and e_data_book_respond_modify_contacts() call this
1020 * function for you. You only need to call this from your backend if
1021 * contacts are created or modified by another (non-PAS-using) client.
1024 e_book_backend_notify_update (EBookBackend *backend,
1025 const EContact *contact)
1027 E_BOOK_BACKEND_GET_CLASS (backend)->notify_update (backend, contact);
1031 view_notify_remove (EDataBookView *view,
1034 e_data_book_view_notify_remove (view, id);
1040 * e_book_backend_notify_remove:
1041 * @backend: an #EBookBackend
1044 * Notifies all of @backend's book views that the contact with UID
1045 * @id has been removed.
1047 * e_data_book_respond_remove_contacts() calls this function for you. You
1048 * only need to call this from your backend if contacts are removed by
1049 * another (non-PAS-using) client.
1052 e_book_backend_notify_remove (EBookBackend *backend,
1055 e_book_backend_foreach_view (backend, view_notify_remove, (gpointer) id);
1059 view_notify_complete (EDataBookView *view,
1062 e_data_book_view_notify_complete (view, NULL /* SUCCESS */);
1068 * e_book_backend_notify_complete:
1069 * @backend: an #EBookbackend
1071 * Notifies all of @backend's book views that the current set of
1072 * notifications is complete; use this after a series of
1073 * e_book_backend_notify_update() and e_book_backend_notify_remove() calls.
1076 e_book_backend_notify_complete (EBookBackend *backend)
1078 e_book_backend_foreach_view (backend, view_notify_complete, NULL);
1083 * e_book_backend_notify_error:
1084 * @backend: an #EBookBackend
1085 * @message: an error message
1087 * Notifies each backend listener about an error. This is meant to be used
1088 * for cases where is no GError return possibility, to notify user about
1094 e_book_backend_notify_error (EBookBackend *backend,
1095 const gchar *message)
1097 EBookBackendPrivate *priv;
1100 priv = backend->priv;
1102 g_mutex_lock (priv->clients_mutex);
1104 for (clients = priv->clients; clients != NULL; clients = g_slist_next (clients))
1105 e_data_book_report_error (E_DATA_BOOK (clients->data), message);
1107 g_mutex_unlock (priv->clients_mutex);
1111 * e_book_backend_notify_readonly:
1112 * @backend: an #EBookBackend
1113 * @is_readonly: flag indicating readonly status
1115 * Notifies all backend's clients about the current readonly state.
1120 e_book_backend_notify_readonly (EBookBackend *backend,
1121 gboolean is_readonly)
1123 EBookBackendPrivate *priv;
1126 priv = backend->priv;
1127 priv->readonly = is_readonly;
1128 g_mutex_lock (priv->clients_mutex);
1130 for (clients = priv->clients; clients != NULL; clients = g_slist_next (clients))
1131 e_data_book_report_readonly (E_DATA_BOOK (clients->data), is_readonly);
1133 g_mutex_unlock (priv->clients_mutex);
1138 * e_book_backend_notify_online:
1139 * @backend: an #EBookBackend
1140 * @is_online: flag indicating whether @backend is connected and online
1142 * Notifies clients of @backend's connection status indicated by @is_online.
1143 * Meant to be used by backend implementations.
1148 e_book_backend_notify_online (EBookBackend *backend,
1151 EBookBackendPrivate *priv;
1154 priv = backend->priv;
1155 priv->online = is_online;
1156 g_mutex_lock (priv->clients_mutex);
1158 for (clients = priv->clients; clients != NULL; clients = g_slist_next (clients))
1159 e_data_book_report_online (E_DATA_BOOK (clients->data), is_online);
1161 g_mutex_unlock (priv->clients_mutex);
1165 * e_book_backend_notify_auth_required:
1166 * @backend: an #EBookBackend
1167 * @is_self: Use %TRUE to indicate the authentication is required
1168 * for the @backend, otheriwse the authentication is for any
1169 * other source. Having @credentials %NULL means @is_self
1171 * @credentials: an #ECredentials that contains extra information for
1172 * a source for which authentication is requested.
1173 * This parameter can be %NULL to indicate "for this book".
1175 * Notifies clients that @backend requires authentication in order to
1176 * connect. This function call does not influence 'opening', but
1177 * influences 'opened' property, which is set to %FALSE when @is_self
1178 * is %TRUE or @credentials is %NULL. Opening phase is finished
1179 * by e_book_backend_notify_opened() if this is requested for @backend.
1181 * See e_book_backend_open() for a description how the whole opening
1184 * Meant to be used by backend implementations.
1187 e_book_backend_notify_auth_required (EBookBackend *backend,
1189 const ECredentials *credentials)
1191 EBookBackendPrivate *priv;
1194 priv = backend->priv;
1195 g_mutex_lock (priv->clients_mutex);
1197 if (is_self || !credentials)
1198 priv->opened = FALSE;
1200 for (clients = priv->clients; clients != NULL; clients = g_slist_next (clients))
1201 e_data_book_report_auth_required (E_DATA_BOOK (clients->data), credentials);
1203 g_mutex_unlock (priv->clients_mutex);
1207 * e_book_backend_notify_opened:
1208 * @backend: an #EBookBackend
1209 * @error: a #GError corresponding to the error encountered during
1210 * the opening phase. Use %NULL for success. The @error is freed
1211 * automatically if not %NULL.
1213 * Notifies clients that @backend finished its opening phase.
1214 * See e_book_backend_open() for more information how the opening
1215 * phase works. Calling this function changes 'opening' property,
1216 * same as 'opened'. 'opening' is set to %FALSE and the backend
1217 * is considered 'opened' only if the @error is %NULL.
1219 * See also: e_book_backend_respond_opened()
1221 * Note: The @error is freed automatically if not %NULL.
1223 * Meant to be used by backend implementations.
1228 e_book_backend_notify_opened (EBookBackend *backend,
1231 EBookBackendPrivate *priv;
1234 priv = backend->priv;
1235 g_mutex_lock (priv->clients_mutex);
1237 priv->opening = FALSE;
1238 priv->opened = error == NULL;
1240 for (clients = priv->clients; clients != NULL; clients = g_slist_next (clients))
1241 e_data_book_report_opened (E_DATA_BOOK (clients->data), error);
1243 g_mutex_unlock (priv->clients_mutex);
1246 g_error_free (error);
1250 * e_book_backend_notify_property_changed:
1251 * @backend: an #EBookBackend
1252 * @prop_name: property name, which changed
1253 * @prop_value: new property value
1255 * Notifies clients about property value change.
1260 e_book_backend_notify_property_changed (EBookBackend *backend,
1261 const gchar *prop_name,
1262 const gchar *prop_value)
1264 EBookBackendPrivate *priv;
1267 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
1268 g_return_if_fail (prop_name != NULL);
1269 g_return_if_fail (*prop_name != '\0');
1270 g_return_if_fail (prop_value != NULL);
1272 priv = backend->priv;
1273 g_mutex_lock (priv->clients_mutex);
1275 for (clients = priv->clients; clients != NULL; clients = g_slist_next (clients))
1276 e_data_book_report_backend_property_changed (E_DATA_BOOK (clients->data), prop_name, prop_value);
1278 g_mutex_unlock (priv->clients_mutex);
1282 * e_book_backend_respond_opened:
1283 * @backend: an #EBookBackend
1284 * @book: an #EDataBook
1285 * @opid: an operation ID
1286 * @error: result error; can be %NULL, if it isn't then it's automatically freed
1288 * This is a replacement for e_data_book_respond_open() for cases where
1289 * the finish of 'open' method call also finishes backend opening phase.
1290 * This function covers calling of both e_book_backend_notify_opened()
1291 * and e_data_book_respond_open() with the same @error.
1293 * See e_book_backend_open() for more details how the opening phase works.
1298 e_book_backend_respond_opened (EBookBackend *backend,
1303 GError *copy = NULL;
1305 g_return_if_fail (backend != NULL);
1306 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
1307 g_return_if_fail (book != NULL);
1308 g_return_if_fail (opid != 0);
1311 copy = g_error_copy (error);
1313 e_book_backend_notify_opened (backend, copy);
1314 e_data_book_respond_open (book, opid, error);