Port libedata-cal to DBus
[platform/upstream/evolution-data-server.git] / calendar / libedata-cal / e-cal-backend.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* Evolution calendar - generic backend class
3  *
4  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
5  *
6  * Authors: Federico Mena-Quintero <federico@ximian.com>
7  *          JP Rosevear <jpr@ximian.com>
8  *          Rodrigo Moya <rodrigo@ximian.com>
9  *
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.
13  *
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.
18  *
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.
22  */
23
24 #include <config.h>
25 #include <libxml/parser.h>
26 #include <libxml/parserInternals.h>
27 #include <libxml/xmlmemory.h>
28
29 #include "e-cal-backend.h"
30 #include "e-cal-backend-cache.h"
31
32 \f
33
34 G_DEFINE_TYPE (ECalBackend, e_cal_backend, G_TYPE_OBJECT);
35
36 /* Private part of the CalBackend structure */
37 struct _ECalBackendPrivate {
38         /* The source for this backend */
39         ESource *source;
40         /* signal handler ID for source's 'changed' signal */
41         gulong source_changed_id;
42
43         /* URI, from source. This is cached, since we return const. */
44         gchar *uri;
45
46         /* The kind of components for this backend */
47         icalcomponent_kind kind;
48
49         /* List of Cal objects */
50         GMutex *clients_mutex;
51         GList *clients;
52
53         GMutex *queries_mutex;
54         EList *queries;
55
56         /* ECalBackend to pass notifications on to */
57         ECalBackend *notification_proxy;
58
59         /* used when notifying clients about progress of some operation,
60          * we do not send multiple notifications with the same percent
61          * value */
62         gint last_percent_notified;
63 };
64
65 #define E_CAL_BACKEND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_CAL_BACKEND, ECalBackendPrivate))
66
67 /* For convenience */
68 #define CLASS(backend) (E_CAL_BACKEND_GET_CLASS(backend))
69
70 /* Property IDs */
71 enum props {
72         PROP_0,
73         PROP_SOURCE,
74         PROP_URI,
75         PROP_KIND
76 };
77
78 /* Signal IDs */
79 enum {
80         LAST_CLIENT_GONE,
81         OPENED,
82         REMOVED,
83         LAST_SIGNAL
84 };
85 static guint e_cal_backend_signals[LAST_SIGNAL];
86
87 static void e_cal_backend_finalize (GObject *object);
88
89 \f
90
91 static void
92 source_changed_cb (ESource *source, ECalBackend *backend)
93 {
94         ECalBackendPrivate *priv;
95         gchar *suri;
96
97         g_return_if_fail (source != NULL);
98         g_return_if_fail (backend != NULL);
99         g_return_if_fail (E_IS_CAL_BACKEND (backend));
100
101         priv = backend->priv;
102         g_return_if_fail (priv != NULL);
103         g_return_if_fail (priv->source == source);
104
105         suri = e_source_get_uri (priv->source);
106         if (!priv->uri || (suri && !g_str_equal (priv->uri, suri))) {
107                 g_free (priv->uri);
108                 priv->uri = suri;
109         } else {
110                 g_free (suri);
111         }
112 }
113
114 static void
115 e_cal_backend_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
116 {
117         ECalBackend *backend;
118         ECalBackendPrivate *priv;
119
120         backend = E_CAL_BACKEND (object);
121         priv = backend->priv;
122
123         switch (property_id) {
124         case PROP_SOURCE:
125                 {
126                         ESource *new_source;
127
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;
131                         }
132
133                         new_source = g_value_get_object (value);
134                         if (new_source) {
135                                 g_object_ref (new_source);
136                                 priv->source_changed_id = g_signal_connect (new_source, "changed", G_CALLBACK (source_changed_cb), backend);
137                         }
138
139                         if (priv->source)
140                                 g_object_unref (priv->source);
141
142                         priv->source = new_source;
143
144                         /* Cache the URI */
145                         if (new_source) {
146                                 g_free (priv->uri);
147                                 priv->uri = e_source_get_uri (priv->source);
148                         }
149                 }
150                 break;
151         case PROP_URI:
152                 if (!priv->source) {
153                         g_free (priv->uri);
154                         priv->uri = g_value_dup_string (value);
155                 }
156                 break;
157         case PROP_KIND:
158                 priv->kind = g_value_get_ulong (value);
159                 break;
160         default:
161                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
162                 break;
163         }
164 }
165
166 static void
167 e_cal_backend_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
168 {
169         ECalBackend *backend;
170         ECalBackendPrivate *priv;
171
172         backend = E_CAL_BACKEND (object);
173         priv = backend->priv;
174
175         switch (property_id) {
176         case PROP_SOURCE:
177                 g_value_set_object (value, e_cal_backend_get_source (backend));
178                 break;
179         case PROP_URI:
180                 g_value_set_string (value, e_cal_backend_get_uri (backend));
181                 break;
182         case PROP_KIND:
183                 g_value_set_ulong (value, e_cal_backend_get_kind (backend));
184                 break;
185         default:
186                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
187                 break;
188         }
189 }
190
191 /* Class initialization function for the calendar backend */
192 static void
193 e_cal_backend_class_init (ECalBackendClass *class)
194 {
195         GObjectClass *object_class;
196
197         object_class = (GObjectClass *) class;
198
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;
202
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));
207
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));
212
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,
216                                                              ICAL_NO_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),
222                               G_SIGNAL_RUN_FIRST,
223                               G_STRUCT_OFFSET (ECalBackendClass, last_client_gone),
224                               NULL, NULL,
225                               g_cclosure_marshal_VOID__VOID,
226                               G_TYPE_NONE, 0);
227         e_cal_backend_signals[OPENED] =
228                 g_signal_new ("opened",
229                               G_TYPE_FROM_CLASS (class),
230                               G_SIGNAL_RUN_FIRST,
231                               G_STRUCT_OFFSET (ECalBackendClass, opened),
232                               NULL, NULL,
233                               g_cclosure_marshal_VOID__ENUM,
234                               G_TYPE_NONE, 1,
235                               G_TYPE_INT);
236         e_cal_backend_signals[REMOVED] =
237                 g_signal_new ("removed",
238                               G_TYPE_FROM_CLASS (class),
239                               G_SIGNAL_RUN_FIRST,
240                               G_STRUCT_OFFSET (ECalBackendClass, removed),
241                               NULL, NULL,
242                               g_cclosure_marshal_VOID__ENUM,
243                               G_TYPE_NONE, 1,
244                               G_TYPE_INT);
245
246         class->last_client_gone = NULL;
247         class->opened = NULL;
248         class->obj_updated = NULL;
249
250         class->get_cal_address = NULL;
251         class->get_alarm_email_address = NULL;
252         class->get_static_capabilities = NULL;
253         class->open = 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;
273
274         g_type_class_add_private (class, sizeof (ECalBackendPrivate));
275 }
276
277 /* Object initialization func for the calendar backend */
278 static void
279 e_cal_backend_init (ECalBackend *backend)
280 {
281         ECalBackendPrivate *priv;
282
283         priv = E_CAL_BACKEND_GET_PRIVATE (backend);
284         backend->priv = priv;
285
286         priv->clients = NULL;
287         priv->clients_mutex = g_mutex_new ();
288         priv->last_percent_notified = 0;
289
290         priv->queries = e_list_new((EListCopyFunc) g_object_ref, (EListFreeFunc) g_object_unref, NULL);
291         priv->queries_mutex = g_mutex_new ();
292 }
293
294 static void
295 e_cal_backend_finalize (GObject *object)
296 {
297         ECalBackend *backend = (ECalBackend *)object;
298         ECalBackendPrivate *priv;
299
300         priv = backend->priv;
301
302         g_assert (priv->clients == NULL);
303
304         g_object_unref (priv->queries);
305
306         g_mutex_free (priv->clients_mutex);
307         g_mutex_free (priv->queries_mutex);
308
309         g_free (priv->uri);
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;
313         }
314         g_object_unref (priv->source);
315
316         G_OBJECT_CLASS (e_cal_backend_parent_class)->finalize (object);
317 }
318
319 \f
320
321 /**
322  * e_cal_backend_get_source:
323  * @backend: An #ECalBackend object.
324  *
325  * Gets the #ESource associated with the given backend.
326  *
327  * Return value: The #ESource for the backend.
328  */
329 ESource *
330 e_cal_backend_get_source (ECalBackend *backend)
331 {
332         ECalBackendPrivate *priv;
333
334         g_return_val_if_fail (backend != NULL, NULL);
335         g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
336
337         priv = backend->priv;
338
339         return priv->source;
340 }
341
342 /**
343  * e_cal_backend_get_uri:
344  * @backend: A calendar backend.
345  *
346  * Queries the URI of a calendar backend, which must already have an open
347  * calendar.
348  *
349  * Return value: The URI where the calendar is stored.
350  **/
351 const gchar *
352 e_cal_backend_get_uri (ECalBackend *backend)
353 {
354         ECalBackendPrivate *priv;
355
356         g_return_val_if_fail (backend != NULL, NULL);
357         g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
358
359         priv = backend->priv;
360
361         return priv->uri;
362 }
363
364 /**
365  * e_cal_backend_get_kind:
366  * @backend: An #ECalBackend object.
367  *
368  * Gets the kind of components the given backend stores.
369  *
370  * Return value: The kind of components for this backend.
371  */
372 icalcomponent_kind
373 e_cal_backend_get_kind (ECalBackend *backend)
374 {
375         ECalBackendPrivate *priv;
376
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);
379
380         priv = backend->priv;
381
382         return priv->kind;
383 }
384
385 static void
386 last_client_gone (ECalBackend *backend)
387 {
388         g_signal_emit (backend, e_cal_backend_signals[LAST_CLIENT_GONE], 0);
389 }
390
391 /**
392  * e_cal_backend_add_client:
393  * @backend: An ECalBackend object.
394  * @cal: An EDataCal object.
395  *
396  * Adds a new client to the given backend. For any event, the backend will
397  * notify all clients added via this function.
398  */
399 void
400 e_cal_backend_add_client (ECalBackend *backend, EDataCal *cal)
401 {
402         ECalBackendPrivate *priv;
403
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));
408
409         priv = backend->priv;
410
411         /* TODO: Implement this? */
412 #if 0
413         bonobo_object_set_immortal (BONOBO_OBJECT (cal), TRUE);
414
415         g_object_weak_ref (G_OBJECT (cal), cal_destroy_cb, backend);
416
417         ORBit_small_listen_for_broken (e_data_cal_get_listener (cal), G_CALLBACK (listener_died_cb), cal);
418 #endif
419
420         g_mutex_lock (priv->clients_mutex);
421         priv->clients = g_list_append (priv->clients, cal);
422         g_mutex_unlock (priv->clients_mutex);
423 }
424
425 /**
426  * e_cal_backend_remove_client:
427  * @backend: An #ECalBackend object.
428  * @cal: An #EDataCal object.
429  *
430  * Removes a client from the list of connected clients to the given backend.
431  */
432 void
433 e_cal_backend_remove_client (ECalBackend *backend, EDataCal *cal)
434 {
435         ECalBackendPrivate *priv;
436
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
439            NULL */
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));
444
445         priv = backend->priv;
446
447         /* Disconnect */
448         g_mutex_lock (priv->clients_mutex);
449         priv->clients = g_list_remove (priv->clients, cal);
450         g_mutex_unlock (priv->clients_mutex);
451
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.
454          */
455         if (!priv->clients)
456                 last_client_gone (backend);
457 }
458
459 /**
460  * e_cal_backend_add_query:
461  * @backend: An #ECalBackend object.
462  * @query: An #EDataCalView object.
463  *
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.
467  */
468 void
469 e_cal_backend_add_query (ECalBackend *backend, EDataCalView *query)
470 {
471         g_return_if_fail (backend != NULL);
472         g_return_if_fail (E_IS_CAL_BACKEND (backend));
473
474         g_mutex_lock (backend->priv->queries_mutex);
475
476         e_list_append (backend->priv->queries, query);
477
478         g_mutex_unlock (backend->priv->queries_mutex);
479 }
480
481 /**
482  * e_cal_backend_get_queries:
483  * @backend: An #ECalBackend object.
484  *
485  * Gets the list of live queries being run on the given backend.
486  *
487  * Return value: The list of live queries.
488  */
489 EList *
490 e_cal_backend_get_queries (ECalBackend *backend)
491 {
492         g_return_val_if_fail (backend != NULL, NULL);
493         g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
494
495         return backend->priv->queries;
496 }
497
498 /**
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.
502  *
503  * Removes query from the list of live queries for the backend.
504  **/
505 void
506 e_cal_backend_remove_query (ECalBackend *backend, EDataCalView *query)
507 {
508         g_return_if_fail (backend != NULL);
509         g_return_if_fail (E_IS_CAL_BACKEND (backend));
510
511         g_mutex_lock (backend->priv->queries_mutex);
512
513         e_list_remove (backend->priv->queries, query);
514
515         g_mutex_unlock (backend->priv->queries_mutex);
516 }
517
518 /**
519  * e_cal_backend_get_cal_address:
520  * @backend: A calendar backend.
521  *
522  * Queries the cal address associated with a calendar backend, which
523  * must already have an open calendar.
524  **/
525 void
526 e_cal_backend_get_cal_address (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
527 {
528         g_return_if_fail (backend != NULL);
529         g_return_if_fail (E_IS_CAL_BACKEND (backend));
530
531         g_assert (CLASS (backend)->get_cal_address != NULL);
532         (* CLASS (backend)->get_cal_address) (backend, cal, context);
533 }
534
535 void
536 e_cal_backend_notify_readonly (ECalBackend *backend, gboolean read_only)
537 {
538         ECalBackendPrivate *priv;
539         GList *l;
540
541         priv = backend->priv;
542
543         if (priv->notification_proxy) {
544                 e_cal_backend_notify_readonly (priv->notification_proxy, read_only);
545                 return;
546         }
547         for (l = priv->clients; l; l = l->next)
548                 e_data_cal_notify_read_only (l->data, GNOME_Evolution_Calendar_Success, read_only);
549 }
550
551 void
552 e_cal_backend_notify_cal_address (ECalBackend *backend, EServerMethodContext context, gchar *address)
553 {
554         ECalBackendPrivate *priv;
555         GList *l;
556
557         priv = backend->priv;
558
559         for (l = priv->clients; l; l = l->next)
560                 e_data_cal_notify_cal_address (l->data, context, GNOME_Evolution_Calendar_Success, address);
561 }
562
563 /**
564  * e_cal_backend_get_alarm_email_address:
565  * @backend: An #ECalBackend object.
566  * @cal: An #EDataCal object.
567  *
568  * Calls the get_alarm_email_address method on the given backend.
569  */
570 void
571 e_cal_backend_get_alarm_email_address (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
572 {
573         g_return_if_fail (backend != NULL);
574         g_return_if_fail (E_IS_CAL_BACKEND (backend));
575
576         g_assert (CLASS (backend)->get_alarm_email_address != NULL);
577         (* CLASS (backend)->get_alarm_email_address) (backend, cal, context);
578 }
579
580 /**
581  *e_cal_backend_get_alarm_email_address:
582  * @backend: An #ECalBackend object.
583  * @cal: An #EDataCal object.
584  *
585  * Calls the get_ldap_attribute method of the given backend.
586  */
587 void
588 e_cal_backend_get_ldap_attribute (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
589 {
590         g_return_if_fail (backend != NULL);
591         g_return_if_fail (E_IS_CAL_BACKEND (backend));
592
593         g_assert (CLASS (backend)->get_ldap_attribute != NULL);
594         (* CLASS (backend)->get_ldap_attribute) (backend, cal, context);
595 }
596
597 /**
598  * e_cal_backend_get_alarm_email_address:
599  * @backend: An #ECalBackend object.
600  * @cal: An #EDataCal object.
601  *
602  * Calls the get_static_capabilities method on the given backend.
603  */
604 void
605 e_cal_backend_get_static_capabilities (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
606 {
607         g_return_if_fail (backend != NULL);
608         g_return_if_fail (E_IS_CAL_BACKEND (backend));
609
610         g_assert (CLASS (backend)->get_static_capabilities != NULL);
611         (* CLASS (backend)->get_static_capabilities) (backend, cal, context);
612 }
613
614 /**
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
620  * does not exist.
621  * @username: User name to use for authentication (if needed).
622  * @password: Password for @username.
623  *
624  * Opens a calendar backend with data from a calendar stored at the specified
625  * URI.
626  */
627 void
628 e_cal_backend_open (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, gboolean only_if_exists,
629                     const gchar *username, const gchar *password)
630 {
631         g_return_if_fail (backend != NULL);
632         g_return_if_fail (E_IS_CAL_BACKEND (backend));
633
634         g_assert (CLASS (backend)->open != NULL);
635         (* CLASS (backend)->open) (backend, cal, context, only_if_exists, username, password);
636 }
637
638 /**
639  * e_cal_backend_remove:
640  * @backend: A calendar backend.
641  * @cal: An #EDataCal object.
642  *
643  * Removes the calendar being accessed by the given backend.
644  */
645 void
646 e_cal_backend_remove (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
647 {
648         g_return_if_fail (backend != NULL);
649         g_return_if_fail (E_IS_CAL_BACKEND (backend));
650
651         g_assert (CLASS (backend)->remove != NULL);
652         (* CLASS (backend)->remove) (backend, cal, context);
653 }
654
655 /**
656  * e_cal_backend_is_loaded:
657  * @backend: A calendar backend.
658  *
659  * Queries whether a calendar backend has been loaded yet.
660  *
661  * Return value: TRUE if the backend has been loaded with data, FALSE
662  * otherwise.
663  */
664 gboolean
665 e_cal_backend_is_loaded (ECalBackend *backend)
666 {
667         gboolean result;
668
669         g_return_val_if_fail (backend != NULL, FALSE);
670         g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
671
672         g_assert (CLASS (backend)->is_loaded != NULL);
673         result = (* CLASS (backend)->is_loaded) (backend);
674
675         return result;
676 }
677
678 /**
679  * e_cal_backend_is_read_only
680  * @backend: A calendar backend.
681  * @cal: An #EDataCal object.
682  *
683  * Queries whether a calendar backend is read only or not.
684  *
685  */
686 void
687 e_cal_backend_is_read_only (ECalBackend *backend, EDataCal *cal)
688 {
689         g_return_if_fail (backend != NULL);
690         g_return_if_fail (E_IS_CAL_BACKEND (backend));
691
692         g_assert (CLASS (backend)->is_read_only != NULL);
693         (* CLASS (backend)->is_read_only) (backend, cal);
694 }
695
696 /**
697  * e_cal_backend_start_query:
698  * @backend: A calendar backend.
699  * @query: The query to be started.
700  *
701  * Starts a new live query on the given backend.
702  */
703 void
704 e_cal_backend_start_query (ECalBackend *backend, EDataCalView *query)
705 {
706         g_return_if_fail (backend != NULL);
707         g_return_if_fail (E_IS_CAL_BACKEND (backend));
708
709         g_assert (CLASS (backend)->start_query != NULL);
710         (* CLASS (backend)->start_query) (backend, query);
711 }
712
713 /**
714  * e_cal_backend_get_mode:
715  * @backend: A calendar backend.
716  *
717  * Queries whether a calendar backend is connected remotely.
718  *
719  * Return value: The current mode the calendar is in
720  **/
721 CalMode
722 e_cal_backend_get_mode (ECalBackend *backend)
723 {
724         CalMode result;
725
726         g_return_val_if_fail (backend != NULL, FALSE);
727         g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
728
729         g_assert (CLASS (backend)->get_mode != NULL);
730         result = (* CLASS (backend)->get_mode) (backend);
731
732         return result;
733 }
734
735 /**
736  * e_cal_backend_set_mode:
737  * @backend: A calendar backend
738  * @mode: Mode to change to
739  *
740  * Sets the mode of the calendar
741  */
742 void
743 e_cal_backend_set_mode (ECalBackend *backend, CalMode mode)
744 {
745         g_return_if_fail (backend != NULL);
746         g_return_if_fail (E_IS_CAL_BACKEND (backend));
747
748         g_assert (CLASS (backend)->set_mode != NULL);
749         (* CLASS (backend)->set_mode) (backend, mode);
750 }
751
752 /**
753  * e_cal_backend_get_default_object:
754  * @backend: A calendar backend.
755  * @cal: An #EDataCal object.
756  *
757  * Calls the get_default_object method on the given backend.
758  */
759 void
760 e_cal_backend_get_default_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
761 {
762         g_return_if_fail (backend != NULL);
763         g_return_if_fail (E_IS_CAL_BACKEND (backend));
764
765         g_assert (CLASS (backend)->get_default_object != NULL);
766         (* CLASS (backend)->get_default_object) (backend, cal, context);
767 }
768
769 /**
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.
775  *
776  * Queries a calendar backend for a calendar object based on its unique
777  * identifier and its recurrence ID (if a recurrent appointment).
778  */
779 void
780 e_cal_backend_get_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid)
781 {
782         g_return_if_fail (backend != NULL);
783         g_return_if_fail (E_IS_CAL_BACKEND (backend));
784         g_return_if_fail (uid != NULL);
785
786         g_assert (CLASS (backend)->get_object != NULL);
787         (* CLASS (backend)->get_object) (backend, cal, context, uid, rid);
788 }
789
790 /**
791  * e_cal_backend_get_object_list:
792  * @backend: A calendar backend.
793  * @cal: An #EDataCal object.
794  * @sexp: Expression to search for.
795  *
796  * Calls the get_object_list method on the given backend.
797  */
798 void
799 e_cal_backend_get_object_list (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *sexp)
800 {
801         g_return_if_fail (backend != NULL);
802         g_return_if_fail (E_IS_CAL_BACKEND (backend));
803
804         g_assert (CLASS (backend)->get_object_list != NULL);
805         (* CLASS (backend)->get_object_list) (backend, cal, context, sexp);
806 }
807
808 /**
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.
814  *
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).
817  */
818 void
819 e_cal_backend_get_attachment_list (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid)
820 {
821         g_return_if_fail (backend != NULL);
822         g_return_if_fail (E_IS_CAL_BACKEND (backend));
823         g_return_if_fail (uid != NULL);
824
825         g_assert (CLASS (backend)->get_object != NULL);
826         (* CLASS (backend)->get_attachment_list) (backend, cal, context, uid, rid);
827 }
828
829 /**
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.
836  *
837  * Gets a free/busy object for the given time interval
838  */
839 void
840 e_cal_backend_get_free_busy (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, GList *users, time_t start, time_t end)
841 {
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);
846
847         g_assert (CLASS (backend)->get_free_busy != NULL);
848         (* CLASS (backend)->get_free_busy) (backend, cal, context, users, start, end);
849 }
850
851 /**
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
856  *
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
859  */
860 void
861 e_cal_backend_get_changes (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *change_id)
862 {
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);
866
867         g_assert (CLASS (backend)->get_changes != NULL);
868         (* CLASS (backend)->get_changes) (backend, cal, context, change_id);
869 }
870
871 /**
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.
876  * @auid: Alarm ID.
877  *
878  * Discards an alarm from the given component. This allows the specific backend
879  * to do whatever is needed to really discard the alarm.
880  */
881 void
882 e_cal_backend_discard_alarm (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *auid)
883 {
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);
888
889         g_assert (CLASS (backend)->discard_alarm != NULL);
890         (* CLASS (backend)->discard_alarm) (backend, cal, context, uid, auid);
891 }
892
893 /**
894  * e_cal_backend_create_object:
895  * @backend: A calendar backend.
896  * @cal: An #EDataCal object.
897  * @calobj: The object to create.
898  *
899  * Calls the create_object method on the given backend.
900  */
901 void
902 e_cal_backend_create_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj)
903 {
904         g_return_if_fail (backend != NULL);
905         g_return_if_fail (E_IS_CAL_BACKEND (backend));
906         g_return_if_fail (calobj != NULL);
907
908         if (CLASS (backend)->create_object)
909                 (* CLASS (backend)->create_object) (backend, cal, context, calobj);
910         else
911                 e_data_cal_notify_object_created (cal, context, PermissionDenied, NULL, NULL);
912 }
913
914 /**
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.
920  *
921  * Calls the modify_object method on the given backend.
922  */
923 void
924 e_cal_backend_modify_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj, CalObjModType mod)
925 {
926         g_return_if_fail (backend != NULL);
927         g_return_if_fail (E_IS_CAL_BACKEND (backend));
928         g_return_if_fail (calobj != NULL);
929
930         if (CLASS (backend)->modify_object)
931                 (* CLASS (backend)->modify_object) (backend, cal, context, calobj, mod);
932         else
933                 e_data_cal_notify_object_removed (cal, context, PermissionDenied, NULL, NULL, NULL);
934 }
935
936 /**
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.
943  *
944  * Removes an object in a calendar backend.  The backend will notify all of its
945  * clients about the change.
946  */
947 void
948 e_cal_backend_remove_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid, CalObjModType mod)
949 {
950         g_return_if_fail (backend != NULL);
951         g_return_if_fail (E_IS_CAL_BACKEND (backend));
952         g_return_if_fail (uid != NULL);
953
954         g_assert (CLASS (backend)->remove_object != NULL);
955         (* CLASS (backend)->remove_object) (backend, cal, context, uid, rid, mod);
956 }
957
958 /**
959  * e_cal_backend_receive_objects:
960  * @backend: A calendar backend.
961  * @cal: An #EDataCal object.
962  * @calobj: iCalendar object.
963  *
964  * Calls the receive_objects method on the given backend.
965  */
966 void
967 e_cal_backend_receive_objects (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj)
968 {
969         g_return_if_fail (backend != NULL);
970         g_return_if_fail (E_IS_CAL_BACKEND (backend));
971         g_return_if_fail (calobj != NULL);
972
973         g_assert (CLASS (backend)->receive_objects != NULL);
974         (* CLASS (backend)->receive_objects) (backend, cal, context, calobj);
975 }
976
977 /**
978  * e_cal_backend_send_objects:
979  * @backend: A calendar backend.
980  * @cal: An #EDataCal object.
981  * @calobj: iCalendar object to be sent.
982  *
983  * Calls the send_objects method on the given backend.
984  */
985 void
986 e_cal_backend_send_objects (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj)
987 {
988         g_return_if_fail (backend != NULL);
989         g_return_if_fail (E_IS_CAL_BACKEND (backend));
990         g_return_if_fail (calobj != NULL);
991
992         g_assert (CLASS (backend)->send_objects != NULL);
993         (* CLASS (backend)->send_objects) (backend, cal, context, calobj);
994 }
995
996 /**
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
1001  * NULL.
1002  *
1003  * Returns the icaltimezone* corresponding to the TZID, or NULL if the TZID
1004  * can't be found.
1005  */
1006 void
1007 e_cal_backend_get_timezone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzid)
1008 {
1009         g_return_if_fail (backend != NULL);
1010         g_return_if_fail (E_IS_CAL_BACKEND (backend));
1011         g_return_if_fail (tzid != NULL);
1012
1013         g_assert (CLASS (backend)->get_timezone != NULL);
1014         (* CLASS (backend)->get_timezone) (backend, cal, context, tzid);
1015 }
1016
1017 /**
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.
1022  *
1023  * Sets the default timezone for the calendar, which is used to resolve
1024  * DATE and floating DATE-TIME values.
1025  */
1026 void
1027 e_cal_backend_set_default_zone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzobj)
1028 {
1029         g_return_if_fail (backend != NULL);
1030         g_return_if_fail (E_IS_CAL_BACKEND (backend));
1031         g_return_if_fail (tzobj != NULL);
1032
1033         (* CLASS (backend)->set_default_zone) (backend, cal, context, tzobj);
1034 }
1035
1036 /**
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.
1040  *
1041  * e_cal_backend_set_default_timezone:
1042  * @backend: A calendar backend.
1043  * @cal: An #EDataCal object.
1044  * @tzid: The TZID identifying the timezone.
1045  *
1046  * Sets the default timezone for the calendar, which is used to resolve
1047  * DATE and floating DATE-TIME values.
1048  *
1049  */
1050 void
1051 e_cal_backend_set_default_timezone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzid)
1052 {
1053         g_return_if_fail (backend != NULL);
1054         g_return_if_fail (E_IS_CAL_BACKEND (backend));
1055         g_return_if_fail (tzid != NULL);
1056
1057         (* CLASS (backend)->set_default_timezone) (backend, cal, context, tzid);
1058 }
1059
1060 /**
1061  * e_cal_backend_add_timezone
1062  * @backend: A calendar backend.
1063  * @cal: An #EDataCal object.
1064  * @tzobj: The timezone object, in a string.
1065  *
1066  * Add a timezone object to the given backend.
1067  */
1068 void
1069 e_cal_backend_add_timezone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzobj)
1070 {
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);
1074
1075         (* CLASS (backend)->add_timezone) (backend, cal, context, tzobj);
1076 }
1077
1078 /**
1079  * e_cal_backend_internal_get_default_timezone:
1080  * @backend: A calendar backend.
1081  *
1082  * Calls the internal_get_default_timezone method on the given backend.
1083  */
1084 icaltimezone *
1085 e_cal_backend_internal_get_default_timezone (ECalBackend *backend)
1086 {
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);
1089
1090         return (* CLASS (backend)->internal_get_default_timezone) (backend);
1091 }
1092
1093 /**
1094  * e_cal_backend_internal_get_timezone:
1095  * @backend: A calendar backend.
1096  * @tzid: ID of the timezone to get.
1097  *
1098  * Calls the internal_get_timezone method on the given backend.
1099  */
1100 icaltimezone *
1101 e_cal_backend_internal_get_timezone (ECalBackend *backend, const gchar *tzid)
1102 {
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);
1106
1107         return (* CLASS (backend)->internal_get_timezone) (backend, tzid);
1108 }
1109
1110 /**
1111  * e_cal_backend_set_notification_proxy:
1112  * @backend: A calendar backend.
1113  * @proxy: The calendar backend to act as notification proxy.
1114  *
1115  * Sets the backend that will act as notification proxy for the given backend.
1116  */
1117 void
1118 e_cal_backend_set_notification_proxy (ECalBackend *backend, ECalBackend *proxy)
1119 {
1120         ECalBackendPrivate *priv;
1121
1122         g_return_if_fail (E_IS_CAL_BACKEND (backend));
1123
1124         priv = backend->priv;
1125
1126         priv->notification_proxy = proxy;
1127 }
1128
1129 /**
1130  * e_cal_backend_notify_object_created:
1131  * @backend: A calendar backend.
1132  * @calobj: iCalendar representation of new object
1133  *
1134  * Notifies each of the backend's listeners about a new object.
1135  *
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.
1139  **/
1140 void
1141 e_cal_backend_notify_object_created (ECalBackend *backend, const gchar *calobj)
1142 {
1143         ECalBackendPrivate *priv;
1144         EList *queries;
1145         EIterator *iter;
1146         EDataCalView *query;
1147
1148         priv = backend->priv;
1149
1150         if (priv->notification_proxy) {
1151                 e_cal_backend_notify_object_created (priv->notification_proxy, calobj);
1152                 return;
1153         }
1154
1155         queries = e_cal_backend_get_queries (backend);
1156         iter = e_list_get_iterator (queries);
1157
1158         while (e_iterator_is_valid (iter)) {
1159                 query = QUERY (e_iterator_get (iter));
1160
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);
1165
1166                 e_iterator_next (iter);
1167         }
1168         g_object_unref (iter);
1169 }
1170
1171 static void
1172 match_query_and_notify (EDataCalView *query, const gchar *old_object, const gchar *object)
1173 {
1174         gboolean old_match = FALSE, new_match = FALSE;
1175
1176         if (old_object)
1177                 old_match = e_data_cal_view_object_matches (query, old_object);
1178
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);
1182         else if (new_match)
1183                 e_data_cal_view_notify_objects_added_1 (query, object);
1184         else if (old_match) {
1185                 ECalComponent *comp = NULL;
1186
1187                 comp = e_cal_component_new_from_string (old_object);
1188                 if (comp) {
1189                         ECalComponentId *id = e_cal_component_get_id (comp);
1190
1191                         e_data_cal_view_notify_objects_removed_1 (query, id);
1192
1193                         e_cal_component_free_id (id);
1194                         g_object_unref (comp);
1195                 }
1196         }
1197 }
1198
1199 /**
1200  * e_cal_backend_notify_view_progress_start
1201  * @backend: A calendar backend.
1202  *
1203  * This methods has to be used before e_cal_backend_notify_view_progress.
1204  * Sets last notified percent value to 0.
1205  **/
1206 void
1207 e_cal_backend_notify_view_progress_start (ECalBackend *backend)
1208 {
1209         ECalBackendPrivate *priv;
1210
1211         priv = backend->priv;
1212
1213         priv->last_percent_notified = 0;
1214 }
1215
1216 /**
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
1221  *
1222  * Notifies each of the backend's listeners about the view_progress in downloading the items.
1223  **/
1224 void
1225 e_cal_backend_notify_view_progress (ECalBackend *backend, const gchar *message, gint percent)
1226 {
1227         ECalBackendPrivate *priv;
1228         EList *queries;
1229         EIterator *iter;
1230         EDataCalView *query;
1231
1232         priv = backend->priv;
1233
1234         if (percent <= priv->last_percent_notified)
1235                 return;
1236
1237         priv->last_percent_notified = percent;
1238
1239         if (priv->notification_proxy) {
1240                 e_cal_backend_notify_view_progress (priv->notification_proxy, message, percent);
1241                 return;
1242         }
1243
1244         queries = e_cal_backend_get_queries (backend);
1245         iter = e_list_get_iterator (queries);
1246
1247         while (e_iterator_is_valid (iter)) {
1248                 query = QUERY (e_iterator_get (iter));
1249
1250                 g_object_ref (query);
1251
1252                 e_data_cal_view_notify_progress (query, message, percent);
1253
1254                 g_object_unref (query);
1255
1256                 e_iterator_next (iter);
1257         }
1258         g_object_unref (iter);
1259 }
1260
1261 /**
1262  * e_cal_backend_notify_view_done:
1263  * @backend: A calendar backend.
1264  * @status: returns the status once the view is fully populated.
1265  *
1266  * Notifies each of the backend's listeners about the view_done in downloading the items.
1267  **/
1268 void
1269 e_cal_backend_notify_view_done (ECalBackend *backend, GNOME_Evolution_Calendar_CallStatus status)
1270 {
1271         ECalBackendPrivate *priv;
1272         EList *queries;
1273         EIterator *iter;
1274         EDataCalView *query;
1275
1276         priv = backend->priv;
1277
1278         if (priv->notification_proxy) {
1279                 e_cal_backend_notify_view_done (priv->notification_proxy, status);
1280                 return;
1281         }
1282
1283         queries = e_cal_backend_get_queries (backend);
1284         iter = e_list_get_iterator (queries);
1285
1286         while (e_iterator_is_valid (iter)) {
1287                 query = QUERY (e_iterator_get (iter));
1288
1289                 g_object_ref (query);
1290
1291                 e_data_cal_view_notify_done (query, status);
1292
1293                 g_object_unref (query);
1294
1295                 e_iterator_next (iter);
1296         }
1297         g_object_unref (iter);
1298 }
1299
1300 /**
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
1305  *
1306  * Notifies each of the backend's listeners about a modified object.
1307  *
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.
1311  **/
1312 void
1313 e_cal_backend_notify_object_modified (ECalBackend *backend,
1314                                       const gchar *old_object, const gchar *object)
1315 {
1316         ECalBackendPrivate *priv;
1317         EList *queries;
1318         EIterator *iter;
1319         EDataCalView *query;
1320
1321         priv = backend->priv;
1322
1323         if (priv->notification_proxy) {
1324                 e_cal_backend_notify_object_modified (priv->notification_proxy, old_object, object);
1325                 return;
1326         }
1327
1328         queries = e_cal_backend_get_queries (backend);
1329         iter = e_list_get_iterator (queries);
1330
1331         while (e_iterator_is_valid (iter)) {
1332                 query = QUERY (e_iterator_get (iter));
1333
1334                 g_object_ref (query);
1335                 match_query_and_notify (query, old_object, object);
1336                 g_object_unref (query);
1337
1338                 e_iterator_next (iter);
1339         }
1340         g_object_unref (iter);
1341 }
1342
1343 /**
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.
1351  *
1352  * Notifies each of the backend's listeners about a removed object.
1353  *
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.
1357  **/
1358 void
1359 e_cal_backend_notify_object_removed (ECalBackend *backend, const ECalComponentId *id,
1360                                      const gchar *old_object, const gchar *object)
1361 {
1362         ECalBackendPrivate *priv;
1363         EList *queries;
1364         EIterator *iter;
1365         EDataCalView *query;
1366
1367         priv = backend->priv;
1368
1369         if (priv->notification_proxy) {
1370                 e_cal_backend_notify_object_removed (priv->notification_proxy, id, old_object, object);
1371                 return;
1372         }
1373
1374         queries = e_cal_backend_get_queries (backend);
1375         iter = e_list_get_iterator (queries);
1376
1377         while (e_iterator_is_valid (iter)) {
1378                 query = QUERY (e_iterator_get (iter));
1379
1380                 g_object_ref (query);
1381
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);
1387                 } else
1388                         match_query_and_notify (query, old_object, object);
1389
1390                 g_object_unref (query);
1391
1392                 e_iterator_next (iter);
1393         }
1394         g_object_unref (iter);
1395 }
1396
1397 void
1398 e_cal_backend_notify_objects_added (ECalBackend *backend, EDataCalView *query, const GList *objects)
1399 {
1400         e_data_cal_view_notify_objects_added (query, objects);
1401 }
1402
1403 void
1404 e_cal_backend_notify_objects_removed (ECalBackend *backend, EDataCalView *query, const GList *ids)
1405 {
1406         e_data_cal_view_notify_objects_removed (query, ids);
1407 }
1408
1409 void
1410 e_cal_backend_notify_objects_modified (ECalBackend *backend, EDataCalView *query, const GList *objects)
1411 {
1412         e_data_cal_view_notify_objects_modified (query, objects);
1413 }
1414
1415 /**
1416  * e_cal_backend_notify_mode:
1417  * @backend: A calendar backend.
1418  * @status: Status of the mode set
1419  * @mode: the current mode
1420  *
1421  * Notifies each of the backend's listeners about the results of a
1422  * setMode call.
1423  **/
1424 void
1425 e_cal_backend_notify_mode (ECalBackend *backend,
1426                            EDataCalViewListenerSetModeStatus status,
1427                            EDataCalMode mode)
1428 {
1429         ECalBackendPrivate *priv = backend->priv;
1430         GList *l;
1431
1432         if (priv->notification_proxy) {
1433                 e_cal_backend_notify_mode (priv->notification_proxy, status, mode);
1434                 return;
1435         }
1436
1437         for (l = priv->clients; l; l = l->next)
1438                 e_data_cal_notify_mode (l->data, status, mode);
1439 }
1440
1441 /**
1442  * e_cal_backend_notify_auth_required:
1443  * @backend: A calendar backend.
1444  *
1445  * Notifies each of the backend's listeners that authentication is required to
1446  * open the calendar.
1447  */
1448 void
1449 e_cal_backend_notify_auth_required (ECalBackend *backend)
1450 {
1451         ECalBackendPrivate *priv = backend->priv;
1452         GList *l;
1453
1454         for (l = priv->clients; l; l = l->next)
1455                 e_data_cal_notify_auth_required (l->data);
1456 }
1457
1458 /**
1459  * e_cal_backend_notify_error:
1460  * @backend: A calendar backend.
1461  * @message: Error message
1462  *
1463  * Notifies each of the backend's listeners about an error
1464  **/
1465 void
1466 e_cal_backend_notify_error (ECalBackend *backend, const gchar *message)
1467 {
1468         ECalBackendPrivate *priv = backend->priv;
1469         GList *l;
1470
1471         if (priv->notification_proxy) {
1472                 e_cal_backend_notify_error (priv->notification_proxy, message);
1473                 return;
1474         }
1475
1476         for (l = priv->clients; l; l = l->next)
1477                 e_data_cal_notify_error (l->data, message);
1478 }
1479
1480 /**
1481  * e_cal_backend_empty_cache:
1482  * @backend: A calendar backend.
1483  * @cache: Backend's cache to empty.
1484  *
1485  * Empties backend's cache with all notifications and so on, thus all listening
1486  * will know there is nothing in this backend.
1487  **/
1488 void
1489 e_cal_backend_empty_cache (ECalBackend *backend, ECalBackendCache *cache)
1490 {
1491         GList *comps_in_cache;
1492
1493         g_return_if_fail (backend != NULL);
1494         g_return_if_fail (E_IS_CAL_BACKEND (backend));
1495
1496         if (!cache)
1497                 return;
1498
1499         g_return_if_fail (E_IS_CAL_BACKEND_CACHE (cache));
1500
1501         e_file_cache_freeze_changes (E_FILE_CACHE (cache));
1502
1503         for (comps_in_cache = e_cal_backend_cache_get_components (cache);
1504              comps_in_cache;
1505              comps_in_cache = comps_in_cache->next) {
1506                 gchar *comp_str;
1507                 ECalComponentId *id;
1508                 ECalComponent *comp = comps_in_cache->data;
1509
1510                 id = e_cal_component_get_id (comp);
1511                 comp_str = e_cal_component_get_as_string (comp);
1512
1513                 e_cal_backend_cache_remove_component (cache, id->uid, id->rid);
1514                 e_cal_backend_notify_object_removed (backend, id, comp_str, NULL);
1515
1516                 g_free (comp_str);
1517                 e_cal_component_free_id (id);
1518                 g_object_unref (comp);
1519         }
1520
1521         g_list_free (comps_in_cache);
1522
1523         e_file_cache_thaw_changes (E_FILE_CACHE (cache));
1524 }