188
* If the GError is a remote error, extract the EBookStatus embedded inside.
189
* Otherwise return CORBA_EXCEPTION (I know this is DBus...).
191
static ECalendarStatus
192
get_status_from_error (GError *error)
194
#define err(a,b) "org.gnome.evolution.dataserver.calendar.Cal." a, b
197
ECalendarStatus err_code;
199
{ err ("Success", E_CALENDAR_STATUS_OK) },
200
{ err ("RepositoryOffline", E_CALENDAR_STATUS_REPOSITORY_OFFLINE) },
201
{ err ("PermissionDenied", E_CALENDAR_STATUS_PERMISSION_DENIED) },
202
{ err ("InvalidRange", E_CALENDAR_STATUS_OTHER_ERROR) },
203
{ err ("ObjectNotFound", E_CALENDAR_STATUS_OBJECT_NOT_FOUND) },
204
{ err ("InvalidObject", E_CALENDAR_STATUS_INVALID_OBJECT) },
205
{ err ("ObjectIdAlreadyExists", E_CALENDAR_STATUS_OBJECT_ID_ALREADY_EXISTS) },
206
{ err ("AuthenticationFailed", E_CALENDAR_STATUS_AUTHENTICATION_FAILED) },
207
{ err ("AuthenticationRequired", E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED) },
208
{ err ("UnsupportedField", E_CALENDAR_STATUS_OTHER_ERROR) },
209
{ err ("UnsupportedMethod", E_CALENDAR_STATUS_OTHER_ERROR) },
210
{ err ("UnsupportedAuthenticationMethod", E_CALENDAR_STATUS_OTHER_ERROR) },
211
{ err ("TLSNotAvailable", E_CALENDAR_STATUS_OTHER_ERROR) },
212
{ err ("NoSuchCal", E_CALENDAR_STATUS_NO_SUCH_CALENDAR) },
213
{ err ("UnknownUser", E_CALENDAR_STATUS_UNKNOWN_USER) },
214
{ err ("OfflineUnavailable", E_CALENDAR_STATUS_OTHER_ERROR) },
215
{ err ("SearchSizeLimitExceeded", E_CALENDAR_STATUS_OTHER_ERROR) },
216
{ err ("SearchTimeLimitExceeded", E_CALENDAR_STATUS_OTHER_ERROR) },
217
{ err ("InvalidQuery", E_CALENDAR_STATUS_OTHER_ERROR) },
218
{ err ("QueryRefused", E_CALENDAR_STATUS_OTHER_ERROR) },
219
{ err ("CouldNotCancel", E_CALENDAR_STATUS_COULD_NOT_CANCEL) },
220
{ err ("OtherError", E_CALENDAR_STATUS_OTHER_ERROR) },
221
{ err ("InvalidServerVersion", E_CALENDAR_STATUS_INVALID_SERVER_VERSION) }
225
if G_LIKELY (error == NULL)
228
if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION) {
232
name = dbus_g_error_get_name (error);
233
for (i = 0; i < G_N_ELEMENTS (errors); i++) {
234
if (g_ascii_strcasecmp (errors[i].name, name) == 0)
235
return errors[i].err_code;
238
g_warning ("Unmatched error name %s", name);
239
return E_CALENDAR_STATUS_OTHER_ERROR;
240
} else if (error->domain == E_CALENDAR_ERROR) {
243
/* In this case the error was caused by DBus */
244
return E_CALENDAR_STATUS_CORBA_EXCEPTION;
249
* If the specified GError is a remote error, then create a new error
250
* representing the remote error. If the error is anything else, then leave it
254
unwrap_gerror(GError **error)
258
if ((*error)->domain == DBUS_GERROR && (*error)->code == DBUS_GERROR_REMOTE_EXCEPTION) {
259
GError *new_error = NULL;
261
code = get_status_from_error (*error);
262
new_error = g_error_new_literal (E_CALENDAR_ERROR, code, (*error)->message);
263
g_error_free (*error);
200
270
* e_cal_source_type_enum_get_type:
202
272
* Registers the #ECalSourceTypeEnum type with glib.
204
* Return value: the ID of the #ECalSourceTypeEnum type.
274
* Returns: the ID of the #ECalSourceTypeEnum type.
207
277
e_cal_source_type_enum_get_type (void)
209
static GType e_cal_source_type_enum_type = 0;
279
static volatile gsize enum_type__volatile = 0;
211
if (!e_cal_source_type_enum_type) {
281
if (g_once_init_enter (&enum_type__volatile)) {
212
283
static GEnumValue values [] = {
213
284
{ E_CAL_SOURCE_TYPE_EVENT, "Event", NULL},
214
285
{ E_CAL_SOURCE_TYPE_TODO, "ToDo", NULL},
272
345
{ -1, NULL, NULL }
275
cal_mode_enum_type = g_enum_register_static ("CalModeEnum", values);
348
enum_type = g_enum_register_static ("CalModeEnum", values);
349
g_once_init_leave (&enum_type__volatile, enum_type);
278
return cal_mode_enum_type;
352
return enum_type__volatile;
281
static GNOME_Evolution_Calendar_CalObjType
355
static EDataCalObjType
282
356
convert_type (ECalSourceType type)
285
359
case E_CAL_SOURCE_TYPE_EVENT:
286
return GNOME_Evolution_Calendar_TYPE_EVENT;
287
361
case E_CAL_SOURCE_TYPE_TODO:
288
return GNOME_Evolution_Calendar_TYPE_TODO;
289
363
case E_CAL_SOURCE_TYPE_JOURNAL:
290
return GNOME_Evolution_Calendar_TYPE_JOURNAL;
292
return GNOME_Evolution_Calendar_TYPE_ANY;
295
return GNOME_Evolution_Calendar_TYPE_ANY;
301
e_calendar_new_op (ECal *ecal, const gchar *str)
303
ECalendarOp *op = g_new0 (ECalendarOp, 1);
305
op->done = e_flag_new ();
307
ecal->priv->current_op = op;
308
op->op_str = g_strdup (str);
314
e_calendar_get_op (ECal *ecal)
316
if (!ecal->priv->current_op) {
317
g_warning ("%s", G_STRLOC ": Unexpected response");
321
return ecal->priv->current_op;
325
e_calendar_free_op (ECalendarOp *op)
327
/* XXX more stuff here */
328
e_flag_free (op->done);
334
e_calendar_remove_op (ECal *ecal, ECalendarOp *op)
336
if (ecal->priv->current_op != op)
337
g_warning ("%s", G_STRLOC ": Cannot remove op, it's not current");
339
ecal->priv->current_op = NULL;
342
/* Gets rid of the factories that a ecal knows about */
344
destroy_factories (ECal *ecal)
347
CORBA_Object factory;
348
CORBA_Environment ev;
354
CORBA_exception_init (&ev);
356
for (f = priv->factories; f; f = f->next) {
359
result = CORBA_Object_is_nil (factory, &ev);
360
if (BONOBO_EX (&ev)) {
361
g_message ("%s", G_STRLOC ": could not see if a factory was nil");
362
CORBA_exception_free (&ev);
370
CORBA_Object_release (factory, &ev);
371
if (BONOBO_EX (&ev)) {
372
g_message ("%s", G_STRLOC ": could not release a factory");
373
CORBA_exception_free (&ev);
377
g_list_free (priv->factories);
378
priv->factories = NULL;
381
/* Gets rid of the calendar ecal interface object that a ecal knows about */
383
destroy_cal (ECal *ecal)
386
CORBA_Environment ev;
391
CORBA_exception_init (&ev);
392
result = CORBA_Object_is_nil (priv->cal, &ev);
393
if (BONOBO_EX (&ev)) {
394
g_message ("%s", G_STRLOC ": could not see if the "
395
"calendar ecal interface object was nil");
396
priv->cal = CORBA_OBJECT_NIL;
397
CORBA_exception_free (&ev);
400
CORBA_exception_free (&ev);
405
bonobo_object_release_unref (priv->cal, NULL);
406
priv->cal = CORBA_OBJECT_NIL;
411
free_timezone (gpointer key, gpointer value, gpointer data)
413
/* Note that the key comes from within the icaltimezone value, so we
415
icaltimezone_free (value, TRUE);
421
backend_died_cb (EComponentListener *cl, gpointer user_data)
424
ECal *ecal = (ECal *) user_data;
427
priv->load_state = E_CAL_LOAD_NOT_LOADED;
428
g_signal_emit (G_OBJECT (ecal), e_cal_signals[BACKEND_DIED], 0);
431
/* Signal handlers for the listener's signals */
432
/* Handle the cal_opened notification from the listener */
435
cal_read_only_cb (ECalListener *listener, ECalendarStatus status, gboolean read_only, gpointer data)
440
op = e_calendar_get_op (ecal);
442
if (op == NULL || !op->bool) {
443
ecal->priv->read_only = read_only;
448
op->bool = read_only;
450
e_flag_set (op->done);
454
cal_cal_address_cb (ECalListener *listener, ECalendarStatus status, const gchar *address, gpointer data)
459
op = e_calendar_get_op (ecal);
461
if (ecal->priv->cal_address) {
462
g_free (ecal->priv->cal_address);
463
ecal->priv->cal_address = NULL;
466
ecal->priv->cal_address = g_strdup (address);
473
op->string = g_strdup (address);
475
e_flag_set (op->done);
479
cal_alarm_address_cb (ECalListener *listener, ECalendarStatus status, const gchar *address, gpointer data)
484
op = e_calendar_get_op (ecal);
487
g_warning ("%s", G_STRLOC ": Cannot find operation ");
492
op->string = g_strdup (address);
494
e_flag_set (op->done);
498
cal_ldap_attribute_cb (ECalListener *listener, ECalendarStatus status, const gchar *attribute, gpointer data)
503
op = e_calendar_get_op (ecal);
506
g_warning ("%s", G_STRLOC ": Cannot find operation ");
511
op->string = g_strdup (attribute);
513
e_flag_set (op->done);
517
cal_static_capabilities_cb (ECalListener *listener, ECalendarStatus status, const gchar *capabilities, gpointer data)
522
op = e_calendar_get_op (ecal);
525
g_warning ("%s", G_STRLOC ": Cannot find operation ");
530
op->string = g_strdup (capabilities);
532
e_flag_set (op->done);
536
cal_opened_cb (ECalListener *listener, ECalendarStatus status, gpointer data)
541
op = e_calendar_get_op (ecal);
544
g_warning ("%s", G_STRLOC ": Cannot find operation ");
550
e_flag_set (op->done);
554
cal_removed_cb (ECalListener *listener, ECalendarStatus status, gpointer data)
559
op = e_calendar_get_op (ecal);
562
g_warning ("%s", G_STRLOC ": Cannot find operation ");
568
e_flag_set (op->done);
572
cal_object_created_cb (ECalListener *listener, ECalendarStatus status, const gchar *uid, gpointer data)
577
op = e_calendar_get_op (ecal);
580
g_warning ("%s", G_STRLOC ": Cannot find operation ");
585
op->uid = g_strdup (uid);
587
e_flag_set (op->done);
591
cal_object_modified_cb (ECalListener *listener, ECalendarStatus status, gpointer data)
596
op = e_calendar_get_op (ecal);
599
g_warning (G_STRLOC ": Cannot find operation ");
605
e_flag_set (op->done);
609
cal_object_removed_cb (ECalListener *listener, ECalendarStatus status, gpointer data)
614
op = e_calendar_get_op (ecal);
617
g_warning (G_STRLOC ": Cannot find operation ");
623
e_flag_set (op->done);
627
cal_alarm_discarded_cb (ECalListener *listener, ECalendarStatus status, gpointer data)
632
op = e_calendar_get_op (ecal);
635
g_warning (G_STRLOC ": Cannot find operation ");
641
e_flag_set (op->done);
645
cal_objects_received_cb (ECalListener *listener, ECalendarStatus status, gpointer data)
650
op = e_calendar_get_op (ecal);
653
g_warning (G_STRLOC ": Cannot find operation ");
659
e_flag_set (op->done);
663
cal_objects_sent_cb (ECalListener *listener, ECalendarStatus status, GList *users, const gchar *object, gpointer data)
669
op = e_calendar_get_op (ecal);
672
g_warning (G_STRLOC ": Cannot find operation ");
677
op->list = g_list_copy (users);
678
op->string = g_strdup (object);
680
for (l = op->list; l; l = l->next)
681
l->data = g_strdup (l->data);
683
e_flag_set (op->done);
687
cal_default_object_requested_cb (ECalListener *listener, ECalendarStatus status, const gchar *object, gpointer data)
692
op = e_calendar_get_op (ecal);
695
g_warning (G_STRLOC ": Cannot find operation ");
700
op->string = g_strdup (object);
702
e_flag_set (op->done);
706
cal_object_requested_cb (ECalListener *listener, ECalendarStatus status, const gchar *object, gpointer data)
711
op = e_calendar_get_op (ecal);
714
g_warning (G_STRLOC ": Cannot find operation ");
719
op->string = g_strdup (object);
721
e_flag_set (op->done);
725
cal_object_list_cb (ECalListener *listener, ECalendarStatus status, GList *objects, gpointer data)
731
op = e_calendar_get_op (ecal);
734
g_warning (G_STRLOC ": Cannot find operation ");
739
op->list = g_list_copy (objects);
741
for (l = op->list; l; l = l->next)
742
l->data = icalcomponent_new_clone (l->data);
744
e_flag_set (op->done);
748
cal_attachment_list_cb (ECalListener *listener, ECalendarStatus status, GSList *attachments, gpointer data)
753
op = e_calendar_get_op (ecal);
756
g_warning (G_STRLOC ": Cannot find operation ");
761
op->slist = g_slist_copy (attachments);
763
e_flag_set (op->done);
767
cal_get_timezone_cb (ECalListener *listener, ECalendarStatus status, const gchar *object, gpointer data)
772
op = e_calendar_get_op (ecal);
775
g_warning (G_STRLOC ": Cannot find operation ");
780
op->string = g_strdup (object);
782
e_flag_set (op->done);
786
cal_add_timezone_cb (ECalListener *listener, ECalendarStatus status, const gchar *tzid, gpointer data)
791
op = e_calendar_get_op (ecal);
794
g_warning (G_STRLOC ": Cannot find operation ");
799
op->uid = g_strdup (tzid);
801
e_flag_set (op->done);
805
cal_set_default_timezone_cb (ECalListener *listener, ECalendarStatus status, gpointer data)
810
op = e_calendar_get_op (ecal);
813
g_warning (G_STRLOC ": Cannot find operation ");
819
e_flag_set (op->done);
823
cal_get_changes_cb (ECalListener *listener, ECalendarStatus status, GList *changes, gpointer data)
829
op = e_calendar_get_op (ecal);
832
g_warning (G_STRLOC ": Cannot find operation ");
837
op->list = g_list_copy (changes);
839
for (l = op->list; l; l = l->next) {
840
ECalChange *ccc = l->data, *new_ccc;
842
new_ccc = g_new (ECalChange, 1);
843
new_ccc->comp = e_cal_component_clone (ccc->comp);
844
new_ccc->type = ccc->type;
849
e_flag_set (op->done);
853
cal_get_free_busy_cb (ECalListener *listener, ECalendarStatus status, GList *freebusy, gpointer data)
859
op = e_calendar_get_op (ecal);
862
g_warning (G_STRLOC ": Cannot find operation ");
867
op->list = g_list_copy (freebusy);
869
for (l = op->list; l; l = l->next)
870
l->data = e_cal_component_clone (l->data);
872
e_flag_set (op->done);
876
cal_query_cb (ECalListener *listener, ECalendarStatus status, GNOME_Evolution_Calendar_CalView query, gpointer data)
881
op = e_calendar_get_op (ecal);
884
g_warning (G_STRLOC ": Cannot find operation ");
889
op->query = e_cal_view_new (query, op->listener, ecal);
891
e_flag_set (op->done);
895
reopen_with_auth (gpointer data)
897
ECalendarStatus status;
899
open_calendar (E_CAL (data), TRUE, NULL, &status, TRUE);
904
auth_required_cb (ECalListener *listener, gpointer data)
906
g_idle_add (reopen_with_auth, data);
910
/* Handle the cal_set_mode notification from the listener */
912
cal_set_mode_cb (ECalListener *listener,
913
GNOME_Evolution_Calendar_CalListener_SetModeStatus status,
914
GNOME_Evolution_Calendar_CalMode mode,
919
ECalSetModeStatus ecal_status;
924
ecal_status = E_CAL_SET_MODE_ERROR;
927
case GNOME_Evolution_Calendar_CalListener_MODE_SET:
928
ecal_status = E_CAL_SET_MODE_SUCCESS;
930
case GNOME_Evolution_Calendar_CalListener_MODE_NOT_SET:
931
ecal_status = E_CAL_SET_MODE_ERROR;
933
case GNOME_Evolution_Calendar_CalListener_MODE_NOT_SUPPORTED:
934
ecal_status = E_CAL_SET_MODE_NOT_SUPPORTED;
937
g_assert_not_reached ();
940
/* We are *not* inside a signal handler (this is just a simple callback
941
* called from the listener), so there is not a temporary reference to
942
* the ecal object. We ref() so that we can safely emit our own
943
* signal and clean up.
946
g_object_ref (G_OBJECT (ecal));
948
g_signal_emit (G_OBJECT (ecal), e_cal_signals[CAL_SET_MODE],
949
0, ecal_status, mode);
951
if (ecal_status == E_CAL_SET_MODE_SUCCESS && ecal->priv->load_state == E_CAL_LOAD_LOADED) {
952
/* the mode has been changed, recheck whether readonly or not */
953
GError *error = NULL;
954
gboolean read_only = TRUE;
956
if (get_read_only (ecal, &read_only, &error)) {
957
priv->read_only = read_only;
961
g_warning ("%s: get_read_only failed: %s", G_STRFUNC, error->message);
962
g_error_free (error);
966
g_object_unref (G_OBJECT (ecal));
976
backend_error_idle_cb (gpointer data)
978
ECalErrorData *error_data = data;
980
g_signal_emit (G_OBJECT (error_data->ecal), e_cal_signals[BACKEND_ERROR], 0, error_data->message);
982
g_object_unref (error_data->ecal);
983
g_free (error_data->message);
989
/* Handle the error_occurred signal from the listener */
991
backend_error_cb (ECalListener *listener, const gchar *message, gpointer data)
993
ECalErrorData *error_data;
995
error_data = g_new0 (ECalErrorData, 1);
997
error_data->ecal = g_object_ref (data);
998
error_data->message = g_strdup (message);
1000
g_idle_add (backend_error_idle_cb, error_data);
1006
get_factories (const gchar *str_uri, GList **factories)
1008
GNOME_Evolution_Calendar_CalFactory factory;
1009
Bonobo_ServerInfoList *servers;
1014
/* Determine the protocol and query for factory supporting that */
1015
uri = e_uri_new (str_uri);
1017
g_warning (G_STRLOC ": Invalid uri string");
1022
query = "repo_ids.has ('IDL:GNOME/Evolution/DataServer/CalFactory:" API_VERSION "')";
1024
servers = bonobo_activation_query (query, NULL, NULL);
1029
g_warning (G_STRLOC ": Unable to query for calendar factories");
1034
/* Try to activate the servers for the protocol */
1035
for (i = 0; i < servers->_length; i++) {
1036
const Bonobo_ServerInfo *info;
1038
info = servers->_buffer + i;
1041
g_message (G_STRLOC ": Activating calendar factory (%s)", info->iid);
1043
factory = bonobo_activation_activate_from_id (info->iid, 0, NULL, NULL);
1045
if (factory == CORBA_OBJECT_NIL)
1046
g_warning (G_STRLOC ": Could not activate calendar factory (%s)", info->iid);
1048
*factories = g_list_append (*factories, factory);
1051
CORBA_free (servers);
1056
/* Object initialization function for the calendar ecal */
1058
e_cal_init (ECal *ecal, ECalClass *klass)
1062
priv = g_new0 (ECalPrivate, 1);
372
e_cal_init (ECal *ecal)
376
ecal->priv = priv = E_CAL_GET_PRIVATE (ecal);
1065
378
priv->load_state = E_CAL_LOAD_NOT_LOADED;
1066
379
priv->uri = NULL;
1067
380
priv->local_attachment_store = NULL;
1068
priv->mutex = g_mutex_new ();
1069
priv->listener = e_cal_listener_new (cal_set_mode_cb, ecal);
1071
382
priv->cal_address = NULL;
1072
383
priv->alarm_email_address = NULL;
1073
384
priv->ldap_attribute = NULL;
1074
priv->capabilities = FALSE;
1075
priv->factories = NULL;
385
priv->capabilities = NULL;
1076
387
priv->timezones = g_hash_table_new (g_str_hash, g_str_equal);
1077
388
priv->default_zone = icaltimezone_get_utc_timezone ();
1078
priv->comp_listener = NULL;
1080
g_signal_connect (G_OBJECT (priv->listener), "read_only", G_CALLBACK (cal_read_only_cb), ecal);
1081
g_signal_connect (G_OBJECT (priv->listener), "cal_address", G_CALLBACK (cal_cal_address_cb), ecal);
1082
g_signal_connect (G_OBJECT (priv->listener), "alarm_address", G_CALLBACK (cal_alarm_address_cb), ecal);
1083
g_signal_connect (G_OBJECT (priv->listener), "ldap_attribute", G_CALLBACK (cal_ldap_attribute_cb), ecal);
1084
g_signal_connect (G_OBJECT (priv->listener), "static_capabilities", G_CALLBACK (cal_static_capabilities_cb), ecal);
1085
g_signal_connect (G_OBJECT (priv->listener), "open", G_CALLBACK (cal_opened_cb), ecal);
1086
g_signal_connect (G_OBJECT (priv->listener), "remove", G_CALLBACK (cal_removed_cb), ecal);
1087
g_signal_connect (G_OBJECT (priv->listener), "create_object", G_CALLBACK (cal_object_created_cb), ecal);
1088
g_signal_connect (G_OBJECT (priv->listener), "modify_object", G_CALLBACK (cal_object_modified_cb), ecal);
1089
g_signal_connect (G_OBJECT (priv->listener), "remove_object", G_CALLBACK (cal_object_removed_cb), ecal);
1090
g_signal_connect (G_OBJECT (priv->listener), "discard_alarm", G_CALLBACK (cal_alarm_discarded_cb), ecal);
1091
g_signal_connect (G_OBJECT (priv->listener), "receive_objects", G_CALLBACK (cal_objects_received_cb), ecal);
1092
g_signal_connect (G_OBJECT (priv->listener), "send_objects", G_CALLBACK (cal_objects_sent_cb), ecal);
1093
g_signal_connect (G_OBJECT (priv->listener), "default_object", G_CALLBACK (cal_default_object_requested_cb), ecal);
1094
g_signal_connect (G_OBJECT (priv->listener), "object", G_CALLBACK (cal_object_requested_cb), ecal);
1095
g_signal_connect (G_OBJECT (priv->listener), "object_list", G_CALLBACK (cal_object_list_cb), ecal);
1096
g_signal_connect (G_OBJECT (priv->listener), "attachment_list", G_CALLBACK (cal_attachment_list_cb), ecal);
1097
g_signal_connect (G_OBJECT (priv->listener), "get_timezone", G_CALLBACK (cal_get_timezone_cb), ecal);
1098
g_signal_connect (G_OBJECT (priv->listener), "add_timezone", G_CALLBACK (cal_add_timezone_cb), ecal);
1099
g_signal_connect (G_OBJECT (priv->listener), "set_default_timezone", G_CALLBACK (cal_set_default_timezone_cb), ecal);
1100
g_signal_connect (G_OBJECT (priv->listener), "get_changes", G_CALLBACK (cal_get_changes_cb), ecal);
1101
g_signal_connect (G_OBJECT (priv->listener), "get_free_busy", G_CALLBACK (cal_get_free_busy_cb), ecal);
1102
g_signal_connect (G_OBJECT (priv->listener), "query", G_CALLBACK (cal_query_cb), ecal);
1103
g_signal_connect (G_OBJECT (priv->listener), "backend_error", G_CALLBACK (backend_error_cb), ecal);
1104
g_signal_connect (G_OBJECT (priv->listener), "auth_required", G_CALLBACK (auth_required_cb), ecal);
392
* Called when the calendar server dies.
395
proxy_destroyed (gpointer data, GObject *object)
400
g_assert (E_IS_CAL (ecal));
404
g_warning (G_STRLOC ": e-d-s proxy died");
406
/* Ensure that everything relevant is reset */
408
factory_proxy = NULL;
410
priv->load_state = E_CAL_LOAD_NOT_LOADED;
413
g_signal_emit (G_OBJECT (ecal), e_cal_signals [BACKEND_DIED], 0);
416
/* Dispose handler for the calendar ecal */
418
e_cal_dispose (GObject *object)
423
ecal = E_CAL (object);
427
GError *error = NULL;
429
g_object_weak_unref (G_OBJECT (priv->proxy), proxy_destroyed, ecal);
431
org_gnome_evolution_dataserver_calendar_Cal_close (priv->proxy, &error);
432
g_object_unref (priv->proxy);
437
g_warning ("%s: Failed to close calendar, %s\n", G_STRFUNC, error->message);
438
g_error_free (error);
442
(* G_OBJECT_CLASS (parent_class)->dispose) (object);
446
free_timezone (gpointer key, gpointer value, gpointer data)
448
/* Note that the key comes from within the icaltimezone value, so we
450
icaltimezone_free (value, TRUE);
1107
453
/* Finalize handler for the calendar ecal */
1234
553
klass->cal_opened = NULL;
1235
554
klass->backend_died = NULL;
556
object_class->dispose = e_cal_dispose;
1237
557
object_class->finalize = e_cal_finalize;
1243
* Registers the #ECal class if necessary, and returns the type ID assigned
1246
* Return value: The type ID of the #ECal class.
1249
e_cal_get_type (void)
1251
static GType e_cal_type = 0;
1254
static GTypeInfo info = {
1256
(GBaseInitFunc) NULL,
1257
(GBaseFinalizeFunc) NULL,
1258
(GClassInitFunc) e_cal_class_init,
1262
(GInstanceInitFunc) e_cal_init
1264
e_cal_type = g_type_register_static (G_TYPE_OBJECT, "ECal", &info, 0);
1271
fetch_corba_cal (ECal *ecal, ESource *source, ECalSourceType type)
1275
CORBA_Environment ev;
1278
gboolean result = FALSE;
1281
g_return_val_if_fail (priv->load_state == E_CAL_LOAD_NOT_LOADED, FALSE);
1282
g_assert (priv->uri == NULL);
1283
g_return_val_if_fail (source != NULL, FALSE);
1285
str_uri = e_source_get_uri (source);
1289
if (!get_factories (str_uri, &priv->factories)) {
1294
g_object_ref (source);
1295
priv->source = source;
1297
priv->uri = g_strdup (str_uri);
1300
source_xml = e_source_to_standalone_xml (source);
1302
for (f = priv->factories; f; f = f->next) {
1303
GNOME_Evolution_Calendar_Cal cal;
1305
CORBA_exception_init (&ev);
1307
cal = GNOME_Evolution_Calendar_CalFactory_getCal (f->data, source_xml, convert_type (priv->type),
1308
BONOBO_OBJREF (priv->listener), &ev);
1309
if (BONOBO_EX (&ev))
1319
g_free (source_xml);
559
g_type_class_add_private (klass, sizeof (ECalPrivate));
562
static DBusHandlerResult
563
filter_dbus_msgs_cb (DBusConnection *pconnection, DBusMessage *message, gpointer user_data)
565
if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
566
DBusGConnection *conn = connection;
569
factory_proxy = NULL;
572
dbus_g_connection_unref (conn);
573
return DBUS_HANDLER_RESULT_HANDLED;
576
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
580
factory_proxy_destroy_cb (DBusGProxy *proxy, gpointer user_data)
583
factory_proxy = NULL;
1323
587
/* one-time start up for libecal */
1325
e_cal_activate (void)
1327
static GStaticMutex e_cal_lock = G_STATIC_MUTEX_INIT;
1328
static gboolean activated = FALSE;
1330
g_static_mutex_lock (&e_cal_lock);
1334
if (!bonobo_is_initialized ())
1335
bonobo_init (NULL, NULL);
1337
g_static_mutex_unlock (&e_cal_lock);
589
e_cal_activate(GError **error)
594
if (G_LIKELY (factory_proxy)) {
600
connection = dbus_g_bus_get (DBUS_BUS_SESSION, error);
606
dbus_connection_add_filter (dbus_g_connection_get_connection (connection), filter_dbus_msgs_cb, NULL, NULL);
609
dbus_error_init (&derror);
610
if (!dbus_bus_start_service_by_name (dbus_g_connection_get_connection (connection),
611
"org.gnome.evolution.dataserver.Calendar",
614
dbus_set_g_error (error, &derror);
615
dbus_error_free (&derror);
620
if (!factory_proxy) {
621
factory_proxy = dbus_g_proxy_new_for_name_owner (connection,
622
"org.gnome.evolution.dataserver.Calendar",
623
"/org/gnome/evolution/dataserver/calendar/CalFactory",
624
"org.gnome.evolution.dataserver.calendar.CalFactory",
626
if (!factory_proxy) {
631
g_signal_connect (factory_proxy, "destroy", G_CALLBACK (factory_proxy_destroy_cb), NULL);
640
reopen_with_auth (gpointer data)
642
ECalendarStatus status;
644
open_calendar (E_CAL (data), TRUE, NULL, &status, TRUE, FALSE);
649
auth_required_cb (DBusGProxy *proxy, ECal *cal)
651
g_return_if_fail (E_IS_CAL (cal));
653
g_idle_add (reopen_with_auth, (gpointer)cal);
657
mode_cb (DBusGProxy *proxy, EDataCalMode mode, ECal *cal)
659
g_return_if_fail (E_IS_CAL (cal));
660
g_return_if_fail (mode & AnyMode);
662
g_signal_emit (G_OBJECT (cal), e_cal_signals[CAL_SET_MODE],
663
0, E_CALENDAR_STATUS_OK, mode);
667
readonly_cb (DBusGProxy *proxy, gboolean read_only, ECal *cal)
671
g_return_if_fail (cal && E_IS_CAL (cal));
674
priv->read_only = read_only;
679
backend_died_cb (EComponentListener *cl, gpointer user_data)
682
ECal *ecal = (ECal *) user_data;
685
priv->load_state = E_CAL_LOAD_NOT_LOADED;
686
g_signal_emit (G_OBJECT (ecal), e_cal_signals[BACKEND_DIED], 0);
696
backend_error_idle_cb (gpointer data)
698
ECalErrorData *error_data = data;
700
g_signal_emit (G_OBJECT (error_data->ecal), e_cal_signals[BACKEND_ERROR], 0, error_data->message);
702
g_object_unref (error_data->ecal);
703
g_free (error_data->message);
709
/* Handle the error_occurred signal from the listener */
711
backend_error_cb (DBusGProxy *proxy, const gchar *message, ECal *ecal)
713
ECalErrorData *error_data;
715
g_return_if_fail (E_IS_CAL (ecal));
717
error_data = g_new0 (ECalErrorData, 1);
719
error_data->ecal = g_object_ref (ecal);
720
error_data->message = g_strdup (message);
722
g_idle_add (backend_error_idle_cb, error_data);
1340
725
/* TODO - For now, the policy of where each backend serializes its
1426
811
* Creates a new calendar client. This does not open the calendar itself,
1427
812
* for that, #e_cal_open or #e_cal_open_async needs to be called.
1429
* Return value: A newly-created calendar client, or NULL if the client could
814
* Returns: A newly-created calendar client, or NULL if the client could
1430
815
* not be constructed because it could not contact the calendar server.
1433
818
e_cal_new (ESource *source, ECalSourceType type)
823
GError *error = NULL;
825
g_return_val_if_fail (source && E_IS_SOURCE (source), NULL);
826
g_return_val_if_fail (type < E_CAL_SOURCE_TYPE_LAST, NULL);
828
if (!e_cal_activate (&error)) {
829
g_warning("Cannot activate ECal: %s\n", error ? error->message : "Unknown error");
830
g_error_free (error);
1439
834
ecal = g_object_new (E_TYPE_CAL, NULL);
1441
if (!fetch_corba_cal (ecal, source, type)) {
837
priv->source = g_object_ref (source);
838
priv->uri = e_source_get_uri (source);
841
xml = e_source_to_standalone_xml (priv->source);
843
if (!org_gnome_evolution_dataserver_calendar_CalFactory_get_cal (factory_proxy, xml, convert_type (priv->type), &path, &error)) {
846
g_warning ("Cannot get cal from factory: %s", error ? error->message : "Unknown error");
847
g_error_free (error);
1442
848
g_object_unref (ecal);
853
priv->proxy = dbus_g_proxy_new_for_name_owner (connection,
854
"org.gnome.evolution.dataserver.Calendar", path,
855
"org.gnome.evolution.dataserver.calendar.Cal",
863
g_object_weak_ref (G_OBJECT (priv->proxy), proxy_destroyed, ecal);
865
dbus_g_proxy_add_signal (priv->proxy, "auth_required", G_TYPE_INVALID);
866
dbus_g_proxy_connect_signal (priv->proxy, "auth_required", G_CALLBACK (auth_required_cb), ecal, NULL);
867
dbus_g_proxy_add_signal (priv->proxy, "backend_error", G_TYPE_STRING, G_TYPE_INVALID);
868
dbus_g_proxy_connect_signal (priv->proxy, "backend_error", G_CALLBACK (backend_error_cb), ecal, NULL);
869
dbus_g_proxy_add_signal (priv->proxy, "readonly", G_TYPE_BOOLEAN, G_TYPE_INVALID);
870
dbus_g_proxy_connect_signal (priv->proxy, "readonly", G_CALLBACK (readonly_cb), ecal, NULL);
871
dbus_g_proxy_add_signal (priv->proxy, "mode", G_TYPE_INT, G_TYPE_INVALID);
872
dbus_g_proxy_connect_signal (priv->proxy, "mode", G_CALLBACK (mode_cb), ecal, NULL);
1447
874
/* Set the local attachment store path for the calendar */
1448
875
set_local_attachment_store (ecal);
1450
/* initialize component listener */
1451
ecal->priv->comp_listener = e_component_listener_new ((Bonobo_Unknown) ecal->priv->cal);
1452
g_signal_connect (G_OBJECT (ecal->priv->comp_listener), "component_died",
1453
G_CALLBACK (backend_died_cb), ecal);
880
/* for each known source calls check_func, which should return TRUE if the required
881
source have been found. Function returns NULL or the source on which was returned
882
TRUE by the check_func. Non-NULL pointer should be unreffed by g_object_unref. */
884
search_known_sources (ECalSourceType type, gboolean (*check_func)(ESource *source, gpointer user_data), gpointer user_data, GError **error)
886
ESourceList *sources;
891
g_return_val_if_fail (check_func != NULL, NULL);
893
if (!e_cal_get_sources (&sources, type, &err)) {
894
g_propagate_error (error, err);
898
for (g = e_source_list_peek_groups (sources); g; g = g->next) {
899
ESourceGroup *group = E_SOURCE_GROUP (g->data);
902
for (s = e_source_group_peek_sources (group); s; s = s->next) {
903
ESource *source = E_SOURCE (s->data);
905
if (check_func (source, user_data)) {
906
res = g_object_ref (source);
915
g_object_unref (sources);
921
check_uri (ESource *source, gpointer uri)
925
g_return_val_if_fail (source != NULL, FALSE);
926
g_return_val_if_fail (uri != NULL, FALSE);
928
suri = e_source_peek_absolute_uri (source);
930
return suri && g_ascii_strcasecmp (suri, uri) == 0;
1459
934
* e_cal_new_from_uri:
1460
935
* @uri: The URI pointing to the calendar to open.
2351
1691
* Queries the LDAP attribute for a calendar client.
2353
* Return value: TRUE if the call was successful, FALSE if there was an
1693
* Returns: TRUE if the call was successful, FALSE if there was an
2354
1694
* error contacting the backend.
2357
1697
e_cal_get_ldap_attribute (ECal *ecal, gchar **ldap_attribute, GError **error)
2359
1699
ECalPrivate *priv;
2360
CORBA_Environment ev;
2361
ECalendarStatus status;
2362
ECalendarOp *our_op;
2364
e_return_error_if_fail (ecal && E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
1701
e_return_error_if_fail (ldap_attribute != NULL, E_CALENDAR_STATUS_INVALID_ARG);
1702
e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
2366
1703
priv = ecal->priv;
2368
g_mutex_lock (ecal->priv->mutex);
2370
if (ecal->priv->load_state != E_CAL_LOAD_LOADED) {
2371
g_mutex_unlock (ecal->priv->mutex);
1704
e_return_error_if_fail (priv->proxy, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
1705
*ldap_attribute = NULL;
1707
if (priv->load_state != E_CAL_LOAD_LOADED) {
2372
1708
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
2375
if (ecal->priv->current_op != NULL) {
2376
g_mutex_unlock (ecal->priv->mutex);
2377
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error);
2380
our_op = e_calendar_new_op (ecal, "get_ldap_attribute");
2382
g_mutex_unlock (ecal->priv->mutex);
2384
CORBA_exception_init (&ev);
2386
GNOME_Evolution_Calendar_Cal_getLdapAttribute (priv->cal, &ev);
2387
if (BONOBO_EX (&ev)) {
2388
e_calendar_remove_op (ecal, our_op);
2389
e_calendar_free_op (our_op);
2391
CORBA_exception_free (&ev);
2393
g_warning (G_STRLOC ": Unable to contact backend");
1712
if (!org_gnome_evolution_dataserver_calendar_Cal_get_ldap_attribute (priv->proxy, ldap_attribute, error)) {
2395
1714
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error);
2398
CORBA_exception_free (&ev);
2400
e_flag_wait (our_op->done);
2402
status = our_op->status;
2403
*ldap_attribute = our_op->string;
2405
e_calendar_remove_op (ecal, our_op);
2406
e_calendar_free_op (our_op);
2408
E_CALENDAR_CHECK_STATUS (status, error);
2411
1721
static gboolean
2412
1722
load_static_capabilities (ECal *ecal, GError **error)
2414
1724
ECalPrivate *priv;
2415
CORBA_Environment ev;
2416
ECalendarStatus status;
2417
ECalendarOp *our_op;
2419
1726
priv = ecal->priv;
1727
e_return_error_if_fail (priv->proxy, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
2421
1729
if (priv->capabilities)
2422
1730
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
2424
g_mutex_lock (ecal->priv->mutex);
2426
if (ecal->priv->load_state != E_CAL_LOAD_LOADED) {
2427
g_mutex_unlock (ecal->priv->mutex);
1732
if (priv->load_state != E_CAL_LOAD_LOADED) {
2428
1733
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
2431
if (ecal->priv->current_op != NULL) {
2432
g_mutex_unlock (ecal->priv->mutex);
2433
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error);
2436
our_op = e_calendar_new_op (ecal, "load_static_capabilities");
2438
g_mutex_unlock (ecal->priv->mutex);
2440
CORBA_exception_init (&ev);
2442
GNOME_Evolution_Calendar_Cal_getStaticCapabilities (priv->cal, &ev);
2443
if (BONOBO_EX (&ev)) {
2444
e_calendar_remove_op (ecal, our_op);
2445
e_calendar_free_op (our_op);
2447
CORBA_exception_free (&ev);
2449
g_warning (G_STRLOC ": Unable to contact backend");
1737
if (!org_gnome_evolution_dataserver_calendar_Cal_get_scheduling_information (priv->proxy, &priv->capabilities, error)) {
2451
1739
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error);
2454
CORBA_exception_free (&ev);
2456
e_flag_wait (our_op->done);
2458
status = our_op->status;
2459
priv->capabilities = our_op->string;
2461
e_calendar_remove_op (ecal, our_op);
2462
e_calendar_free_op (our_op);
2464
E_CALENDAR_CHECK_STATUS (status, error);
2467
1746
static gboolean
2785
2043
* Queries a calendar for a calendar component object based on its unique
2788
* Return value: TRUE if the call was successful, FALSE otherwise.
2046
* Returns: TRUE if the call was successful, FALSE otherwise.
2791
2049
e_cal_get_object (ECal *ecal, const gchar *uid, const gchar *rid, icalcomponent **icalcomp, GError **error)
2793
2051
ECalPrivate *priv;
2794
CORBA_Environment ev;
2795
2052
ECalendarStatus status;
2796
ECalendarOp *our_op;
2798
e_return_error_if_fail (ecal && E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
2054
icalcomponent *tmp_icalcomp;
2055
icalcomponent_kind kind;
2057
e_return_error_if_fail (uid != NULL, E_CALENDAR_STATUS_INVALID_ARG);
2058
e_return_error_if_fail (icalcomp != NULL, E_CALENDAR_STATUS_INVALID_ARG);
2059
e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
2800
2060
priv = ecal->priv;
2802
g_mutex_lock (ecal->priv->mutex);
2804
if (ecal->priv->load_state != E_CAL_LOAD_LOADED) {
2805
g_mutex_unlock (ecal->priv->mutex);
2061
e_return_error_if_fail (priv->proxy, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
2064
if (priv->load_state != E_CAL_LOAD_LOADED) {
2806
2065
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
2809
if (ecal->priv->current_op != NULL) {
2810
g_mutex_unlock (ecal->priv->mutex);
2811
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error);
2814
our_op = e_calendar_new_op (ecal, "get_object");
2816
g_mutex_unlock (ecal->priv->mutex);
2818
CORBA_exception_init (&ev);
2820
GNOME_Evolution_Calendar_Cal_getObject (priv->cal, uid, rid ? rid : "", &ev);
2821
if (BONOBO_EX (&ev)) {
2822
e_calendar_remove_op (ecal, our_op);
2823
e_calendar_free_op (our_op);
2825
CORBA_exception_free (&ev);
2827
g_warning (G_STRLOC ": Unable to contact backend");
2069
if (!org_gnome_evolution_dataserver_calendar_Cal_get_object (priv->proxy, uid, rid ? rid : "", &object, error)) {
2829
2071
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error);
2832
CORBA_exception_free (&ev);
2834
e_flag_wait (our_op->done);
2836
status = our_op->status;
2837
if (status != E_CALENDAR_STATUS_OK) {
2840
icalcomponent *tmp_icalcomp;
2841
icalcomponent_kind kind;
2843
tmp_icalcomp = icalparser_parse_string (our_op->string);
2844
if (!tmp_icalcomp) {
2845
status = E_CALENDAR_STATUS_INVALID_OBJECT;
2848
kind = icalcomponent_isa (tmp_icalcomp);
2849
if ((kind == ICAL_VEVENT_COMPONENT && priv->type == E_CAL_SOURCE_TYPE_EVENT) ||
2850
(kind == ICAL_VTODO_COMPONENT && priv->type == E_CAL_SOURCE_TYPE_TODO) ||
2851
(kind == ICAL_VJOURNAL_COMPONENT && priv->type == E_CAL_SOURCE_TYPE_JOURNAL)) {
2852
*icalcomp = icalcomponent_new_clone (tmp_icalcomp);
2853
} else if (kind == ICAL_VCALENDAR_COMPONENT) {
2854
icalcomponent *subcomp = NULL;
2856
switch (priv->type) {
2857
case E_CAL_SOURCE_TYPE_EVENT :
2858
subcomp = icalcomponent_get_first_component (tmp_icalcomp, ICAL_VEVENT_COMPONENT);
2860
case E_CAL_SOURCE_TYPE_TODO :
2861
subcomp = icalcomponent_get_first_component (tmp_icalcomp, ICAL_VTODO_COMPONENT);
2863
case E_CAL_SOURCE_TYPE_JOURNAL :
2864
subcomp = icalcomponent_get_first_component (tmp_icalcomp, ICAL_VJOURNAL_COMPONENT);
2867
/* ignore everything else */
2871
/* we are only interested in the first component */
2873
*icalcomp = icalcomponent_new_clone (subcomp);
2075
status = E_CALENDAR_STATUS_OK;
2076
tmp_icalcomp = icalparser_parse_string (object);
2077
if (!tmp_icalcomp) {
2078
status = E_CALENDAR_STATUS_INVALID_OBJECT;
2081
kind = icalcomponent_isa (tmp_icalcomp);
2082
if ((kind == ICAL_VEVENT_COMPONENT && priv->type == E_CAL_SOURCE_TYPE_EVENT) ||
2083
(kind == ICAL_VTODO_COMPONENT && priv->type == E_CAL_SOURCE_TYPE_TODO) ||
2084
(kind == ICAL_VJOURNAL_COMPONENT && priv->type == E_CAL_SOURCE_TYPE_JOURNAL)) {
2085
*icalcomp = icalcomponent_new_clone (tmp_icalcomp);
2086
} else if (kind == ICAL_VCALENDAR_COMPONENT) {
2087
icalcomponent *subcomp = NULL;
2089
switch (priv->type) {
2090
case E_CAL_SOURCE_TYPE_EVENT :
2091
subcomp = icalcomponent_get_first_component (tmp_icalcomp, ICAL_VEVENT_COMPONENT);
2093
case E_CAL_SOURCE_TYPE_TODO :
2094
subcomp = icalcomponent_get_first_component (tmp_icalcomp, ICAL_VTODO_COMPONENT);
2096
case E_CAL_SOURCE_TYPE_JOURNAL :
2097
subcomp = icalcomponent_get_first_component (tmp_icalcomp, ICAL_VJOURNAL_COMPONENT);
2100
/* ignore everything else */
2876
icalcomponent_free (tmp_icalcomp);
2104
/* we are only interested in the first component */
2106
*icalcomp = icalcomponent_new_clone (subcomp);
2109
icalcomponent_free (tmp_icalcomp);
2879
g_free (our_op->string);
2881
e_calendar_remove_op (ecal, our_op);
2882
e_calendar_free_op (our_op);
2884
2114
E_CALENDAR_CHECK_STATUS (status, error);