Fix FSF address (Tobias Mueller, #470445)
[platform/upstream/evolution-data-server.git] / calendar / libecal / e-cal-listener.c
1 /*-*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* Evolution calendar listener
3  *
4  * Copyright (C) 2001 Ximian, Inc.
5  *
6  * Author: Federico Mena-Quintero <federico@ximian.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of version 2 of the GNU Lesser General Public
10  * License as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21
22 #include <config.h>
23
24 #include <bonobo/bonobo-main.h>
25 #include "e-cal-marshal.h"
26 #include "e-cal-listener.h"
27
28 \f
29
30 /* Private part of the CalListener structure */
31 struct ECalListenerPrivate {
32         /* Notification functions and their closure data */
33         ECalListenerCalSetModeFn cal_set_mode_fn;
34         gpointer fn_data;
35
36         /* Whether notification is desired */
37         guint notify : 1;
38 };
39
40 /* Signal IDs */
41 enum {
42         READ_ONLY,
43         CAL_ADDRESS,
44         ALARM_ADDRESS,
45         LDAP_ATTRIBUTE,
46         STATIC_CAPABILITIES,
47         OPEN,
48         REMOVE,
49         CREATE_OBJECT,
50         MODIFY_OBJECT,
51         REMOVE_OBJECT,
52         DISCARD_ALARM,
53         RECEIVE_OBJECTS,
54         SEND_OBJECTS,
55         DEFAULT_OBJECT,
56         OBJECT,
57         OBJECT_LIST,
58         ATTACHMENT_LIST,
59         GET_TIMEZONE,
60         ADD_TIMEZONE,
61         SET_DEFAULT_TIMEZONE,
62         GET_CHANGES,
63         GET_FREE_BUSY,
64         QUERY,
65         AUTH_REQUIRED,
66         BACKEND_ERROR,
67         LAST_SIGNAL
68 };
69
70 static guint signals[LAST_SIGNAL] = { 0 };
71
72 static BonoboObjectClass *parent_class;
73
74 static ECalendarStatus
75 convert_status (const GNOME_Evolution_Calendar_CallStatus status)
76 {
77         switch (status) {
78         case GNOME_Evolution_Calendar_Success:
79                 return E_CALENDAR_STATUS_OK;
80         case GNOME_Evolution_Calendar_RepositoryOffline:
81                 return E_CALENDAR_STATUS_REPOSITORY_OFFLINE;
82         case GNOME_Evolution_Calendar_PermissionDenied:
83                 return E_CALENDAR_STATUS_PERMISSION_DENIED;
84         case GNOME_Evolution_Calendar_ObjectNotFound:
85                 return E_CALENDAR_STATUS_OBJECT_NOT_FOUND;
86         case GNOME_Evolution_Calendar_InvalidObject:
87                 return E_CALENDAR_STATUS_INVALID_OBJECT;
88         case GNOME_Evolution_Calendar_ObjectIdAlreadyExists:
89                 return E_CALENDAR_STATUS_OBJECT_ID_ALREADY_EXISTS;
90         case GNOME_Evolution_Calendar_AuthenticationFailed:
91                 return E_CALENDAR_STATUS_AUTHENTICATION_FAILED;
92         case GNOME_Evolution_Calendar_AuthenticationRequired:
93                 return E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED;
94         case GNOME_Evolution_Calendar_UnknownUser:
95                 return E_CALENDAR_STATUS_UNKNOWN_USER;
96         case GNOME_Evolution_Calendar_InvalidServerVersion:
97                 return E_CALENDAR_STATUS_INVALID_SERVER_VERSION;
98         case GNOME_Evolution_Calendar_NoSuchCal:
99               return E_CALENDAR_STATUS_NO_SUCH_CALENDAR;
100         
101         case GNOME_Evolution_Calendar_OtherError:
102         default:
103                 return E_CALENDAR_STATUS_OTHER_ERROR;
104         }
105 }
106
107 static void
108 impl_notifyReadOnly (PortableServer_Servant servant,
109                      GNOME_Evolution_Calendar_CallStatus status,
110                      const CORBA_boolean read_only,
111                      CORBA_Environment *ev)
112 {
113         ECalListener *listener;
114         ECalListenerPrivate *priv;
115
116         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
117         priv = listener->priv;
118
119         if (!priv->notify)
120                 return;
121
122         g_signal_emit (G_OBJECT (listener), signals[READ_ONLY], 0, convert_status (status), read_only);
123 }
124
125 static void
126 impl_notifyCalAddress (PortableServer_Servant servant,
127                        GNOME_Evolution_Calendar_CallStatus status,
128                        const CORBA_char *address,
129                        CORBA_Environment *ev)
130 {
131         ECalListener *listener;
132         ECalListenerPrivate *priv;
133
134         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
135         priv = listener->priv;
136
137         if (!priv->notify)
138                 return;
139
140         g_signal_emit (G_OBJECT (listener), signals[CAL_ADDRESS], 0, convert_status (status), address);
141 }
142
143 static void
144 impl_notifyAlarmEmailAddress (PortableServer_Servant servant,
145                               GNOME_Evolution_Calendar_CallStatus status,
146                               const CORBA_char *address,
147                               CORBA_Environment *ev)
148 {
149         ECalListener *listener;
150         ECalListenerPrivate *priv;
151
152         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
153         priv = listener->priv;
154
155         if (!priv->notify)
156                 return;
157
158         g_signal_emit (G_OBJECT (listener), signals[ALARM_ADDRESS], 0, convert_status (status), address);
159 }
160
161 static void
162 impl_notifyLDAPAttribute (PortableServer_Servant servant,
163                           GNOME_Evolution_Calendar_CallStatus status,
164                           const CORBA_char *ldap_attribute,
165                           CORBA_Environment *ev)
166 {
167         ECalListener *listener;
168         ECalListenerPrivate *priv;
169
170         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
171         priv = listener->priv;
172
173         if (!priv->notify)
174                 return;
175
176         g_signal_emit (G_OBJECT (listener), signals[LDAP_ATTRIBUTE], 0, convert_status (status), ldap_attribute);
177 }
178
179 static void
180 impl_notifyStaticCapabilities (PortableServer_Servant servant,
181                                GNOME_Evolution_Calendar_CallStatus status,
182                                const CORBA_char *capabilities,
183                                CORBA_Environment *ev)
184 {
185         ECalListener *listener;
186         ECalListenerPrivate *priv;
187
188         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
189         priv = listener->priv;
190
191         if (!priv->notify)
192                 return;
193
194         g_signal_emit (G_OBJECT (listener), signals[STATIC_CAPABILITIES], 0, convert_status (status), capabilities);
195 }
196
197 /* ::notifyCalOpened method */
198 static void
199 impl_notifyCalOpened (PortableServer_Servant servant,
200                       GNOME_Evolution_Calendar_CallStatus status,
201                       CORBA_Environment *ev)
202 {
203         ECalListener *listener;
204         ECalListenerPrivate *priv;
205
206         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
207         priv = listener->priv;
208
209         if (!priv->notify)
210                 return;
211
212         g_signal_emit (G_OBJECT (listener), signals[OPEN], 0, convert_status (status));
213 }
214
215 static void
216 impl_notifyCalRemoved (PortableServer_Servant servant,
217                       GNOME_Evolution_Calendar_CallStatus status,
218                       CORBA_Environment *ev)
219 {
220         ECalListener *listener;
221         ECalListenerPrivate *priv;
222
223         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
224         priv = listener->priv;
225
226         if (!priv->notify)
227                 return;
228
229         g_signal_emit (G_OBJECT (listener), signals[REMOVE], 0, convert_status (status));
230 }
231
232 static void
233 impl_notifyObjectCreated (PortableServer_Servant servant,
234                           GNOME_Evolution_Calendar_CallStatus status,
235                           const CORBA_char *uid,
236                           CORBA_Environment *ev)
237 {
238         ECalListener *listener;
239         ECalListenerPrivate *priv;
240
241         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
242         priv = listener->priv;
243
244         if (!priv->notify)
245                 return;
246
247         g_signal_emit (G_OBJECT (listener), signals[CREATE_OBJECT], 0, convert_status (status), uid);
248 }
249
250 static void
251 impl_notifyObjectModified (PortableServer_Servant servant,
252                            GNOME_Evolution_Calendar_CallStatus status,
253                            CORBA_Environment *ev)
254 {
255         ECalListener *listener;
256         ECalListenerPrivate *priv;
257
258         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
259         priv = listener->priv;
260
261         if (!priv->notify)
262                 return;
263
264         g_signal_emit (G_OBJECT (listener), signals[MODIFY_OBJECT], 0, convert_status (status));
265 }
266
267 static void
268 impl_notifyObjectRemoved (PortableServer_Servant servant,
269                           GNOME_Evolution_Calendar_CallStatus status,
270                           CORBA_Environment *ev)
271 {
272         ECalListener *listener;
273         ECalListenerPrivate *priv;
274
275         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
276         priv = listener->priv;
277
278         if (!priv->notify)
279                 return;
280
281         g_signal_emit (G_OBJECT (listener), signals[REMOVE_OBJECT], 0, convert_status (status));
282 }
283
284 static void
285 impl_notifyAlarmDiscarded (PortableServer_Servant servant,
286                            GNOME_Evolution_Calendar_CallStatus status,
287                            CORBA_Environment *ev)
288 {
289         ECalListener *listener;
290         ECalListenerPrivate *priv;
291
292         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
293         priv = listener->priv;
294
295         if (!priv->notify)
296                 return;
297
298         g_signal_emit (G_OBJECT (listener), signals[DISCARD_ALARM], 0, convert_status (status));
299 }
300
301 static void
302 impl_notifyObjectsReceived (PortableServer_Servant servant,
303                             GNOME_Evolution_Calendar_CallStatus status,
304                             CORBA_Environment *ev)
305 {
306         ECalListener *listener;
307         ECalListenerPrivate *priv;
308         
309         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
310         priv = listener->priv;
311
312         if (!priv->notify)
313                 return;
314
315         g_signal_emit (G_OBJECT (listener), signals[RECEIVE_OBJECTS], 0, convert_status (status));
316 }
317
318 static void
319 impl_notifyObjectsSent (PortableServer_Servant servant,
320                         const GNOME_Evolution_Calendar_CallStatus status,
321                         const GNOME_Evolution_Calendar_UserList *user_list,
322                         const CORBA_char *calobj,
323                         CORBA_Environment *ev)
324 {
325         ECalListener *listener;
326         ECalListenerPrivate *priv;
327         GList *users = NULL;
328         int i;
329
330         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
331         priv = listener->priv;
332
333         if (!priv->notify)
334                 return;
335
336         for (i = 0; i < user_list->_length; i++)
337                 users = g_list_append (users, g_strdup (user_list->_buffer[i]));
338
339         g_signal_emit (G_OBJECT (listener), signals[SEND_OBJECTS], 0, convert_status (status), users, calobj);
340
341         g_list_foreach (users, (GFunc) g_free, NULL);
342         g_list_free (users);
343 }
344
345 static void 
346 impl_notifyDefaultObjectRequested (PortableServer_Servant servant,
347                                    const GNOME_Evolution_Calendar_CallStatus status,
348                                    const CORBA_char *object,
349                                    CORBA_Environment *ev) 
350 {
351         ECalListener *listener;
352         ECalListenerPrivate *priv;
353         
354         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
355         priv = listener->priv;
356
357         if (!priv->notify)
358                 return;
359
360         g_signal_emit (G_OBJECT (listener), signals[DEFAULT_OBJECT], 0, convert_status (status), object);
361 }
362
363 static void 
364 impl_notifyObjectRequested (PortableServer_Servant servant,
365                             const GNOME_Evolution_Calendar_CallStatus status,
366                             const CORBA_char *object,
367                             CORBA_Environment *ev) 
368 {
369         ECalListener *listener;
370         ECalListenerPrivate *priv;
371         
372         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
373         priv = listener->priv;
374
375         if (!priv->notify)
376                 return;
377
378         g_signal_emit (G_OBJECT (listener), signals[OBJECT], 0, convert_status (status), object);
379 }
380
381 static GList *
382 build_object_list (const GNOME_Evolution_Calendar_stringlist *seq)
383 {
384         GList *list;
385         int i;
386
387         list = NULL;
388         for (i = 0; i < seq->_length; i++) {
389                 icalcomponent *comp;
390                 
391                 comp = icalcomponent_new_from_string (seq->_buffer[i]);
392                 if (!comp)
393                         continue;
394                 
395                 list = g_list_prepend (list, comp);
396         }
397
398         return list;
399 }
400
401 static void 
402 impl_notifyObjectListRequested (PortableServer_Servant servant,
403                                 const GNOME_Evolution_Calendar_CallStatus status,
404                                 const GNOME_Evolution_Calendar_stringlist *objects,
405                                 CORBA_Environment *ev) 
406 {
407         ECalListener *listener;
408         ECalListenerPrivate *priv;
409         GList *object_list, *l;
410         
411         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
412         priv = listener->priv;
413
414         if (!priv->notify)
415                 return;
416
417         object_list = build_object_list (objects);
418         
419         g_signal_emit (G_OBJECT (listener), signals[OBJECT_LIST], 0, convert_status (status), object_list);
420
421         for (l = object_list; l; l = l->next)
422                 icalcomponent_free (l->data);
423         g_list_free (object_list);
424 }
425
426 static void 
427 impl_notifyAttachmentListRequested (PortableServer_Servant servant,
428                                 const GNOME_Evolution_Calendar_CallStatus status,
429                                 const GNOME_Evolution_Calendar_stringlist *attachments,
430                                 CORBA_Environment *ev) 
431 {
432         ECalListener *listener;
433         ECalListenerPrivate *priv;
434         GSList *a_list = NULL;
435         int i;
436         
437         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
438         priv = listener->priv;
439
440         if (!priv->notify)
441                 return;
442
443         for (i = 0; i < attachments->_length; i++) {
444                 a_list = g_slist_append (a_list, g_strdup (attachments->_buffer[i]));
445         }
446
447         g_signal_emit (G_OBJECT (listener), signals[ATTACHMENT_LIST], 0, convert_status (status), a_list);
448
449         g_slist_foreach (a_list, (GFunc) g_free, NULL);
450         g_slist_free (a_list);
451 }
452
453 static void
454 impl_notifyTimezoneRequested (PortableServer_Servant servant,
455                               const GNOME_Evolution_Calendar_CallStatus status,
456                               const CORBA_char *object,
457                               CORBA_Environment *ev)
458 {
459         ECalListener *listener;
460         ECalListenerPrivate *priv;
461         
462         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
463         priv = listener->priv;
464
465         if (!priv->notify)
466                 return;
467         
468         g_signal_emit (G_OBJECT (listener), signals[GET_TIMEZONE], 0, convert_status (status), object);
469 }
470
471 static void
472 impl_notifyTimezoneAdded (PortableServer_Servant servant,
473                           const GNOME_Evolution_Calendar_CallStatus status,
474                           const CORBA_char *tzid,
475                           CORBA_Environment *ev)
476 {
477         ECalListener *listener;
478         ECalListenerPrivate *priv;
479         
480         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
481         priv = listener->priv;
482
483         if (!priv->notify)
484                 return;
485         
486         g_signal_emit (G_OBJECT (listener), signals[ADD_TIMEZONE], 0, convert_status (status), tzid);
487 }
488
489 static void
490 impl_notifyDefaultTimezoneSet (PortableServer_Servant servant,
491                                const GNOME_Evolution_Calendar_CallStatus status,
492                                CORBA_Environment *ev)
493 {
494         ECalListener *listener;
495         ECalListenerPrivate *priv;
496         
497         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
498         priv = listener->priv;
499
500         if (!priv->notify)
501                 return;
502         
503         g_signal_emit (G_OBJECT (listener), signals[SET_DEFAULT_TIMEZONE], 0, convert_status (status));
504 }
505
506 static GList *
507 build_change_list (const GNOME_Evolution_Calendar_CalObjChangeSeq *seq)
508 {
509         GList *list = NULL;
510         icalcomponent *icalcomp;
511         int i;
512
513         /* Create the list in reverse order */
514         for (i = 0; i < seq->_length; i++) {
515                 GNOME_Evolution_Calendar_CalObjChange *corba_coc;
516                 ECalChange *ccc;
517
518                 corba_coc = &seq->_buffer[i];
519                 ccc = g_new (ECalChange, 1);
520
521                 icalcomp = icalparser_parse_string (corba_coc->calobj);
522                 if (!icalcomp)
523                         continue;
524
525                 ccc->comp = e_cal_component_new ();
526                 if (!e_cal_component_set_icalcomponent (ccc->comp, icalcomp)) {
527                         icalcomponent_free (icalcomp);
528                         g_object_unref (G_OBJECT (ccc->comp));
529                         continue;
530                 }
531                 ccc->type = corba_coc->type;
532
533                 list = g_list_prepend (list, ccc);
534         }
535
536         list = g_list_reverse (list);
537
538         return list;
539 }
540
541 static void
542 impl_notifyChanges (PortableServer_Servant servant,
543                     const GNOME_Evolution_Calendar_CallStatus status,
544                     const GNOME_Evolution_Calendar_CalObjChangeSeq *seq,
545                     CORBA_Environment *ev)
546 {
547         ECalListener *listener;
548         ECalListenerPrivate *priv;
549         GList *changes, *l;
550         
551         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
552         priv = listener->priv;
553
554         if (!priv->notify)
555                 return;
556         
557         changes = build_change_list (seq);
558         
559         g_signal_emit (G_OBJECT (listener), signals[GET_CHANGES], 0, convert_status (status), changes);
560
561         for (l = changes; l; l = l->next)
562                 g_free (l->data);
563         g_list_free (changes);
564 }
565
566 static GList *
567 build_free_busy_list (const GNOME_Evolution_Calendar_CalObjSeq *seq)
568 {
569         GList *list = NULL;
570         int i;
571
572         /* Create the list in reverse order */
573         for (i = 0; i < seq->_length; i++) {
574                 ECalComponent *comp;
575                 icalcomponent *icalcomp;
576                 icalcomponent_kind kind;
577
578                 icalcomp = icalcomponent_new_from_string (seq->_buffer[i]);
579                 if (!icalcomp)
580                         continue;
581
582                 kind = icalcomponent_isa (icalcomp);
583                 if (kind == ICAL_VFREEBUSY_COMPONENT) {
584                         comp = e_cal_component_new ();
585                         if (!e_cal_component_set_icalcomponent (comp, icalcomp)) {
586                                 icalcomponent_free (icalcomp);
587                                 g_object_unref (G_OBJECT (comp));
588                                 continue;
589                         }
590                         
591                         list = g_list_append (list, comp);
592                 } else {
593                         icalcomponent_free (icalcomp);
594                 }
595         }
596
597         return list;
598 }
599
600 static void
601 impl_notifyFreeBusy (PortableServer_Servant servant,
602                      const GNOME_Evolution_Calendar_CallStatus status,
603                      const GNOME_Evolution_Calendar_CalObjSeq *seq,
604                      CORBA_Environment *ev)
605 {
606         ECalListener *listener;
607         ECalListenerPrivate *priv;
608         GList *freebusy, *l;
609         
610         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
611         priv = listener->priv;
612
613         if (!priv->notify)
614                 return;
615         
616         freebusy = build_free_busy_list (seq);
617         
618         g_signal_emit (G_OBJECT (listener), signals[GET_FREE_BUSY], 0, convert_status (status), freebusy);
619
620         for (l = freebusy; l; l = l->next)
621                 g_object_unref (G_OBJECT (l->data));
622         g_list_free (freebusy);
623 }
624
625 static void 
626 impl_notifyQuery (PortableServer_Servant servant,
627                   const GNOME_Evolution_Calendar_CallStatus status,
628                   const GNOME_Evolution_Calendar_CalView query,
629                   CORBA_Environment *ev) 
630 {
631         ECalListener *listener;
632         ECalListenerPrivate *priv;
633         
634         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
635         priv = listener->priv;
636
637         if (!priv->notify)
638                 return;
639         
640         g_signal_emit (G_OBJECT (listener), signals[QUERY], 0, convert_status (status), query);
641 }
642
643 /* ::notifyCalSetMode method */
644 static void
645 impl_notifyCalSetMode (PortableServer_Servant servant,
646                        GNOME_Evolution_Calendar_CalListener_SetModeStatus status,
647                        GNOME_Evolution_Calendar_CalMode mode,
648                        CORBA_Environment *ev)
649 {
650         ECalListener *listener;
651         ECalListenerPrivate *priv;
652
653         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
654         priv = listener->priv;
655
656         if (!priv->notify)
657                 return;
658
659         g_assert (priv->cal_set_mode_fn != NULL);
660         (* priv->cal_set_mode_fn) (listener, status, mode, priv->fn_data);
661 }
662
663 static void
664 impl_notifyAuthRequired (PortableServer_Servant servant,
665                          CORBA_Environment *ev)
666 {
667         ECalListener *listener;
668         ECalListenerPrivate *priv;
669
670         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
671         priv = listener->priv;
672
673         if (!priv->notify)
674                 return;
675        
676         g_signal_emit (G_OBJECT (listener), signals[AUTH_REQUIRED], 0);
677 }
678
679 /* ::notifyErrorOccurred method */
680 static void
681 impl_notifyErrorOccurred (PortableServer_Servant servant,
682                           const CORBA_char *message,
683                           CORBA_Environment *ev)
684 {
685         ECalListener *listener;
686         ECalListenerPrivate *priv;
687
688         listener = E_CAL_LISTENER (bonobo_object_from_servant (servant));
689         priv = listener->priv;
690
691         if (!priv->notify)
692                 return;
693
694         g_signal_emit (G_OBJECT (listener), signals[BACKEND_ERROR], 0, message);
695 }
696
697 \f
698
699 /* Object initialization function for the calendar listener */
700 static void
701 e_cal_listener_init (ECalListener *listener, ECalListenerClass *klass)
702 {
703         ECalListenerPrivate *priv;
704
705         priv = g_new0 (ECalListenerPrivate, 1);
706         listener->priv = priv;
707
708         priv->notify = TRUE;
709 }
710
711 /* Finalize handler for the calendar listener */
712 static void
713 e_cal_listener_finalize (GObject *object)
714 {
715         ECalListener *listener;
716         ECalListenerPrivate *priv;
717
718         g_return_if_fail (object != NULL);
719         g_return_if_fail (E_IS_CAL_LISTENER (object));
720
721         listener = E_CAL_LISTENER (object);
722         priv = listener->priv;
723
724         priv->fn_data = NULL;
725
726         priv->notify = FALSE;
727
728         g_free (priv);
729         listener->priv = NULL;
730
731         if (G_OBJECT_CLASS (parent_class)->finalize)
732                 (* G_OBJECT_CLASS (parent_class)->finalize) (object);
733 }
734
735 /* Class initialization function for the calendar listener */
736 static void
737 e_cal_listener_class_init (ECalListenerClass *klass)
738 {
739         GObjectClass *object_class;
740
741         object_class = (GObjectClass *) klass;
742
743         parent_class = g_type_class_peek_parent (klass);
744
745         klass->epv.notifyReadOnly = impl_notifyReadOnly;
746         klass->epv.notifyCalAddress = impl_notifyCalAddress;
747         klass->epv.notifyAlarmEmailAddress = impl_notifyAlarmEmailAddress;
748         klass->epv.notifyLDAPAttribute = impl_notifyLDAPAttribute;
749         klass->epv.notifyStaticCapabilities = impl_notifyStaticCapabilities;
750         klass->epv.notifyCalOpened = impl_notifyCalOpened;
751         klass->epv.notifyCalRemoved = impl_notifyCalRemoved;
752         klass->epv.notifyObjectCreated = impl_notifyObjectCreated;
753         klass->epv.notifyObjectModified = impl_notifyObjectModified;
754         klass->epv.notifyObjectRemoved = impl_notifyObjectRemoved;
755         klass->epv.notifyAlarmDiscarded = impl_notifyAlarmDiscarded;
756         klass->epv.notifyObjectsReceived = impl_notifyObjectsReceived;
757         klass->epv.notifyObjectsSent = impl_notifyObjectsSent;
758         klass->epv.notifyDefaultObjectRequested = impl_notifyDefaultObjectRequested;
759         klass->epv.notifyObjectRequested = impl_notifyObjectRequested;
760         klass->epv.notifyObjectListRequested = impl_notifyObjectListRequested;
761         klass->epv.notifyAttachmentListRequested = impl_notifyAttachmentListRequested;
762         klass->epv.notifyTimezoneRequested = impl_notifyTimezoneRequested;
763         klass->epv.notifyTimezoneAdded = impl_notifyTimezoneAdded;
764         klass->epv.notifyDefaultTimezoneSet = impl_notifyDefaultTimezoneSet;
765         klass->epv.notifyChanges = impl_notifyChanges;
766         klass->epv.notifyFreeBusy = impl_notifyFreeBusy;
767         klass->epv.notifyQuery = impl_notifyQuery;
768         klass->epv.notifyCalSetMode = impl_notifyCalSetMode;
769         klass->epv.notifyErrorOccurred = impl_notifyErrorOccurred;
770         klass->epv.notifyAuthRequired      = impl_notifyAuthRequired;
771         object_class->finalize = e_cal_listener_finalize;
772
773         signals[READ_ONLY] =
774                 g_signal_new ("read_only",
775                               G_TYPE_FROM_CLASS (klass),
776                               G_SIGNAL_RUN_LAST,
777                               G_STRUCT_OFFSET (ECalListenerClass, read_only),
778                               NULL, NULL,
779                               e_cal_marshal_VOID__INT_BOOLEAN,
780                               G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_BOOLEAN);
781         signals[CAL_ADDRESS] =
782                 g_signal_new ("cal_address",
783                               G_TYPE_FROM_CLASS (klass),
784                               G_SIGNAL_RUN_LAST,
785                               G_STRUCT_OFFSET (ECalListenerClass, cal_address),
786                               NULL, NULL,
787                               e_cal_marshal_VOID__INT_STRING,
788                               G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING);
789         signals[ALARM_ADDRESS] =
790                 g_signal_new ("alarm_address",
791                               G_TYPE_FROM_CLASS (klass),
792                               G_SIGNAL_RUN_LAST,
793                               G_STRUCT_OFFSET (ECalListenerClass, alarm_address),
794                               NULL, NULL,
795                               e_cal_marshal_VOID__INT_STRING,
796                               G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING);
797         signals[LDAP_ATTRIBUTE] =
798                 g_signal_new ("ldap_attribute",
799                               G_TYPE_FROM_CLASS (klass),
800                               G_SIGNAL_RUN_LAST,
801                               G_STRUCT_OFFSET (ECalListenerClass, ldap_attribute),
802                               NULL, NULL,
803                               e_cal_marshal_VOID__INT_STRING,
804                               G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING);       
805         signals[STATIC_CAPABILITIES] =
806                 g_signal_new ("static_capabilities",
807                               G_TYPE_FROM_CLASS (klass),
808                               G_SIGNAL_RUN_LAST,
809                               G_STRUCT_OFFSET (ECalListenerClass, static_capabilities),
810                               NULL, NULL,
811                               e_cal_marshal_VOID__INT_STRING,
812                               G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING);
813         signals[OPEN] =
814                 g_signal_new ("open",
815                               G_TYPE_FROM_CLASS (klass),
816                               G_SIGNAL_RUN_LAST,
817                               G_STRUCT_OFFSET (ECalListenerClass, open),
818                               NULL, NULL,
819                               g_cclosure_marshal_VOID__INT,
820                               G_TYPE_NONE, 1, G_TYPE_INT);      
821         signals[REMOVE] =
822                 g_signal_new ("remove",
823                               G_TYPE_FROM_CLASS (klass),
824                               G_SIGNAL_RUN_LAST,
825                               G_STRUCT_OFFSET (ECalListenerClass, remove),
826                               NULL, NULL,
827                               g_cclosure_marshal_VOID__INT,
828                               G_TYPE_NONE, 1, G_TYPE_INT);
829         signals[CREATE_OBJECT] =
830                 g_signal_new ("create_object",
831                               G_TYPE_FROM_CLASS (klass),
832                               G_SIGNAL_RUN_LAST,
833                               G_STRUCT_OFFSET (ECalListenerClass, create_object),
834                               NULL, NULL,
835                               e_cal_marshal_VOID__INT_STRING,
836                               G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING);
837         signals[MODIFY_OBJECT] =
838                 g_signal_new ("modify_object",
839                               G_TYPE_FROM_CLASS (klass),
840                               G_SIGNAL_RUN_LAST,
841                               G_STRUCT_OFFSET (ECalListenerClass, modify_object),
842                               NULL, NULL,
843                               g_cclosure_marshal_VOID__INT,
844                               G_TYPE_NONE, 1, G_TYPE_INT);      
845         signals[REMOVE_OBJECT] =
846                 g_signal_new ("remove_object",
847                               G_TYPE_FROM_CLASS (klass),
848                               G_SIGNAL_RUN_LAST,
849                               G_STRUCT_OFFSET (ECalListenerClass, remove_object),
850                               NULL, NULL,
851                               g_cclosure_marshal_VOID__INT,
852                               G_TYPE_NONE, 1, G_TYPE_INT);
853         signals[DISCARD_ALARM] =
854                 g_signal_new ("discard_alarm",
855                               G_TYPE_FROM_CLASS (klass),
856                               G_SIGNAL_RUN_LAST,
857                               G_STRUCT_OFFSET (ECalListenerClass, discard_alarm),
858                               NULL, NULL,
859                               g_cclosure_marshal_VOID__INT,
860                               G_TYPE_NONE, 1, G_TYPE_INT);
861         signals[RECEIVE_OBJECTS] =
862                 g_signal_new ("receive_objects",
863                               G_TYPE_FROM_CLASS (klass),
864                               G_SIGNAL_RUN_LAST,
865                               G_STRUCT_OFFSET (ECalListenerClass, receive_objects),
866                               NULL, NULL,
867                               g_cclosure_marshal_VOID__INT,
868                               G_TYPE_NONE, 1, G_TYPE_INT);
869         signals[SEND_OBJECTS] =
870                 g_signal_new ("send_objects",
871                               G_TYPE_FROM_CLASS (klass),
872                               G_SIGNAL_RUN_LAST,
873                               G_STRUCT_OFFSET (ECalListenerClass, send_objects),
874                               NULL, NULL,
875                               e_cal_marshal_VOID__INT_POINTER_STRING,
876                               G_TYPE_NONE, 3, G_TYPE_INT, G_TYPE_POINTER, G_TYPE_STRING);
877         signals[DEFAULT_OBJECT] =
878                 g_signal_new ("default_object",
879                               G_TYPE_FROM_CLASS (klass),
880                               G_SIGNAL_RUN_LAST,
881                               G_STRUCT_OFFSET (ECalListenerClass, default_object),
882                               NULL, NULL,
883                               e_cal_marshal_VOID__INT_STRING,
884                               G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING);
885         signals[OBJECT] =
886                 g_signal_new ("object",
887                               G_TYPE_FROM_CLASS (klass),
888                               G_SIGNAL_RUN_LAST,
889                               G_STRUCT_OFFSET (ECalListenerClass, object),
890                               NULL, NULL,
891                               e_cal_marshal_VOID__INT_STRING,
892                               G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING);
893         signals[OBJECT_LIST] =
894                 g_signal_new ("object_list",
895                               G_TYPE_FROM_CLASS (klass),
896                               G_SIGNAL_RUN_LAST,
897                               G_STRUCT_OFFSET (ECalListenerClass, object_list),
898                               NULL, NULL,
899                               e_cal_marshal_VOID__INT_POINTER,
900                               G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_POINTER);
901         signals[ATTACHMENT_LIST] =
902                 g_signal_new ("attachment_list",
903                               G_TYPE_FROM_CLASS (klass),
904                               G_SIGNAL_RUN_LAST,
905                               G_STRUCT_OFFSET (ECalListenerClass, attachment_list),
906                               NULL, NULL,
907                               e_cal_marshal_VOID__INT_POINTER,
908                               G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_POINTER);
909         signals[GET_TIMEZONE] =
910                 g_signal_new ("get_timezone",
911                               G_TYPE_FROM_CLASS (klass),
912                               G_SIGNAL_RUN_LAST,
913                               G_STRUCT_OFFSET (ECalListenerClass, get_timezone),
914                               NULL, NULL,
915                               e_cal_marshal_VOID__INT_STRING,
916                               G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING);
917         signals[ADD_TIMEZONE] =
918                 g_signal_new ("add_timezone",
919                               G_TYPE_FROM_CLASS (klass),
920                               G_SIGNAL_RUN_LAST,
921                               G_STRUCT_OFFSET (ECalListenerClass, add_timezone),
922                               NULL, NULL,
923                               e_cal_marshal_VOID__INT_STRING,
924                               G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING);
925         signals[SET_DEFAULT_TIMEZONE] =
926                 g_signal_new ("set_default_timezone",
927                               G_TYPE_FROM_CLASS (klass),
928                               G_SIGNAL_RUN_LAST,
929                               G_STRUCT_OFFSET (ECalListenerClass, set_default_timezone),
930                               NULL, NULL,
931                               g_cclosure_marshal_VOID__INT,
932                               G_TYPE_NONE, 1, G_TYPE_INT);
933         signals[GET_CHANGES] =
934                 g_signal_new ("get_changes",
935                               G_TYPE_FROM_CLASS (klass),
936                               G_SIGNAL_RUN_LAST,
937                               G_STRUCT_OFFSET (ECalListenerClass, get_changes),
938                               NULL, NULL,
939                               e_cal_marshal_VOID__INT_POINTER,
940                               G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_POINTER);
941         signals[GET_FREE_BUSY] =
942                 g_signal_new ("get_free_busy",
943                               G_TYPE_FROM_CLASS (klass),
944                               G_SIGNAL_RUN_LAST,
945                               G_STRUCT_OFFSET (ECalListenerClass, get_free_busy),
946                               NULL, NULL,
947                               e_cal_marshal_VOID__INT_POINTER,
948                               G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_POINTER);
949         signals[QUERY] =
950                 g_signal_new ("query",
951                               G_TYPE_FROM_CLASS (klass),
952                               G_SIGNAL_RUN_LAST,
953                               G_STRUCT_OFFSET (ECalListenerClass, query),
954                               NULL, NULL,
955                               e_cal_marshal_VOID__INT_POINTER,
956                               G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_POINTER);
957         signals [AUTH_REQUIRED] =
958                 g_signal_new ("auth_required",
959                               G_OBJECT_CLASS_TYPE (object_class),
960                               G_SIGNAL_RUN_LAST,
961                               G_STRUCT_OFFSET (ECalListenerClass, auth_required),
962                               NULL, NULL,
963                               g_cclosure_marshal_VOID__VOID,
964                               G_TYPE_NONE, 0);
965         signals[BACKEND_ERROR] =
966                 g_signal_new ("backend_error",
967                               G_TYPE_FROM_CLASS (klass),
968                               G_SIGNAL_RUN_LAST,
969                               G_STRUCT_OFFSET (ECalListenerClass, backend_error),
970                               NULL, NULL,
971                               g_cclosure_marshal_VOID__STRING,
972                               G_TYPE_NONE, 1, G_TYPE_STRING);
973 }
974
975 BONOBO_TYPE_FUNC_FULL (ECalListener,
976                        GNOME_Evolution_Calendar_CalListener,
977                        BONOBO_TYPE_OBJECT,
978                        e_cal_listener);
979
980 /**
981  * e_cal_listener_construct:
982  * @listener: A calendar listener.
983  * @cal_set_mode_fn: Function callback for notification that a
984  * calendar changed modes.
985  * @fn_data: Closure data pointer that will be passed to the notification
986  * functions.
987  *
988  * Constructs all internal information for a calendar listener. This function
989  * usually does not need to be called, unless creating a ECalListener-derived
990  * class.
991  *
992  * Return value: the calendar listener ready to be used.
993  */
994 ECalListener *
995 e_cal_listener_construct (ECalListener *listener,
996                           ECalListenerCalSetModeFn cal_set_mode_fn,
997                           gpointer fn_data)
998 {
999         ECalListenerPrivate *priv;
1000
1001         g_return_val_if_fail (listener != NULL, NULL);
1002         g_return_val_if_fail (E_IS_CAL_LISTENER (listener), NULL);
1003         g_return_val_if_fail (cal_set_mode_fn != NULL, NULL);
1004
1005         priv = listener->priv;
1006
1007         priv->cal_set_mode_fn = cal_set_mode_fn;
1008         priv->fn_data = fn_data;
1009
1010         return listener;
1011 }
1012
1013 /**
1014  * e_cal_listener_new:
1015  * @cal_set_mode_fn: Function callback for notification that a
1016  * calendar changed modes.
1017  * @fn_data: Closure data pointer that will be passed to the notification
1018  * functions.
1019  * 
1020  * Creates a new #ECalListener object.
1021  *
1022  * Return value: A newly-created #ECalListener object.
1023  **/
1024 ECalListener *
1025 e_cal_listener_new (ECalListenerCalSetModeFn cal_set_mode_fn,
1026                     gpointer fn_data)
1027 {
1028         ECalListener *listener;
1029
1030         g_return_val_if_fail (cal_set_mode_fn != NULL, NULL);
1031
1032         listener = g_object_new (E_TYPE_CAL_LISTENER, 
1033                                  "poa", bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_REQUEST, NULL),
1034                                  NULL);
1035
1036         return e_cal_listener_construct (listener,
1037                                          cal_set_mode_fn,
1038                                          fn_data);
1039 }
1040
1041 /**
1042  * e_cal_listener_stop_notification:
1043  * @listener: A calendar listener.
1044  * 
1045  * Informs a calendar listener that no further notification is desired.  The
1046  * callbacks specified when the listener was created will no longer be invoked
1047  * after this function is called.
1048  **/
1049 void
1050 e_cal_listener_stop_notification (ECalListener *listener)
1051 {
1052         ECalListenerPrivate *priv;
1053
1054         g_return_if_fail (listener != NULL);
1055         g_return_if_fail (E_IS_CAL_LISTENER (listener));
1056
1057         priv = listener->priv;
1058         g_return_if_fail (priv->notify != FALSE);
1059
1060         priv->notify = FALSE;
1061 }