1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* Evolution calendar - generic backend class
4 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
6 * Authors: Federico Mena-Quintero <federico@ximian.com>
7 * JP Rosevear <jpr@ximian.com>
8 * Rodrigo Moya <rodrigo@ximian.com>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of version 2 of the GNU Lesser General Public
12 * License as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 #include <glib/gi18n-lib.h>
28 #include <libedataserver/e-data-server-util.h>
30 #include "e-cal-backend.h"
31 #include "e-cal-backend-cache.h"
33 #define EDC_ERROR(_code) e_data_cal_create_error (_code, NULL)
34 #define EDC_OPENING_ERROR e_data_cal_create_error (Busy, _("Cannot process, calendar backend is opening"))
35 #define EDC_NOT_OPENED_ERROR e_data_cal_create_error (NotOpened, NULL)
37 /* Private part of the CalBackend structure */
38 struct _ECalBackendPrivate {
39 /* The kind of components for this backend */
40 icalcomponent_kind kind;
42 gboolean opening, opened, readonly, removed;
44 /* URI, from source. This is cached, since we return const. */
49 /* List of Cal objects */
50 GMutex *clients_mutex;
56 /* ECalBackend to pass notifications on to */
57 ECalBackend *notification_proxy;
68 static void e_cal_backend_remove_client_private (ECalBackend *backend, EDataCal *cal, gboolean weak_unref);
70 G_DEFINE_TYPE (ECalBackend, e_cal_backend, E_TYPE_BACKEND);
73 cal_backend_set_default_cache_dir (ECalBackend *backend)
76 icalcomponent_kind kind;
77 const gchar *component_type;
78 const gchar *user_cache_dir;
82 user_cache_dir = e_get_user_cache_dir ();
84 kind = e_cal_backend_get_kind (backend);
85 source = e_backend_get_source (E_BACKEND (backend));
88 case ICAL_VEVENT_COMPONENT:
89 component_type = "calendar";
91 case ICAL_VTODO_COMPONENT:
92 component_type = "tasks";
94 case ICAL_VJOURNAL_COMPONENT:
95 component_type = "memos";
98 g_return_if_reached ();
101 /* Mangle the URI to not contain invalid characters. */
102 mangled_uri = g_strdelimit (e_source_get_uri (source), ":/", '_');
104 filename = g_build_filename (
105 user_cache_dir, component_type, mangled_uri, NULL);
106 e_cal_backend_set_cache_dir (backend, filename);
109 g_free (mangled_uri);
113 cal_backend_set_kind (ECalBackend *backend,
114 icalcomponent_kind kind)
116 backend->priv->kind = kind;
120 cal_backend_get_backend_property (ECalBackend *backend,
123 GCancellable *cancellable,
124 const gchar *prop_name)
126 g_return_if_fail (backend != NULL);
127 g_return_if_fail (E_IS_CAL_BACKEND (backend));
128 g_return_if_fail (cal != NULL);
129 g_return_if_fail (prop_name != NULL);
131 if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_OPENED)) {
132 e_data_cal_respond_get_backend_property (cal, opid, NULL, e_cal_backend_is_opened (backend) ? "TRUE" : "FALSE");
133 } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_OPENING)) {
134 e_data_cal_respond_get_backend_property (cal, opid, NULL, e_cal_backend_is_opening (backend) ? "TRUE" : "FALSE");
135 } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_ONLINE)) {
136 e_data_cal_respond_get_backend_property (cal, opid, NULL, e_backend_get_online (E_BACKEND (backend)) ? "TRUE" : "FALSE");
137 } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_READONLY)) {
138 e_data_cal_respond_get_backend_property (cal, opid, NULL, e_cal_backend_is_readonly (backend) ? "TRUE" : "FALSE");
139 } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CACHE_DIR)) {
140 e_data_cal_respond_get_backend_property (cal, opid, NULL, e_cal_backend_get_cache_dir (backend));
142 e_data_cal_respond_get_backend_property (cal, opid, e_data_cal_create_error_fmt (NotSupported, _("Unknown calendar property '%s'"), prop_name), NULL);
147 cal_backend_set_backend_property (ECalBackend *backend,
150 GCancellable *cancellable,
151 const gchar *prop_name,
152 const gchar *prop_value)
154 g_return_if_fail (backend != NULL);
155 g_return_if_fail (E_IS_CAL_BACKEND (backend));
156 g_return_if_fail (cal != NULL);
157 g_return_if_fail (prop_name != NULL);
159 e_data_cal_respond_set_backend_property (cal, opid, e_data_cal_create_error_fmt (NotSupported, _("Cannot change value of calendar property '%s'"), prop_name));
163 cal_backend_set_property (GObject *object,
168 switch (property_id) {
170 e_cal_backend_set_cache_dir (
171 E_CAL_BACKEND (object),
172 g_value_get_string (value));
175 cal_backend_set_kind (
176 E_CAL_BACKEND (object),
177 g_value_get_ulong (value));
181 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
185 cal_backend_get_property (GObject *object,
190 switch (property_id) {
193 value, e_cal_backend_get_cache_dir (
194 E_CAL_BACKEND (object)));
198 value, e_cal_backend_get_kind (
199 E_CAL_BACKEND (object)));
203 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
207 cal_backend_finalize (GObject *object)
209 ECalBackendPrivate *priv;
211 priv = E_CAL_BACKEND (object)->priv;
213 g_assert (priv->clients == NULL);
215 g_slist_free (priv->views);
216 /* should be NULL, anyway */
217 g_slist_free (priv->clients);
219 g_mutex_free (priv->clients_mutex);
220 g_mutex_free (priv->views_mutex);
222 g_free (priv->cache_dir);
224 /* Chain up to parent's finalize() method. */
225 G_OBJECT_CLASS (e_cal_backend_parent_class)->finalize (object);
229 cal_backend_constructed (GObject *object)
231 cal_backend_set_default_cache_dir (E_CAL_BACKEND (object));
233 G_OBJECT_CLASS (e_cal_backend_parent_class)->constructed (object);
237 e_cal_backend_class_init (ECalBackendClass *klass)
239 GObjectClass *object_class;
241 g_type_class_add_private (klass, sizeof (ECalBackendPrivate));
243 object_class = G_OBJECT_CLASS (klass);
244 object_class->set_property = cal_backend_set_property;
245 object_class->get_property = cal_backend_get_property;
246 object_class->finalize = cal_backend_finalize;
247 object_class->constructed = cal_backend_constructed;
249 klass->get_backend_property = cal_backend_get_backend_property;
250 klass->set_backend_property = cal_backend_set_backend_property;
252 g_object_class_install_property (
255 g_param_spec_string (
262 g_object_class_install_property (
270 ICAL_XLICMIMEPART_COMPONENT,
273 G_PARAM_CONSTRUCT_ONLY));
277 e_cal_backend_init (ECalBackend *backend)
279 backend->priv = G_TYPE_INSTANCE_GET_PRIVATE (
280 backend, E_TYPE_CAL_BACKEND, ECalBackendPrivate);
282 backend->priv->clients = NULL;
283 backend->priv->clients_mutex = g_mutex_new ();
285 backend->priv->views = NULL;
286 backend->priv->views_mutex = g_mutex_new ();
288 backend->priv->readonly = TRUE;
292 * e_cal_backend_get_kind:
293 * @backend: an #ECalBackend
295 * Gets the kind of components the given backend stores.
297 * Returns: The kind of components for this backend.
300 e_cal_backend_get_kind (ECalBackend *backend)
302 g_return_val_if_fail (E_IS_CAL_BACKEND (backend), ICAL_NO_COMPONENT);
304 return backend->priv->kind;
308 * e_cal_backend_is_opened:
309 * @backend: an #ECalBackend
311 * Checks if @backend's storage has been opened (and
312 * authenticated, if necessary) and the backend itself
313 * is ready for accessing. This property is changed automatically
314 * within call of e_cal_backend_notify_opened().
316 * Returns: %TRUE if fully opened, %FALSE otherwise.
321 e_cal_backend_is_opened (ECalBackend *backend)
323 g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
325 return backend->priv->opened;
329 * e_cal_backend_is_opening:
330 * @backend: an #ECalBackend
332 * Checks if @backend is processing its opening phase, which
333 * includes everything since the e_cal_backend_open() call,
334 * through authentication, up to e_cal_backend_notify_opened().
335 * This property is managed automatically and the backend deny
336 * every operation except of cancel and authenticate_user while
337 * it is being opening.
339 * Returns: %TRUE if opening phase is in the effect, %FALSE otherwise.
344 e_cal_backend_is_opening (ECalBackend *backend)
346 g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
348 return backend->priv->opening;
352 * e_cal_backend_is_readonly:
353 * @backend: an #ECalBackend
355 * Returns: Whether is backend read-only. This value is the last used
356 * in a call of e_cal_backend_notify_readonly().
361 e_cal_backend_is_readonly (ECalBackend *backend)
363 g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
365 return backend->priv->readonly;
369 * e_cal_backend_is_removed:
370 * @backend: an #ECalBackend
372 * Checks if @backend has been removed from its physical storage.
374 * Returns: %TRUE if @backend has been removed, %FALSE otherwise.
379 e_cal_backend_is_removed (ECalBackend *backend)
381 g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
383 return backend->priv->removed;
387 * e_cal_backend_set_is_removed:
388 * @backend: an #ECalBackend
389 * @is_removed: A flag indicating whether the backend's storage was removed
391 * Sets the flag indicating whether @backend was removed to @is_removed.
392 * Meant to be used by backend implementations.
397 e_cal_backend_set_is_removed (ECalBackend *backend,
400 g_return_if_fail (E_IS_CAL_BACKEND (backend));
402 backend->priv->removed = is_removed;
406 * e_cal_backend_get_cache_dir:
407 * @backend: an #ECalBackend
409 * Returns the cache directory for the given backend.
411 * Returns: the cache directory for the backend
416 e_cal_backend_get_cache_dir (ECalBackend *backend)
418 g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
420 return backend->priv->cache_dir;
424 * e_cal_backend_set_cache_dir:
425 * @backend: an #ECalBackend
426 * @cache_dir: a local cache directory
428 * Sets the cache directory for the given backend.
430 * Note that #ECalBackend is initialized with a usable default based on
431 * #ECalBackend:source and #ECalBackend:kind properties. Backends should
432 * not override the default without good reason.
437 e_cal_backend_set_cache_dir (ECalBackend *backend,
438 const gchar *cache_dir)
440 g_return_if_fail (E_IS_CAL_BACKEND (backend));
441 g_return_if_fail (cache_dir != NULL);
443 g_free (backend->priv->cache_dir);
444 backend->priv->cache_dir = g_strdup (cache_dir);
446 g_object_notify (G_OBJECT (backend), "cache-dir");
450 * e_cal_backend_create_cache_filename:
451 * @backend: an #ECalBackend
452 * @uid: a component UID
453 * @filename: a filename to use; can be NULL
454 * @fileindex: index of a file; used only when @filename is NULL
456 * Returns: a filename for an attachment in a local cache dir. Free returned
457 * pointer with a g_free().
462 e_cal_backend_create_cache_filename (ECalBackend *backend, const gchar *uid, const gchar *filename, gint fileindex)
464 g_return_val_if_fail (backend != NULL, NULL);
465 g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
467 return e_filename_mkdir_encoded (e_cal_backend_get_cache_dir (backend), uid, filename, fileindex);
471 * e_cal_backend_get_backend_property:
472 * @backend: an #ECalBackend
474 * @opid: the ID to use for this operation
475 * @cancellable: a #GCancellable for the operation
476 * @prop_name: property name to get value of; cannot be NULL
478 * Calls the get_backend_property method on the given backend.
479 * This might be finished with e_data_cal_respond_get_backend_property().
480 * Default implementation takes care of common properties and returns
481 * an 'unsupported' error for any unknown properties. The subclass may
482 * always call this default implementation for properties which fetching
483 * it doesn't overwrite.
488 e_cal_backend_get_backend_property (ECalBackend *backend,
491 GCancellable *cancellable,
492 const gchar *prop_name)
494 g_return_if_fail (backend != NULL);
495 g_return_if_fail (E_IS_CAL_BACKEND (backend));
496 g_return_if_fail (prop_name != NULL);
497 g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_backend_property != NULL);
499 (* E_CAL_BACKEND_GET_CLASS (backend)->get_backend_property) (backend, cal, opid, cancellable, prop_name);
503 * e_cal_backend_set_backend_property:
504 * @backend: an #ECalBackend
506 * @opid: the ID to use for this operation
507 * @cancellable: a #GCancellable for the operation
508 * @prop_name: property name to change; cannot be NULL
509 * @prop_value: value to set to @prop_name; cannot be NULL
511 * Calls the set_backend_property method on the given backend.
512 * This might be finished with e_data_cal_respond_set_backend_property().
513 * Default implementation simply returns an 'unsupported' error.
514 * The subclass may always call this default implementation for properties
515 * which fetching it doesn't overwrite.
520 e_cal_backend_set_backend_property (ECalBackend *backend,
523 GCancellable *cancellable,
524 const gchar *prop_name,
525 const gchar *prop_value)
527 g_return_if_fail (backend != NULL);
528 g_return_if_fail (E_IS_CAL_BACKEND (backend));
529 g_return_if_fail (prop_name != NULL);
530 g_return_if_fail (prop_value != NULL);
531 g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->set_backend_property != NULL);
533 (* E_CAL_BACKEND_GET_CLASS (backend)->set_backend_property) (backend, cal, opid, cancellable, prop_name, prop_value);
537 cal_destroy_cb (gpointer data,
538 GObject *where_cal_was)
540 e_cal_backend_remove_client_private (E_CAL_BACKEND (data),
541 (EDataCal *) where_cal_was, FALSE);
545 * e_cal_backend_add_client:
546 * @backend: an #ECalBackend
549 * Adds a new client to the given backend. For any event, the backend will
550 * notify all clients added via this function.
553 e_cal_backend_add_client (ECalBackend *backend,
556 ECalBackendPrivate *priv;
558 g_return_if_fail (backend != NULL);
559 g_return_if_fail (E_IS_CAL_BACKEND (backend));
560 g_return_if_fail (cal != NULL);
561 g_return_if_fail (E_IS_DATA_CAL (cal));
563 priv = backend->priv;
565 g_object_weak_ref (G_OBJECT (cal), cal_destroy_cb, backend);
567 g_mutex_lock (priv->clients_mutex);
568 priv->clients = g_slist_append (priv->clients, cal);
569 g_mutex_unlock (priv->clients_mutex);
573 e_cal_backend_remove_client_private (ECalBackend *backend,
577 ECalBackendPrivate *priv;
579 /* XXX this needs a bit more thinking wrt the mutex - we
580 * should be holding it when we check to see if clients is
582 g_return_if_fail (backend != NULL);
583 g_return_if_fail (E_IS_CAL_BACKEND (backend));
584 g_return_if_fail (cal != NULL);
585 g_return_if_fail (E_IS_DATA_CAL (cal));
587 priv = backend->priv;
590 g_object_weak_unref (G_OBJECT (cal), cal_destroy_cb, backend);
593 g_mutex_lock (priv->clients_mutex);
594 priv->clients = g_slist_remove (priv->clients, cal);
595 g_mutex_unlock (priv->clients_mutex);
597 /* When all clients go away, notify the parent factory about it so that
598 * it may decide whether to kill the backend or not.
600 if (!priv->clients) {
601 priv->opening = FALSE;
602 e_backend_last_client_gone (E_BACKEND (backend));
607 * e_cal_backend_remove_client:
608 * @backend: an #ECalBackend
611 * Removes a client from the list of connected clients to the given backend.
614 e_cal_backend_remove_client (ECalBackend *backend,
617 e_cal_backend_remove_client_private (backend, cal, TRUE);
621 * e_cal_backend_add_view:
622 * @backend: an #ECalBackend
623 * @view: An #EDataCalView object.
625 * Adds a view to the list of live views being run by the given backend.
626 * Doing so means that any listener on the view will get notified of any
627 * change that affect the live view.
632 e_cal_backend_add_view (ECalBackend *backend,
635 g_return_if_fail (backend != NULL);
636 g_return_if_fail (E_IS_CAL_BACKEND (backend));
638 g_mutex_lock (backend->priv->views_mutex);
640 backend->priv->views = g_slist_append (backend->priv->views, view);
642 g_mutex_unlock (backend->priv->views_mutex);
646 * e_cal_backend_remove_view
647 * @backend: an #ECalBackend
648 * @view: An #EDataCalView object, previously added with @ref e_cal_backend_add_view.
650 * Removes view from the list of live views for the backend.
655 e_cal_backend_remove_view (ECalBackend *backend,
658 g_return_if_fail (backend != NULL);
659 g_return_if_fail (E_IS_CAL_BACKEND (backend));
661 g_mutex_lock (backend->priv->views_mutex);
663 backend->priv->views = g_slist_remove (backend->priv->views, view);
665 g_mutex_unlock (backend->priv->views_mutex);
669 * e_cal_backend_foreach_view:
670 * @backend: an #ECalBackend
671 * @callback: callback to call
672 * @user_data: user_data passed into the @callback
674 * Calls @callback for each known calendar view of this @backend.
675 * @callback returns %FALSE to stop further processing.
680 e_cal_backend_foreach_view (ECalBackend *backend,
681 gboolean (*callback) (EDataCalView *view,
687 gboolean stop = FALSE;
689 g_return_if_fail (backend != NULL);
690 g_return_if_fail (callback != NULL);
692 g_mutex_lock (backend->priv->views_mutex);
694 for (views = backend->priv->views; views && !stop; views = views->next) {
695 view = E_DATA_CAL_VIEW (views->data);
698 stop = !callback (view, user_data);
699 g_object_unref (view);
702 g_mutex_unlock (backend->priv->views_mutex);
706 * e_cal_backend_set_notification_proxy:
707 * @backend: an #ECalBackend
708 * @proxy: The calendar backend to act as notification proxy.
710 * Sets the backend that will act as notification proxy for the given backend.
715 e_cal_backend_set_notification_proxy (ECalBackend *backend,
718 g_return_if_fail (E_IS_CAL_BACKEND (backend));
720 backend->priv->notification_proxy = proxy;
724 * e_cal_backend_open:
725 * @backend: an #ECalBackend
727 * @opid: the ID to use for this operation
728 * @cancellable: a #GCancellable for the operation
729 * @only_if_exists: Whether the calendar should be opened only if it already
730 * exists. If FALSE, a new calendar will be created when the specified @uri
733 * Opens a calendar backend with data from a calendar stored at the specified URI.
734 * This might be finished with e_data_cal_respond_open() or e_cal_backend_respond_opened(),
735 * though the overall opening phase finishes only after call
736 * of e_cal_backend_notify_opened() after which call the backend
737 * is either fully opened (including authentication against (remote)
738 * server/storage) or an error was encountered during this opening phase.
739 * 'opened' and 'opening' properties are updated automatically.
740 * The backend refuses all other operations until the opening phase is finished.
742 * The e_cal_backend_notify_opened() is called either from this function
743 * or from e_cal_backend_authenticate_user(), or after necessary steps
744 * initiated by these two functions.
746 * The opening phase usually works like this:
747 * 1) client requests open for the backend
748 * 2) server receives this request and calls e_cal_backend_open() - the opening phase begun
749 * 3) either the backend is opened during this call, and notifies client
750 * with e_cal_backend_notify_opened() about that. This is usually
751 * for local backends; their opening phase is finished
752 * 4) or the backend requires authentication, thus it notifies client
753 * about that with e_cal_backend_notify_auth_required() and is
754 * waiting for credentials, which will be received from client
755 * by e_cal_backend_authenticate_user() call. Backend's opening
756 * phase is still running in this case, thus it doesn't call
757 * e_cal_backend_notify_opened() within e_cal_backend_open() call.
758 * 5) when backend receives credentials in e_cal_backend_authenticate_user()
759 * then it tries to authenticate against a server/storage with them
760 * and only after it knows result of the authentication, whether user
761 * was or wasn't authenticated, it notifies client with the result
762 * by e_cal_backend_notify_opened() and it's opening phase is
763 * finished now. If there was no error returned then the backend is
764 * considered opened, otherwise it's considered closed. Use AuthenticationFailed
765 * error when the given credentials were rejected by the server/store, which
766 * will result in a re-prompt on the client side, otherwise use AuthenticationRequired
767 * if there was anything wrong with the given credentials. Set error's
768 * message to a reason for a re-prompt, it'll be shown to a user.
769 * 6) client checks error returned from e_cal_backend_notify_opened() and
770 * reprompts for a password if it was AuthenticationFailed. Otherwise
771 * considers backend opened based on the error presence (no error means success).
773 * In any case, the call of e_cal_backend_open() should be always finished
774 * with e_data_cal_respond_open(), which has no influence on the opening phase,
775 * or alternatively with e_cal_backend_respond_opened(). Never use authentication
776 * errors in e_data_cal_respond_open() to notify the client the authentication is
777 * required, there is e_cal_backend_notify_auth_required() for this.
780 e_cal_backend_open (ECalBackend *backend,
783 GCancellable *cancellable,
784 gboolean only_if_exists)
786 g_return_if_fail (backend != NULL);
787 g_return_if_fail (E_IS_CAL_BACKEND (backend));
788 g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->open != NULL);
790 g_mutex_lock (backend->priv->clients_mutex);
792 if (e_cal_backend_is_opened (backend)) {
795 g_mutex_unlock (backend->priv->clients_mutex);
797 e_data_cal_report_readonly (cal, backend->priv->readonly);
799 online = e_backend_get_online (E_BACKEND (backend));
800 e_data_cal_report_online (cal, online);
802 e_cal_backend_respond_opened (backend, cal, opid, NULL);
803 } else if (e_cal_backend_is_opening (backend)) {
804 g_mutex_unlock (backend->priv->clients_mutex);
806 e_data_cal_respond_open (cal, opid, EDC_OPENING_ERROR);
808 backend->priv->opening = TRUE;
809 g_mutex_unlock (backend->priv->clients_mutex);
811 (* E_CAL_BACKEND_GET_CLASS (backend)->open) (backend, cal, opid, cancellable, only_if_exists);
816 * e_cal_backend_authenticate_user:
817 * @backend: an #ECalBackend
818 * @cancellable: a #GCancellable for the operation
819 * @credentials: #ECredentials to use for authentication
821 * Notifies @backend about @credentials provided by user to use
822 * for authentication. This notification is usually called during
823 * opening phase as a response to e_cal_backend_notify_auth_required()
824 * on the client side and it results in setting property 'opening' to %TRUE
825 * unless the backend is already opened. This function finishes opening
826 * phase, thus it should be finished with e_cal_backend_notify_opened().
828 * See information at e_cal_backend_open() for more details
829 * how the opening phase works.
834 e_cal_backend_authenticate_user (ECalBackend *backend,
835 GCancellable *cancellable,
836 ECredentials *credentials)
838 g_return_if_fail (E_IS_CAL_BACKEND (backend));
839 g_return_if_fail (credentials != NULL);
840 g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->authenticate_user);
842 if (!e_cal_backend_is_opened (backend))
843 backend->priv->opening = TRUE;
845 (* E_CAL_BACKEND_GET_CLASS (backend)->authenticate_user) (backend, cancellable, credentials);
849 * e_cal_backend_remove:
850 * @backend: an #ECalBackend
852 * @opid: the ID to use for this operation
853 * @cancellable: a #GCancellable for the operation
855 * Removes the calendar being accessed by the given backend.
856 * This might be finished with e_data_cal_respond_remove().
859 e_cal_backend_remove (ECalBackend *backend,
862 GCancellable *cancellable)
864 g_return_if_fail (backend != NULL);
865 g_return_if_fail (E_IS_CAL_BACKEND (backend));
866 g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->remove != NULL);
868 if (e_cal_backend_is_opening (backend))
869 e_data_cal_respond_remove (cal, opid, EDC_OPENING_ERROR);
871 (* E_CAL_BACKEND_GET_CLASS (backend)->remove) (backend, cal, opid, cancellable);
875 * e_cal_backend_refresh:
876 * @backend: an #ECalBackend
878 * @opid: the ID to use for this operation
879 * @cancellable: a #GCancellable for the operation
881 * Refreshes the calendar being accessed by the given backend.
882 * This might be finished with e_data_cal_respond_refresh(),
883 * and it might be called as soon as possible; it doesn't mean
884 * that the refreshing is done after calling that, the backend
885 * is only notifying client whether it started the refresh process
891 e_cal_backend_refresh (ECalBackend *backend,
894 GCancellable *cancellable)
896 g_return_if_fail (backend != NULL);
897 g_return_if_fail (E_IS_CAL_BACKEND (backend));
899 if (e_cal_backend_is_opening (backend))
900 e_data_cal_respond_refresh (cal, opid, EDC_OPENING_ERROR);
901 else if (!E_CAL_BACKEND_GET_CLASS (backend)->refresh)
902 e_data_cal_respond_refresh (cal, opid, EDC_ERROR (UnsupportedMethod));
903 else if (!e_cal_backend_is_opened (backend))
904 e_data_cal_respond_refresh (cal, opid, EDC_NOT_OPENED_ERROR);
906 (* E_CAL_BACKEND_GET_CLASS (backend)->refresh) (backend, cal, opid, cancellable);
910 * e_cal_backend_get_object:
911 * @backend: an #ECalBackend
913 * @opid: the ID to use for this operation
914 * @cancellable: a #GCancellable for the operation
915 * @uid: Unique identifier for a calendar object.
916 * @rid: ID for the object's recurrence to get.
918 * Queries a calendar backend for a calendar object based on its unique
919 * identifier and its recurrence ID (if a recurrent appointment).
920 * This might be finished with e_data_cal_respond_get_object().
923 e_cal_backend_get_object (ECalBackend *backend,
926 GCancellable *cancellable,
930 g_return_if_fail (backend != NULL);
931 g_return_if_fail (E_IS_CAL_BACKEND (backend));
932 g_return_if_fail (uid != NULL);
933 g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_object != NULL);
935 if (e_cal_backend_is_opening (backend))
936 e_data_cal_respond_get_object (cal, opid, EDC_OPENING_ERROR, NULL);
937 else if (!e_cal_backend_is_opened (backend))
938 e_data_cal_respond_get_object (cal, opid, EDC_NOT_OPENED_ERROR, NULL);
940 (* E_CAL_BACKEND_GET_CLASS (backend)->get_object) (backend, cal, opid, cancellable, uid, rid);
944 * e_cal_backend_get_object_list:
945 * @backend: an #ECalBackend
947 * @opid: the ID to use for this operation
948 * @cancellable: a #GCancellable for the operation
949 * @sexp: Expression to search for.
951 * Calls the get_object_list method on the given backend.
952 * This might be finished with e_data_cal_respond_get_object_list().
955 e_cal_backend_get_object_list (ECalBackend *backend,
958 GCancellable *cancellable,
961 g_return_if_fail (backend != NULL);
962 g_return_if_fail (E_IS_CAL_BACKEND (backend));
963 g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_object_list != NULL);
965 if (e_cal_backend_is_opening (backend))
966 e_data_cal_respond_get_object_list (cal, opid, EDC_OPENING_ERROR, NULL);
967 else if (!e_cal_backend_is_opened (backend))
968 e_data_cal_respond_get_object_list (cal, opid, EDC_NOT_OPENED_ERROR, NULL);
970 (* E_CAL_BACKEND_GET_CLASS (backend)->get_object_list) (backend, cal, opid, cancellable, sexp);
974 * e_cal_backend_get_free_busy:
975 * @backend: an #ECalBackend
977 * @opid: the ID to use for this operation
978 * @cancellable: a #GCancellable for the operation
979 * @users: List of users to get free/busy information for.
980 * @start: Start time for query.
981 * @end: End time for query.
983 * Gets a free/busy object for the given time interval. Client side is
984 * notified about free/busy objects throug e_data_cal_report_free_busy_data().
985 * This might be finished with e_data_cal_respond_get_free_busy().
988 e_cal_backend_get_free_busy (ECalBackend *backend,
991 GCancellable *cancellable,
996 g_return_if_fail (backend != NULL);
997 g_return_if_fail (E_IS_CAL_BACKEND (backend));
998 g_return_if_fail (start != -1 && end != -1);
999 g_return_if_fail (start <= end);
1000 g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_free_busy != NULL);
1002 if (e_cal_backend_is_opening (backend))
1003 e_data_cal_respond_get_free_busy (cal, opid, EDC_OPENING_ERROR);
1004 else if (!e_cal_backend_is_opened (backend))
1005 e_data_cal_respond_get_free_busy (cal, opid, EDC_NOT_OPENED_ERROR);
1007 (* E_CAL_BACKEND_GET_CLASS (backend)->get_free_busy) (backend, cal, opid, cancellable, users, start, end);
1011 * e_cal_backend_create_object:
1012 * @backend: an #ECalBackend
1013 * @cal: an #EDataCal
1014 * @opid: the ID to use for this operation
1015 * @cancellable: a #GCancellable for the operation
1016 * @calobj: The object to create.
1018 * Calls the create_object method on the given backend.
1019 * This might be finished with e_data_cal_respond_create_object().
1022 e_cal_backend_create_object (ECalBackend *backend,
1025 GCancellable *cancellable,
1026 const gchar *calobj)
1028 g_return_if_fail (backend != NULL);
1029 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1030 g_return_if_fail (calobj != NULL);
1032 if (e_cal_backend_is_opening (backend))
1033 e_data_cal_respond_create_object (cal, opid, EDC_OPENING_ERROR, NULL, NULL);
1034 else if (!E_CAL_BACKEND_GET_CLASS (backend)->create_object)
1035 e_data_cal_respond_create_object (cal, opid, EDC_ERROR (UnsupportedMethod), NULL, NULL);
1036 else if (!e_cal_backend_is_opened (backend))
1037 e_data_cal_respond_create_object (cal, opid, EDC_NOT_OPENED_ERROR, NULL, NULL);
1039 (* E_CAL_BACKEND_GET_CLASS (backend)->create_object) (backend, cal, opid, cancellable, calobj);
1043 * e_cal_backend_modify_object:
1044 * @backend: an #ECalBackend
1045 * @cal: an #EDataCal
1046 * @opid: the ID to use for this operation
1047 * @cancellable: a #GCancellable for the operation
1048 * @calobj: Object to be modified.
1049 * @mod: Type of modification.
1051 * Calls the modify_object method on the given backend.
1052 * This might be finished with e_data_cal_respond_modify_object().
1055 e_cal_backend_modify_object (ECalBackend *backend,
1058 GCancellable *cancellable,
1059 const gchar *calobj,
1062 g_return_if_fail (backend != NULL);
1063 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1064 g_return_if_fail (calobj != NULL);
1066 if (e_cal_backend_is_opening (backend))
1067 e_data_cal_respond_modify_object (cal, opid, EDC_OPENING_ERROR, NULL, NULL);
1068 else if (!E_CAL_BACKEND_GET_CLASS (backend)->modify_object)
1069 e_data_cal_respond_modify_object (cal, opid, EDC_ERROR (UnsupportedMethod), NULL, NULL);
1070 else if (!e_cal_backend_is_opened (backend))
1071 e_data_cal_respond_modify_object (cal, opid, EDC_NOT_OPENED_ERROR, NULL, NULL);
1073 (* E_CAL_BACKEND_GET_CLASS (backend)->modify_object) (backend, cal, opid, cancellable, calobj, mod);
1077 * e_cal_backend_remove_object:
1078 * @backend: an #ECalBackend
1079 * @cal: an #EDataCal
1080 * @opid: the ID to use for this operation
1081 * @cancellable: a #GCancellable for the operation
1082 * @uid: Unique identifier of the object to remove.
1083 * @rid: A recurrence ID.
1084 * @mod: Type of removal.
1086 * Removes an object in a calendar backend. The backend will notify all of its
1087 * clients about the change.
1088 * This might be finished with e_data_cal_respond_remove_object().
1091 e_cal_backend_remove_object (ECalBackend *backend,
1094 GCancellable *cancellable,
1099 g_return_if_fail (backend != NULL);
1100 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1101 g_return_if_fail (uid != NULL);
1102 g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->remove_object != NULL);
1104 if (e_cal_backend_is_opening (backend))
1105 e_data_cal_respond_remove_object (cal, opid, EDC_OPENING_ERROR, NULL, NULL, NULL);
1106 else if (!e_cal_backend_is_opened (backend))
1107 e_data_cal_respond_remove_object (cal, opid, EDC_NOT_OPENED_ERROR, NULL, NULL, NULL);
1109 (* E_CAL_BACKEND_GET_CLASS (backend)->remove_object) (backend, cal, opid, cancellable, uid, rid, mod);
1113 * e_cal_backend_receive_objects:
1114 * @backend: an #ECalBackend
1115 * @cal: an #EDataCal
1116 * @opid: the ID to use for this operation
1117 * @cancellable: a #GCancellable for the operation
1118 * @calobj: iCalendar object.
1120 * Calls the receive_objects method on the given backend.
1121 * This might be finished with e_data_cal_respond_receive_objects().
1124 e_cal_backend_receive_objects (ECalBackend *backend,
1127 GCancellable *cancellable,
1128 const gchar *calobj)
1130 g_return_if_fail (backend != NULL);
1131 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1132 g_return_if_fail (calobj != NULL);
1133 g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->receive_objects != NULL);
1135 if (e_cal_backend_is_opening (backend))
1136 e_data_cal_respond_receive_objects (cal, opid, EDC_OPENING_ERROR);
1137 else if (!e_cal_backend_is_opened (backend))
1138 e_data_cal_respond_receive_objects (cal, opid, EDC_NOT_OPENED_ERROR);
1140 (* E_CAL_BACKEND_GET_CLASS (backend)->receive_objects) (backend, cal, opid, cancellable, calobj);
1144 * e_cal_backend_send_objects:
1145 * @backend: an #ECalBackend
1146 * @cal: an #EDataCal
1147 * @opid: the ID to use for this operation
1148 * @cancellable: a #GCancellable for the operation
1149 * @calobj: iCalendar object to be sent.
1151 * Calls the send_objects method on the given backend.
1152 * This might be finished with e_data_cal_respond_send_objects().
1155 e_cal_backend_send_objects (ECalBackend *backend,
1158 GCancellable *cancellable,
1159 const gchar *calobj)
1161 g_return_if_fail (backend != NULL);
1162 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1163 g_return_if_fail (calobj != NULL);
1164 g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->send_objects != NULL);
1166 if (e_cal_backend_is_opening (backend))
1167 e_data_cal_respond_send_objects (cal, opid, EDC_OPENING_ERROR, NULL, NULL);
1168 else if (!e_cal_backend_is_opened (backend))
1169 e_data_cal_respond_send_objects (cal, opid, EDC_NOT_OPENED_ERROR, NULL, NULL);
1171 (* E_CAL_BACKEND_GET_CLASS (backend)->send_objects) (backend, cal, opid, cancellable, calobj);
1175 * e_cal_backend_get_attachment_uris:
1176 * @backend: an #ECalBackend
1177 * @cal: an #EDataCal
1178 * @opid: the ID to use for this operation
1179 * @cancellable: a #GCancellable for the operation
1180 * @uid: Unique identifier for a calendar object.
1181 * @rid: ID for the object's recurrence to get.
1183 * Queries a calendar backend for attachments present in a calendar object based
1184 * on its unique identifier and its recurrence ID (if a recurrent appointment).
1185 * This might be finished with e_data_cal_respond_get_attachment_uris().
1190 e_cal_backend_get_attachment_uris (ECalBackend *backend,
1193 GCancellable *cancellable,
1197 g_return_if_fail (backend != NULL);
1198 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1199 g_return_if_fail (uid != NULL);
1200 g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_attachment_uris != NULL);
1202 if (e_cal_backend_is_opening (backend))
1203 e_data_cal_respond_get_attachment_uris (cal, opid, EDC_OPENING_ERROR, NULL);
1204 else if (!e_cal_backend_is_opened (backend))
1205 e_data_cal_respond_get_attachment_uris (cal, opid, EDC_NOT_OPENED_ERROR, NULL);
1207 (* E_CAL_BACKEND_GET_CLASS (backend)->get_attachment_uris) (backend, cal, opid, cancellable, uid, rid);
1211 * e_cal_backend_discard_alarm:
1212 * @backend: an #ECalBackend
1213 * @cal: an #EDataCal
1214 * @opid: the ID to use for this operation
1215 * @cancellable: a #GCancellable for the operation
1216 * @uid: Unique identifier for a calendar object.
1217 * @rid: ID for the object's recurrence to discard alarm in.
1218 * @auid: Unique identifier of the alarm itself.
1220 * Discards alarm @auid from the object identified by @uid and @rid.
1221 * This might be finished with e_data_cal_respond_discard_alarm().
1222 * Default implementation of this method returns Not Supported error.
1225 e_cal_backend_discard_alarm (ECalBackend *backend,
1228 GCancellable *cancellable,
1233 g_return_if_fail (backend != NULL);
1234 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1235 g_return_if_fail (uid != NULL);
1236 g_return_if_fail (auid != NULL);
1238 if (e_cal_backend_is_opening (backend))
1239 e_data_cal_respond_discard_alarm (cal, opid, EDC_OPENING_ERROR);
1240 else if (!E_CAL_BACKEND_GET_CLASS (backend)->discard_alarm)
1241 e_data_cal_respond_discard_alarm (cal, opid, e_data_cal_create_error (NotSupported, NULL));
1242 else if (!e_cal_backend_is_opened (backend))
1243 e_data_cal_respond_discard_alarm (cal, opid, EDC_NOT_OPENED_ERROR);
1245 (* E_CAL_BACKEND_GET_CLASS (backend)->discard_alarm) (backend, cal, opid, cancellable, uid, rid, auid);
1249 * e_cal_backend_get_timezone:
1250 * @backend: an #ECalBackend
1251 * @cal: an #EDataCal
1252 * @opid: the ID to use for this operation
1253 * @cancellable: a #GCancellable for the operation
1254 * @tzid: Unique identifier of a VTIMEZONE object. Note that this must not be
1257 * Returns the icaltimezone* corresponding to the TZID, or NULL if the TZID
1259 * This might be finished with e_data_cal_respond_get_timezone().
1262 e_cal_backend_get_timezone (ECalBackend *backend,
1265 GCancellable *cancellable,
1268 g_return_if_fail (backend != NULL);
1269 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1270 g_return_if_fail (tzid != NULL);
1271 g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_timezone != NULL);
1273 if (e_cal_backend_is_opening (backend))
1274 e_data_cal_respond_get_timezone (cal, opid, EDC_OPENING_ERROR, NULL);
1275 else if (!e_cal_backend_is_opened (backend))
1276 e_data_cal_respond_get_timezone (cal, opid, EDC_NOT_OPENED_ERROR, NULL);
1278 (* E_CAL_BACKEND_GET_CLASS (backend)->get_timezone) (backend, cal, opid, cancellable, tzid);
1282 * e_cal_backend_add_timezone
1283 * @backend: an #ECalBackend
1284 * @cal: an #EDataCal
1285 * @opid: the ID to use for this operation
1286 * @cancellable: a #GCancellable for the operation
1287 * @tzobj: The timezone object, in a string.
1289 * Add a timezone object to the given backend.
1290 * This might be finished with e_data_cal_respond_add_timezone().
1293 e_cal_backend_add_timezone (ECalBackend *backend,
1296 GCancellable *cancellable,
1297 const gchar *tzobject)
1299 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1300 g_return_if_fail (tzobject != NULL);
1301 g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->add_timezone != NULL);
1303 if (e_cal_backend_is_opening (backend))
1304 e_data_cal_respond_add_timezone (cal, opid, EDC_OPENING_ERROR);
1305 else if (!e_cal_backend_is_opened (backend))
1306 e_data_cal_respond_add_timezone (cal, opid, EDC_NOT_OPENED_ERROR);
1308 (* E_CAL_BACKEND_GET_CLASS (backend)->add_timezone) (backend, cal, opid, cancellable, tzobject);
1312 * e_cal_backend_internal_get_timezone:
1313 * @backend: an #ECalBackend
1314 * @tzid: ID of the timezone to get.
1316 * Calls the internal_get_timezone method on the given backend.
1319 e_cal_backend_internal_get_timezone (ECalBackend *backend,
1322 g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
1323 g_return_val_if_fail (tzid != NULL, NULL);
1324 g_return_val_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->internal_get_timezone != NULL, NULL);
1326 return (* E_CAL_BACKEND_GET_CLASS (backend)->internal_get_timezone) (backend, tzid);
1330 * e_cal_backend_start_view:
1331 * @backend: an #ECalBackend
1332 * @view: The view to be started.
1334 * Starts a new live view on the given backend.
1339 e_cal_backend_start_view (ECalBackend *backend,
1342 g_return_if_fail (backend != NULL);
1343 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1344 g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->start_view != NULL);
1346 (* E_CAL_BACKEND_GET_CLASS (backend)->start_view) (backend, view);
1350 * e_cal_backend_stop_view:
1351 * @backend: an #ECalBackend
1352 * @view: The view to be stopped.
1354 * Stops a previously started live view on the given backend.
1359 e_cal_backend_stop_view (ECalBackend *backend,
1362 g_return_if_fail (backend != NULL);
1363 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1365 /* backward compatibility, do not force each backend define this function */
1366 if (!E_CAL_BACKEND_GET_CLASS (backend)->stop_view)
1369 (* E_CAL_BACKEND_GET_CLASS (backend)->stop_view) (backend, view);
1373 object_created_cb (EDataCalView *view,
1376 if (e_data_cal_view_object_matches (view, calobj))
1377 e_data_cal_view_notify_objects_added_1 (view, calobj);
1383 * e_cal_backend_notify_object_created:
1384 * @backend: an #ECalBackend
1385 * @calobj: iCalendar representation of new object
1387 * Notifies each of the backend's listeners about a new object.
1389 * #e_data_cal_notify_object_created() calls this for you. You only need to
1390 * call e_cal_backend_notify_object_created() yourself to report objects
1391 * created by non-EDS clients.
1394 e_cal_backend_notify_object_created (ECalBackend *backend,
1395 const gchar *calobj)
1397 ECalBackendPrivate *priv;
1399 priv = backend->priv;
1401 if (priv->notification_proxy) {
1402 e_cal_backend_notify_object_created (priv->notification_proxy, calobj);
1406 e_cal_backend_foreach_view (backend, object_created_cb, (gpointer) calobj);
1410 * e_cal_backend_notify_objects_added:
1415 e_cal_backend_notify_objects_added (ECalBackend *backend,
1417 const GSList *objects)
1419 e_data_cal_view_notify_objects_added (view, objects);
1423 match_view_and_notify (EDataCalView *view,
1424 const gchar *old_object,
1425 const gchar *object)
1427 gboolean old_match = FALSE, new_match = FALSE;
1430 old_match = e_data_cal_view_object_matches (view, old_object);
1432 new_match = e_data_cal_view_object_matches (view, object);
1433 if (old_match && new_match)
1434 e_data_cal_view_notify_objects_modified_1 (view, object);
1436 e_data_cal_view_notify_objects_added_1 (view, object);
1437 else if (old_match) {
1438 ECalComponent *comp = NULL;
1440 comp = e_cal_component_new_from_string (old_object);
1442 ECalComponentId *id = e_cal_component_get_id (comp);
1444 e_data_cal_view_notify_objects_removed_1 (view, id);
1446 e_cal_component_free_id (id);
1447 g_object_unref (comp);
1453 const gchar *old_object;
1454 const gchar *object;
1455 const ECalComponentId *id;
1459 call_match_and_notify (EDataCalView *view,
1462 struct call_data *cd = user_data;
1464 g_return_val_if_fail (user_data != NULL, FALSE);
1466 match_view_and_notify (view, cd->old_object, cd->object);
1472 * e_cal_backend_notify_object_modified:
1473 * @backend: an #ECalBackend
1474 * @old_object: iCalendar representation of the original form of the object
1475 * @object: iCalendar representation of the new form of the object
1477 * Notifies each of the backend's listeners about a modified object.
1479 * #e_data_cal_notify_object_modified() calls this for you. You only need to
1480 * call e_cal_backend_notify_object_modified() yourself to report objects
1481 * modified by non-EDS clients.
1484 e_cal_backend_notify_object_modified (ECalBackend *backend,
1485 const gchar *old_object,
1486 const gchar *object)
1488 ECalBackendPrivate *priv;
1489 struct call_data cd;
1491 priv = backend->priv;
1493 if (priv->notification_proxy) {
1494 e_cal_backend_notify_object_modified (priv->notification_proxy, old_object, object);
1498 cd.old_object = old_object;
1502 e_cal_backend_foreach_view (backend, call_match_and_notify, &cd);
1506 * e_cal_backend_notify_objects_modified:
1511 e_cal_backend_notify_objects_modified (ECalBackend *backend,
1513 const GSList *objects)
1515 e_data_cal_view_notify_objects_modified (view, objects);
1519 object_removed_cb (EDataCalView *view,
1522 struct call_data *cd = user_data;
1524 g_return_val_if_fail (user_data != NULL, FALSE);
1526 if (cd->object == NULL) {
1527 /* if object == NULL, it means the object has been completely
1528 * removed from the backend */
1529 if (!cd->old_object || e_data_cal_view_object_matches (view, cd->old_object))
1530 e_data_cal_view_notify_objects_removed_1 (view, cd->id);
1532 match_view_and_notify (view, cd->old_object, cd->object);
1538 * e_cal_backend_notify_object_removed:
1539 * @backend: an #ECalBackend
1540 * @id: the Id of the removed object
1541 * @old_object: iCalendar representation of the removed object
1542 * @new_object: iCalendar representation of the object after the removal. This
1543 * only applies to recurrent appointments that had an instance removed. In that
1544 * case, this function notifies a modification instead of a removal.
1546 * Notifies each of the backend's listeners about a removed object.
1548 * e_data_cal_notify_object_removed() calls this for you. You only need to
1549 * call e_cal_backend_notify_object_removed() yourself to report objects
1550 * removed by non-EDS clients.
1553 e_cal_backend_notify_object_removed (ECalBackend *backend,
1554 const ECalComponentId *id,
1555 const gchar *old_object,
1556 const gchar *object)
1558 ECalBackendPrivate *priv;
1559 struct call_data cd;
1561 priv = backend->priv;
1563 if (priv->notification_proxy) {
1564 e_cal_backend_notify_object_removed (priv->notification_proxy, id, old_object, object);
1568 cd.old_object = old_object;
1572 e_cal_backend_foreach_view (backend, object_removed_cb, &cd);
1576 * e_cal_backend_notify_objects_removed:
1581 e_cal_backend_notify_objects_removed (ECalBackend *backend,
1585 e_data_cal_view_notify_objects_removed (view, ids);
1589 * e_cal_backend_notify_error:
1590 * @backend: an #ECalBackend
1591 * @message: Error message
1593 * Notifies each of the backend's listeners about an error
1596 e_cal_backend_notify_error (ECalBackend *backend,
1597 const gchar *message)
1599 ECalBackendPrivate *priv = backend->priv;
1602 if (priv->notification_proxy) {
1603 e_cal_backend_notify_error (priv->notification_proxy, message);
1607 g_mutex_lock (priv->clients_mutex);
1609 for (l = priv->clients; l; l = l->next)
1610 e_data_cal_report_error (l->data, message);
1612 g_mutex_unlock (priv->clients_mutex);
1616 * e_cal_backend_notify_readonly:
1617 * @backend: an #ECalBackend
1618 * @is_readonly: flag indicating readonly status
1620 * Notifies all backend's clients about the current readonly state.
1621 * Meant to be used by backend implementations.
1624 e_cal_backend_notify_readonly (ECalBackend *backend,
1625 gboolean is_readonly)
1627 ECalBackendPrivate *priv;
1630 priv = backend->priv;
1631 priv->readonly = is_readonly;
1633 if (priv->notification_proxy) {
1634 e_cal_backend_notify_readonly (priv->notification_proxy, is_readonly);
1638 g_mutex_lock (priv->clients_mutex);
1640 for (l = priv->clients; l; l = l->next)
1641 e_data_cal_report_readonly (l->data, is_readonly);
1643 g_mutex_unlock (priv->clients_mutex);
1647 * e_cal_backend_notify_online:
1648 * @backend: an #ECalBackend
1649 * @is_online: flag indicating whether @backend is connected and online
1651 * Notifies clients of @backend's connection status indicated by @is_online.
1652 * Meant to be used by backend implementations.
1657 e_cal_backend_notify_online (ECalBackend *backend,
1660 ECalBackendPrivate *priv;
1663 priv = backend->priv;
1665 if (priv->notification_proxy) {
1666 e_cal_backend_notify_online (priv->notification_proxy, is_online);
1670 g_mutex_lock (priv->clients_mutex);
1672 for (clients = priv->clients; clients != NULL; clients = g_slist_next (clients))
1673 e_data_cal_report_online (E_DATA_CAL (clients->data), is_online);
1675 g_mutex_unlock (priv->clients_mutex);
1679 * e_cal_backend_notify_auth_required:
1680 * @backend: an #ECalBackend
1681 * @is_self: Use %TRUE to indicate the authentication is required
1682 * for the @backend, otheriwse the authentication is for any
1683 * other source. Having @credentials %NULL means @is_self
1685 * @credentials: an #ECredentials that contains extra information for
1686 * a source for which authentication is requested.
1687 * This parameter can be NULL to indicate "for this calendar".
1689 * Notifies clients that @backend requires authentication in order to
1690 * connect. This function call does not influence 'opening', but
1691 * influences 'opened' property, which is set to %FALSE when @is_self
1692 * is %TRUE or @credentials is %NULL. Opening phase is finished
1693 * by e_cal_backend_notify_opened() if this is requested for @backend.
1695 * See e_cal_backend_open() for a description how the whole opening
1698 * Meant to be used by backend implementations.
1701 e_cal_backend_notify_auth_required (ECalBackend *backend,
1703 const ECredentials *credentials)
1705 ECalBackendPrivate *priv;
1708 priv = backend->priv;
1710 if (priv->notification_proxy) {
1711 e_cal_backend_notify_auth_required (priv->notification_proxy, is_self, credentials);
1715 g_mutex_lock (priv->clients_mutex);
1717 if (is_self || !credentials)
1718 priv->opened = FALSE;
1720 for (clients = priv->clients; clients != NULL; clients = g_slist_next (clients))
1721 e_data_cal_report_auth_required (E_DATA_CAL (clients->data), credentials);
1723 g_mutex_unlock (priv->clients_mutex);
1727 * e_cal_backend_notify_opened:
1728 * @backend: an #ECalBackend
1729 * @error: a #GError corresponding to the error encountered during
1730 * the opening phase. Use %NULL for success. The @error is freed
1731 * automatically if not %NULL.
1733 * Notifies clients that @backend finished its opening phase.
1734 * See e_cal_backend_open() for more information how the opening
1735 * phase works. Calling this function changes 'opening' property,
1736 * same as 'opened'. 'opening' is set to %FALSE and the backend
1737 * is considered 'opened' only if the @error is %NULL.
1739 * See also: e_cal_backend_respond_opened()
1741 * Note: The @error is freed automatically if not %NULL.
1743 * Meant to be used by backend implementations.
1748 e_cal_backend_notify_opened (ECalBackend *backend,
1751 ECalBackendPrivate *priv;
1754 priv = backend->priv;
1755 g_mutex_lock (priv->clients_mutex);
1757 priv->opening = FALSE;
1758 priv->opened = error == NULL;
1760 for (clients = priv->clients; clients != NULL; clients = g_slist_next (clients))
1761 e_data_cal_report_opened (E_DATA_CAL (clients->data), error);
1763 g_mutex_unlock (priv->clients_mutex);
1766 g_error_free (error);
1770 * e_cal_backend_notify_property_changed:
1771 * @backend: an #ECalBackend
1772 * @prop_name: property name, which changed
1773 * @prop_value: new property value
1775 * Notifies client about property value change.
1780 e_cal_backend_notify_property_changed (ECalBackend *backend,
1781 const gchar *prop_name,
1782 const gchar *prop_value)
1784 ECalBackendPrivate *priv;
1787 g_return_if_fail (backend != NULL);
1788 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1789 g_return_if_fail (backend->priv != NULL);
1790 g_return_if_fail (prop_name != NULL);
1791 g_return_if_fail (*prop_name != '\0');
1792 g_return_if_fail (prop_value != NULL);
1794 priv = backend->priv;
1795 g_mutex_lock (priv->clients_mutex);
1797 for (clients = priv->clients; clients != NULL; clients = g_slist_next (clients))
1798 e_data_cal_report_backend_property_changed (E_DATA_CAL (clients->data), prop_name, prop_value);
1800 g_mutex_unlock (priv->clients_mutex);
1804 * e_cal_backend_respond_opened:
1805 * @backend: an #ECalBackend
1806 * @cal: an #EDataCal
1807 * @opid: an operation ID
1808 * @error: result error; can be %NULL, if it isn't then it's automatically freed
1810 * This is a replacement for e_data_cal_respond_open() for cases where
1811 * the finish of 'open' method call also finishes backend opening phase.
1812 * This function covers calling of both e_cal_backend_notify_opened() and
1813 * e_data_cal_respond_open() with the same @error.
1815 * See e_cal_backend_open() for more details how the opening phase works.
1820 e_cal_backend_respond_opened (ECalBackend *backend,
1825 GError *copy = NULL;
1827 g_return_if_fail (backend != NULL);
1828 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1829 g_return_if_fail (cal != NULL);
1830 g_return_if_fail (opid != 0);
1833 copy = g_error_copy (error);
1835 e_cal_backend_notify_opened (backend, copy);
1836 e_data_cal_respond_open (cal, opid, error);
1840 * e_cal_backend_empty_cache:
1841 * @backend: an #ECalBackend
1842 * @cache: Backend's cache to empty.
1844 * Empties backend's cache with all notifications and so on, thus all listening
1845 * will know there is nothing in this backend.
1850 e_cal_backend_empty_cache (ECalBackend *backend,
1851 ECalBackendCache *cache)
1853 GList *comps_in_cache;
1855 g_return_if_fail (backend != NULL);
1856 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1861 g_return_if_fail (E_IS_CAL_BACKEND_CACHE (cache));
1863 e_file_cache_freeze_changes (E_FILE_CACHE (cache));
1865 for (comps_in_cache = e_cal_backend_cache_get_components (cache);
1867 comps_in_cache = comps_in_cache->next) {
1869 ECalComponentId *id;
1870 ECalComponent *comp = comps_in_cache->data;
1872 id = e_cal_component_get_id (comp);
1873 comp_str = e_cal_component_get_as_string (comp);
1875 e_cal_backend_cache_remove_component (cache, id->uid, id->rid);
1876 e_cal_backend_notify_object_removed (backend, id, comp_str, NULL);
1879 e_cal_component_free_id (id);
1880 g_object_unref (comp);
1883 g_list_free (comps_in_cache);
1885 e_file_cache_thaw_changes (E_FILE_CACHE (cache));