From: Chenthill Palanisamy Date: Fri, 8 Jul 2005 11:04:19 +0000 (+0000) Subject: Support for groupwise recurrences. X-Git-Tag: upstream/3.7.4~7257 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b2e14915de47dabf500628946483f492447249c4;p=platform%2Fupstream%2Fevolution-data-server.git Support for groupwise recurrences. --- diff --git a/calendar/ChangeLog b/calendar/ChangeLog index 4d54c89..c30076b 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,41 @@ +2005-07-08 Chenthill Palanisamy + + * backends/groupwise/e-cal-backend-groupwise.c + (e_cal_backend_groupwise_remove_object): Use removeItemsRequest + for removing all the recurring posted appointments. + (get_gw_item_id): Get the item id from the component. + (get_deltas): Commented the read cursors request to get the icalids, + since we need recurrece keys as we use it as the uid for recurrence items. + Get the component from cache using uid and rid. + * e-cal.c (e_cal_remove_object): Used CALOBJ_MOD_THIS since we are just removing + one component. + +2005-07-08 Harish Krishnaswamy + + * backends/groupwise/e-cal-backend-groupwise-utils.c: + (set_rrule_from_comp), (set_properties_from_cal_component), + (e_gw_item_to_cal_component), (e_gw_connection_send_appointment): + add support for creation of recurrence items by sending the + recurrence formula to the server instead of generating the + instances at the client end. + * backends/groupwise/e-cal-backend-groupwise.c: + (e_cal_backend_groupwise_get_static_capabilities): + add capability RECURRENCES_NO_MASTER. + (e_cal_backend_groupwise_remove_object): add support for + removing all instances of a recurrence at one shot. + * libecal/e-cal-util.h: Add a static capability + RECURRENCES_NO_MASTER. Backends that do not use master objects + to represent recurrence information and store them as individual + instances. + * libecal/e-cal.c: (e_cal_get_recurrences_no_master) + (e_cal_generate_instances_for_object): Do not expand instances for objects from + backends that do not have master object to represent recurrences. + * libecal/e-cal.h: + * libedata-cal/e-cal-backend-cache.[ch] + (e_cal_backend_cache_get_components_by_uid): Function to + fetch all items in the cache that have the same uid. (recurrence + items, detached instances etc.) + 2005-07-08 Sankar P * backends/groupwise/e-cal-backend-groupwise.c: (get_deltas) diff --git a/calendar/backends/groupwise/e-cal-backend-groupwise-utils.c b/calendar/backends/groupwise/e-cal-backend-groupwise-utils.c index 5143d2e..325d4c9 100644 --- a/calendar/backends/groupwise/e-cal-backend-groupwise-utils.c +++ b/calendar/backends/groupwise/e-cal-backend-groupwise-utils.c @@ -395,6 +395,83 @@ set_attendees_to_item (EGwItem *item, ECalComponent *comp, icaltimezone *default } +static void +set_rrule_from_comp (ECalComponent *comp, EGwItem *item, ECalBackendGroupwise *cbgw) +{ + + EGwItemRecurrenceRule *item_rrule; + struct icalrecurrencetype *ical_recur; + GSList *rrule_list = NULL, *exdate_list; + int i; + + item_rrule = g_new0 (EGwItemRecurrenceRule, 1); + e_cal_component_get_rrule_list (comp, &rrule_list); + if (rrule_list) { + /* assumes only one rrule is present */ + ical_recur = (struct icalrecurrencetype *) rrule_list->data; + + g_message ("DEBUG: Processing rule\n%s\n", icalrecurrencetype_as_string (ical_recur)); + /*set the data */ + switch (ical_recur->freq) { + case ICAL_DAILY_RECURRENCE : + item_rrule->frequency = E_GW_ITEM_RECURRENCE_FREQUENCY_DAILY; + break; + case ICAL_WEEKLY_RECURRENCE: + item_rrule->frequency = E_GW_ITEM_RECURRENCE_FREQUENCY_WEEKLY; + break; + case ICAL_MONTHLY_RECURRENCE: + item_rrule->frequency = E_GW_ITEM_RECURRENCE_FREQUENCY_MONTHLY; + break; + case ICAL_YEARLY_RECURRENCE: + item_rrule->frequency = E_GW_ITEM_RECURRENCE_FREQUENCY_YEARLY; + break; + default: + break; + } + if (ical_recur->count != 0) + item_rrule->count = ical_recur->count; + else + item_rrule->until = g_strdup (icaltime_as_ical_string (ical_recur->until)); + + item_rrule->interval = ical_recur->interval; + + /*xxx -byday, bymonthday and byyearday not handled FIXME*/ + for (i = 0; i < ICAL_BY_DAY_SIZE; i++) + item_rrule->by_day[i] = ical_recur->by_day[i]; + for (i = 0; i < ICAL_BY_MONTHDAY_SIZE; i++) + item_rrule->by_month_day[i] = ical_recur->by_month_day[i]; + for (i = 0; i < ICAL_BY_YEARDAY_SIZE; i++) + item_rrule->by_year_day[i] = ical_recur->by_year_day[i]; + for (i = 0; i < ICAL_BY_MONTH_SIZE; i++) + item_rrule->by_month[i] = ical_recur->by_month[i]; + + e_gw_item_set_rrule (item, item_rrule); + + /* set exceptions */ + if (e_cal_component_has_exdates (comp)) { + GSList *l, *item_exdate_list = NULL; + icaltimezone *default_zone, *utc; + struct icaltimetype itt_utc; + + + e_cal_component_get_exdate_list (comp, &exdate_list); + default_zone = e_cal_backend_groupwise_get_default_zone (cbgw); + utc = icaltimezone_get_utc_timezone (); + for (l = exdate_list; l ; l = l->next) { + ECalComponentDateTime *dt = (ECalComponentDateTime *) l->data; + if (dt->value) { + if (!icaltime_get_timezone (*(dt->value))) + icaltime_set_timezone (dt->value, default_zone ? default_zone : utc); + itt_utc = icaltime_convert_to_zone (*dt->value, utc); + item_exdate_list = g_slist_append (item_exdate_list, g_strdup (icaltime_as_ical_string (itt_utc))); + } + } + e_gw_item_set_exdate_list (item, item_exdate_list); + e_cal_component_free_exdate_list (exdate_list); + } + } +} + static EGwItem * set_properties_from_cal_component (EGwItem *item, ECalComponent *comp, ECalBackendGroupwise *cbgw) { @@ -584,18 +661,22 @@ set_properties_from_cal_component (EGwItem *item, ECalComponent *comp, ECalBacke /* check if recurrences exist and update the item */ if (e_cal_component_has_recurrences (comp)) { + if (e_cal_component_has_rrules (comp)) + set_rrule_from_comp (comp, item, cbgw); + else { - GSList *recur_dates = NULL; - - if (dt.tzid) - e_cal_recur_generate_instances (comp, -1, -1,get_recur_instance, &recur_dates, resolve_tzid_cb, NULL, (icaltimezone *) default_zone); - else - e_cal_recur_generate_instances (comp, -1, -1,get_recur_instance, &recur_dates, resolve_tzid_cb, NULL, utc); + GSList *recur_dates = NULL; + + if (dt.tzid) + e_cal_recur_generate_instances (comp, -1, -1,get_recur_instance, &recur_dates, resolve_tzid_cb, NULL, (icaltimezone *) default_zone); + else + e_cal_recur_generate_instances (comp, -1, -1,get_recur_instance, &recur_dates, resolve_tzid_cb, NULL, utc); - recur_dates = g_slist_delete_link (recur_dates, recur_dates); - - e_gw_item_set_recurrence_dates (item, recur_dates); - } + recur_dates = g_slist_delete_link (recur_dates, recur_dates); + + e_gw_item_set_recurrence_dates (item, recur_dates); + } + } /* attachments */ if (e_cal_component_has_attachments (comp)) { @@ -710,6 +791,7 @@ set_attachments_to_cal_component (EGwItem *item, ECalComponent *comp, ECalBacken e_cal_component_set_attachment_list (comp, comp_attachment_list); } + ECalComponent * e_gw_item_to_cal_component (EGwItem *item, ECalBackendGroupwise *cbgw) { @@ -761,15 +843,7 @@ e_gw_item_to_cal_component (EGwItem *item, ECalBackendGroupwise *cbgw) icalcomponent_add_property (e_cal_component_get_icalcomponent (comp), icalprop); } - /* UID */ - uid = e_gw_item_get_icalid (item); - if (uid) - e_cal_component_set_uid (comp, e_gw_item_get_icalid (item)); - else { - g_object_unref (comp); - return NULL; - } - + if (e_gw_item_get_reply_request (item)) { char *reply_within; const char *mess = e_gw_item_get_message (item); @@ -875,6 +949,31 @@ e_gw_item_to_cal_component (EGwItem *item, ECalBackendGroupwise *cbgw) else return NULL; + /* UID */ + if (e_gw_item_get_recurrence_key (item) != 0) { + + ECalComponentRange *recur_id; + char *recur_key = g_strdup_printf ("%d", e_gw_item_get_recurrence_key (item)); + + e_cal_component_set_uid (comp, (const char *) recur_key); + g_free (recur_key); + + /* set the recurrence id and the X-GW-RECORDID too */ + recur_id = g_new0 (ECalComponentRange, 1); + recur_id->type = E_CAL_COMPONENT_RANGE_SINGLE; + recur_id->datetime = dt; + e_cal_component_set_recurid (comp, recur_id); + + } else { + + uid = e_gw_item_get_icalid (item); + if (uid) + e_cal_component_set_uid (comp, e_gw_item_get_icalid (item)); + else { + g_object_unref (comp); + return NULL; + } + } /* classification */ description = e_gw_item_get_classification (item); @@ -1067,7 +1166,10 @@ e_gw_connection_send_appointment (ECalBackendGroupwise *cbgw, const char *contai EGwConnectionStatus status; icalparameter_partstat partstat; char *item_id; - + gboolean all_instances = FALSE; + icalproperty *icalprop; + icalcomponent *icalcomp; + const char *recurrence_key = NULL; cnc = e_cal_backend_groupwise_get_connection (cbgw); g_return_val_if_fail (E_IS_GW_CONNECTION (cnc), E_GW_CONNECTION_STATUS_INVALID_CONNECTION); @@ -1077,17 +1179,40 @@ e_gw_connection_send_appointment (ECalBackendGroupwise *cbgw, const char *contai /* When the icalcomponent is obtained through the itip message rather * than from the SOAP protocol, the container id has to be explicitly * added to the xgwrecordid inorder to obtain the item id. */ - - switch (e_cal_component_get_vtype (comp)) { - case E_CAL_COMPONENT_EVENT: - item_id = g_strconcat (e_cal_component_get_gw_id (comp), GW_EVENT_TYPE_ID, container, NULL); - break; - case E_CAL_COMPONENT_TODO: - item_id = g_strconcat (e_cal_component_get_gw_id (comp), GW_TODO_TYPE_ID, container, NULL); - break; - default: - return E_GW_CONNECTION_STATUS_INVALID_OBJECT; + + /* handle recurrences - All */ + icalcomp = e_cal_component_get_icalcomponent (comp); + + icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY); + while (icalprop) { + const char *x_name; + + x_name = icalproperty_get_x_name (icalprop); + if (!strcmp (x_name, "X-GW-RECUR-INSTANCE-MOD-TYPE")) { + if (!strcmp (icalproperty_get_x (icalprop), "All")) + all_instances = TRUE; + if (recurrence_key) + break; + } + if (!strcmp (x_name, "X-GW-RECURRENCE-KEY")) { + recurrence_key = icalproperty_get_x (icalprop); + } + icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY); + } + + if (all_instances) { + switch (e_cal_component_get_vtype (comp)) { + case E_CAL_COMPONENT_EVENT: + item_id = g_strconcat (e_cal_component_get_gw_id (comp), GW_EVENT_TYPE_ID, container, NULL); + break; + case E_CAL_COMPONENT_TODO: + item_id = g_strconcat (e_cal_component_get_gw_id (comp), GW_TODO_TYPE_ID, container, NULL); + break; + default: + return E_GW_CONNECTION_STATUS_INVALID_OBJECT; + } } + switch (method) { case ICAL_METHOD_REQUEST: /* get attendee here and add the list along. */ @@ -1130,17 +1255,31 @@ e_gw_connection_send_appointment (ECalBackendGroupwise *cbgw, const char *contai case ICAL_PARTSTAT_ACCEPTED: e_cal_component_get_transparency (comp, &transp); - if (transp == E_CAL_COMPONENT_TRANSP_OPAQUE) - status = e_gw_connection_accept_request (cnc, item_id, "Busy"); - else - status = e_gw_connection_accept_request (cnc, item_id, "Free"); + if (transp == E_CAL_COMPONENT_TRANSP_OPAQUE) { + if (all_instances) + status = e_gw_connection_accept_request_by_recurrence_key (cnc, recurrence_key, "Busy", NULL); + else + status = e_gw_connection_accept_request (cnc, item_id, "Busy"); + } + else { + if (all_instances) + status = e_gw_connection_accept_request_by_recurrence_key (cnc, recurrence_key, "Free", NULL); + else + status = e_gw_connection_accept_request (cnc, item_id, "Free"); + } break; case ICAL_PARTSTAT_DECLINED: - status = e_gw_connection_decline_request (cnc, item_id); + if (all_instances) + status = e_gw_connection_decline_request_by_recurrence_key (cnc, recurrence_key, NULL); + else + status = e_gw_connection_decline_request (cnc, item_id); *remove = TRUE; break; case ICAL_PARTSTAT_TENTATIVE: - status = e_gw_connection_accept_request (cnc, item_id, "Tentative"); + if (all_instances) + status = e_gw_connection_accept_request_by_recurrence_key (cnc, recurrence_key, "Tentative", NULL); + else + status = e_gw_connection_accept_request (cnc, item_id, "Tentative"); break; case ICAL_PARTSTAT_COMPLETED: status = e_gw_connection_complete_request (cnc, item_id); @@ -1163,6 +1302,7 @@ e_gw_connection_send_appointment (ECalBackendGroupwise *cbgw, const char *contai if (status == E_GW_CONNECTION_STATUS_ITEM_ALREADY_ACCEPTED) return status; + /*FIXME - handling recurrence items */ if (!*remove && status == E_GW_CONNECTION_STATUS_OK) { EGwItem *item; diff --git a/calendar/backends/groupwise/e-cal-backend-groupwise.c b/calendar/backends/groupwise/e-cal-backend-groupwise.c index 48103cb..c3b6b9b 100644 --- a/calendar/backends/groupwise/e-cal-backend-groupwise.c +++ b/calendar/backends/groupwise/e-cal-backend-groupwise.c @@ -372,14 +372,18 @@ get_deltas (gpointer handle) item = E_GW_ITEM(item_list->data); ECalComponent *modified_comp = NULL, *cache_comp = NULL; char *cache_comp_str = NULL; - + const char *uid, *rid = NULL; modified_comp = e_gw_item_to_cal_component (item, cbgw); if (!modified_comp) { g_message ("Invalid component returned in update"); continue; } - cache_comp = e_cal_backend_cache_get_component (cache, e_gw_item_get_icalid (item), NULL); + if ((r_key = e_gw_item_get_recurrence_key (item)) != 0) + rid = e_cal_component_get_recurid_as_string (modified_comp) + + e_cal_component_get_uid (modified_comp, &uid); + cache_comp = e_cal_backend_cache_get_component (cache, uid, rid); e_cal_component_commit_sequence (modified_comp); e_cal_component_commit_sequence (cache_comp); @@ -390,6 +394,7 @@ get_deltas (gpointer handle) cache_comp_str = NULL; } e_cal_backend_cache_put_component (cache, modified_comp); + g_object_unref (item); g_object_unref (modified_comp); } @@ -422,10 +427,15 @@ get_deltas (gpointer handle) g_list_free (item_list); item_list = NULL; } - + + /* TODO currently the read cursors response does not give us the recurrencKey, uncomment + this once the response gives the recurrenceKey */ +#if 0 + /* handle deleted items here by going over the entire cache and + * checking for deleted items.*/ position = E_GW_CURSOR_POSITION_END; cursor = 0; - status = e_gw_connection_create_cursor (cnc, cbgw->priv->container_id, "iCalId", NULL, &cursor); + status = e_gw_connection_create_cursor (cnc, cbgw->priv->container_id, "iCalId recurrenceKey", NULL, &cursor); if (status != E_GW_CONNECTION_STATUS_OK) { if (status == E_GW_CONNECTION_STATUS_NO_RESPONSE) { @@ -438,9 +448,6 @@ get_deltas (gpointer handle) return TRUE; } - /* handle deleted items here by going over the entire cache and - * checking for deleted items.*/ - cache_keys = e_cal_backend_cache_get_keys (cache); done = FALSE; while (!done) { @@ -507,6 +514,7 @@ get_deltas (gpointer handle) g_slist_free (cache_keys); item_list = NULL; } +#endif g_static_mutex_unlock (&connecting); @@ -957,10 +965,12 @@ e_cal_backend_groupwise_get_static_capabilities (ECalBackendSync *backend, EData CAL_STATIC_CAPABILITY_NO_CONV_TO_ASSIGN_TASK "," \ CAL_STATIC_CAPABILITY_NO_CONV_TO_RECUR "," \ CAL_STATIC_CAPABILITY_REQ_SEND_OPTIONS "," \ + CAL_STATIC_CAPABILITY_SAVE_SCHEDULES "," \ CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ACCEPT "," \ CAL_STATIC_CAPABILITY_DELEGATE_SUPPORTED "," \ CAL_STATIC_CAPABILITY_DELEGATE_TO_MANY "," \ CAL_STATIC_CAPABILITY_NO_ORGANIZER "," \ + CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER "," \ CAL_STATIC_CAPABILITY_SAVE_SCHEDULES); return GNOME_Evolution_Calendar_Success; @@ -1802,6 +1812,27 @@ e_cal_backend_groupwise_modify_object (ECalBackendSync *backend, EDataCal *cal, return GNOME_Evolution_Calendar_Success; } +static const char * +get_gw_item_id (icalcomponent *icalcomp) +{ + icalproperty *icalprop; + + /* search the component for the X-GWRECORDID property */ + icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY); + while (icalprop) { + const char *x_name, *x_val; + + x_name = icalproperty_get_x_name (icalprop); + x_val = icalproperty_get_x (icalprop); + if (!strcmp (x_name, "X-GWRECORDID")) { + return x_val; + } + + icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY); + } + return NULL; +} + /* Remove_object handler for the file backend */ static ECalBackendSyncStatus e_cal_backend_groupwise_remove_object (ECalBackendSync *backend, EDataCal *cal, @@ -1822,74 +1853,97 @@ e_cal_backend_groupwise_remove_object (ECalBackendSync *backend, EDataCal *cal, if (priv->mode == CAL_MODE_REMOTE) { ECalBackendSyncStatus status; const char *id_to_remove = NULL; - icalproperty *icalprop; icalcomponent *icalcomp; - status = e_cal_backend_groupwise_get_object (backend, cal, uid, rid, &calobj); - if (status != GNOME_Evolution_Calendar_Success) - return status; - - *old_object = strdup (calobj); + if (mod == CALOBJ_MOD_THIS) { - icalcomp = icalparser_parse_string (calobj); - if (!icalcomp) { - g_free (calobj); - return GNOME_Evolution_Calendar_InvalidObject; - } + status = e_cal_backend_groupwise_get_object (backend, cal, uid, rid, &calobj); + if (status != GNOME_Evolution_Calendar_Success) + return status; - /* search the component for the X-GWRECORDID property */ - icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY); - while (icalprop) { - const char *x_name, *x_val; + *old_object = strdup (calobj); - x_name = icalproperty_get_x_name (icalprop); - x_val = icalproperty_get_x (icalprop); - if (!strcmp (x_name, "X-GWRECORDID")) { - id_to_remove = x_val; - break; + icalcomp = icalparser_parse_string (calobj); + if (!icalcomp) { + g_free (calobj); + return GNOME_Evolution_Calendar_InvalidObject; + } + + id_to_remove = get_gw_item_id (icalcomp); + if (!id_to_remove) { + /* use the iCalId to remove the object */ + id_to_remove = uid; } - icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY); - } + /* remove the object */ + status = e_gw_connection_remove_item (priv->cnc, priv->container_id, id_to_remove); - if (!id_to_remove) { - /* use the iCalId to remove the object */ - id_to_remove = uid; - } + if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION) + status = e_gw_connection_remove_item (priv->cnc, priv->container_id, id_to_remove); + + icalcomponent_free (icalcomp); + if (status == E_GW_CONNECTION_STATUS_OK) { + /* remove the component from the cache */ + if (!e_cal_backend_cache_remove_component (priv->cache, uid, rid)) { + g_free (calobj); + return GNOME_Evolution_Calendar_ObjectNotFound; + } + *object = NULL; + g_free (calobj); + return GNOME_Evolution_Calendar_Success; + } else { + g_free (calobj); + return GNOME_Evolution_Calendar_OtherError; + } + } else if (mod == CALOBJ_MOD_ALL) { + GSList *l, *comp_list = e_cal_backend_cache_get_components_by_uid (priv->cache, uid); - /* remove the object */ - status = e_gw_connection_remove_item (priv->cnc, priv->container_id, id_to_remove); + if (e_cal_component_has_attendees (E_CAL_COMPONENT (comp_list->data))) { + /* get recurrence key and send it to + * e_gw_connection_remove_recurrence_item */ + status = e_gw_connection_decline_request_by_recurrence_key (priv->cnc, uid, NULL); + if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION) + status = e_gw_connection_decline_request_by_recurrence_key (priv->cnc, uid, NULL); + } else { + GList *item_ids; + for (l = comp_list; l; l = l->next) { + ECalComponent *comp = E_CAL_COMPONENT (l->data); + + id_to_remove = get_gw_item_id (e_cal_component_get_icalcomponent (comp)); + item_ids = g_list_append (item_ids, (char *) id_to_remove); + } + status = e_gw_connection_remove_items (priv->cnc, priv->container_id, item_ids); + + if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION) + status = e_gw_connection_remove_items (priv->cnc, priv->container_id, item_ids); + } - if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION) - status = e_gw_connection_remove_item (priv->cnc, priv->container_id, id_to_remove); + if (status == E_GW_CONNECTION_STATUS_OK) { - icalcomponent_free (icalcomp); - if (status == E_GW_CONNECTION_STATUS_OK) { - /* remove the component from the cache */ - if (!e_cal_backend_cache_remove_component (priv->cache, uid, rid)) { - g_free (calobj); - return GNOME_Evolution_Calendar_ObjectNotFound; + for (l = comp_list; l; l = l->next) { + ECalComponent *comp = E_CAL_COMPONENT (l->data); + e_cal_backend_cache_remove_component (priv->cache, uid, + e_cal_component_get_recurid_as_string (comp)); + e_cal_backend_notify_object_removed (E_CAL_BACKEND (cbgw), + uid, e_cal_component_get_as_string (comp), NULL); + g_object_unref (comp); + + } + /* Setting NULL would trigger another signal. + * We do not set the *object to NULL */ + g_slist_free (comp_list); + return GNOME_Evolution_Calendar_Success; + } else { + return GNOME_Evolution_Calendar_OtherError; } - *object = NULL; - g_free (calobj); - return GNOME_Evolution_Calendar_Success; - } else { - g_free (calobj); - return GNOME_Evolution_Calendar_OtherError; - } + } else + return GNOME_Evolution_Calendar_UnsupportedMethod; } else if (priv->mode == CAL_MODE_LOCAL) { in_offline (cbgw); return GNOME_Evolution_Calendar_RepositoryOffline; - } - - /* remove the component from the cache */ - if (!e_cal_backend_cache_remove_component (priv->cache, uid, rid)) { - g_free (calobj); - return GNOME_Evolution_Calendar_ObjectNotFound; - } - - g_free (calobj); - return GNOME_Evolution_Calendar_Success; + } else + return GNOME_Evolution_Calendar_CalListener_MODE_NOT_SUPPORTED; + } static void @@ -1985,6 +2039,7 @@ receive_object (ECalBackendGroupwise *cbgw, EDataCal *cal, icalcomponent *icalco if (e_cal_component_has_attachments (comp)) fetch_attachments (cbgw, comp); + modif_comp = comp; status = e_gw_connection_send_appointment (cbgw, priv->container_id, comp, method, &remove, &modif_comp); if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION) diff --git a/calendar/libecal/e-cal-util.h b/calendar/libecal/e-cal-util.h index 14d7835..1f3418b 100644 --- a/calendar/libecal/e-cal-util.h +++ b/calendar/libecal/e-cal-util.h @@ -123,6 +123,7 @@ gboolean e_cal_util_event_dates_match (icalcomponent *icalcomp1, icalcomponent * #define CAL_STATIC_CAPABILITY_NO_CONV_TO_RECUR "no-conv-to-recur" #define CAL_STATIC_CAPABILITY_NO_GEN_OPTIONS "no-general-options" #define CAL_STATIC_CAPABILITY_REQ_SEND_OPTIONS "require-send-options" +#define CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER "recurrences-no-master-object" #define CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ACCEPT "organizer-must-accept" #define CAL_STATIC_CAPABILITY_DELEGATE_SUPPORTED "delegate-support" #define CAL_STATIC_CAPABILITY_NO_ORGANIZER "no-organizer" diff --git a/calendar/libecal/e-cal.c b/calendar/libecal/e-cal.c index a36a49e..ef22d05 100644 --- a/calendar/libecal/e-cal.c +++ b/calendar/libecal/e-cal.c @@ -2421,6 +2421,24 @@ e_cal_get_organizer_must_attend (ECal *ecal) } /** + * e_cal_get_recurrences_no_master: + * @ecal: A calendar client. + * + * Checks if the calendar has a master object for recurrences. + * + * Return value: TRUE if the calendar has a master object for recurrences, + * FALSE otherwise. + */ +gboolean +e_cal_get_recurrences_no_master (ECal *ecal) +{ + g_return_val_if_fail (ecal != NULL, FALSE); + g_return_val_if_fail (E_IS_CAL (ecal), FALSE); + + return check_capability (ecal, CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER); +} + +/** * e_cal_get_static_capability: * @ecal: A calendar client. * @cap: Name of the static capability to check. @@ -2507,7 +2525,6 @@ e_cal_set_mode (ECal *ecal, CalMode mode) return retval; } - /* This is used in the callback which fetches all the timezones needed for an object. */ typedef struct _ECalGetTimezonesData ECalGetTimezonesData; @@ -3502,6 +3519,17 @@ e_cal_generate_instances_for_object (ECal *ecal, icalcomponent *icalcomp, comp = e_cal_component_new (); e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (icalcomp)); + /*If the backend stores it as individual instances and does not + * have a master object - do not expand*/ + if (e_cal_get_static_capability (ecal, CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER)) { + time_t start, end; + /*return the same instance */ + result = (* cb) (comp, icaltime_as_timet_with_zone (icalcomponent_get_dtstart (icalcomp), ecal->priv->default_zone), + icaltime_as_timet_with_zone (icalcomponent_get_dtend (icalcomp), ecal->priv->default_zone), cb_data); + g_object_unref (comp); + return; + } + e_cal_component_get_uid (comp, &uid); rid = e_cal_component_get_recurid_as_string (comp); @@ -4213,7 +4241,7 @@ e_cal_remove_object (ECal *ecal, const char *uid, GError **error) e_return_error_if_fail (ecal && E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG); e_return_error_if_fail (uid, E_CALENDAR_STATUS_INVALID_ARG); - return e_cal_remove_object_with_mod (ecal, uid, NULL, CALOBJ_MOD_ALL, error); + return e_cal_remove_object_with_mod (ecal, uid, NULL, CALOBJ_MOD_THIS, error); } /** diff --git a/calendar/libecal/e-cal.h b/calendar/libecal/e-cal.h index 46dc836..d24e277 100644 --- a/calendar/libecal/e-cal.h +++ b/calendar/libecal/e-cal.h @@ -204,7 +204,7 @@ gboolean e_cal_set_default (ECal *ecal, GError **error); gboolean e_cal_set_default_source (ESource *source, ECalSourceType type, GError **error); gboolean e_cal_get_sources (ESourceList **sources, ECalSourceType type, GError **error); const char * e_cal_get_local_attachment_store (ECal *ecal); - +gboolean e_cal_get_recurrences_no_master (ECal *ecal); G_END_DECLS #endif diff --git a/calendar/libedata-cal/e-cal-backend-cache.c b/calendar/libedata-cal/e-cal-backend-cache.c index 714fd9d..34795a6 100644 --- a/calendar/libedata-cal/e-cal-backend-cache.c +++ b/calendar/libedata-cal/e-cal-backend-cache.c @@ -452,6 +452,55 @@ e_cal_backend_cache_get_components (ECalBackendCache *cache) } /** + * e_cal_backend_cache_get_components_by_uid: + * @cache: An #ECalBackendCache object. + * @uid: ID of the component to retrieve. + * + * Retrieves a ical components from the cache. + * + * Return value: The list of calendar components if found, or NULL otherwise. + */ +GSList * +e_cal_backend_cache_get_components_by_uid (ECalBackendCache *cache, const char *uid) +{ + char *comp_str; + GSList *l; + GSList *list = NULL; + icalcomponent *icalcomp; + ECalComponent *comp = NULL; + + /* return null if cache is not a valid Backend Cache. */ + g_return_val_if_fail (E_IS_CAL_BACKEND_CACHE (cache), NULL); + l = e_file_cache_get_objects (E_FILE_CACHE (cache)); + if (!l) + return NULL; + for ( ; l != NULL; l = g_slist_next (l)) { + comp_str = l->data; + if (comp_str) { + icalcomp = icalparser_parse_string (comp_str); + if (icalcomp) { + icalcomponent_kind kind; + + kind = icalcomponent_isa (icalcomp); + if (kind == ICAL_VEVENT_COMPONENT || kind == ICAL_VTODO_COMPONENT) { + comp = e_cal_component_new (); + if ((e_cal_component_set_icalcomponent (comp, icalcomp)) && + !strcmp (icalcomponent_get_uid (icalcomp), uid)) + list = g_slist_append (list, comp); + else { + g_object_unref (comp); + } + } else + icalcomponent_free (icalcomp); + } + } + + } + + return list; +} + +/** * e_cal_backend_cache_get_timezone: * @cache: An #ECalBackendCache object. * @tzid: ID of the timezone to retrieve. diff --git a/calendar/libedata-cal/e-cal-backend-cache.h b/calendar/libedata-cal/e-cal-backend-cache.h index f9edd29..984d9c0 100644 --- a/calendar/libedata-cal/e-cal-backend-cache.h +++ b/calendar/libedata-cal/e-cal-backend-cache.h @@ -55,6 +55,8 @@ gboolean e_cal_backend_cache_remove_component (ECalBackendCache *cach const char *uid, const char *rid); GList *e_cal_backend_cache_get_components (ECalBackendCache *cache); +GSList *e_cal_backend_cache_get_components_by_uid (ECalBackendCache *cache, const char *uid); + const icaltimezone *e_cal_backend_cache_get_timezone (ECalBackendCache *cache, const char *tzid);