1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* Evolution calendar client interface object
4 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
5 * Copyright (C) 2009 Intel Corporation
7 * Authors: Federico Mena-Quintero <federico@ximian.com>
8 * Rodrigo Moya <rodrigo@ximian.com>
9 * Ross Burton <ross@linux.intel.com>
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of version 2 of the GNU Lesser General Public
13 * License as published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
29 #include <libical/ical.h>
30 #include <glib/gi18n-lib.h>
33 #include <libedataserver/libedataserver.h>
35 #include "e-data-cal.h"
36 #include "e-gdbus-cal.h"
37 #include "e-cal-backend.h"
38 #include "e-cal-backend-sexp.h"
40 #define E_DATA_CAL_GET_PRIVATE(obj) \
41 (G_TYPE_INSTANCE_GET_PRIVATE \
42 ((obj), E_TYPE_DATA_CAL, EDataCalPrivate))
44 #define EDC_ERROR(_code) e_data_cal_create_error (_code, NULL)
45 #define EDC_ERROR_EX(_code, _msg) e_data_cal_create_error (_code, _msg)
47 struct _EDataCalPrivate {
48 EGdbusCal *gdbus_object;
52 GStaticRecMutex pending_ops_lock;
53 GHashTable *pending_ops; /* opid to GCancellable for still running operations */
61 static EOperationPool *ops_pool = NULL;
67 OP_GET_BACKEND_PROPERTY,
68 OP_SET_BACKEND_PROPERTY,
77 OP_GET_ATTACHMENT_URIS,
89 guint32 id; /* operation id */
90 EDataCal *cal; /* calendar */
91 GCancellable *cancellable;
95 gboolean only_if_exists;
97 /* OP_GET_ATTACHMENT_URIS */
102 /* OP_DISCARD_ALARM */
108 /* OP_GET_OBJECT_LIST */
111 /* OP_GET_FREE_BUSY */
116 /* OP_CREATE_OBJECTS */
118 /* OP_RECEIVE_OBJECTS */
119 /* OP_SEND_OBJECTS */
123 /* OP_MODIFY_OBJECTS */
126 EDataCalObjModType mod;
128 /* OP_REMOVE_OBJECTS */
131 EDataCalObjModType mod;
133 /* OP_GET_TIMEZONE */
135 /* OP_ADD_TIMEZONE */
137 /* OP_CANCEL_OPERATION */
139 /* OP_GET_BACKEND_PROPERTY */
141 /* OP_SET_BACKEND_PROPERTY */
154 G_DEFINE_TYPE (EDataCal, e_data_cal, G_TYPE_OBJECT);
156 /* Function to get a new EDataCalView path, used by get_view below */
158 construct_calview_path (void)
160 static guint counter = 1;
161 return g_strdup_printf ("/org/gnome/evolution/dataserver/CalendarView/%d/%d", getpid (), counter++);
165 cancel_ops_cb (gpointer opid,
166 gpointer cancellable,
169 g_return_if_fail (cancellable != NULL);
171 g_cancellable_cancel (cancellable);
175 operation_thread (gpointer data,
178 OperationData *op = data;
179 ECalBackend *backend;
181 backend = e_data_cal_get_backend (op->cal);
185 e_cal_backend_open (backend, op->cal, op->id, op->cancellable, op->d.only_if_exists);
188 e_cal_backend_remove (backend, op->cal, op->id, op->cancellable);
191 e_cal_backend_refresh (backend, op->cal, op->id, op->cancellable);
193 case OP_GET_BACKEND_PROPERTY:
194 e_cal_backend_get_backend_property (backend, op->cal, op->id, op->cancellable, op->d.prop_name);
195 g_free (op->d.prop_name);
197 case OP_SET_BACKEND_PROPERTY:
198 e_cal_backend_set_backend_property (backend, op->cal, op->id, op->cancellable, op->d.sbp.prop_name, op->d.sbp.prop_value);
199 g_free (op->d.sbp.prop_name);
200 g_free (op->d.sbp.prop_value);
203 e_cal_backend_get_object (backend, op->cal, op->id, op->cancellable, op->d.ur.uid, op->d.ur.rid && *op->d.ur.rid ? op->d.ur.rid : NULL);
204 g_free (op->d.ur.uid);
205 g_free (op->d.ur.rid);
207 case OP_GET_OBJECT_LIST:
208 e_cal_backend_get_object_list (backend, op->cal, op->id, op->cancellable, op->d.sexp);
211 case OP_GET_FREE_BUSY:
212 e_cal_backend_get_free_busy (backend, op->cal, op->id, op->cancellable, op->d.fb.users, op->d.fb.start, op->d.fb.end);
213 g_slist_free_full (op->d.fb.users, g_free);
215 case OP_CREATE_OBJECTS:
216 e_cal_backend_create_objects (backend, op->cal, op->id, op->cancellable, op->d.calobjs);
217 g_slist_free_full (op->d.calobjs, g_free);
219 case OP_MODIFY_OBJECTS:
220 e_cal_backend_modify_objects (backend, op->cal, op->id, op->cancellable, op->d.mo.calobjs, op->d.mo.mod);
221 g_slist_free_full (op->d.mo.calobjs, g_free);
223 case OP_REMOVE_OBJECTS:
224 e_cal_backend_remove_objects (backend, op->cal, op->id, op->cancellable, op->d.ro.ids, op->d.ro.mod);
225 g_slist_free_full (op->d.ro.ids, (GDestroyNotify) e_cal_component_free_id);
227 case OP_RECEIVE_OBJECTS:
228 e_cal_backend_receive_objects (backend, op->cal, op->id, op->cancellable, op->d.co.calobj);
229 g_free (op->d.co.calobj);
231 case OP_SEND_OBJECTS:
232 e_cal_backend_send_objects (backend, op->cal, op->id, op->cancellable, op->d.co.calobj);
233 g_free (op->d.co.calobj);
235 case OP_GET_ATTACHMENT_URIS:
236 e_cal_backend_get_attachment_uris (backend, op->cal, op->id, op->cancellable, op->d.ur.uid, op->d.ur.rid && *op->d.ur.rid ? op->d.ur.rid : NULL);
237 g_free (op->d.ur.uid);
238 g_free (op->d.ur.rid);
240 case OP_DISCARD_ALARM:
241 e_cal_backend_discard_alarm (backend, op->cal, op->id, op->cancellable, op->d.ura.uid, op->d.ura.rid && *op->d.ura.rid ? op->d.ura.rid : NULL, op->d.ura.auid);
242 g_free (op->d.ura.uid);
243 g_free (op->d.ura.rid);
244 g_free (op->d.ura.auid);
249 ECalBackendSExp *obj_sexp;
251 GError *error = NULL;
253 /* we handle this entirely here, since it doesn't require any
254 * backend involvement now that we have e_cal_view_start to
255 * actually kick off the search. */
257 obj_sexp = e_cal_backend_sexp_new (op->d.sexp);
260 e_data_cal_respond_get_view (op->cal, op->id, EDC_ERROR (InvalidQuery), NULL);
264 view = e_data_cal_view_new (backend, obj_sexp);
265 g_object_unref (obj_sexp);
268 e_data_cal_respond_get_view (op->cal, op->id, EDC_ERROR (OtherError), NULL);
272 path = construct_calview_path ();
273 e_data_cal_view_register_gdbus_object (view, e_gdbus_cal_stub_get_connection (op->cal->priv->gdbus_object), path, &error);
276 g_object_unref (view);
278 e_data_cal_respond_get_view (op->cal, op->id, EDC_ERROR_EX (OtherError, error->message), NULL);
279 g_error_free (error);
285 e_cal_backend_add_view (backend, view);
287 e_data_cal_respond_get_view (op->cal, op->id, EDC_ERROR (Success), path);
293 case OP_GET_TIMEZONE:
294 e_cal_backend_get_timezone (backend, op->cal, op->id, op->cancellable, op->d.tzid);
297 case OP_ADD_TIMEZONE:
298 e_cal_backend_add_timezone (backend, op->cal, op->id, op->cancellable, op->d.tzobject);
299 g_free (op->d.tzobject);
301 case OP_CANCEL_OPERATION:
302 g_static_rec_mutex_lock (&op->cal->priv->pending_ops_lock);
304 if (g_hash_table_lookup (op->cal->priv->pending_ops, GUINT_TO_POINTER (op->d.opid))) {
305 GCancellable *cancellable = g_hash_table_lookup (op->cal->priv->pending_ops, GUINT_TO_POINTER (op->d.opid));
307 g_cancellable_cancel (cancellable);
310 g_static_rec_mutex_unlock (&op->cal->priv->pending_ops_lock);
313 /* close just cancels all pending ops and frees data cal */
314 e_cal_backend_remove_client (backend, op->cal);
316 g_static_rec_mutex_lock (&op->cal->priv->pending_ops_lock);
317 g_hash_table_foreach (op->cal->priv->pending_ops, cancel_ops_cb, NULL);
318 g_static_rec_mutex_unlock (&op->cal->priv->pending_ops_lock);
322 g_object_unref (op->cal);
323 g_object_unref (op->cancellable);
324 g_slice_free (OperationData, op);
327 static OperationData *
328 op_new (OperationID op,
333 data = g_slice_new0 (OperationData);
335 data->cal = g_object_ref (cal);
336 data->id = e_operation_pool_reserve_opid (ops_pool);
337 data->cancellable = g_cancellable_new ();
339 g_static_rec_mutex_lock (&cal->priv->pending_ops_lock);
340 g_hash_table_insert (cal->priv->pending_ops, GUINT_TO_POINTER (data->id), g_object_ref (data->cancellable));
341 g_static_rec_mutex_unlock (&cal->priv->pending_ops_lock);
347 op_complete (EDataCal *cal,
350 g_return_if_fail (cal != NULL);
352 e_operation_pool_release_opid (ops_pool, opid);
354 g_static_rec_mutex_lock (&cal->priv->pending_ops_lock);
355 g_hash_table_remove (cal->priv->pending_ops, GUINT_TO_POINTER (opid));
356 g_static_rec_mutex_unlock (&cal->priv->pending_ops_lock);
359 /* Create the EDataCal error quark */
361 e_data_cal_error_quark (void)
363 #define ERR_PREFIX "org.gnome.evolution.dataserver.Calendar."
365 static const GDBusErrorEntry entries[] = {
366 { Success, ERR_PREFIX "Success" },
367 { Busy, ERR_PREFIX "Busy" },
368 { RepositoryOffline, ERR_PREFIX "RepositoryOffline" },
369 { PermissionDenied, ERR_PREFIX "PermissionDenied" },
370 { InvalidRange, ERR_PREFIX "InvalidRange" },
371 { ObjectNotFound, ERR_PREFIX "ObjectNotFound" },
372 { InvalidObject, ERR_PREFIX "InvalidObject" },
373 { ObjectIdAlreadyExists, ERR_PREFIX "ObjectIdAlreadyExists" },
374 { AuthenticationFailed, ERR_PREFIX "AuthenticationFailed" },
375 { AuthenticationRequired, ERR_PREFIX "AuthenticationRequired" },
376 { UnsupportedField, ERR_PREFIX "UnsupportedField" },
377 { UnsupportedMethod, ERR_PREFIX "UnsupportedMethod" },
378 { UnsupportedAuthenticationMethod, ERR_PREFIX "UnsupportedAuthenticationMethod" },
379 { TLSNotAvailable, ERR_PREFIX "TLSNotAvailable" },
380 { NoSuchCal, ERR_PREFIX "NoSuchCal" },
381 { UnknownUser, ERR_PREFIX "UnknownUser" },
382 { OfflineUnavailable, ERR_PREFIX "OfflineUnavailable" },
383 { SearchSizeLimitExceeded, ERR_PREFIX "SearchSizeLimitExceeded" },
384 { SearchTimeLimitExceeded, ERR_PREFIX "SearchTimeLimitExceeded" },
385 { InvalidQuery, ERR_PREFIX "InvalidQuery" },
386 { QueryRefused, ERR_PREFIX "QueryRefused" },
387 { CouldNotCancel, ERR_PREFIX "CouldNotCancel" },
388 { OtherError, ERR_PREFIX "OtherError" },
389 { InvalidServerVersion, ERR_PREFIX "InvalidServerVersion" },
390 { InvalidArg, ERR_PREFIX "InvalidArg" },
391 { NotSupported, ERR_PREFIX "NotSupported" },
392 { NotOpened, ERR_PREFIX "NotOpened" }
397 static volatile gsize quark_volatile = 0;
399 g_dbus_error_register_error_domain ("e-data-cal-error", &quark_volatile, entries, G_N_ELEMENTS (entries));
401 return (GQuark) quark_volatile;
405 * e_data_cal_status_to_string:
410 e_data_cal_status_to_string (EDataCalCallStatus status)
413 static struct _statuses {
414 EDataCalCallStatus status;
417 { Success, N_("Success") },
418 { Busy, N_("Backend is busy") },
419 { RepositoryOffline, N_("Repository offline") },
420 { PermissionDenied, N_("Permission denied") },
421 { InvalidRange, N_("Invalid range") },
422 { ObjectNotFound, N_("Object not found") },
423 { InvalidObject, N_("Invalid object") },
424 { ObjectIdAlreadyExists, N_("Object ID already exists") },
425 { AuthenticationFailed, N_("Authentication Failed") },
426 { AuthenticationRequired, N_("Authentication Required") },
427 { UnsupportedField, N_("Unsupported field") },
428 { UnsupportedMethod, N_("Unsupported method") },
429 { UnsupportedAuthenticationMethod, N_("Unsupported authentication method") },
430 { TLSNotAvailable, N_("TLS not available") },
431 { NoSuchCal, N_("Calendar does not exist") },
432 { UnknownUser, N_("Unknown user") },
433 { OfflineUnavailable, N_("Not available in offline mode") },
434 { SearchSizeLimitExceeded, N_("Search size limit exceeded") },
435 { SearchTimeLimitExceeded, N_("Search time limit exceeded") },
436 { InvalidQuery, N_("Invalid query") },
437 { QueryRefused, N_("Query refused") },
438 { CouldNotCancel, N_("Could not cancel") },
439 /* { OtherError, N_("Other error") }, */
440 { InvalidServerVersion, N_("Invalid server version") },
441 { InvalidArg, N_("Invalid argument") },
442 /* Translators: The string for NOT_SUPPORTED error */
443 { NotSupported, N_("Not supported") },
444 { NotOpened, N_("Backend is not opened yet") }
447 for (i = 0; i < G_N_ELEMENTS (statuses); i++) {
448 if (statuses[i].status == status)
449 return _(statuses[i].msg);
452 return _("Other error");
456 * e_data_cal_create_error:
457 * @status: #EDataCalStatus code
458 * @custom_msg: Custom message to use for the error. When NULL,
459 * then uses a default message based on the @status code.
461 * Returns: NULL, when the @status is Success,
462 * or a newly allocated GError, which should be freed
463 * with g_error_free() call.
468 e_data_cal_create_error (EDataCalCallStatus status,
469 const gchar *custom_msg)
471 if (status == Success)
474 return g_error_new_literal (E_DATA_CAL_ERROR, status, custom_msg ? custom_msg : e_data_cal_status_to_string (status));
478 * e_data_cal_create_error_fmt:
480 * Similar as e_data_cal_create_error(), only here, instead of custom_msg,
481 * is used a printf() format to create a custom_msg for the error.
486 e_data_cal_create_error_fmt (EDataCalCallStatus status,
487 const gchar *custom_msg_fmt,
495 return e_data_cal_create_error (status, NULL);
497 va_start (ap, custom_msg_fmt);
498 custom_msg = g_strdup_vprintf (custom_msg_fmt, ap);
501 error = e_data_cal_create_error (status, custom_msg);
509 * e_data_cal_register_gdbus_object:
511 * Registers GDBus object of this EDataCal.
516 e_data_cal_register_gdbus_object (EDataCal *cal,
517 GDBusConnection *connection,
518 const gchar *object_path,
521 g_return_val_if_fail (cal != NULL, 0);
522 g_return_val_if_fail (E_IS_DATA_CAL (cal), 0);
523 g_return_val_if_fail (connection != NULL, 0);
524 g_return_val_if_fail (object_path != NULL, 0);
526 return e_gdbus_cal_register_object (cal->priv->gdbus_object, connection, object_path, error);
530 impl_Cal_open (EGdbusCal *object,
531 GDBusMethodInvocation *invocation,
532 gboolean in_only_if_exists,
537 op = op_new (OP_OPEN, cal);
538 op->d.only_if_exists = in_only_if_exists;
540 e_gdbus_cal_complete_open (cal->priv->gdbus_object, invocation, op->id);
541 e_operation_pool_push (ops_pool, op);
547 impl_Cal_remove (EGdbusCal *object,
548 GDBusMethodInvocation *invocation,
553 op = op_new (OP_REMOVE, cal);
555 e_gdbus_cal_complete_remove (cal->priv->gdbus_object, invocation, op->id);
556 e_operation_pool_push (ops_pool, op);
562 impl_Cal_refresh (EGdbusCal *object,
563 GDBusMethodInvocation *invocation,
568 op = op_new (OP_REFRESH, cal);
570 e_gdbus_cal_complete_refresh (cal->priv->gdbus_object, invocation, op->id);
571 e_operation_pool_push (ops_pool, op);
577 impl_Cal_get_backend_property (EGdbusCal *object,
578 GDBusMethodInvocation *invocation,
579 const gchar *in_prop_name,
584 op = op_new (OP_GET_BACKEND_PROPERTY, cal);
585 op->d.prop_name = g_strdup (in_prop_name);
587 e_gdbus_cal_complete_get_backend_property (cal->priv->gdbus_object, invocation, op->id);
588 e_operation_pool_push (ops_pool, op);
594 impl_Cal_set_backend_property (EGdbusCal *object,
595 GDBusMethodInvocation *invocation,
596 const gchar * const *in_prop_name_value,
601 op = op_new (OP_SET_BACKEND_PROPERTY, cal);
602 g_return_val_if_fail (e_gdbus_cal_decode_set_backend_property (in_prop_name_value, &op->d.sbp.prop_name, &op->d.sbp.prop_value), FALSE);
604 e_gdbus_cal_complete_set_backend_property (cal->priv->gdbus_object, invocation, op->id);
605 e_operation_pool_push (ops_pool, op);
611 impl_Cal_get_object (EGdbusCal *object,
612 GDBusMethodInvocation *invocation,
613 const gchar * const *in_uid_rid,
618 op = op_new (OP_GET_OBJECT, cal);
619 g_return_val_if_fail (e_gdbus_cal_decode_get_object (in_uid_rid, &op->d.ur.uid, &op->d.ur.rid), FALSE);
621 e_gdbus_cal_complete_get_object (cal->priv->gdbus_object, invocation, op->id);
622 e_operation_pool_push (ops_pool, op);
628 impl_Cal_get_object_list (EGdbusCal *object,
629 GDBusMethodInvocation *invocation,
630 const gchar *in_sexp,
635 op = op_new (OP_GET_OBJECT_LIST, cal);
636 op->d.sexp = g_strdup (in_sexp);
638 e_gdbus_cal_complete_get_object_list (cal->priv->gdbus_object, invocation, op->id);
639 e_operation_pool_push (ops_pool, op);
645 impl_Cal_get_free_busy (EGdbusCal *object,
646 GDBusMethodInvocation *invocation,
647 const gchar * const *in_start_end_userlist,
653 op = op_new (OP_GET_FREE_BUSY, cal);
654 g_return_val_if_fail (e_gdbus_cal_decode_get_free_busy (in_start_end_userlist, &start, &end, &op->d.fb.users), FALSE);
656 op->d.fb.start = (time_t) start;
657 op->d.fb.end = (time_t) end;
659 e_gdbus_cal_complete_get_free_busy (cal->priv->gdbus_object, invocation, op->id);
660 e_operation_pool_push (ops_pool, op);
666 impl_Cal_create_objects (EGdbusCal *object,
667 GDBusMethodInvocation *invocation,
668 const gchar * const *in_calobjs,
673 op = op_new (OP_CREATE_OBJECTS, cal);
674 op->d.calobjs = e_util_strv_to_slist (in_calobjs);
676 e_gdbus_cal_complete_create_objects (cal->priv->gdbus_object, invocation, op->id);
677 e_operation_pool_push (ops_pool, op);
683 impl_Cal_modify_objects (EGdbusCal *object,
684 GDBusMethodInvocation *invocation,
685 const gchar * const *in_mod_calobjs,
691 op = op_new (OP_MODIFY_OBJECTS, cal);
692 g_return_val_if_fail (e_gdbus_cal_decode_modify_objects (in_mod_calobjs, &op->d.mo.calobjs, &mod), FALSE);
695 e_gdbus_cal_complete_modify_objects (cal->priv->gdbus_object, invocation, op->id);
696 e_operation_pool_push (ops_pool, op);
702 impl_Cal_remove_objects (EGdbusCal *object,
703 GDBusMethodInvocation *invocation,
704 const gchar * const *in_mod_ids,
710 op = op_new (OP_REMOVE_OBJECTS, cal);
711 g_return_val_if_fail (e_gdbus_cal_decode_remove_objects (in_mod_ids, &op->d.ro.ids, &mod), FALSE);
714 e_gdbus_cal_complete_remove_objects (cal->priv->gdbus_object, invocation, op->id);
715 e_operation_pool_push (ops_pool, op);
721 impl_Cal_receive_objects (EGdbusCal *object,
722 GDBusMethodInvocation *invocation,
723 const gchar *in_calobj,
728 op = op_new (OP_RECEIVE_OBJECTS, cal);
729 op->d.co.calobj = g_strdup (in_calobj);
731 e_gdbus_cal_complete_receive_objects (cal->priv->gdbus_object, invocation, op->id);
732 e_operation_pool_push (ops_pool, op);
738 impl_Cal_send_objects (EGdbusCal *object,
739 GDBusMethodInvocation *invocation,
740 const gchar *in_calobj,
745 op = op_new (OP_SEND_OBJECTS, cal);
746 op->d.co.calobj = g_strdup (in_calobj);
748 e_gdbus_cal_complete_send_objects (cal->priv->gdbus_object, invocation, op->id);
749 e_operation_pool_push (ops_pool, op);
755 impl_Cal_get_attachment_uris (EGdbusCal *object,
756 GDBusMethodInvocation *invocation,
757 const gchar * const *in_uid_rid,
762 op = op_new (OP_GET_ATTACHMENT_URIS, cal);
763 g_return_val_if_fail (e_gdbus_cal_decode_get_attachment_uris (in_uid_rid, &op->d.ur.uid, &op->d.ur.rid), FALSE);
765 e_gdbus_cal_complete_get_attachment_uris (cal->priv->gdbus_object, invocation, op->id);
766 e_operation_pool_push (ops_pool, op);
772 impl_Cal_discard_alarm (EGdbusCal *object,
773 GDBusMethodInvocation *invocation,
774 const gchar * const *in_uid_rid_auid,
779 op = op_new (OP_DISCARD_ALARM, cal);
780 g_return_val_if_fail (e_gdbus_cal_decode_discard_alarm (in_uid_rid_auid, &op->d.ura.uid, &op->d.ura.rid, &op->d.ura.auid), FALSE);
782 e_gdbus_cal_complete_discard_alarm (cal->priv->gdbus_object, invocation, op->id);
783 e_operation_pool_push (ops_pool, op);
789 impl_Cal_get_view (EGdbusCal *object,
790 GDBusMethodInvocation *invocation,
791 const gchar *in_sexp,
796 op = op_new (OP_GET_VIEW, cal);
797 op->d.sexp = g_strdup (in_sexp);
799 e_gdbus_cal_complete_get_view (cal->priv->gdbus_object, invocation, op->id);
800 e_operation_pool_push (ops_pool, op);
806 impl_Cal_get_timezone (EGdbusCal *object,
807 GDBusMethodInvocation *invocation,
808 const gchar *in_tzid,
813 op = op_new (OP_GET_TIMEZONE, cal);
814 op->d.tzid = g_strdup (in_tzid);
816 e_gdbus_cal_complete_get_timezone (cal->priv->gdbus_object, invocation, op->id);
817 e_operation_pool_push (ops_pool, op);
823 impl_Cal_add_timezone (EGdbusCal *object,
824 GDBusMethodInvocation *invocation,
825 const gchar *in_tzobject,
830 op = op_new (OP_ADD_TIMEZONE, cal);
831 op->d.tzobject = g_strdup (in_tzobject);
833 e_gdbus_cal_complete_add_timezone (cal->priv->gdbus_object, invocation, op->id);
834 e_operation_pool_push (ops_pool, op);
840 impl_Cal_cancel_operation (EGdbusCal *object,
841 GDBusMethodInvocation *invocation,
847 op = op_new (OP_CANCEL_OPERATION, cal);
848 op->d.opid = in_opid;
850 e_gdbus_cal_complete_cancel_operation (cal->priv->gdbus_object, invocation, NULL);
851 e_operation_pool_push (ops_pool, op);
857 impl_Cal_cancel_all (EGdbusCal *object,
858 GDBusMethodInvocation *invocation,
863 op = op_new (OP_CANCEL_ALL, cal);
865 e_gdbus_cal_complete_cancel_all (cal->priv->gdbus_object, invocation, NULL);
866 e_operation_pool_push (ops_pool, op);
872 impl_Cal_close (EGdbusCal *object,
873 GDBusMethodInvocation *invocation,
878 op = op_new (OP_CLOSE, cal);
879 /* unref here makes sure the cal is freed in a separate thread */
880 g_object_unref (cal);
882 e_gdbus_cal_complete_close (cal->priv->gdbus_object, invocation, NULL);
883 e_operation_pool_push (ops_pool, op);
888 /* free returned pointer with g_strfreev() */
890 gslist_to_strv (const GSList *lst)
896 seq = g_new0 (gchar *, g_slist_length ((GSList *) lst) + 1);
897 for (l = lst, i = 0; l; l = l->next, i++) {
898 seq[i] = e_util_utf8_make_valid (l->data);
905 * e_data_cal_respond_open:
906 * @cal: A calendar client interface.
907 * @error: Operation error, if any, automatically freed if passed it.
909 * Notifies listeners of the completion of the open method call.
914 e_data_cal_respond_open (EDataCal *cal,
918 op_complete (cal, opid);
920 /* Translators: This is prefix to a detailed error message */
921 g_prefix_error (&error, "%s", _("Cannot open calendar: "));
923 e_gdbus_cal_emit_open_done (cal->priv->gdbus_object, opid, error);
926 g_error_free (error);
930 * e_data_cal_respond_remove:
931 * @cal: A calendar client interface.
932 * @error: Operation error, if any, automatically freed if passed it.
934 * Notifies listeners of the completion of the remove method call.
939 e_data_cal_respond_remove (EDataCal *cal,
943 op_complete (cal, opid);
945 /* Translators: This is prefix to a detailed error message */
946 g_prefix_error (&error, "%s", _("Cannot remove calendar: "));
948 e_gdbus_cal_emit_remove_done (cal->priv->gdbus_object, opid, error);
951 g_error_free (error);
953 e_cal_backend_set_is_removed (cal->priv->backend, TRUE);
957 * e_data_cal_respond_refresh:
958 * @cal: A calendar client interface.
959 * @error: Operation error, if any, automatically freed if passed it.
961 * Notifies listeners of the completion of the refresh method call.
966 e_data_cal_respond_refresh (EDataCal *cal,
970 op_complete (cal, opid);
972 /* Translators: This is prefix to a detailed error message */
973 g_prefix_error (&error, "%s", _("Cannot refresh calendar: "));
975 e_gdbus_cal_emit_refresh_done (cal->priv->gdbus_object, opid, error);
978 g_error_free (error);
982 * e_data_cal_respond_get_backend_property:
983 * @cal: A calendar client interface.
984 * @error: Operation error, if any, automatically freed if passed it.
985 * @prop_value: Value of a property
987 * Notifies listeners of the completion of the get_backend_property method call.
992 e_data_cal_respond_get_backend_property (EDataCal *cal,
995 const gchar *prop_value)
997 gchar *gdbus_prop_value = NULL;
999 op_complete (cal, opid);
1001 /* Translators: This is prefix to a detailed error message */
1002 g_prefix_error (&error, "%s", _("Cannot retrieve backend property: "));
1004 e_gdbus_cal_emit_get_backend_property_done (cal->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (prop_value, &gdbus_prop_value));
1006 g_free (gdbus_prop_value);
1008 g_error_free (error);
1012 * e_data_cal_respond_set_backend_property:
1013 * @cal: A calendar client interface.
1014 * @error: Operation error, if any, automatically freed if passed it.
1016 * Notifies listeners of the completion of the set_backend_property method call.
1021 e_data_cal_respond_set_backend_property (EDataCal *cal,
1025 op_complete (cal, opid);
1027 /* Translators: This is prefix to a detailed error message */
1028 g_prefix_error (&error, "%s", _("Cannot set backend property: "));
1030 e_gdbus_cal_emit_set_backend_property_done (cal->priv->gdbus_object, opid, error);
1033 g_error_free (error);
1037 * e_data_cal_respond_get_object:
1038 * @cal: A calendar client interface.
1039 * @error: Operation error, if any, automatically freed if passed it.
1040 * @object: The object retrieved as an iCalendar string.
1042 * Notifies listeners of the completion of the get_object method call.
1047 e_data_cal_respond_get_object (EDataCal *cal,
1050 const gchar *object)
1052 gchar *gdbus_object = NULL;
1054 op_complete (cal, opid);
1056 /* Translators: This is prefix to a detailed error message */
1057 g_prefix_error (&error, "%s", _("Cannot retrieve calendar object path: "));
1059 e_gdbus_cal_emit_get_object_done (cal->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (object, &gdbus_object));
1061 g_free (gdbus_object);
1063 g_error_free (error);
1067 * e_data_cal_respond_get_object_list:
1068 * @cal: A calendar client interface.
1069 * @error: Operation error, if any, automatically freed if passed it.
1070 * @objects: List of retrieved objects.
1072 * Notifies listeners of the completion of the get_object_list method call.
1077 e_data_cal_respond_get_object_list (EDataCal *cal,
1080 const GSList *objects)
1082 gchar **strv_objects;
1084 op_complete (cal, opid);
1086 /* Translators: This is prefix to a detailed error message */
1087 g_prefix_error (&error, "%s", _("Cannot retrieve calendar object list: "));
1089 strv_objects = gslist_to_strv (objects);
1091 e_gdbus_cal_emit_get_object_list_done (cal->priv->gdbus_object, opid, error, (const gchar * const *) strv_objects);
1093 g_strfreev (strv_objects);
1095 g_error_free (error);
1099 * e_data_cal_respond_get_free_busy:
1100 * @cal: A calendar client interface.
1101 * @error: Operation error, if any, automatically freed if passed it.
1103 * Notifies listeners of the completion of the get_free_busy method call.
1104 * To pass actual free/busy objects to the client use e_data_cal_report_free_busy_data().
1109 e_data_cal_respond_get_free_busy (EDataCal *cal,
1113 op_complete (cal, opid);
1115 /* Translators: This is prefix to a detailed error message */
1116 g_prefix_error (&error, "%s", _("Cannot retrieve calendar free/busy list: "));
1118 e_gdbus_cal_emit_get_free_busy_done (cal->priv->gdbus_object, opid, error);
1121 g_error_free (error);
1125 * e_data_cal_respond_create_objects:
1126 * @cal: A calendar client interface.
1127 * @error: Operation error, if any, automatically freed if passed it.
1128 * @uids: UIDs of the objects created.
1129 * @new_components: The newly created #ECalComponent objects.
1131 * Notifies listeners of the completion of the create_objects method call.
1136 e_data_cal_respond_create_objects (EDataCal *cal,
1140 /* const */ GSList *new_components)
1142 gchar **array = NULL;
1146 op_complete (cal, opid);
1148 array = g_new0 (gchar *, g_slist_length ((GSList *) uids) + 1);
1149 for (l = uids; l != NULL; l = l->next) {
1150 array[i++] = e_util_utf8_make_valid (l->data);
1153 /* Translators: This is prefix to a detailed error message */
1154 g_prefix_error (&error, "%s", _("Cannot create calendar object: "));
1156 e_gdbus_cal_emit_create_objects_done (cal->priv->gdbus_object, opid, error, (const gchar * const *) array);
1160 g_error_free (error);
1162 for (l = new_components; l; l = l->next) {
1163 e_cal_backend_notify_component_created (cal->priv->backend, l->data);
1169 * e_data_cal_respond_modify_objects:
1170 * @cal: A calendar client interface.
1171 * @error: Operation error, if any, automatically freed if passed it.
1172 * @old_components: The old #ECalComponents.
1173 * @new_components: The new #ECalComponents.
1175 * Notifies listeners of the completion of the modify_objects method call.
1180 e_data_cal_respond_modify_objects (EDataCal *cal,
1183 /* const */ GSList *old_components,
1184 /* const */ GSList *new_components)
1186 op_complete (cal, opid);
1188 /* Translators: This is prefix to a detailed error message */
1189 g_prefix_error (&error, "%s", _("Cannot modify calendar object: "));
1191 e_gdbus_cal_emit_modify_objects_done (cal->priv->gdbus_object, opid, error);
1194 g_error_free (error);
1196 const GSList *lold = old_components, *lnew = new_components;
1197 while (lold && lnew) {
1198 e_cal_backend_notify_component_modified (cal->priv->backend, lold->data, lnew->data);
1206 * e_data_cal_respond_remove_objects:
1207 * @cal: A calendar client interface.
1208 * @error: Operation error, if any, automatically freed if passed it.
1209 * @ids: IDs of the removed objects.
1210 * @old_components: The old #ECalComponents.
1211 * @new_components: The new #ECalComponents. They will not be NULL only
1212 * when removing instances of recurring appointments.
1214 * Notifies listeners of the completion of the remove_objects method call.
1219 e_data_cal_respond_remove_objects (EDataCal *cal,
1223 /* const */ GSList *old_components,
1224 /* const */ GSList *new_components)
1226 op_complete (cal, opid);
1228 /* Translators: This is prefix to a detailed error message */
1229 g_prefix_error (&error, "%s", _("Cannot remove calendar object: "));
1231 e_gdbus_cal_emit_remove_objects_done (cal->priv->gdbus_object, opid, error);
1234 g_error_free (error);
1236 const GSList *lid = ids, *lold = old_components, *lnew = new_components;
1237 while (lid && lold) {
1238 e_cal_backend_notify_component_removed (cal->priv->backend, lid->data, lold->data, lnew ? lnew->data : NULL);
1250 * e_data_cal_respond_receive_objects:
1251 * @cal: A calendar client interface.
1252 * @error: Operation error, if any, automatically freed if passed it.
1254 * Notifies listeners of the completion of the receive_objects method call.
1259 e_data_cal_respond_receive_objects (EDataCal *cal,
1263 op_complete (cal, opid);
1265 /* Translators: This is prefix to a detailed error message */
1266 g_prefix_error (&error, "%s", _("Cannot receive calendar objects: "));
1268 e_gdbus_cal_emit_receive_objects_done (cal->priv->gdbus_object, opid, error);
1271 g_error_free (error);
1275 * e_data_cal_respond_send_objects:
1276 * @cal: A calendar client interface.
1277 * @error: Operation error, if any, automatically freed if passed it.
1278 * @users: List of users.
1279 * @calobj: An iCalendar string representing the object sent.
1281 * Notifies listeners of the completion of the send_objects method call.
1286 e_data_cal_respond_send_objects (EDataCal *cal,
1289 const GSList *users,
1290 const gchar *calobj)
1292 gchar **strv_users_calobj;
1294 op_complete (cal, opid);
1296 /* Translators: This is prefix to a detailed error message */
1297 g_prefix_error (&error, "%s", _("Cannot send calendar objects: "));
1299 strv_users_calobj = e_gdbus_cal_encode_send_objects (calobj, users);
1301 e_gdbus_cal_emit_send_objects_done (cal->priv->gdbus_object, opid, error, (const gchar * const *) strv_users_calobj);
1303 g_strfreev (strv_users_calobj);
1305 g_error_free (error);
1309 * e_data_cal_respond_get_attachment_uris:
1310 * @cal: A calendar client interface.
1311 * @error: Operation error, if any, automatically freed if passed it.
1312 * @attachment_uris: List of retrieved attachment uri's.
1314 * Notifies listeners of the completion of the get_attachment_uris method call.
1319 e_data_cal_respond_get_attachment_uris (EDataCal *cal,
1322 const GSList *attachment_uris)
1324 gchar **strv_attachment_uris;
1326 op_complete (cal, opid);
1328 /* Translators: This is prefix to a detailed error message */
1329 g_prefix_error (&error, "%s", _("Could not retrieve attachment uris: "));
1331 strv_attachment_uris = gslist_to_strv (attachment_uris);
1333 e_gdbus_cal_emit_get_attachment_uris_done (cal->priv->gdbus_object, opid, error, (const gchar * const *) strv_attachment_uris);
1335 g_strfreev (strv_attachment_uris);
1337 g_error_free (error);
1341 * e_data_cal_respond_discard_alarm:
1342 * @cal: A calendar client interface.
1343 * @error: Operation error, if any, automatically freed if passed it.
1345 * Notifies listeners of the completion of the discard_alarm method call.
1350 e_data_cal_respond_discard_alarm (EDataCal *cal,
1354 op_complete (cal, opid);
1356 /* Translators: This is prefix to a detailed error message */
1357 g_prefix_error (&error, "%s", _("Could not discard reminder: "));
1359 e_gdbus_cal_emit_discard_alarm_done (cal->priv->gdbus_object, opid, error);
1362 g_error_free (error);
1366 * e_data_cal_respond_get_view:
1367 * @cal: A calendar client interface.
1368 * @error: Operation error, if any, automatically freed if passed it.
1369 * @view_path: The new live view path.
1371 * Notifies listeners of the completion of the get_view method call.
1376 e_data_cal_respond_get_view (EDataCal *cal,
1379 const gchar *view_path)
1381 gchar *gdbus_view_path = NULL;
1383 op_complete (cal, opid);
1385 /* Translators: This is prefix to a detailed error message */
1386 g_prefix_error (&error, "%s", _("Could not get calendar view path: "));
1388 e_gdbus_cal_emit_get_view_done (cal->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (view_path, &gdbus_view_path));
1390 g_free (gdbus_view_path);
1392 g_error_free (error);
1396 * e_data_cal_respond_get_timezone:
1397 * @cal: A calendar client interface.
1398 * @error: Operation error, if any, automatically freed if passed it.
1399 * @tzobject: The requested timezone as an iCalendar string.
1401 * Notifies listeners of the completion of the get_timezone method call.
1406 e_data_cal_respond_get_timezone (EDataCal *cal,
1409 const gchar *tzobject)
1411 gchar *gdbus_tzobject = NULL;
1413 op_complete (cal, opid);
1415 /* Translators: This is prefix to a detailed error message */
1416 g_prefix_error (&error, "%s", _("Could not retrieve calendar time zone: "));
1418 e_gdbus_cal_emit_get_timezone_done (cal->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (tzobject, &gdbus_tzobject));
1420 g_free (gdbus_tzobject);
1422 g_error_free (error);
1426 * e_data_cal_respond_add_timezone:
1427 * @cal: A calendar client interface.
1428 * @error: Operation error, if any, automatically freed if passed it.
1430 * Notifies listeners of the completion of the add_timezone method call.
1435 e_data_cal_respond_add_timezone (EDataCal *cal,
1439 op_complete (cal, opid);
1441 /* Translators: This is prefix to a detailed error message */
1442 g_prefix_error (&error, "%s", _("Could not add calendar time zone: "));
1444 e_gdbus_cal_emit_add_timezone_done (cal->priv->gdbus_object, opid, error);
1447 g_error_free (error);
1451 * e_data_cal_report_error:
1453 * FIXME: Document me.
1458 e_data_cal_report_error (EDataCal *cal,
1459 const gchar *message)
1461 g_return_if_fail (cal != NULL);
1462 g_return_if_fail (message != NULL);
1464 e_gdbus_cal_emit_backend_error (cal->priv->gdbus_object, message);
1468 * e_data_cal_report_readonly:
1470 * FIXME: Document me.
1475 e_data_cal_report_readonly (EDataCal *cal,
1478 g_return_if_fail (cal != NULL);
1480 e_gdbus_cal_emit_readonly (cal->priv->gdbus_object, readonly);
1484 * e_data_cal_report_online:
1486 * FIXME: Document me.
1491 e_data_cal_report_online (EDataCal *cal,
1494 g_return_if_fail (cal != NULL);
1496 e_gdbus_cal_emit_online (cal->priv->gdbus_object, is_online);
1500 * e_data_cal_report_opened:
1502 * Reports to associated client that opening phase of the cal is finished.
1503 * error being NULL means successfully, otherwise reports an error which
1504 * happened during opening phase. By opening phase is meant a process
1505 * including successfull authentication to the server/storage.
1510 e_data_cal_report_opened (EDataCal *cal,
1511 const GError *error)
1515 strv_error = e_gdbus_templates_encode_error (error);
1517 e_gdbus_cal_emit_opened (cal->priv->gdbus_object, (const gchar * const *) strv_error);
1519 g_strfreev (strv_error);
1523 * e_data_cal_report_free_busy_data:
1525 * FIXME: Document me.
1530 e_data_cal_report_free_busy_data (EDataCal *cal,
1531 const GSList *freebusy)
1533 gchar **strv_freebusy;
1535 g_return_if_fail (cal != NULL);
1537 strv_freebusy = gslist_to_strv (freebusy);
1539 e_gdbus_cal_emit_free_busy_data (cal->priv->gdbus_object, (const gchar * const *) strv_freebusy);
1541 g_strfreev (strv_freebusy);
1545 * e_data_cal_report_backend_property_changed:
1547 * Notifies client about certain property value change
1552 e_data_cal_report_backend_property_changed (EDataCal *cal,
1553 const gchar *prop_name,
1554 const gchar *prop_value)
1558 g_return_if_fail (cal != NULL);
1559 g_return_if_fail (prop_name != NULL);
1560 g_return_if_fail (*prop_name != '\0');
1561 g_return_if_fail (prop_value != NULL);
1563 strv = e_gdbus_templates_encode_two_strings (prop_name, prop_value);
1564 g_return_if_fail (strv != NULL);
1566 e_gdbus_cal_emit_backend_property_changed (cal->priv->gdbus_object, (const gchar * const *) strv);
1572 data_cal_set_backend (EDataCal *cal,
1573 ECalBackend *backend)
1575 g_return_if_fail (E_IS_CAL_BACKEND (backend));
1576 g_return_if_fail (cal->priv->backend == NULL);
1578 cal->priv->backend = g_object_ref (backend);
1582 data_cal_set_property (GObject *object,
1584 const GValue *value,
1587 switch (property_id) {
1589 data_cal_set_backend (
1590 E_DATA_CAL (object),
1591 g_value_get_object (value));
1595 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1599 data_cal_get_property (GObject *object,
1604 switch (property_id) {
1606 g_value_set_object (
1608 e_data_cal_get_backend (
1609 E_DATA_CAL (object)));
1613 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1617 data_cal_dispose (GObject *object)
1619 EDataCalPrivate *priv;
1621 priv = E_DATA_CAL_GET_PRIVATE (object);
1623 if (priv->backend) {
1624 g_object_unref (priv->backend);
1625 priv->backend = NULL;
1628 /* Chain up to parent's dispose() method. */
1629 G_OBJECT_CLASS (e_data_cal_parent_class)->dispose (object);
1633 data_cal_finalize (GObject *object)
1635 EDataCalPrivate *priv;
1637 priv = E_DATA_CAL_GET_PRIVATE (object);
1639 if (priv->pending_ops) {
1640 g_hash_table_destroy (priv->pending_ops);
1641 priv->pending_ops = NULL;
1644 g_static_rec_mutex_free (&priv->pending_ops_lock);
1646 if (priv->gdbus_object) {
1647 g_object_unref (priv->gdbus_object);
1648 priv->gdbus_object = NULL;
1651 /* Chain up to parent's finalize() method. */
1652 G_OBJECT_CLASS (e_data_cal_parent_class)->finalize (object);
1656 e_data_cal_class_init (EDataCalClass *class)
1658 GObjectClass *object_class;
1660 g_type_class_add_private (class, sizeof (EDataCalPrivate));
1662 object_class = G_OBJECT_CLASS (class);
1663 object_class->set_property = data_cal_set_property;
1664 object_class->get_property = data_cal_get_property;
1665 object_class->dispose = data_cal_dispose;
1666 object_class->finalize = data_cal_finalize;
1668 g_object_class_install_property (
1671 g_param_spec_object (
1674 "The backend driving this connection",
1677 G_PARAM_CONSTRUCT_ONLY |
1678 G_PARAM_STATIC_STRINGS));
1681 ops_pool = e_operation_pool_new (10, operation_thread, NULL);
1685 e_data_cal_init (EDataCal *ecal)
1687 EGdbusCal *gdbus_object;
1689 ecal->priv = E_DATA_CAL_GET_PRIVATE (ecal);
1691 ecal->priv->gdbus_object = e_gdbus_cal_stub_new ();
1692 ecal->priv->pending_ops = g_hash_table_new_full (
1693 g_direct_hash, g_direct_equal, NULL, g_object_unref);
1694 g_static_rec_mutex_init (&ecal->priv->pending_ops_lock);
1696 gdbus_object = ecal->priv->gdbus_object;
1698 gdbus_object, "handle-open",
1699 G_CALLBACK (impl_Cal_open), ecal);
1701 gdbus_object, "handle-remove",
1702 G_CALLBACK (impl_Cal_remove), ecal);
1704 gdbus_object, "handle-refresh",
1705 G_CALLBACK (impl_Cal_refresh), ecal);
1707 gdbus_object, "handle-get-backend-property",
1708 G_CALLBACK (impl_Cal_get_backend_property), ecal);
1710 gdbus_object, "handle-set-backend-property",
1711 G_CALLBACK (impl_Cal_set_backend_property), ecal);
1713 gdbus_object, "handle-get-object",
1714 G_CALLBACK (impl_Cal_get_object), ecal);
1716 gdbus_object, "handle-get-object-list",
1717 G_CALLBACK (impl_Cal_get_object_list), ecal);
1719 gdbus_object, "handle-get-free-busy",
1720 G_CALLBACK (impl_Cal_get_free_busy), ecal);
1722 gdbus_object, "handle-create-objects",
1723 G_CALLBACK (impl_Cal_create_objects), ecal);
1725 gdbus_object, "handle-modify-objects",
1726 G_CALLBACK (impl_Cal_modify_objects), ecal);
1728 gdbus_object, "handle-remove-objects",
1729 G_CALLBACK (impl_Cal_remove_objects), ecal);
1731 gdbus_object, "handle-receive-objects",
1732 G_CALLBACK (impl_Cal_receive_objects), ecal);
1734 gdbus_object, "handle-send-objects",
1735 G_CALLBACK (impl_Cal_send_objects), ecal);
1737 gdbus_object, "handle-get-attachment-uris",
1738 G_CALLBACK (impl_Cal_get_attachment_uris), ecal);
1740 gdbus_object, "handle-discard-alarm",
1741 G_CALLBACK (impl_Cal_discard_alarm), ecal);
1743 gdbus_object, "handle-get-view",
1744 G_CALLBACK (impl_Cal_get_view), ecal);
1746 gdbus_object, "handle-get-timezone",
1747 G_CALLBACK (impl_Cal_get_timezone), ecal);
1749 gdbus_object, "handle-add-timezone",
1750 G_CALLBACK (impl_Cal_add_timezone), ecal);
1752 gdbus_object, "handle-cancel-operation",
1753 G_CALLBACK (impl_Cal_cancel_operation), ecal);
1755 gdbus_object, "handle-cancel-all",
1756 G_CALLBACK (impl_Cal_cancel_all), ecal);
1758 gdbus_object, "handle-close",
1759 G_CALLBACK (impl_Cal_close), ecal);
1763 e_data_cal_new (ECalBackend *backend)
1765 g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
1767 return g_object_new (E_TYPE_DATA_CAL, "backend", backend, NULL);
1771 e_data_cal_get_backend (EDataCal *cal)
1773 g_return_val_if_fail (E_IS_DATA_CAL (cal), NULL);
1775 return cal->priv->backend;