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.
25 #include <libxml/parser.h>
26 #include <libxml/parserInternals.h>
27 #include <libxml/xmlmemory.h>
29 #include "e-cal-backend.h"
30 #include "e-cal-backend-cache.h"
34 G_DEFINE_TYPE (ECalBackend, e_cal_backend, G_TYPE_OBJECT);
36 /* Private part of the CalBackend structure */
37 struct _ECalBackendPrivate {
38 /* The source for this backend */
40 /* signal handler ID for source's 'changed' signal */
41 gulong source_changed_id;
43 /* URI, from source. This is cached, since we return const. */
46 /* The kind of components for this backend */
47 icalcomponent_kind kind;
49 /* List of Cal objects */
50 GMutex *clients_mutex;
53 GMutex *queries_mutex;
56 /* ECalBackend to pass notifications on to */
57 ECalBackend *notification_proxy;
59 /* used when notifying clients about progress of some operation,
60 * we do not send multiple notifications with the same percent
62 gint last_percent_notified;
65 #define E_CAL_BACKEND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_CAL_BACKEND, ECalBackendPrivate))
68 #define CLASS(backend) (E_CAL_BACKEND_GET_CLASS(backend))
85 static guint e_cal_backend_signals[LAST_SIGNAL];
87 static void e_cal_backend_finalize (GObject *object);
92 source_changed_cb (ESource *source, ECalBackend *backend)
94 ECalBackendPrivate *priv;
97 g_return_if_fail (source != NULL);
98 g_return_if_fail (backend != NULL);
99 g_return_if_fail (E_IS_CAL_BACKEND (backend));
101 priv = backend->priv;
102 g_return_if_fail (priv != NULL);
103 g_return_if_fail (priv->source == source);
105 suri = e_source_get_uri (priv->source);
106 if (!priv->uri || (suri && !g_str_equal (priv->uri, suri))) {
115 e_cal_backend_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
117 ECalBackend *backend;
118 ECalBackendPrivate *priv;
120 backend = E_CAL_BACKEND (object);
121 priv = backend->priv;
123 switch (property_id) {
128 if (priv->source_changed_id && priv->source) {
129 g_signal_handler_disconnect (priv->source, priv->source_changed_id);
130 priv->source_changed_id = 0;
133 new_source = g_value_get_object (value);
135 g_object_ref (new_source);
136 priv->source_changed_id = g_signal_connect (new_source, "changed", G_CALLBACK (source_changed_cb), backend);
140 g_object_unref (priv->source);
142 priv->source = new_source;
147 priv->uri = e_source_get_uri (priv->source);
154 priv->uri = g_value_dup_string (value);
158 priv->kind = g_value_get_ulong (value);
161 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
167 e_cal_backend_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
169 ECalBackend *backend;
170 ECalBackendPrivate *priv;
172 backend = E_CAL_BACKEND (object);
173 priv = backend->priv;
175 switch (property_id) {
177 g_value_set_object (value, e_cal_backend_get_source (backend));
180 g_value_set_string (value, e_cal_backend_get_uri (backend));
183 g_value_set_ulong (value, e_cal_backend_get_kind (backend));
186 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
191 /* Class initialization function for the calendar backend */
193 e_cal_backend_class_init (ECalBackendClass *class)
195 GObjectClass *object_class;
197 object_class = (GObjectClass *) class;
199 object_class->set_property = e_cal_backend_set_property;
200 object_class->get_property = e_cal_backend_get_property;
201 object_class->finalize = e_cal_backend_finalize;
203 g_object_class_install_property (object_class, PROP_SOURCE,
204 g_param_spec_object ("source", NULL, NULL, E_TYPE_SOURCE,
205 G_PARAM_READABLE | G_PARAM_WRITABLE
206 | G_PARAM_CONSTRUCT_ONLY));
208 g_object_class_install_property (object_class, PROP_URI,
209 g_param_spec_string ("uri", NULL, NULL, "",
210 G_PARAM_READABLE | G_PARAM_WRITABLE
211 | G_PARAM_CONSTRUCT_ONLY));
213 g_object_class_install_property (object_class, PROP_KIND,
214 g_param_spec_ulong ("kind", NULL, NULL,
215 ICAL_NO_COMPONENT, ICAL_XLICMIMEPART_COMPONENT,
217 G_PARAM_READABLE | G_PARAM_WRITABLE
218 | G_PARAM_CONSTRUCT_ONLY));
219 e_cal_backend_signals[LAST_CLIENT_GONE] =
220 g_signal_new ("last_client_gone",
221 G_TYPE_FROM_CLASS (class),
223 G_STRUCT_OFFSET (ECalBackendClass, last_client_gone),
225 g_cclosure_marshal_VOID__VOID,
227 e_cal_backend_signals[OPENED] =
228 g_signal_new ("opened",
229 G_TYPE_FROM_CLASS (class),
231 G_STRUCT_OFFSET (ECalBackendClass, opened),
233 g_cclosure_marshal_VOID__ENUM,
236 e_cal_backend_signals[REMOVED] =
237 g_signal_new ("removed",
238 G_TYPE_FROM_CLASS (class),
240 G_STRUCT_OFFSET (ECalBackendClass, removed),
242 g_cclosure_marshal_VOID__ENUM,
246 class->last_client_gone = NULL;
247 class->opened = NULL;
248 class->obj_updated = NULL;
250 class->get_cal_address = NULL;
251 class->get_alarm_email_address = NULL;
252 class->get_static_capabilities = NULL;
254 class->is_loaded = NULL;
255 class->is_read_only = NULL;
256 class->start_query = NULL;
257 class->get_mode = NULL;
258 class->set_mode = NULL;
259 class->get_object = NULL;
260 class->get_default_object = NULL;
261 class->get_object_list = NULL;
262 class->get_free_busy = NULL;
263 class->get_changes = NULL;
264 class->discard_alarm = NULL;
265 class->create_object = NULL;
266 class->modify_object = NULL;
267 class->remove_object = NULL;
268 class->receive_objects = NULL;
269 class->send_objects = NULL;
270 class->get_timezone = NULL;
271 class->add_timezone = NULL;
272 class->set_default_timezone = NULL;
274 g_type_class_add_private (class, sizeof (ECalBackendPrivate));
277 /* Object initialization func for the calendar backend */
279 e_cal_backend_init (ECalBackend *backend)
281 ECalBackendPrivate *priv;
283 priv = E_CAL_BACKEND_GET_PRIVATE (backend);
284 backend->priv = priv;
286 priv->clients = NULL;
287 priv->clients_mutex = g_mutex_new ();
288 priv->last_percent_notified = 0;
290 priv->queries = e_list_new((EListCopyFunc) g_object_ref, (EListFreeFunc) g_object_unref, NULL);
291 priv->queries_mutex = g_mutex_new ();
295 e_cal_backend_finalize (GObject *object)
297 ECalBackend *backend = (ECalBackend *)object;
298 ECalBackendPrivate *priv;
300 priv = backend->priv;
302 g_assert (priv->clients == NULL);
304 g_object_unref (priv->queries);
306 g_mutex_free (priv->clients_mutex);
307 g_mutex_free (priv->queries_mutex);
310 if (priv->source_changed_id && priv->source) {
311 g_signal_handler_disconnect (priv->source, priv->source_changed_id);
312 priv->source_changed_id = 0;
314 g_object_unref (priv->source);
316 G_OBJECT_CLASS (e_cal_backend_parent_class)->finalize (object);
322 * e_cal_backend_get_source:
323 * @backend: An #ECalBackend object.
325 * Gets the #ESource associated with the given backend.
327 * Return value: The #ESource for the backend.
330 e_cal_backend_get_source (ECalBackend *backend)
332 ECalBackendPrivate *priv;
334 g_return_val_if_fail (backend != NULL, NULL);
335 g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
337 priv = backend->priv;
343 * e_cal_backend_get_uri:
344 * @backend: A calendar backend.
346 * Queries the URI of a calendar backend, which must already have an open
349 * Return value: The URI where the calendar is stored.
352 e_cal_backend_get_uri (ECalBackend *backend)
354 ECalBackendPrivate *priv;
356 g_return_val_if_fail (backend != NULL, NULL);
357 g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
359 priv = backend->priv;
365 * e_cal_backend_get_kind:
366 * @backend: An #ECalBackend object.
368 * Gets the kind of components the given backend stores.
370 * Return value: The kind of components for this backend.
373 e_cal_backend_get_kind (ECalBackend *backend)
375 ECalBackendPrivate *priv;
377 g_return_val_if_fail (backend != NULL, ICAL_NO_COMPONENT);
378 g_return_val_if_fail (E_IS_CAL_BACKEND (backend), ICAL_NO_COMPONENT);
380 priv = backend->priv;
386 last_client_gone (ECalBackend *backend)
388 g_signal_emit (backend, e_cal_backend_signals[LAST_CLIENT_GONE], 0);
392 * e_cal_backend_add_client:
393 * @backend: An ECalBackend object.
394 * @cal: An EDataCal object.
396 * Adds a new client to the given backend. For any event, the backend will
397 * notify all clients added via this function.
400 e_cal_backend_add_client (ECalBackend *backend, EDataCal *cal)
402 ECalBackendPrivate *priv;
404 g_return_if_fail (backend != NULL);
405 g_return_if_fail (E_IS_CAL_BACKEND (backend));
406 g_return_if_fail (cal != NULL);
407 g_return_if_fail (E_IS_DATA_CAL (cal));
409 priv = backend->priv;
411 /* TODO: Implement this? */
413 bonobo_object_set_immortal (BONOBO_OBJECT (cal), TRUE);
415 g_object_weak_ref (G_OBJECT (cal), cal_destroy_cb, backend);
417 ORBit_small_listen_for_broken (e_data_cal_get_listener (cal), G_CALLBACK (listener_died_cb), cal);
420 g_mutex_lock (priv->clients_mutex);
421 priv->clients = g_list_append (priv->clients, cal);
422 g_mutex_unlock (priv->clients_mutex);
426 * e_cal_backend_remove_client:
427 * @backend: An #ECalBackend object.
428 * @cal: An #EDataCal object.
430 * Removes a client from the list of connected clients to the given backend.
433 e_cal_backend_remove_client (ECalBackend *backend, EDataCal *cal)
435 ECalBackendPrivate *priv;
437 /* XXX this needs a bit more thinking wrt the mutex - we
438 should be holding it when we check to see if clients is
440 g_return_if_fail (backend != NULL);
441 g_return_if_fail (E_IS_CAL_BACKEND (backend));
442 g_return_if_fail (cal != NULL);
443 g_return_if_fail (E_IS_DATA_CAL (cal));
445 priv = backend->priv;
448 g_mutex_lock (priv->clients_mutex);
449 priv->clients = g_list_remove (priv->clients, cal);
450 g_mutex_unlock (priv->clients_mutex);
452 /* When all clients go away, notify the parent factory about it so that
453 * it may decide whether to kill the backend or not.
456 last_client_gone (backend);
460 * e_cal_backend_add_query:
461 * @backend: An #ECalBackend object.
462 * @query: An #EDataCalView object.
464 * Adds a query to the list of live queries being run by the given backend.
465 * Doing so means that any listener on the query will get notified of any
466 * change that affect the live query.
469 e_cal_backend_add_query (ECalBackend *backend, EDataCalView *query)
471 g_return_if_fail (backend != NULL);
472 g_return_if_fail (E_IS_CAL_BACKEND (backend));
474 g_mutex_lock (backend->priv->queries_mutex);
476 e_list_append (backend->priv->queries, query);
478 g_mutex_unlock (backend->priv->queries_mutex);
482 * e_cal_backend_get_queries:
483 * @backend: An #ECalBackend object.
485 * Gets the list of live queries being run on the given backend.
487 * Return value: The list of live queries.
490 e_cal_backend_get_queries (ECalBackend *backend)
492 g_return_val_if_fail (backend != NULL, NULL);
493 g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
495 return backend->priv->queries;
499 * e_cal_backend_remove_query
500 * @backend: An #ECalBackend object.
501 * @query: An #EDataCalView object, previously added with @ref e_cal_backend_add_query.
503 * Removes query from the list of live queries for the backend.
506 e_cal_backend_remove_query (ECalBackend *backend, EDataCalView *query)
508 g_return_if_fail (backend != NULL);
509 g_return_if_fail (E_IS_CAL_BACKEND (backend));
511 g_mutex_lock (backend->priv->queries_mutex);
513 e_list_remove (backend->priv->queries, query);
515 g_mutex_unlock (backend->priv->queries_mutex);
519 * e_cal_backend_get_cal_address:
520 * @backend: A calendar backend.
522 * Queries the cal address associated with a calendar backend, which
523 * must already have an open calendar.
526 e_cal_backend_get_cal_address (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
528 g_return_if_fail (backend != NULL);
529 g_return_if_fail (E_IS_CAL_BACKEND (backend));
531 g_assert (CLASS (backend)->get_cal_address != NULL);
532 (* CLASS (backend)->get_cal_address) (backend, cal, context);
536 e_cal_backend_notify_readonly (ECalBackend *backend, gboolean read_only)
538 ECalBackendPrivate *priv;
541 priv = backend->priv;
543 if (priv->notification_proxy) {
544 e_cal_backend_notify_readonly (priv->notification_proxy, read_only);
547 for (l = priv->clients; l; l = l->next)
548 e_data_cal_notify_read_only (l->data, GNOME_Evolution_Calendar_Success, read_only);
552 e_cal_backend_notify_cal_address (ECalBackend *backend, EServerMethodContext context, gchar *address)
554 ECalBackendPrivate *priv;
557 priv = backend->priv;
559 for (l = priv->clients; l; l = l->next)
560 e_data_cal_notify_cal_address (l->data, context, GNOME_Evolution_Calendar_Success, address);
564 * e_cal_backend_get_alarm_email_address:
565 * @backend: An #ECalBackend object.
566 * @cal: An #EDataCal object.
568 * Calls the get_alarm_email_address method on the given backend.
571 e_cal_backend_get_alarm_email_address (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
573 g_return_if_fail (backend != NULL);
574 g_return_if_fail (E_IS_CAL_BACKEND (backend));
576 g_assert (CLASS (backend)->get_alarm_email_address != NULL);
577 (* CLASS (backend)->get_alarm_email_address) (backend, cal, context);
581 *e_cal_backend_get_alarm_email_address:
582 * @backend: An #ECalBackend object.
583 * @cal: An #EDataCal object.
585 * Calls the get_ldap_attribute method of the given backend.
588 e_cal_backend_get_ldap_attribute (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
590 g_return_if_fail (backend != NULL);
591 g_return_if_fail (E_IS_CAL_BACKEND (backend));
593 g_assert (CLASS (backend)->get_ldap_attribute != NULL);
594 (* CLASS (backend)->get_ldap_attribute) (backend, cal, context);
598 * e_cal_backend_get_alarm_email_address:
599 * @backend: An #ECalBackend object.
600 * @cal: An #EDataCal object.
602 * Calls the get_static_capabilities method on the given backend.
605 e_cal_backend_get_static_capabilities (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
607 g_return_if_fail (backend != NULL);
608 g_return_if_fail (E_IS_CAL_BACKEND (backend));
610 g_assert (CLASS (backend)->get_static_capabilities != NULL);
611 (* CLASS (backend)->get_static_capabilities) (backend, cal, context);
615 * e_cal_backend_open:
616 * @backend: A calendar backend.
617 * @cal: An #EDataCal object.
618 * @only_if_exists: Whether the calendar should be opened only if it already
619 * exists. If FALSE, a new calendar will be created when the specified @uri
621 * @username: User name to use for authentication (if needed).
622 * @password: Password for @username.
624 * Opens a calendar backend with data from a calendar stored at the specified
628 e_cal_backend_open (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, gboolean only_if_exists,
629 const gchar *username, const gchar *password)
631 g_return_if_fail (backend != NULL);
632 g_return_if_fail (E_IS_CAL_BACKEND (backend));
634 g_assert (CLASS (backend)->open != NULL);
635 (* CLASS (backend)->open) (backend, cal, context, only_if_exists, username, password);
639 * e_cal_backend_remove:
640 * @backend: A calendar backend.
641 * @cal: An #EDataCal object.
643 * Removes the calendar being accessed by the given backend.
646 e_cal_backend_remove (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
648 g_return_if_fail (backend != NULL);
649 g_return_if_fail (E_IS_CAL_BACKEND (backend));
651 g_assert (CLASS (backend)->remove != NULL);
652 (* CLASS (backend)->remove) (backend, cal, context);
656 * e_cal_backend_is_loaded:
657 * @backend: A calendar backend.
659 * Queries whether a calendar backend has been loaded yet.
661 * Return value: TRUE if the backend has been loaded with data, FALSE
665 e_cal_backend_is_loaded (ECalBackend *backend)
669 g_return_val_if_fail (backend != NULL, FALSE);
670 g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
672 g_assert (CLASS (backend)->is_loaded != NULL);
673 result = (* CLASS (backend)->is_loaded) (backend);
679 * e_cal_backend_is_read_only
680 * @backend: A calendar backend.
681 * @cal: An #EDataCal object.
683 * Queries whether a calendar backend is read only or not.
687 e_cal_backend_is_read_only (ECalBackend *backend, EDataCal *cal)
689 g_return_if_fail (backend != NULL);
690 g_return_if_fail (E_IS_CAL_BACKEND (backend));
692 g_assert (CLASS (backend)->is_read_only != NULL);
693 (* CLASS (backend)->is_read_only) (backend, cal);
697 * e_cal_backend_start_query:
698 * @backend: A calendar backend.
699 * @query: The query to be started.
701 * Starts a new live query on the given backend.
704 e_cal_backend_start_query (ECalBackend *backend, EDataCalView *query)
706 g_return_if_fail (backend != NULL);
707 g_return_if_fail (E_IS_CAL_BACKEND (backend));
709 g_assert (CLASS (backend)->start_query != NULL);
710 (* CLASS (backend)->start_query) (backend, query);
714 * e_cal_backend_get_mode:
715 * @backend: A calendar backend.
717 * Queries whether a calendar backend is connected remotely.
719 * Return value: The current mode the calendar is in
722 e_cal_backend_get_mode (ECalBackend *backend)
726 g_return_val_if_fail (backend != NULL, FALSE);
727 g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
729 g_assert (CLASS (backend)->get_mode != NULL);
730 result = (* CLASS (backend)->get_mode) (backend);
736 * e_cal_backend_set_mode:
737 * @backend: A calendar backend
738 * @mode: Mode to change to
740 * Sets the mode of the calendar
743 e_cal_backend_set_mode (ECalBackend *backend, CalMode mode)
745 g_return_if_fail (backend != NULL);
746 g_return_if_fail (E_IS_CAL_BACKEND (backend));
748 g_assert (CLASS (backend)->set_mode != NULL);
749 (* CLASS (backend)->set_mode) (backend, mode);
753 * e_cal_backend_get_default_object:
754 * @backend: A calendar backend.
755 * @cal: An #EDataCal object.
757 * Calls the get_default_object method on the given backend.
760 e_cal_backend_get_default_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
762 g_return_if_fail (backend != NULL);
763 g_return_if_fail (E_IS_CAL_BACKEND (backend));
765 g_assert (CLASS (backend)->get_default_object != NULL);
766 (* CLASS (backend)->get_default_object) (backend, cal, context);
770 * e_cal_backend_get_object:
771 * @backend: A calendar backend.
772 * @cal: An #EDataCal object.
773 * @uid: Unique identifier for a calendar object.
774 * @rid: ID for the object's recurrence to get.
776 * Queries a calendar backend for a calendar object based on its unique
777 * identifier and its recurrence ID (if a recurrent appointment).
780 e_cal_backend_get_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid)
782 g_return_if_fail (backend != NULL);
783 g_return_if_fail (E_IS_CAL_BACKEND (backend));
784 g_return_if_fail (uid != NULL);
786 g_assert (CLASS (backend)->get_object != NULL);
787 (* CLASS (backend)->get_object) (backend, cal, context, uid, rid);
791 * e_cal_backend_get_object_list:
792 * @backend: A calendar backend.
793 * @cal: An #EDataCal object.
794 * @sexp: Expression to search for.
796 * Calls the get_object_list method on the given backend.
799 e_cal_backend_get_object_list (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *sexp)
801 g_return_if_fail (backend != NULL);
802 g_return_if_fail (E_IS_CAL_BACKEND (backend));
804 g_assert (CLASS (backend)->get_object_list != NULL);
805 (* CLASS (backend)->get_object_list) (backend, cal, context, sexp);
809 * e_cal_backend_get_attachment_list:
810 * @backend: A calendar backend.
811 * @cal: An #EDataCal object.
812 * @uid: Unique identifier for a calendar object.
813 * @rid: ID for the object's recurrence to get.
815 * Queries a calendar backend for attachments present in a calendar object based
816 * on its unique identifier and its recurrence ID (if a recurrent appointment).
819 e_cal_backend_get_attachment_list (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid)
821 g_return_if_fail (backend != NULL);
822 g_return_if_fail (E_IS_CAL_BACKEND (backend));
823 g_return_if_fail (uid != NULL);
825 g_assert (CLASS (backend)->get_object != NULL);
826 (* CLASS (backend)->get_attachment_list) (backend, cal, context, uid, rid);
830 * e_cal_backend_get_free_busy:
831 * @backend: A calendar backend.
832 * @cal: An #EDataCal object.
833 * @users: List of users to get free/busy information for.
834 * @start: Start time for query.
835 * @end: End time for query.
837 * Gets a free/busy object for the given time interval
840 e_cal_backend_get_free_busy (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, GList *users, time_t start, time_t end)
842 g_return_if_fail (backend != NULL);
843 g_return_if_fail (E_IS_CAL_BACKEND (backend));
844 g_return_if_fail (start != -1 && end != -1);
845 g_return_if_fail (start <= end);
847 g_assert (CLASS (backend)->get_free_busy != NULL);
848 (* CLASS (backend)->get_free_busy) (backend, cal, context, users, start, end);
852 * e_cal_backend_get_changes:
853 * @backend: A calendar backend.
854 * @cal: An #EDataCal object.
855 * @change_id: A unique uid for the callers change list
857 * Builds a sequence of objects and the type of change that occurred on them since
858 * the last time the give change_id was seen
861 e_cal_backend_get_changes (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *change_id)
863 g_return_if_fail (backend != NULL);
864 g_return_if_fail (E_IS_CAL_BACKEND (backend));
865 g_return_if_fail (change_id != NULL);
867 g_assert (CLASS (backend)->get_changes != NULL);
868 (* CLASS (backend)->get_changes) (backend, cal, context, change_id);
872 * e_cal_backend_discard_alarm
873 * @backend: A calendar backend.
874 * @cal: An #EDataCal object.
875 * @uid: UID of the component to discard the alarm from.
878 * Discards an alarm from the given component. This allows the specific backend
879 * to do whatever is needed to really discard the alarm.
882 e_cal_backend_discard_alarm (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *auid)
884 g_return_if_fail (backend != NULL);
885 g_return_if_fail (E_IS_CAL_BACKEND (backend));
886 g_return_if_fail (uid != NULL);
887 g_return_if_fail (auid != NULL);
889 g_assert (CLASS (backend)->discard_alarm != NULL);
890 (* CLASS (backend)->discard_alarm) (backend, cal, context, uid, auid);
894 * e_cal_backend_create_object:
895 * @backend: A calendar backend.
896 * @cal: An #EDataCal object.
897 * @calobj: The object to create.
899 * Calls the create_object method on the given backend.
902 e_cal_backend_create_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj)
904 g_return_if_fail (backend != NULL);
905 g_return_if_fail (E_IS_CAL_BACKEND (backend));
906 g_return_if_fail (calobj != NULL);
908 if (CLASS (backend)->create_object)
909 (* CLASS (backend)->create_object) (backend, cal, context, calobj);
911 e_data_cal_notify_object_created (cal, context, PermissionDenied, NULL, NULL);
915 * e_cal_backend_modify_object:
916 * @backend: A calendar backend.
917 * @cal: An #EDataCal object.
918 * @calobj: Object to be modified.
919 * @mod: Type of modification.
921 * Calls the modify_object method on the given backend.
924 e_cal_backend_modify_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj, CalObjModType mod)
926 g_return_if_fail (backend != NULL);
927 g_return_if_fail (E_IS_CAL_BACKEND (backend));
928 g_return_if_fail (calobj != NULL);
930 if (CLASS (backend)->modify_object)
931 (* CLASS (backend)->modify_object) (backend, cal, context, calobj, mod);
933 e_data_cal_notify_object_removed (cal, context, PermissionDenied, NULL, NULL, NULL);
937 * e_cal_backend_remove_object:
938 * @backend: A calendar backend.
939 * @cal: An #EDataCal object.
940 * @uid: Unique identifier of the object to remove.
941 * @rid: A recurrence ID.
942 * @mod: Type of removal.
944 * Removes an object in a calendar backend. The backend will notify all of its
945 * clients about the change.
948 e_cal_backend_remove_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid, CalObjModType mod)
950 g_return_if_fail (backend != NULL);
951 g_return_if_fail (E_IS_CAL_BACKEND (backend));
952 g_return_if_fail (uid != NULL);
954 g_assert (CLASS (backend)->remove_object != NULL);
955 (* CLASS (backend)->remove_object) (backend, cal, context, uid, rid, mod);
959 * e_cal_backend_receive_objects:
960 * @backend: A calendar backend.
961 * @cal: An #EDataCal object.
962 * @calobj: iCalendar object.
964 * Calls the receive_objects method on the given backend.
967 e_cal_backend_receive_objects (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj)
969 g_return_if_fail (backend != NULL);
970 g_return_if_fail (E_IS_CAL_BACKEND (backend));
971 g_return_if_fail (calobj != NULL);
973 g_assert (CLASS (backend)->receive_objects != NULL);
974 (* CLASS (backend)->receive_objects) (backend, cal, context, calobj);
978 * e_cal_backend_send_objects:
979 * @backend: A calendar backend.
980 * @cal: An #EDataCal object.
981 * @calobj: iCalendar object to be sent.
983 * Calls the send_objects method on the given backend.
986 e_cal_backend_send_objects (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj)
988 g_return_if_fail (backend != NULL);
989 g_return_if_fail (E_IS_CAL_BACKEND (backend));
990 g_return_if_fail (calobj != NULL);
992 g_assert (CLASS (backend)->send_objects != NULL);
993 (* CLASS (backend)->send_objects) (backend, cal, context, calobj);
997 * e_cal_backend_get_timezone:
998 * @backend: A calendar backend.
999 * @cal: An #EDataCal object.
1000 * @tzid: Unique identifier of a VTIMEZONE object. Note that this must not be
1003 * Returns the icaltimezone* corresponding to the TZID, or NULL if the TZID
1007 e_cal_backend_get_timezone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzid)
1009 g_return_if_fail (backend != NULL);
1010 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1011 g_return_if_fail (tzid != NULL);
1013 g_assert (CLASS (backend)->get_timezone != NULL);
1014 (* CLASS (backend)->get_timezone) (backend, cal, context, tzid);
1018 * e_cal_backend_set_default_zone:
1019 * @backend: A calendar backend.
1020 * @cal: An #EDataCal object.
1021 * @tzobj: The timezone object, in a string.
1023 * Sets the default timezone for the calendar, which is used to resolve
1024 * DATE and floating DATE-TIME values.
1027 e_cal_backend_set_default_zone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzobj)
1029 g_return_if_fail (backend != NULL);
1030 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1031 g_return_if_fail (tzobj != NULL);
1033 (* CLASS (backend)->set_default_zone) (backend, cal, context, tzobj);
1037 * @deprecated This virual function should not be used in the backends, use
1038 * e_cal_backend_set_zone instead. This function restricts the default timezone
1039 * to be libical builtin timezone.
1041 * e_cal_backend_set_default_timezone:
1042 * @backend: A calendar backend.
1043 * @cal: An #EDataCal object.
1044 * @tzid: The TZID identifying the timezone.
1046 * Sets the default timezone for the calendar, which is used to resolve
1047 * DATE and floating DATE-TIME values.
1051 e_cal_backend_set_default_timezone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzid)
1053 g_return_if_fail (backend != NULL);
1054 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1055 g_return_if_fail (tzid != NULL);
1057 (* CLASS (backend)->set_default_timezone) (backend, cal, context, tzid);
1061 * e_cal_backend_add_timezone
1062 * @backend: A calendar backend.
1063 * @cal: An #EDataCal object.
1064 * @tzobj: The timezone object, in a string.
1066 * Add a timezone object to the given backend.
1069 e_cal_backend_add_timezone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzobj)
1071 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1072 g_return_if_fail (tzobj != NULL);
1073 g_return_if_fail (CLASS (backend)->add_timezone != NULL);
1075 (* CLASS (backend)->add_timezone) (backend, cal, context, tzobj);
1079 * e_cal_backend_internal_get_default_timezone:
1080 * @backend: A calendar backend.
1082 * Calls the internal_get_default_timezone method on the given backend.
1085 e_cal_backend_internal_get_default_timezone (ECalBackend *backend)
1087 g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
1088 g_return_val_if_fail (CLASS (backend)->internal_get_default_timezone != NULL, NULL);
1090 return (* CLASS (backend)->internal_get_default_timezone) (backend);
1094 * e_cal_backend_internal_get_timezone:
1095 * @backend: A calendar backend.
1096 * @tzid: ID of the timezone to get.
1098 * Calls the internal_get_timezone method on the given backend.
1101 e_cal_backend_internal_get_timezone (ECalBackend *backend, const gchar *tzid)
1103 g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
1104 g_return_val_if_fail (tzid != NULL, NULL);
1105 g_return_val_if_fail (CLASS (backend)->internal_get_timezone != NULL, NULL);
1107 return (* CLASS (backend)->internal_get_timezone) (backend, tzid);
1111 * e_cal_backend_set_notification_proxy:
1112 * @backend: A calendar backend.
1113 * @proxy: The calendar backend to act as notification proxy.
1115 * Sets the backend that will act as notification proxy for the given backend.
1118 e_cal_backend_set_notification_proxy (ECalBackend *backend, ECalBackend *proxy)
1120 ECalBackendPrivate *priv;
1122 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1124 priv = backend->priv;
1126 priv->notification_proxy = proxy;
1130 * e_cal_backend_notify_object_created:
1131 * @backend: A calendar backend.
1132 * @calobj: iCalendar representation of new object
1134 * Notifies each of the backend's listeners about a new object.
1136 * #e_data_cal_notify_object_created() calls this for you. You only need to
1137 * call e_cal_backend_notify_object_created() yourself to report objects
1138 * created by non-EDS clients.
1141 e_cal_backend_notify_object_created (ECalBackend *backend, const gchar *calobj)
1143 ECalBackendPrivate *priv;
1146 EDataCalView *query;
1148 priv = backend->priv;
1150 if (priv->notification_proxy) {
1151 e_cal_backend_notify_object_created (priv->notification_proxy, calobj);
1155 queries = e_cal_backend_get_queries (backend);
1156 iter = e_list_get_iterator (queries);
1158 while (e_iterator_is_valid (iter)) {
1159 query = QUERY (e_iterator_get (iter));
1161 g_object_ref (query);
1162 if (e_data_cal_view_object_matches (query, calobj))
1163 e_data_cal_view_notify_objects_added_1 (query, calobj);
1164 g_object_unref (query);
1166 e_iterator_next (iter);
1168 g_object_unref (iter);
1172 match_query_and_notify (EDataCalView *query, const gchar *old_object, const gchar *object)
1174 gboolean old_match = FALSE, new_match = FALSE;
1177 old_match = e_data_cal_view_object_matches (query, old_object);
1179 new_match = e_data_cal_view_object_matches (query, object);
1180 if (old_match && new_match)
1181 e_data_cal_view_notify_objects_modified_1 (query, object);
1183 e_data_cal_view_notify_objects_added_1 (query, object);
1184 else if (old_match) {
1185 ECalComponent *comp = NULL;
1187 comp = e_cal_component_new_from_string (old_object);
1189 ECalComponentId *id = e_cal_component_get_id (comp);
1191 e_data_cal_view_notify_objects_removed_1 (query, id);
1193 e_cal_component_free_id (id);
1194 g_object_unref (comp);
1200 * e_cal_backend_notify_view_progress_start
1201 * @backend: A calendar backend.
1203 * This methods has to be used before e_cal_backend_notify_view_progress.
1204 * Sets last notified percent value to 0.
1207 e_cal_backend_notify_view_progress_start (ECalBackend *backend)
1209 ECalBackendPrivate *priv;
1211 priv = backend->priv;
1213 priv->last_percent_notified = 0;
1217 * e_cal_backend_notify_view_progress:
1218 * @backend: A calendar backend.
1219 * @message: the UID of the removed object
1220 * @percent: percentage of the objects loaded in the view
1222 * Notifies each of the backend's listeners about the view_progress in downloading the items.
1225 e_cal_backend_notify_view_progress (ECalBackend *backend, const gchar *message, gint percent)
1227 ECalBackendPrivate *priv;
1230 EDataCalView *query;
1232 priv = backend->priv;
1234 if (percent <= priv->last_percent_notified)
1237 priv->last_percent_notified = percent;
1239 if (priv->notification_proxy) {
1240 e_cal_backend_notify_view_progress (priv->notification_proxy, message, percent);
1244 queries = e_cal_backend_get_queries (backend);
1245 iter = e_list_get_iterator (queries);
1247 while (e_iterator_is_valid (iter)) {
1248 query = QUERY (e_iterator_get (iter));
1250 g_object_ref (query);
1252 e_data_cal_view_notify_progress (query, message, percent);
1254 g_object_unref (query);
1256 e_iterator_next (iter);
1258 g_object_unref (iter);
1262 * e_cal_backend_notify_view_done:
1263 * @backend: A calendar backend.
1264 * @status: returns the status once the view is fully populated.
1266 * Notifies each of the backend's listeners about the view_done in downloading the items.
1269 e_cal_backend_notify_view_done (ECalBackend *backend, GNOME_Evolution_Calendar_CallStatus status)
1271 ECalBackendPrivate *priv;
1274 EDataCalView *query;
1276 priv = backend->priv;
1278 if (priv->notification_proxy) {
1279 e_cal_backend_notify_view_done (priv->notification_proxy, status);
1283 queries = e_cal_backend_get_queries (backend);
1284 iter = e_list_get_iterator (queries);
1286 while (e_iterator_is_valid (iter)) {
1287 query = QUERY (e_iterator_get (iter));
1289 g_object_ref (query);
1291 e_data_cal_view_notify_done (query, status);
1293 g_object_unref (query);
1295 e_iterator_next (iter);
1297 g_object_unref (iter);
1301 * e_cal_backend_notify_object_modified:
1302 * @backend: A calendar backend.
1303 * @old_object: iCalendar representation of the original form of the object
1304 * @object: iCalendar representation of the new form of the object
1306 * Notifies each of the backend's listeners about a modified object.
1308 * #e_data_cal_notify_object_modified() calls this for you. You only need to
1309 * call e_cal_backend_notify_object_modified() yourself to report objects
1310 * modified by non-EDS clients.
1313 e_cal_backend_notify_object_modified (ECalBackend *backend,
1314 const gchar *old_object, const gchar *object)
1316 ECalBackendPrivate *priv;
1319 EDataCalView *query;
1321 priv = backend->priv;
1323 if (priv->notification_proxy) {
1324 e_cal_backend_notify_object_modified (priv->notification_proxy, old_object, object);
1328 queries = e_cal_backend_get_queries (backend);
1329 iter = e_list_get_iterator (queries);
1331 while (e_iterator_is_valid (iter)) {
1332 query = QUERY (e_iterator_get (iter));
1334 g_object_ref (query);
1335 match_query_and_notify (query, old_object, object);
1336 g_object_unref (query);
1338 e_iterator_next (iter);
1340 g_object_unref (iter);
1344 * e_cal_backend_notify_object_removed:
1345 * @backend: A calendar backend.
1346 * @id: the Id of the removed object
1347 * @old_object: iCalendar representation of the removed object
1348 * @new_object: iCalendar representation of the object after the removal. This
1349 * only applies to recurrent appointments that had an instance removed. In that
1350 * case, this function notifies a modification instead of a removal.
1352 * Notifies each of the backend's listeners about a removed object.
1354 * e_data_cal_notify_object_removed() calls this for you. You only need to
1355 * call e_cal_backend_notify_object_removed() yourself to report objects
1356 * removed by non-EDS clients.
1359 e_cal_backend_notify_object_removed (ECalBackend *backend, const ECalComponentId *id,
1360 const gchar *old_object, const gchar *object)
1362 ECalBackendPrivate *priv;
1365 EDataCalView *query;
1367 priv = backend->priv;
1369 if (priv->notification_proxy) {
1370 e_cal_backend_notify_object_removed (priv->notification_proxy, id, old_object, object);
1374 queries = e_cal_backend_get_queries (backend);
1375 iter = e_list_get_iterator (queries);
1377 while (e_iterator_is_valid (iter)) {
1378 query = QUERY (e_iterator_get (iter));
1380 g_object_ref (query);
1382 if (object == NULL) {
1383 /* if object == NULL, it means the object has been completely
1384 removed from the backend */
1385 if (e_data_cal_view_object_matches (query, old_object))
1386 e_data_cal_view_notify_objects_removed_1 (query, id);
1388 match_query_and_notify (query, old_object, object);
1390 g_object_unref (query);
1392 e_iterator_next (iter);
1394 g_object_unref (iter);
1398 e_cal_backend_notify_objects_added (ECalBackend *backend, EDataCalView *query, const GList *objects)
1400 e_data_cal_view_notify_objects_added (query, objects);
1404 e_cal_backend_notify_objects_removed (ECalBackend *backend, EDataCalView *query, const GList *ids)
1406 e_data_cal_view_notify_objects_removed (query, ids);
1410 e_cal_backend_notify_objects_modified (ECalBackend *backend, EDataCalView *query, const GList *objects)
1412 e_data_cal_view_notify_objects_modified (query, objects);
1416 * e_cal_backend_notify_mode:
1417 * @backend: A calendar backend.
1418 * @status: Status of the mode set
1419 * @mode: the current mode
1421 * Notifies each of the backend's listeners about the results of a
1425 e_cal_backend_notify_mode (ECalBackend *backend,
1426 EDataCalViewListenerSetModeStatus status,
1429 ECalBackendPrivate *priv = backend->priv;
1432 if (priv->notification_proxy) {
1433 e_cal_backend_notify_mode (priv->notification_proxy, status, mode);
1437 for (l = priv->clients; l; l = l->next)
1438 e_data_cal_notify_mode (l->data, status, mode);
1442 * e_cal_backend_notify_auth_required:
1443 * @backend: A calendar backend.
1445 * Notifies each of the backend's listeners that authentication is required to
1446 * open the calendar.
1449 e_cal_backend_notify_auth_required (ECalBackend *backend)
1451 ECalBackendPrivate *priv = backend->priv;
1454 for (l = priv->clients; l; l = l->next)
1455 e_data_cal_notify_auth_required (l->data);
1459 * e_cal_backend_notify_error:
1460 * @backend: A calendar backend.
1461 * @message: Error message
1463 * Notifies each of the backend's listeners about an error
1466 e_cal_backend_notify_error (ECalBackend *backend, const gchar *message)
1468 ECalBackendPrivate *priv = backend->priv;
1471 if (priv->notification_proxy) {
1472 e_cal_backend_notify_error (priv->notification_proxy, message);
1476 for (l = priv->clients; l; l = l->next)
1477 e_data_cal_notify_error (l->data, message);
1481 * e_cal_backend_empty_cache:
1482 * @backend: A calendar backend.
1483 * @cache: Backend's cache to empty.
1485 * Empties backend's cache with all notifications and so on, thus all listening
1486 * will know there is nothing in this backend.
1489 e_cal_backend_empty_cache (ECalBackend *backend, ECalBackendCache *cache)
1491 GList *comps_in_cache;
1493 g_return_if_fail (backend != NULL);
1494 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1499 g_return_if_fail (E_IS_CAL_BACKEND_CACHE (cache));
1501 e_file_cache_freeze_changes (E_FILE_CACHE (cache));
1503 for (comps_in_cache = e_cal_backend_cache_get_components (cache);
1505 comps_in_cache = comps_in_cache->next) {
1507 ECalComponentId *id;
1508 ECalComponent *comp = comps_in_cache->data;
1510 id = e_cal_component_get_id (comp);
1511 comp_str = e_cal_component_get_as_string (comp);
1513 e_cal_backend_cache_remove_component (cache, id->uid, id->rid);
1514 e_cal_backend_notify_object_removed (backend, id, comp_str, NULL);
1517 e_cal_component_free_id (id);
1518 g_object_unref (comp);
1521 g_list_free (comps_in_cache);
1523 e_file_cache_thaw_changes (E_FILE_CACHE (cache));