[evolution-patches] patch for #59904 (calendar) for 2.0.x



The attached patch backports the change I did to HEAD for speeding up
calendar viewing. Bug #59904 has got a lot of duplicates, so we really
need this to go to the 2.0.x branch
-- 
Rodrigo Moya <rodrigo novell com>
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/ChangeLog,v
retrieving revision 1.324.2.8
diff -u -p -r1.324.2.8 ChangeLog
--- ChangeLog	7 Oct 2004 14:21:30 -0000	1.324.2.8
+++ ChangeLog	10 Nov 2004 17:00:13 -0000
@@ -1,3 +1,20 @@
+2004-11-10  Rodrigo Moya <rodrigo novell com>
+
+	Fixes #59904
+
+	* 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-07  JP Rosevear  <jpr novell com>
  
  	* libecal/e-cal.c (e_cal_new_system_tasks): load the correct type
Index: backends/file/e-cal-backend-file.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/backends/file/e-cal-backend-file.c,v
retrieving revision 1.35
diff -u -p -r1.35 e-cal-backend-file.c
--- backends/file/e-cal-backend-file.c	17 Aug 2004 14:32:39 -0000	1.35
+++ backends/file/e-cal-backend-file.c	10 Nov 2004 17:00:13 -0000
@@ -997,6 +997,17 @@ e_cal_backend_file_get_default_object (E
 	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 (ECalBacke
 	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 (ECalBacke
 		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 (ECalBacke
 			if (!icalcomp)
 				return GNOME_Evolution_Calendar_ObjectNotFound;
 
-			comp = e_cal_component_new ();
-			free_comp = TRUE;
-			e_cal_component_set_icalcomponent (comp, icalcomp);
-		}
-	} else
-		comp = obj_data->full_object;
-	
-	if (!comp)
-		return GNOME_Evolution_Calendar_ObjectNotFound;
+			*object = g_strdup (icalcomponent_as_ical_string (icalcomp));
 
-	*object = e_cal_component_get_as_string (comp);
+			icalcomponent_free (icalcomp);
+		}
+	} else {
+		if (g_hash_table_size (obj_data->recurrences) > 0) {
+			icalcomponent *icalcomp;
 
-	if (free_comp)
-		g_object_unref (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)));
+
+			/* 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: libecal/e-cal.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/libecal/e-cal.c,v
retrieving revision 1.75.2.3
diff -u -p -r1.75.2.3 e-cal.c
--- libecal/e-cal.c	7 Oct 2004 14:21:30 -0000	1.75.2.3
+++ libecal/e-cal.c	10 Nov 2004 17:00:14 -0000
@@ -2368,9 +2368,9 @@ e_cal_get_default_object (ECal *ecal, ic
  * 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.
@@ -2380,7 +2380,6 @@ e_cal_get_default_object (ECal *ecal, ic
 gboolean
 e_cal_get_object (ECal *ecal, const char *uid, const char *rid, icalcomponent **icalcomp, GError **error)
 {
-
 	ECalPrivate *priv;
 	CORBA_Environment ev;
 	ECalendarStatus status;
@@ -2433,9 +2432,164 @@ e_cal_get_object (ECal *ecal, const char
         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);
 
@@ -2887,30 +3041,32 @@ generate_instances (ECal *ecal, time_t s
 
 	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)
-		query = g_strdup_printf ("(and (occur-in-time-range? (make-time \"%s\") (make-time \"%s\")) (uid? \"%s\"))",
-					 iso_start, iso_end, uid);
-	else
+	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;
+		}
+
 		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: libecal/e-cal.h
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/libecal/e-cal.h,v
retrieving revision 1.19
diff -u -p -r1.19 e-cal.h
--- libecal/e-cal.h	2 Jun 2004 16:15:00 -0000	1.19
+++ libecal/e-cal.h	10 Nov 2004 17:00:14 -0000
@@ -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);


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