new function to retrieve objects and detached recurrences for that object.
authorRodrigo Moya <rodrigo@novell.com>
Thu, 28 Oct 2004 00:16:21 +0000 (00:16 +0000)
committerRodrigo Moya <rodrigo@src.gnome.org>
Thu, 28 Oct 2004 00:16:21 +0000 (00:16 +0000)
2004-10-28  Rodrigo Moya <rodrigo@novell.com>

* libecal/e-cal.[ch] (e_cal_get_objects_for_uid): new function
to retrieve objects and detached recurrences for that object.
(e_cal_get_object): deal with the backend returning a VCALENDAR
object. In that case, just get the first component of the same
type we are using.
(generate_instances): when we have an UID, use the new function
e_cal_get_objects_for_uid, avoiding countless calls to
e_cal_get_object_list.

* backends/file/e-cal-backend-file.c (e_cal_backend_file_get_object):
if we have detached instances, return a VCALENDAR with the master
object and any detached instance.

calendar/ChangeLog
calendar/backends/file/e-cal-backend-file.c
calendar/libecal/e-cal.c
calendar/libecal/e-cal.h

index ccf0945..6a84f34 100644 (file)
@@ -1,3 +1,18 @@
+2004-10-28  Rodrigo Moya <rodrigo@novell.com>
+
+       * libecal/e-cal.[ch] (e_cal_get_objects_for_uid): new function
+       to retrieve objects and detached recurrences for that object.
+       (e_cal_get_object): deal with the backend returning a VCALENDAR
+       object. In that case, just get the first component of the same
+       type we are using.
+       (generate_instances): when we have an UID, use the new function
+       e_cal_get_objects_for_uid, avoiding countless calls to
+       e_cal_get_object_list.
+
+       * backends/file/e-cal-backend-file.c (e_cal_backend_file_get_object):
+       if we have detached instances, return a VCALENDAR with the master
+       object and any detached instance.
+
 2004-10-15  Chenthill Palanisamy <pchenthill@novell.com>
        
        Fixes #67031
@@ -14,6 +29,7 @@
        of the backends
 
 2004-10-14  Harish Krishnaswamy  <kharish@novell.com>
+
        * backends/groupwise/e-cal-backend-groupwise.c:
        (get_deltas) : removed stray debug code that should not have
        been there in the first place.
index a29c664..32ce33f 100644 (file)
@@ -997,6 +997,17 @@ e_cal_backend_file_get_default_object (ECalBackendSync *backend, EDataCal *cal,
        return GNOME_Evolution_Calendar_Success;
 }
 
+static void
+add_detached_recur_to_vcalendar (gpointer key, gpointer value, gpointer user_data)
+{
+       ECalComponent *recurrence = value;
+       icalcomponent *vcalendar = user_data;
+
+       icalcomponent_add_component (
+               vcalendar,
+               icalcomponent_new_clone (e_cal_component_get_icalcomponent (recurrence)));                   
+}
+
 /* Get_object_component handler for the file backend */
 static ECalBackendSyncStatus
 e_cal_backend_file_get_object (ECalBackendSync *backend, EDataCal *cal, const char *uid, const char *rid, char **object)
@@ -1004,8 +1015,6 @@ e_cal_backend_file_get_object (ECalBackendSync *backend, EDataCal *cal, const ch
        ECalBackendFile *cbfile;
        ECalBackendFilePrivate *priv;
        ECalBackendFileObject *obj_data;
-       ECalComponent *comp = NULL;
-       gboolean free_comp = FALSE;
 
        cbfile = E_CAL_BACKEND_FILE (backend);
        priv = cbfile->priv;
@@ -1019,8 +1028,12 @@ e_cal_backend_file_get_object (ECalBackendSync *backend, EDataCal *cal, const ch
                return GNOME_Evolution_Calendar_ObjectNotFound;
 
        if (rid && *rid) {
+               ECalComponent *comp;
+
                comp = g_hash_table_lookup (obj_data->recurrences, rid);
-               if (!comp) {
+               if (comp) {
+                       *object = e_cal_component_get_as_string (comp);
+               } else {
                        icalcomponent *icalcomp;
                        struct icaltimetype itt;
 
@@ -1031,20 +1044,29 @@ e_cal_backend_file_get_object (ECalBackendSync *backend, EDataCal *cal, const ch
                        if (!icalcomp)
                                return GNOME_Evolution_Calendar_ObjectNotFound;
 
-                       comp = e_cal_component_new ();
-                       free_comp = TRUE;
-                       e_cal_component_set_icalcomponent (comp, icalcomp);
+                       *object = g_strdup (icalcomponent_as_ical_string (icalcomp));
+
+                       icalcomponent_free (icalcomp);
                }
-       } else
-               comp = obj_data->full_object;
-       
-       if (!comp)
-               return GNOME_Evolution_Calendar_ObjectNotFound;
+       } else {
+               if (g_hash_table_size (obj_data->recurrences) > 0) {
+                       icalcomponent *icalcomp;
 
-       *object = e_cal_component_get_as_string (comp);
+                       /* if we have detached recurrences, return a VCALENDAR */
+                       icalcomp = e_cal_util_new_top_level ();
+                       icalcomponent_add_component (
+                               icalcomp,
+                               icalcomponent_new_clone (e_cal_component_get_icalcomponent (obj_data->full_object)));
 
-       if (free_comp)
-               g_object_unref (comp);
+                       /* add all detached recurrences */
+                       g_hash_table_foreach (obj_data->recurrences, (GHFunc) add_detached_recur_to_vcalendar, icalcomp);
+
+                       *object = g_strdup (icalcomponent_as_ical_string (icalcomp));
+
+                       icalcomponent_free (icalcomp);
+               } else
+                       *object = e_cal_component_get_as_string (obj_data->full_object);
+       }
 
        return GNOME_Evolution_Calendar_Success;
 }
index 22984e4..20288b5 100644 (file)
@@ -2366,9 +2366,9 @@ e_cal_get_default_object (ECal *ecal, icalcomponent **icalcomp, GError **error)
  * e_cal_get_object:
  * @ecal: A calendar ecal.
  * @uid: Unique identifier for a calendar component.
- * @rid: 
+ * @rid: Recurrence identifier.
  * @icalcomp: Return value for the calendar component object.
- * @error: 
+ * @error: Placeholder for error information.
  *
  * Queries a calendar for a calendar component object based on its unique
  * identifier.
@@ -2378,7 +2378,6 @@ e_cal_get_default_object (ECal *ecal, icalcomponent **icalcomp, GError **error)
 gboolean
 e_cal_get_object (ECal *ecal, const char *uid, const char *rid, icalcomponent **icalcomp, GError **error)
 {
-
        ECalPrivate *priv;
        CORBA_Environment ev;
        ECalendarStatus status;
@@ -2431,9 +2430,164 @@ e_cal_get_object (ECal *ecal, const char *uid, const char *rid, icalcomponent **
         if (status != E_CALENDAR_STATUS_OK){ 
                 *icalcomp = NULL;
         } else {
-                *icalcomp = icalparser_parse_string (our_op->string);
-               if (!(*icalcomp))
+               icalcomponent *tmp_icalcomp;
+               icalcomponent_kind kind;
+
+                tmp_icalcomp = icalparser_parse_string (our_op->string);
+               if (!tmp_icalcomp) {
                        status = E_CALENDAR_STATUS_INVALID_OBJECT;
+                       *icalcomp = NULL;
+               } else {
+                       kind = icalcomponent_isa (tmp_icalcomp);
+                       if ((kind == ICAL_VEVENT_COMPONENT && priv->type == E_CAL_SOURCE_TYPE_EVENT) ||
+                           (kind == ICAL_VTODO_COMPONENT && priv->type == E_CAL_SOURCE_TYPE_TODO)) {
+                               *icalcomp = icalcomponent_new_clone (tmp_icalcomp);
+                       } else if (kind == ICAL_VCALENDAR_COMPONENT) {
+                               icalcomponent *subcomp = NULL;
+
+                               switch (priv->type) {
+                               case E_CAL_SOURCE_TYPE_EVENT :
+                                       subcomp = icalcomponent_get_first_component (tmp_icalcomp, ICAL_VEVENT_COMPONENT);
+                                       break;
+                               case E_CAL_SOURCE_TYPE_TODO :
+                                       subcomp = icalcomponent_get_first_component (tmp_icalcomp, ICAL_VTODO_COMPONENT);
+                                       break;
+                               case E_CAL_SOURCE_TYPE_JOURNAL :
+                                       subcomp = icalcomponent_get_first_component (tmp_icalcomp, ICAL_VJOURNAL_COMPONENT);
+                                       break;
+                               }
+
+                               /* we are only interested in the first component */
+                               if (subcomp)
+                                       *icalcomp = icalcomponent_new_clone (subcomp);
+                       }
+
+                       icalcomponent_free (tmp_icalcomp);
+               }
+       }
+       g_free (our_op->string);
+
+       e_calendar_remove_op (ecal, our_op);
+       g_mutex_unlock (our_op->mutex);
+       e_calendar_free_op (our_op);
+
+       E_CALENDAR_CHECK_STATUS (status, error);
+}
+
+/**
+ * e_cal_get_objects_for_uid:
+ * @ecal: A calendar ecal.
+ * @uid: Unique identifier for a calendar component.
+ * @objects: Return value for the list of objects obtained from the backend.
+ * @error: Placeholder for error information.
+ *
+ * Queries a calendar for all calendar components with the given unique
+ * ID. This will return any recurring event and all its detached recurrences.
+ * For non-recurring events, it will just return the object with that ID.
+ *
+ * Return value: Result code based on the status of the operation.
+ **/
+gboolean
+e_cal_get_objects_for_uid (ECal *ecal, const char *uid, GList **objects, GError **error)
+{
+       ECalPrivate *priv;
+       CORBA_Environment ev;
+       ECalendarStatus status;
+       ECalendarOp *our_op;
+
+       e_return_error_if_fail (ecal && E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
+
+       priv = ecal->priv;
+       *objects = NULL;
+
+       g_mutex_lock (ecal->priv->mutex);
+
+       if (ecal->priv->load_state != E_CAL_LOAD_LOADED) {
+               g_mutex_unlock (ecal->priv->mutex);
+               E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
+       }
+
+       if (ecal->priv->current_op != NULL) {
+               g_mutex_unlock (ecal->priv->mutex);
+               E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error);
+       }
+
+       our_op = e_calendar_new_op (ecal);
+
+       g_mutex_lock (our_op->mutex);
+
+       g_mutex_unlock (ecal->priv->mutex);
+
+       CORBA_exception_init (&ev);
+
+       GNOME_Evolution_Calendar_Cal_getObject (priv->cal, uid, "", &ev);
+       if (BONOBO_EX (&ev)) {
+               e_calendar_remove_op (ecal, our_op);
+               g_mutex_unlock (our_op->mutex);
+               e_calendar_free_op (our_op);
+
+               CORBA_exception_free (&ev);
+
+               g_warning (G_STRLOC ": Unable to contact backend");
+
+               E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error);
+       }
+
+       CORBA_exception_free (&ev);
+
+       /* wait for something to happen (both cancellation and a
+          successful response will notity us via our cv */
+       g_cond_wait (our_op->cond, our_op->mutex);
+
+       status = our_op->status;
+        if (status != E_CALENDAR_STATUS_OK){ 
+                *objects = NULL;
+        } else {
+               icalcomponent *icalcomp;
+               icalcomponent_kind kind;
+
+               icalcomp = icalparser_parse_string (our_op->string);
+               if (!icalcomp) {
+                       status = E_CALENDAR_STATUS_INVALID_OBJECT;
+                       *objects = NULL;
+               } else {
+                       ECalComponent *comp;
+
+                       kind = icalcomponent_isa (icalcomp);
+                       if ((kind == ICAL_VEVENT_COMPONENT && priv->type == E_CAL_SOURCE_TYPE_EVENT) ||
+                           (kind == ICAL_VTODO_COMPONENT && priv->type == E_CAL_SOURCE_TYPE_TODO)) {
+                               comp = e_cal_component_new ();
+                               e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (icalcomp));
+                               *objects = g_list_append (NULL, comp);
+                       } else if (kind == ICAL_VCALENDAR_COMPONENT) {
+                               icalcomponent *subcomp;
+                               icalcomponent_kind kind_to_find;
+
+                               switch (priv->type) {
+                               case E_CAL_SOURCE_TYPE_EVENT :
+                                       kind_to_find = ICAL_VEVENT_COMPONENT;
+                                       break;
+                               case E_CAL_SOURCE_TYPE_TODO :
+                                       kind_to_find = ICAL_VTODO_COMPONENT;
+                                       break;
+                               case E_CAL_SOURCE_TYPE_JOURNAL :
+                                       kind_to_find = ICAL_VJOURNAL_COMPONENT;
+                                       break;
+                               }
+
+                               *objects = NULL;
+                               subcomp = icalcomponent_get_first_component (icalcomp, kind_to_find);
+                               while (subcomp) {
+                                       comp = e_cal_component_new ();
+                                       e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (subcomp));
+                                       *objects = g_list_append (*objects, comp);
+
+                                       subcomp = icalcomponent_get_next_component (icalcomp, kind_to_find);
+                               }
+                       }
+
+                       icalcomponent_free (icalcomp);
+               }
        }
        g_free (our_op->string);
 
@@ -2885,30 +3039,32 @@ generate_instances (ECal *ecal, time_t start, time_t end, const char *uid,
 
        priv = ecal->priv;
 
-       iso_start = isodate_from_time_t (start);
-       if (!iso_start)
-               return;
-
-       iso_end = isodate_from_time_t (end);
-       if (!iso_end) {
-               g_free (iso_start);
-               return;
+       /* Generate objects */
+       if (uid && *uid) {
+               if (!e_cal_get_objects_for_uid (ecal, uid, &objects, NULL))
+                       return;
        }
+       else {
+               iso_start = isodate_from_time_t (start);
+               if (!iso_start)
+                       return;
+
+               iso_end = isodate_from_time_t (end);
+               if (!iso_end) {
+                       g_free (iso_start);
+                       return;
+               }
 
-       /* Generate objects */
-       if (uid && *uid)
-               query = g_strdup_printf ("(and (occur-in-time-range? (make-time \"%s\") (make-time \"%s\")) (uid? \"%s\"))",
-                                        iso_start, iso_end, uid);
-       else
                query = g_strdup_printf ("(occur-in-time-range? (make-time \"%s\") (make-time \"%s\"))",
                                         iso_start, iso_end);
-       g_free (iso_start);
-       g_free (iso_end);
-       if (!e_cal_get_object_list_as_comp (ecal, query, &objects, NULL)) {
+               g_free (iso_start);
+               g_free (iso_end);
+               if (!e_cal_get_object_list_as_comp (ecal, query, &objects, NULL)) {
+                       g_free (query);
+                       return;
+               }
                g_free (query);
-               return;
-       }       
-       g_free (query);
+       }
 
        instances = NULL;
 
index 7046059..a78e21f 100644 (file)
@@ -141,6 +141,10 @@ gboolean e_cal_get_object (ECal *ecal,
                           const char *rid,
                           icalcomponent **icalcomp,
                           GError **error);
+gboolean e_cal_get_objects_for_uid (ECal *ecal,
+                                   const char *uid,
+                                   GList **objects,
+                                   GError **error);
 
 gboolean e_cal_get_changes (ECal *ecal, const char *change_id, GList **changes, GError **error);
 void e_cal_free_change_list (GList *list);