[evolution-patches] Calendar backend recurrences fixes [Groupwise]



hi,

 the attached patch allows the GW backend to send recurrence formulae to
the server, instead of computing the instances and also allows
accept/delete of an entire recurrence group at one shot.
Details in Changelog.

Harish
Index: calendar/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/ChangeLog,v
retrieving revision 1.440
diff -u -p -r1.440 ChangeLog
--- calendar/ChangeLog	15 Mar 2005 01:48:03 -0000	1.440
+++ calendar/ChangeLog	15 Mar 2005 10:30:34 -0000
@@ -1,3 +1,28 @@
+2005-03-15  Harish Krishnaswamy  <kharish novell com>
+
+	* 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_generate_instances_for_object): 
+	Do not expand instances for objects from backends that do not
+	have master object to represent recurrences.
+	* 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-03-12  Chenthill Palanisamy  <pchenthill novell com>
 
 	* backends/groupwise/e-cal-backend-groupwise.c:
Index: calendar/backends/groupwise/e-cal-backend-groupwise.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/backends/groupwise/e-cal-backend-groupwise.c,v
retrieving revision 1.139
diff -u -p -r1.139 e-cal-backend-groupwise.c
--- calendar/backends/groupwise/e-cal-backend-groupwise.c	14 Mar 2005 05:19:44 -0000	1.139
+++ calendar/backends/groupwise/e-cal-backend-groupwise.c	15 Mar 2005 10:30:34 -0000
@@ -764,7 +764,8 @@ e_cal_backend_groupwise_get_static_capab
 				  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_SAVE_SCHEDULES "," \
+				  CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER);
 
 	return GNOME_Evolution_Calendar_Success;
 }
@@ -1605,71 +1606,89 @@ e_cal_backend_groupwise_remove_object (E
 		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);
-
-		icalcomp = icalparser_parse_string (calobj);
-		if (!icalcomp) {
-			g_free (calobj);
-			return GNOME_Evolution_Calendar_InvalidObject;
-		}
-
-		/* 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")) {
-				id_to_remove = x_val;
-				break;
-			}
+		if (mod == CALOBJ_MOD_THIS) {
 
-			icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY);
-		}
+			status = e_cal_backend_groupwise_get_object (backend, cal, uid, rid, &calobj);
+			if (status != GNOME_Evolution_Calendar_Success)
+				return status;
 
-		if (!id_to_remove) {
-			/* use the iCalId to remove the object */
-			id_to_remove = uid;
-		}
+			*old_object = strdup (calobj);
 
-		/* remove the object */
-		status = e_gw_connection_remove_item (priv->cnc, priv->container_id, id_to_remove);
+			icalcomp = icalparser_parse_string (calobj);
+			if (!icalcomp) {
+				g_free (calobj);
+				return GNOME_Evolution_Calendar_InvalidObject;
+			}
+			/* 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")) {
+					id_to_remove = x_val;
+					break;
+				}
 
-		if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
+				icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY);
+			}
+
+			if (!id_to_remove) {
+				/* use the iCalId to remove the object */
+				id_to_remove = uid;
+			}
+
+			/* remove the object */
 			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)) {
+			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_ObjectNotFound;
+				return GNOME_Evolution_Calendar_Success;
+			} else {
+				g_free (calobj);
+				return GNOME_Evolution_Calendar_OtherError;
+			}
+		} else if (mod == CALOBJ_MOD_ALL) {
+			/* 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);
+			if (status == E_GW_CONNECTION_STATUS_OK) {
+				GSList *l, *comp_list = e_cal_backend_cache_get_components_by_uid (priv->cache, uid);
+			
+				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 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;
 }
 
 static void
Index: calendar/backends/groupwise/e-cal-backend-groupwise-utils.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/backends/groupwise/e-cal-backend-groupwise-utils.c,v
retrieving revision 1.53
diff -u -p -r1.53 e-cal-backend-groupwise-utils.c
--- calendar/backends/groupwise/e-cal-backend-groupwise-utils.c	22 Feb 2005 05:10:19 -0000	1.53
+++ calendar/backends/groupwise/e-cal-backend-groupwise-utils.c	15 Mar 2005 10:30:34 -0000
@@ -337,6 +337,73 @@ e_cal_backend_groupwise_set_attachments_
 	e_gw_item_set_attach_id_list (item, attach_list);
 }
 
+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*/
+		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_list_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)
 {
@@ -572,18 +639,22 @@ set_properties_from_cal_component (EGwIt
 	
 	/* 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)) {
@@ -729,15 +800,7 @@ e_gw_item_to_cal_component (EGwItem *ite
 		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);
@@ -843,6 +906,31 @@ e_gw_item_to_cal_component (EGwItem *ite
 	else 
 		return NULL;
 	
+	/* UID */
+	if (e_gw_item_get_recurrence_key != 0)
+	{
+		ECalComponentRange *recur_id;
+		const char *recur_key = g_strdup_printf ("%d", e_gw_item_get_recurrence_key (item));
+
+		e_cal_component_set_uid (comp, 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);
@@ -1036,7 +1124,10 @@ e_gw_connection_send_appointment (ECalBa
 	EGwConnectionStatus status;
 	icalparameter_partstat partstat;
 	char *item_id;
-	
+	gboolean all_instances = FALSE;
+	icalproperty *icalprop;
+	icalcomponent *icalcomp;
+	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);
@@ -1046,16 +1137,38 @@ e_gw_connection_send_appointment (ECalBa
 	/* 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:
@@ -1099,17 +1212,31 @@ e_gw_connection_send_appointment (ECalBa
 			
 		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);
Index: calendar/libecal/e-cal-util.h
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/libecal/e-cal-util.h,v
retrieving revision 1.6
diff -u -p -r1.6 e-cal-util.h
--- calendar/libecal/e-cal-util.h	15 Dec 2004 09:08:04 -0000	1.6
+++ calendar/libecal/e-cal-util.h	15 Mar 2005 10:30:34 -0000
@@ -125,6 +125,7 @@ gboolean e_cal_util_event_dates_match (i
 #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"
 
 /* Recurrent events. Management for instances */
 icalcomponent *e_cal_util_construct_instance (icalcomponent *icalcomp,
Index: calendar/libecal/e-cal.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/libecal/e-cal.c,v
retrieving revision 1.96
diff -u -p -r1.96 e-cal.c
--- calendar/libecal/e-cal.c	15 Mar 2005 01:48:03 -0000	1.96
+++ calendar/libecal/e-cal.c	15 Mar 2005 10:30:35 -0000
@@ -2307,6 +2307,17 @@ e_cal_get_save_schedules (ECal *ecal)
 	return check_capability (ecal, CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
 }
 
+#if 0
+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);
+}
+#endif
+
 gboolean
 e_cal_set_mode (ECal *ecal, CalMode mode)
 {
@@ -2331,7 +2342,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;
@@ -3261,6 +3271,18 @@ e_cal_generate_instances_for_object (ECa
 
 	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);
Index: calendar/libedata-cal/e-cal-backend-cache.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/libedata-cal/e-cal-backend-cache.c,v
retrieving revision 1.20
diff -u -p -r1.20 e-cal-backend-cache.c
--- calendar/libedata-cal/e-cal-backend-cache.c	25 Feb 2005 06:36:51 -0000	1.20
+++ calendar/libedata-cal/e-cal-backend-cache.c	15 Mar 2005 10:30:35 -0000
@@ -422,6 +422,47 @@ e_cal_backend_cache_get_components (ECal
         return list;
 }
 
+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 {
+						icalcomponent_free (icalcomp);
+						g_object_unref (comp);
+					}
+				} else
+					icalcomponent_free (icalcomp);
+                        }
+                }
+                
+        }
+
+        return list;
+}
+
 const icaltimezone *
 e_cal_backend_cache_get_timezone (ECalBackendCache *cache, const char *tzid)
 {
Index: calendar/libedata-cal/e-cal-backend-cache.h
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/libedata-cal/e-cal-backend-cache.h,v
retrieving revision 1.13
diff -u -p -r1.13 e-cal-backend-cache.h
--- calendar/libedata-cal/e-cal-backend-cache.h	25 Feb 2005 06:36:51 -0000	1.13
+++ calendar/libedata-cal/e-cal-backend-cache.h	15 Mar 2005 10:30:35 -0000
@@ -55,6 +55,8 @@ gboolean            e_cal_backend_cache_
 							  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);
Index: servers/groupwise/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution-data-server/servers/groupwise/ChangeLog,v
retrieving revision 1.129
diff -u -p -r1.129 ChangeLog
--- servers/groupwise/ChangeLog	28 Feb 2005 12:46:13 -0000	1.129
+++ servers/groupwise/ChangeLog	15 Mar 2005 10:30:36 -0000
@@ -1,3 +1,20 @@
+2005-03-15  Harish Krishnaswamy  <kharish novell com>
+
+	* e-gw-connection.[ch]:
+	(e_gw_connection_accept_request_by_recurrence_key),
+	(e_gw_connection_decline_request),
+	(e_gw_connection_decline_request_by_recurrence_key):
+	Accept/Decline all recurrence items at one go by using
+	the recurrence key.
+	* e-gw-item.[ch]: (e_gw_item_dispose),
+	(e_gw_item_new_from_soap_parameter), (e_gw_item_get_exdate_list),
+	(e_gw_item_set_exdate_list), (e_gw_item_get_rrule),
+	(e_gw_item_set_rrule), (e_gw_item_get_recurrence_key),
+	(e_gw_item_set_recurrence_key),
+	(e_gw_item_set_calendar_item_elements): Create recurrence events
+	by sending the Recurrence formula to the server rather than 
+	computing the instances.
+
 2005-02-28  Harish Krishnaswamy  <kharish novell com>
 
 	* e-gw-connection.c: (e_gw_connection_get_quick_messages):
Index: servers/groupwise/e-gw-connection.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/servers/groupwise/e-gw-connection.c,v
retrieving revision 1.112
diff -u -p -r1.112 e-gw-connection.c
--- servers/groupwise/e-gw-connection.c	28 Feb 2005 12:46:13 -0000	1.112
+++ servers/groupwise/e-gw-connection.c	15 Mar 2005 10:30:36 -0000
@@ -1246,6 +1246,35 @@ e_gw_connection_accept_request (EGwConne
 }
 
 EGwConnectionStatus
+e_gw_connection_accept_request_by_recurrence_key (EGwConnection *cnc, const char *recurrence_key, const char *accept_level, const char *accept_comment)
+{
+	SoupSoapMessage *msg;
+	int status;
+	SoupSoapResponse *response;
+
+	msg = e_gw_message_new_with_header (cnc->priv->uri, cnc->priv->session_id, "acceptRequest");
+	if (accept_comment)
+		e_gw_message_write_string_parameter (msg, "comment", NULL, accept_comment);
+
+	e_gw_message_write_string_parameter (msg, "acceptLevel", NULL, accept_level);
+	e_gw_message_write_string_parameter (msg, "recurrenceKey", NULL, recurrence_key);
+	e_gw_message_write_footer (msg);
+
+	response = e_gw_connection_send_message (cnc, msg);
+        if (!response) {
+                g_object_unref (msg);
+                return E_GW_CONNECTION_STATUS_NO_RESPONSE;
+        }
+
+        status = e_gw_connection_parse_response_status (response);
+	if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
+		reauthenticate (cnc);
+	g_object_unref (response);
+	g_object_unref (msg);
+	return status;
+}
+
+EGwConnectionStatus
 e_gw_connection_decline_request (EGwConnection *cnc, const char *id)
 {
 	SoupSoapMessage *msg;
@@ -1256,6 +1285,33 @@ e_gw_connection_decline_request (EGwConn
 	soup_soap_message_start_element (msg, "items", NULL, NULL);
 	e_gw_message_write_string_parameter (msg, "item", NULL, id);
 	soup_soap_message_end_element (msg);
+	e_gw_message_write_footer (msg);
+
+	response = e_gw_connection_send_message (cnc, msg);
+        if (!response) {
+                g_object_unref (msg);
+                return E_GW_CONNECTION_STATUS_NO_RESPONSE;
+        }
+
+        status = e_gw_connection_parse_response_status (response);
+	if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
+		reauthenticate (cnc);
+	g_object_unref (response);
+	g_object_unref (msg);
+	return status;
+}
+
+EGwConnectionStatus
+e_gw_connection_decline_request_by_recurrence_key (EGwConnection *cnc, const char *recurrence_key, const char *decline_comment)
+{
+	SoupSoapMessage *msg;
+	int status;
+	SoupSoapResponse *response;
+
+	msg = e_gw_message_new_with_header (cnc->priv->uri, cnc->priv->session_id, "declineRequest");
+	if (decline_comment)
+		e_gw_message_write_string_parameter (msg, "comment", NULL, decline_comment);
+	e_gw_message_write_string_parameter (msg, "recurrenceKey", NULL, recurrence_key);
 	e_gw_message_write_footer (msg);
 
 	response = e_gw_connection_send_message (cnc, msg);
Index: servers/groupwise/e-gw-connection.h
===================================================================
RCS file: /cvs/gnome/evolution-data-server/servers/groupwise/e-gw-connection.h,v
retrieving revision 1.57
diff -u -p -r1.57 e-gw-connection.h
--- servers/groupwise/e-gw-connection.h	25 Feb 2005 06:30:22 -0000	1.57
+++ servers/groupwise/e-gw-connection.h	15 Mar 2005 10:30:36 -0000
@@ -109,6 +109,8 @@ EGwConnectionStatus e_gw_connection_acce
 EGwConnectionStatus e_gw_connection_decline_request (EGwConnection *cnc, const char *id);
 EGwConnectionStatus e_gw_connection_retract_request (EGwConnection *cnc, const char *id, const char *comment, gboolean retract_all, gboolean resend);
 EGwConnectionStatus e_gw_connection_complete_request (EGwConnection *cnc, const char *id);
+EGwConnectionStatus e_gw_connection_decline_request_by_recurrence_key (EGwConnection *cnc, const char *recurrence_key, const char *decline_comment);
+EGwConnectionStatus e_gw_connection_accept_request_by_recurrence_key (EGwConnection *cnc, const char *recurrence_key, const char *accept_level, const char *accept_comment);
 EGwConnectionStatus e_gw_connection_create_book (EGwConnection *cnc, char *book_name, char**id);
 EGwConnectionStatus e_gw_connection_remove_book (EGwConnection *cnc, char *book_uid);
 EGwConnectionStatus e_gw_connection_get_address_book_list (EGwConnection *cnc, GList **container_list);
Index: servers/groupwise/e-gw-item.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/servers/groupwise/e-gw-item.c,v
retrieving revision 1.75
diff -u -p -r1.75 e-gw-item.c
--- servers/groupwise/e-gw-item.c	28 Feb 2005 15:30:58 -0000	1.75
+++ servers/groupwise/e-gw-item.c	15 Mar 2005 10:30:37 -0000
@@ -54,7 +54,12 @@ struct _EGwItemPrivate {
 	char *place;
 	char *source ;
 	GSList *recipient_list;
+
 	GSList *recurrence_dates;
+	GSList *exdate_list;
+	EGwItemRecurrenceRule *rrule;
+	int recurrence_key;
+
 	int trigger; /* alarm */
 	EGwItemOrganizer *organizer;
 
@@ -343,10 +348,19 @@ e_gw_item_dispose (GObject *object)
 			g_slist_free (priv->recurrence_dates);
 			priv->recurrence_dates = NULL;
 		}
+		if (priv->exdate_list) {
+			g_slist_foreach (priv->exdate_list, free_string, NULL);
+			g_slist_free (priv->exdate_list);
+			priv->exdate_list = NULL;
+		}
+		if (priv->rrule) {
+			/*TODO free all the strings */
+			priv->rrule = NULL;
+		}
 		if (priv->full_name) {
 			free_full_name (priv->full_name);
 			priv->full_name = NULL;
-			}
+		}
 		if (priv->simple_fields)
 			g_hash_table_destroy (priv->simple_fields);
 		if (priv->addresses)
@@ -372,7 +386,7 @@ e_gw_item_dispose (GObject *object)
 			g_list_free (priv->category_list);
 			priv->category_list = NULL;
 		}
-		if(priv->attach_list) {
+		if (priv->attach_list) {
 			g_slist_foreach (priv->attach_list, free_attach, NULL); 
 			g_slist_free (priv->attach_list) ;
 			priv->attach_list = NULL ;
@@ -1752,6 +1766,8 @@ e_gw_item_new_from_soap_parameter (const
 
 		} else if (!g_ascii_strcasecmp (name, "id"))
 			item->priv->id = soup_soap_parameter_get_string_value (child);
+		else if (!g_ascii_strcasecmp (name, "recurrenceKey"))
+			item->priv->recurrence_key = soup_soap_parameter_get_int_value (child);
 
 		else if (!g_ascii_strcasecmp (name, "message")) {
 			SoupSoapParameter *part;
@@ -2229,6 +2245,51 @@ e_gw_item_set_recurrence_dates (EGwItem 
 	item->priv->recurrence_dates = new_recurrence_dates;
 }
 
+GSList *
+e_gw_item_get_exdate_list (EGwItem *item)
+{
+	g_return_val_if_fail (E_IS_GW_ITEM (item), NULL);
+	return item->priv->exdate_list;
+}
+
+void
+e_gw_item_set_exdate_list (EGwItem  *item, GSList *new_exdate_list)
+{
+	/* free old list and set a new one*/
+	g_slist_foreach (item->priv->exdate_list, free_string, NULL);
+	/*free the list */
+	g_slist_free (item->priv->exdate_list);
+	item->priv->exdate_list = new_exdate_list;
+}
+
+EGwItemRecurrenceRule *
+e_gw_item_get_rrule (EGwItem *item)
+{
+	g_return_val_if_fail (E_IS_GW_ITEM (item), NULL);
+	return item->priv->rrule;
+}
+
+void
+e_gw_item_set_rrule (EGwItem  *item, EGwItemRecurrenceRule *new_rrule)
+{
+	if (item->priv->rrule) {
+	/* TODO free old list and set a new one*/
+	}
+	item->priv->rrule = new_rrule;
+}
+
+int
+e_gw_item_get_recurrence_key (EGwItem *item)
+{
+	g_return_val_if_fail (E_IS_GW_ITEM (item), 0);
+	return item->priv->recurrence_key;
+}
+
+void
+e_gw_item_set_recurrence_key (EGwItem *item, int recur_key)
+{
+	item->priv->recurrence_key = recur_key;
+}
 int
 e_gw_item_get_trigger (EGwItem *item)
 {
@@ -2726,7 +2787,18 @@ e_gw_item_set_calendar_item_elements (EG
 		}
 	
 	/* handle recurrences */
-	if (item->priv->recurrence_dates) {
+	if (item->priv->rrule) {
+		soup_soap_message_start_element (msg, "rrule", NULL, NULL);
+		
+		e_gw_message_write_string_parameter (msg, "frequency", NULL, item->priv->rrule->frequency); 
+		if (item->priv->rrule->until)
+			e_gw_message_write_string_parameter (msg, "until", NULL, item->priv->rrule->until);
+		else
+			e_gw_message_write_int_parameter (msg, "count", NULL, item->priv->rrule->count);
+		soup_soap_message_end_element (msg);
+		
+	}
+	else if (item->priv->recurrence_dates) {
 		GSList *date;
 		soup_soap_message_start_element (msg, "rdate", NULL, NULL);
 		for (date = item->priv->recurrence_dates; date != NULL; date = g_slist_next (date)) {
@@ -2734,12 +2806,15 @@ e_gw_item_set_calendar_item_elements (EG
 		}
 		soup_soap_message_end_element (msg);
 	}
-	else {
-		/*the icalid is fed to the server only if we are not saving
-		 * recurring items */
-		e_gw_message_write_string_parameter (msg, "iCalId", NULL, priv->icalid ? priv->icalid : "");
+	if (item->priv->exdate_list) {
+		GSList *date;
+		soup_soap_message_start_element (msg, "exdate", NULL, NULL);
+		for (date = item->priv->exdate_list; date != NULL; date = g_slist_next (date)) {
+			e_gw_message_write_string_parameter (msg, "date", NULL, (char *) date->data);
+		}
+		soup_soap_message_end_element (msg);
 	}
-
+	/*xxx - byday, bymonthday and byyearday not handled - FIXME */	
 	/*attachments*/
 	if (priv->attach_list) {
 		soup_soap_message_start_element (msg, "attachments", NULL, NULL) ;
Index: servers/groupwise/e-gw-item.h
===================================================================
RCS file: /cvs/gnome/evolution-data-server/servers/groupwise/e-gw-item.h,v
retrieving revision 1.29
diff -u -p -r1.29 e-gw-item.h
--- servers/groupwise/e-gw-item.h	8 Feb 2005 15:29:25 -0000	1.29
+++ servers/groupwise/e-gw-item.h	15 Mar 2005 10:30:37 -0000
@@ -252,10 +252,53 @@ void e_gw_item_set_organizer (EGwItem  *
 GSList * e_gw_item_get_attach_id_list (EGwItem *item) ;
 void e_gw_item_set_attach_id_list (EGwItem *item, GSList *attach_list) ;
 
+/* E_GW_ITEM_RECURRENCE DECLARATIONS - BEGIN */
+#define E_GW_ITEM_RECURRENCE_FREQUENCY_DAILY "Daily"
+#define E_GW_ITEM_RECURRENCE_FREQUENCY_WEEKLY "Weekly"
+#define E_GW_ITEM_RECURRENCE_FREQUENCY_MONTHLY "Monthly"
+#define E_GW_ITEM_RECURRENCE_FREQUENCY_YEARLY "Yearly"
+
+
+#define E_GW_ITEM_RECUR_OCCURRENCE_TYPE_FIRST  "First" 
+#define E_GW_ITEM_RECUR_OCCURRENCE_TYPE_SECOND "Second" 
+#define E_GW_ITEM_RECUR_OCCURRENCE_TYPE_THIRD  "Third" 
+#define E_GW_ITEM_RECUR_OCCURRENCE_TYPE_FOURTH "Fourth" 
+#define E_GW_ITEM_RECUR_OCCURRENCE_TYPE_FIFTH  "Fifth"
+#define E_GW_ITEM_RECUR_OCCURRENCE_TYPE_LAST   "Last"
+
+#define E_GW_ITEM_RECUR_WEEKDAY_SUNDAY
+#define E_GW_ITEM_RECUR_WEEKDAY_MONDAY
+#define E_GW_ITEM_RECUR_WEEKDAY_TUESDAY
+#define E_GW_ITEM_RECUR_WEEKDAY_WEDNESDAY
+#define E_GW_ITEM_RECUR_WEEKDAY_THURSDAY
+#define E_GW_ITEM_RECUR_WEEKDAY_FRIDAY
+#define E_GW_ITEM_RECUR_WEEKDAY_SATURDAY
+
+typedef struct {
+	const char *frequency;
+	char *until;
+	int count;
+	int interval;
+	GSList *by_day;
+	GSList *by_month_day;
+	GSList *by_year_day;
+	GSList *by_month;
+} EGwItemRecurrenceRule;
 
 GSList *e_gw_item_get_recurrence_dates (EGwItem *item);
 void e_gw_item_set_recurrence_dates (EGwItem  *item, GSList *new_recurrence_dates);
 
+GSList *e_gw_item_get_exdate_list (EGwItem *item);
+void e_gw_item_set_exdate_list (EGwItem  *item, GSList *new_exdate_list);
+
+void e_gw_item_set_rrule (EGwItem *item, EGwItemRecurrenceRule *rrule);
+EGwItemRecurrenceRule *e_gw_item_get_rrule (EGwItem *item);
+		
+int e_gw_item_get_recurrence_key (EGwItem *item);
+void e_gw_item_set_recurrence_key (EGwItem *item, int recurrence_key);
+
+
+/*E_GW_ITEM_RECURRENCE DECLARATIONS - END */
 void e_gw_item_set_source (EGwItem *item, char *source) ;
 
 int e_gw_item_get_trigger (EGwItem *item);
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/plugins/itip-formatter/ChangeLog,v
retrieving revision 1.39
diff -u -p -r1.39 ChangeLog
--- ChangeLog	25 Feb 2005 15:54:21 -0000	1.39
+++ ChangeLog	15 Mar 2005 10:31:28 -0000
@@ -1,3 +1,15 @@
+2005-03-15  Harish Krishnaswamy  <kharish novell com>
+
+	* itip-formatter.c (source_selected_cb), 
+	(find_cal_opened_cb), (extract_itip_data): enable the
+	'Apply to all instances' option for gw recurrence instances.
+	(view_response_cb): embed X-GW-RECUR-INSTANCE-MOD-TYPE property in the
+	component to indicate whether the accept/decline status applies
+	to the instance or the entire group.
+	* itip-view.[ch]: (set_buttons), (recur_toggled_cb), (itip_view_init),
+	(itip_view_get_recur_check_state), (itip_view_set_show_recur_check):
+	utility methods to manipulate the recur_check widget.
+
 2005-02-24  Björn Torkelsson  <torkel acc umu se>
 
 	* org-gnome-itip-formatter.eplug.in: Added author and description.
Index: itip-view.c
===================================================================
RCS file: /cvs/gnome/evolution/plugins/itip-formatter/itip-view.c,v
retrieving revision 1.12
diff -u -p -r1.12 itip-view.c
--- itip-view.c	3 Feb 2005 16:53:35 -0000	1.12
+++ itip-view.c	15 Mar 2005 10:31:28 -0000
@@ -112,6 +112,9 @@ struct _ItipViewPrivate {
 	GtkWidget *rsvp_comment_entry;
 	gboolean rsvp_show;
 
+	GtkWidget *recur_box;
+	GtkWidget *recur_check;
+
 	GtkWidget *button_box;
 	gboolean buttons_sensitive;
 };
@@ -685,9 +688,11 @@ static void
 set_buttons (ItipView *view) 
 {
 	ItipViewPrivate *priv;
-	
+	gboolean is_recur_set = FALSE;
+
 	priv = view->priv;
 
+	is_recur_set = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->recur_check));
 	gtk_container_foreach (GTK_CONTAINER (priv->button_box), (GtkCallback) gtk_widget_destroy, NULL);
 
 	/* Everything gets the open button */
@@ -699,9 +704,9 @@ set_buttons (ItipView *view) 
 		set_one_button (view, "_Accept", GTK_STOCK_APPLY, ITIP_VIEW_RESPONSE_ACCEPT);
 		break;
 	case ITIP_VIEW_MODE_REQUEST:
-		set_one_button (view, "_Decline", GTK_STOCK_CANCEL, ITIP_VIEW_RESPONSE_DECLINE);
-		set_one_button (view, "_Tentative", GTK_STOCK_DIALOG_QUESTION, ITIP_VIEW_RESPONSE_TENTATIVE);
-		set_one_button (view, "_Accept", GTK_STOCK_APPLY, ITIP_VIEW_RESPONSE_ACCEPT);
+		set_one_button (view, is_recur_set ? "_Decline all" : "_Decline", GTK_STOCK_CANCEL, ITIP_VIEW_RESPONSE_DECLINE);
+		set_one_button (view, is_recur_set ? "_Tentative all" : "_Tentative", GTK_STOCK_DIALOG_QUESTION, ITIP_VIEW_RESPONSE_TENTATIVE);
+		set_one_button (view, is_recur_set ? "_Accept all" : "_Accept", GTK_STOCK_APPLY, ITIP_VIEW_RESPONSE_ACCEPT);
 		break;
 	case ITIP_VIEW_MODE_ADD:
 		set_one_button (view, "_Decline", GTK_STOCK_CANCEL, ITIP_VIEW_RESPONSE_DECLINE);
@@ -807,6 +812,20 @@ rsvp_toggled_cb (GtkWidget *widget, gpoi
 }
 
 static void
+recur_toggled_cb (GtkWidget *widget, gpointer data) 
+{
+	ItipView *view = data;
+	ItipViewPrivate *priv;
+	gboolean is_recur;
+	
+	priv = view->priv;
+	
+	is_recur = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->recur_check));
+	itip_view_set_mode (view, priv->mode);
+}
+
+
+static void
 itip_view_init (ItipView *view)
 {
 	ItipViewPrivate *priv;
@@ -949,6 +968,16 @@ itip_view_init (ItipView *view)
 	gtk_widget_show (priv->rsvp_comment_entry);
 	gtk_box_pack_start (GTK_BOX (hbox), priv->rsvp_comment_entry, FALSE, TRUE, 0);
 
+	/* The recurrence check button */
+	priv->recur_box = gtk_vbox_new (FALSE, 12);
+	gtk_widget_show (priv->recur_box);
+	gtk_box_pack_start (GTK_BOX (vbox), priv->recur_box, FALSE, FALSE, 0);
+
+	priv->recur_check = gtk_check_button_new_with_mnemonic (_("A_pply to all instances"));
+	gtk_box_pack_start (GTK_BOX (priv->recur_box), priv->recur_check, FALSE, FALSE, 0);
+
+	g_signal_connect (priv->recur_check, "toggled", G_CALLBACK (recur_toggled_cb), view);
+
 	/* The buttons for actions */
 	priv->button_box = gtk_hbutton_box_new ();
 	gtk_button_box_set_layout (GTK_BUTTON_BOX (priv->button_box), GTK_BUTTONBOX_END);
@@ -1781,4 +1810,22 @@ itip_view_get_buttons_sensitive (ItipVie
 	return priv->buttons_sensitive;
 }
 
+gboolean	
+itip_view_get_recur_check_state (ItipView *view)
+{
+	return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (view->priv->recur_check));
+}
+
+void
+itip_view_set_show_recur_check (ItipView *view, gboolean show)
+{
+	g_return_if_fail (view != NULL);
+	g_return_if_fail (ITIP_IS_VIEW (view));	
 	
+	if (show)
+		gtk_widget_show (view->priv->recur_check);
+	else  {
+		gtk_widget_hide (view->priv->recur_check);
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (view->priv->recur_check), FALSE);
+	}
+}
Index: itip-view.h
===================================================================
RCS file: /cvs/gnome/evolution/plugins/itip-formatter/itip-view.h,v
retrieving revision 1.10
diff -u -p -r1.10 itip-view.h
--- itip-view.h	10 Jan 2005 03:54:42 -0000	1.10
+++ itip-view.h	15 Mar 2005 10:31:28 -0000
@@ -159,6 +159,10 @@ const char *itip_view_get_rsvp_comment (
 void itip_view_set_buttons_sensitive (ItipView *view, gboolean sensitive);
 gboolean itip_view_get_buttons_sensitive (ItipView *view);
 
+void itip_view_set_show_recur_check (ItipView *view, gboolean show);
+gboolean itip_view_get_recur_check_state (ItipView *view);
+
+
 G_END_DECLS
 
 #endif
Index: itip-formatter.c
===================================================================
RCS file: /cvs/gnome/evolution/plugins/itip-formatter/itip-formatter.c,v
retrieving revision 1.38
diff -u -p -r1.38 itip-formatter.c
--- itip-formatter.c	2 Feb 2005 09:08:14 -0000	1.38
+++ itip-formatter.c	15 Mar 2005 10:31:29 -0000
@@ -350,6 +350,30 @@ source_selected_cb (ItipView *view, ESou
 	itip_view_set_buttons_sensitive (ITIP_VIEW (pitip->view), FALSE);
 
 	start_calendar_server (pitip, source, pitip->type, cal_opened_cb, pitip);
+	/* If it is a GW recurrence instance, enable the 'Apply to all
+	 * instances' option */
+	if (e_cal_get_static_capability (pitip->current_ecal, CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER)) {
+		gboolean is_instance = FALSE;
+		icalcomponent *icalcomp = e_cal_component_get_icalcomponent (pitip->comp);
+		icalproperty *icalprop;
+
+		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-RECURRENCE-KEY")) {
+				is_instance = TRUE;
+				break;
+			}
+			icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY);
+		}
+		if (is_instance)
+			itip_view_set_show_recur_check (ITIP_VIEW (pitip->view), TRUE);
+		else
+			itip_view_set_show_recur_check (ITIP_VIEW (pitip->view), FALSE);
+	}
+		
 }
 
 static void
@@ -420,6 +444,9 @@ find_cal_opened_cb (ECal *ecal, ECalenda
 						      "Found the appointment in the calendar '%s'", e_source_peek_name (source));
 
 		set_buttons_sensitive (pitip);
+		if (e_cal_get_static_capability (pitip->current_ecal, CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER))
+			itip_view_set_show_recur_check (ITIP_VIEW (pitip->view), TRUE);
+
 	}
 
 	zone = calendar_config_get_icaltimezone ();
@@ -1010,6 +1037,22 @@ extract_itip_data (FormatItipPObject *pi
 
 		return FALSE;	       
 	}
+
+	switch (kind) {
+	case ICAL_VEVENT_COMPONENT:
+		pitip->type = E_CAL_SOURCE_TYPE_EVENT;
+		break;
+	case ICAL_VTODO_COMPONENT:
+		pitip->type = E_CAL_SOURCE_TYPE_TODO;
+		break;
+	case ICAL_VFREEBUSY_COMPONENT:
+		/* FIXME free busy needs to be distinguished some how */
+		pitip->type = E_CAL_SOURCE_TYPE_EVENT;
+		break;
+	default:
+		g_assert_not_reached ();
+		break;
+	}
 	
 	pitip->total = icalcomponent_count_components (pitip->main_comp, ICAL_VEVENT_COMPONENT);
 	pitip->total += icalcomponent_count_components (pitip->main_comp, ICAL_VTODO_COMPONENT);
@@ -1132,9 +1175,17 @@ view_response_cb (GtkWidget *widget, Iti
 {
 	FormatItipPObject *pitip = data;
 	gboolean status = FALSE;
+	icalproperty *prop;
+
 
 	if (!pitip->my_address && pitip->current_ecal != NULL)
 		e_cal_get_cal_address (pitip->current_ecal, &pitip->my_address, NULL);
+
+	/* check if it is a  recur instance (no master object) and
+	 * add a property */
+	prop = icalproperty_new_x ("All");	
+	icalproperty_set_x_name (prop, "X-GW-RECUR-INSTANCES-MOD-TYPE");
+	icalcomponent_add_property (e_cal_component_get_icalcomponent (pitip->comp), prop);
 
 	switch (response) {
 	case ITIP_VIEW_RESPONSE_ACCEPT:


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]