[evolution-patches] calendar patch for #57622



This fixes #57622. I don't like very much to remove all recurrences and
re-add them again in the objects_modified_cb, but trying to update every
individual recurrence (and removing the ones that don't apply anymore as
well as adding the new ones) might get the code too complicated for 2.0
I guess. With the attached patch, when you update a recurring
appointment, the recurrences disappear from the list view and show up
again at the end of the list, which might be confusing. Any suggestion?

cheers
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/calendar/ChangeLog,v
retrieving revision 1.2464
diff -u -p -r1.2464 ChangeLog
--- ChangeLog	28 Jul 2004 18:03:32 -0000	1.2464
+++ ChangeLog	29 Jul 2004 09:37:44 -0000
@@ -1,3 +1,26 @@
+2004-07-29  Rodrigo Moya <rodrigo novell com>
+
+	Fixes #57622
+
+	* gui/e-cal-model.h: added ECalModelFlags enum type.
+
+	* gui/e-cal-model.c (e_cal_model_set_flags, e_cal_model_get_flags):
+	new functions.
+	(e_cal_model_init): initialize the new internal field to keep the flags.
+	(e_cal_view_objects_added_cb): expand recurrences if the model flags
+	contain the EXPAND_RECUR bit.
+	(e_cal_view_objects_modified_cb): if EXPAND_RECUR is on, remove all
+	recurrences and regenerate them.
+	(e_cal_view_objects_removed_cb): remove all instances for given UIDs.
+	(add_new_client): killed warning.
+	(get_dtstart): use the instance_start time when dealing with recurrences.
+
+	* gui/e-cal-model-calendar.c (get_dtend): use the instance_end time
+	when dealing with recurrences.
+
+	* gui/e-cal-list-view.c (e_cal_list_view_new): set the EXPAND_RECUR
+	flag on the model for the list view.
+
 2004-07-27  JP Rosevear  <jpr novell com>
 
 	Fixes #62006
Index: gui/e-cal-list-view.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-cal-list-view.c,v
retrieving revision 1.9
diff -u -p -r1.9 e-cal-list-view.c
--- gui/e-cal-list-view.c	3 May 2004 18:23:10 -0000	1.9
+++ gui/e-cal-list-view.c	29 Jul 2004 09:37:44 -0000
@@ -318,6 +318,7 @@ e_cal_list_view_new (void)
 	ECalModel *model;
 	
 	model = E_CAL_MODEL (e_cal_model_calendar_new ());
+	e_cal_model_set_flags (model, E_CAL_MODEL_FLAGS_EXPAND_RECURRENCES);
 
 	cal_list_view = g_object_new (e_cal_list_view_get_type (), "model", model, NULL);
 	if (!e_cal_list_view_construct (cal_list_view)) {
Index: gui/e-cal-model-calendar.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-cal-model-calendar.c,v
retrieving revision 1.12
diff -u -p -r1.12 e-cal-model-calendar.c
--- gui/e-cal-model-calendar.c	13 Jul 2004 11:07:19 -0000	1.12
+++ gui/e-cal-model-calendar.c	29 Jul 2004 09:37:44 -0000
@@ -112,22 +112,34 @@ ecmc_column_count (ETableModel *etm)
 }
 
 static ECellDateEditValue *
-get_dtend (ECalModelComponent *comp_data)
+get_dtend (ECalModel *model, ECalModelComponent *comp_data)
 {
 	struct icaltimetype tt_end;
 
 	if (!comp_data->dtend) {
 		icaltimezone *zone;
+		gboolean got_zone = FALSE;
 
 		tt_end = icalcomponent_get_dtend (comp_data->icalcomp);
+		if (icaltime_get_tzid (tt_end)
+		    && e_cal_get_timezone (comp_data->client, icaltime_get_tzid (tt_end), &zone, NULL))
+			got_zone = TRUE;
+
+		if ((e_cal_model_get_flags (model) & E_CAL_MODEL_FLAGS_EXPAND_RECURRENCES) &&
+		    (e_cal_util_component_has_recurrences (comp_data->icalcomp))) {
+			if (got_zone)
+				tt_end = icaltime_from_timet_with_zone (comp_data->instance_end, tt_end.is_date, zone);
+			else
+				tt_end = icaltime_from_timet (comp_data->instance_end, tt_end.is_date);
+		}
+
 		if (!icaltime_is_valid_time (tt_end))
 			return NULL;
 
 		comp_data->dtend = g_new0 (ECellDateEditValue, 1);
 		comp_data->dtend->tt = tt_end;
 
-		if (icaltime_get_tzid (tt_end)
-		    && e_cal_get_timezone (comp_data->client, icaltime_get_tzid (tt_end), &zone, NULL)) 
+		if (got_zone)
 			comp_data->dtend->zone = zone;
 		else
 			comp_data->dtend->zone = NULL;
@@ -192,7 +204,7 @@ ecmc_value_at (ETableModel *etm, int col
 
 	switch (col) {
 	case E_CAL_MODEL_CALENDAR_FIELD_DTEND :
-		return get_dtend (comp_data);
+		return get_dtend (model, comp_data);
 	case E_CAL_MODEL_CALENDAR_FIELD_LOCATION :
 		return get_location (comp_data);
 	case E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY :
Index: gui/e-cal-model.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-cal-model.c,v
retrieving revision 1.41
diff -u -p -r1.41 e-cal-model.c
--- gui/e-cal-model.c	28 Jul 2004 18:03:32 -0000	1.41
+++ gui/e-cal-model.c	29 Jul 2004 09:37:45 -0000
@@ -53,6 +53,7 @@ struct _ECalModelPrivate {
 	GPtrArray *objects;
 
 	icalcomponent_kind kind;
+	ECalModelFlags flags;
 	icaltimezone *zone;
 
 	/* The time range to display */
@@ -174,6 +175,7 @@ e_cal_model_init (ECalModel *model, ECal
 
 	priv->objects = g_ptr_array_new ();
 	priv->kind = ICAL_NO_COMPONENT;
+	priv->flags = 0;
 
 	priv->accounts = itip_addresses_get ();
 
@@ -400,21 +402,28 @@ get_dtstart (ECalModel *model, ECalModel
 
 	if (!comp_data->dtstart) {
 		icaltimezone *zone;
-		icalproperty *prop;
+		gboolean got_zone = FALSE;
 
-		prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_DTSTART_PROPERTY);
-		if (!prop)
-			return NULL;
+		tt_start = icalcomponent_get_dtstart (comp_data->icalcomp);
+		if (icaltime_get_tzid (tt_start)
+		    && e_cal_get_timezone (comp_data->client, icaltime_get_tzid (tt_start), &zone, NULL))
+			got_zone = TRUE;
+
+		if ((priv->flags & E_CAL_MODEL_FLAGS_EXPAND_RECURRENCES) &&
+		    (e_cal_util_component_has_recurrences (comp_data->icalcomp))) {
+			if (got_zone)
+				tt_start = icaltime_from_timet_with_zone (comp_data->instance_start, tt_start.is_date, zone);
+			else
+				tt_start = icaltime_from_timet (comp_data->instance_start, tt_start.is_date);
+		}
 
-		tt_start = icalproperty_get_dtstart (prop);
 		if (!icaltime_is_valid_time (tt_start))
 			return NULL;
 
 		comp_data->dtstart = g_new0 (ECellDateEditValue, 1);
 		comp_data->dtstart->tt = tt_start;
 
-		if (icaltime_get_tzid (tt_start)
-		    && e_cal_get_timezone (comp_data->client, icaltime_get_tzid (tt_start), &zone, NULL)) 
+		if (got_zone)
 			comp_data->dtstart->zone = zone;
 		else
 			comp_data->dtstart->zone = NULL;
@@ -1037,6 +1046,34 @@ e_cal_model_set_component_kind (ECalMode
 }
 
 /**
+ * e_cal_model_get_flags
+ */
+ECalModelFlags
+e_cal_model_get_flags (ECalModel *model)
+{
+	ECalModelPrivate *priv;
+
+	g_return_val_if_fail (E_IS_CAL_MODEL (model), E_CAL_MODEL_FLAGS_INVALID);
+
+	priv = model->priv;
+	return priv->flags;
+}
+
+/**
+ * e_cal_model_set_flags
+ */
+void
+e_cal_model_set_flags (ECalModel *model, ECalModelFlags flags)
+{
+	ECalModelPrivate *priv;
+
+	g_return_if_fail (E_IS_CAL_MODEL (model));
+
+	priv = model->priv;
+	priv->flags = flags;
+}
+
+/**
  * e_cal_model_get_timezone
  */
 icaltimezone *
@@ -1263,6 +1300,36 @@ get_position_in_array (GPtrArray *object
 	return -1;
 }
 
+typedef struct {
+	ECal *client;
+	ECalView *query;
+	ECalModel *model;
+	icalcomponent *icalcomp;
+} RecurrenceExpansionData;
+
+static gboolean
+add_instance_cb (ECalComponent *comp, time_t instance_start, time_t instance_end, gpointer user_data)
+{
+	ECalModelComponent *comp_data;
+	ECalModelPrivate *priv;
+	RecurrenceExpansionData *rdata = user_data;
+
+	priv = rdata->model->priv;
+
+	e_table_model_pre_change (E_TABLE_MODEL (rdata->model));
+
+	comp_data = g_new0 (ECalModelComponent, 1);
+	comp_data->client = g_object_ref (e_cal_view_get_client (rdata->query));
+	comp_data->icalcomp = icalcomponent_new_clone (rdata->icalcomp);
+	comp_data->instance_start = instance_start;
+	comp_data->instance_end = instance_end;
+
+	g_ptr_array_add (priv->objects, comp_data);
+	e_table_model_row_inserted (E_TABLE_MODEL (rdata->model), priv->objects->len - 1);
+
+	return TRUE;
+}
+
 static void
 e_cal_view_objects_added_cb (ECalView *query, GList *objects, gpointer user_data)
 {
@@ -1273,17 +1340,30 @@ e_cal_view_objects_added_cb (ECalView *q
 	priv = model->priv;
 
 	for (l = objects; l; l = l->next) {
-		ECalModelComponent *comp_data;
+		if ((priv->flags & E_CAL_MODEL_FLAGS_EXPAND_RECURRENCES) &&
+		    e_cal_util_component_has_recurrences (l->data)) {
+			RecurrenceExpansionData rdata;
+
+			rdata.client = e_cal_view_get_client (query);
+			rdata.query = query;
+			rdata.model = model;
+			rdata.icalcomp = l->data;
+			e_cal_generate_instances_for_object (rdata.client, l->data,
+							     priv->start, priv->end,
+							     (ECalRecurInstanceFn) add_instance_cb,
+							     &rdata);
+		} else {
+			ECalModelComponent *comp_data;
 
-		e_table_model_pre_change (E_TABLE_MODEL (model));
+			e_table_model_pre_change (E_TABLE_MODEL (model));
 
-		comp_data = g_new0 (ECalModelComponent, 1);
-		comp_data->client = g_object_ref (e_cal_view_get_client (query));
-		comp_data->icalcomp = icalcomponent_new_clone (l->data);
-		
-		g_ptr_array_add (priv->objects, comp_data);
+			comp_data = g_new0 (ECalModelComponent, 1);
+			comp_data->client = g_object_ref (e_cal_view_get_client (query));
+			comp_data->icalcomp = icalcomponent_new_clone (l->data);
 
-		e_table_model_row_inserted (E_TABLE_MODEL (model), priv->objects->len - 1);
+			g_ptr_array_add (priv->objects, comp_data);
+			e_table_model_row_inserted (E_TABLE_MODEL (model), priv->objects->len - 1);
+		}
 	}
 }
 
@@ -1299,38 +1379,61 @@ e_cal_view_objects_modified_cb (ECalView
 	for (l = objects; l; l = l->next) {
 		ECalModelComponent *comp_data;
 
-		e_table_model_pre_change (E_TABLE_MODEL (model));
+		if ((priv->flags & E_CAL_MODEL_FLAGS_EXPAND_RECURRENCES) &&
+		    e_cal_util_component_has_recurrences (l->data)) {
+			GList node;
+
+			/* remove all recurrences and re-add them after generating them */
+			while ((comp_data = search_by_uid_and_client (priv, e_cal_view_get_client (query),
+								      icalcomponent_get_uid (l->data)))) {
+				int pos;
 
-		comp_data = search_by_uid_and_client (priv, e_cal_view_get_client (query), icalcomponent_get_uid (l->data));
-		if (!comp_data)
-			continue;
+				pos = get_position_in_array (priv->objects, comp_data);
+		
+				g_ptr_array_remove (priv->objects, comp_data);
+				free_comp_data (comp_data);
+		
+				e_table_model_row_deleted (E_TABLE_MODEL (model), pos);
+			}
+
+			node.prev = node.next = NULL;
+			node.data = l->data;
+			e_cal_view_objects_added_cb (query, &node, model);
+		} else {
+			e_table_model_pre_change (E_TABLE_MODEL (model));
+
+			comp_data = search_by_uid_and_client (priv, e_cal_view_get_client (query),
+							      icalcomponent_get_uid (l->data));
+			if (!comp_data)
+				continue;
 	
-		if (comp_data->icalcomp)
-			icalcomponent_free (comp_data->icalcomp);
-		if (comp_data->dtstart) {
-			g_free (comp_data->dtstart);
-			comp_data->dtstart = NULL;
-		}
-		if (comp_data->dtend) {
-			g_free (comp_data->dtend);
-			comp_data->dtend = NULL;
-		}
-		if (comp_data->due) {
-			g_free (comp_data->due);
-			comp_data->due = NULL;
-		}
-		if (comp_data->completed) {
-			g_free (comp_data->completed);
-			comp_data->completed = NULL;
-		}
-		if (comp_data->color) {
-			g_free (comp_data->color);
-			comp_data->color = NULL;
-		}
+			if (comp_data->icalcomp)
+				icalcomponent_free (comp_data->icalcomp);
+			if (comp_data->dtstart) {
+				g_free (comp_data->dtstart);
+				comp_data->dtstart = NULL;
+			}
+			if (comp_data->dtend) {
+				g_free (comp_data->dtend);
+				comp_data->dtend = NULL;
+			}
+			if (comp_data->due) {
+				g_free (comp_data->due);
+				comp_data->due = NULL;
+			}
+			if (comp_data->completed) {
+				g_free (comp_data->completed);
+				comp_data->completed = NULL;
+			}
+			if (comp_data->color) {
+				g_free (comp_data->color);
+				comp_data->color = NULL;
+			}
 		     
-		comp_data->icalcomp = icalcomponent_new_clone (l->data);
+			comp_data->icalcomp = icalcomponent_new_clone (l->data);
 
-		e_table_model_row_changed (E_TABLE_MODEL (model), get_position_in_array (priv->objects, comp_data));
+			e_table_model_row_changed (E_TABLE_MODEL (model), get_position_in_array (priv->objects, comp_data));
+		}
 	}
 }
 
@@ -1349,16 +1452,15 @@ e_cal_view_objects_removed_cb (ECalView 
 
 		e_table_model_pre_change (E_TABLE_MODEL (model));
 		
-		comp_data = search_by_uid_and_client (priv, e_cal_view_get_client (query), l->data);
-		if (!comp_data)
-			continue;
-		
-		pos = get_position_in_array (priv->objects, comp_data);
+		/* make sure we remove all objects with this UID */
+		while ((comp_data = search_by_uid_and_client (priv, e_cal_view_get_client (query), l->data))) {
+			pos = get_position_in_array (priv->objects, comp_data);
 		
-		g_ptr_array_remove (priv->objects, comp_data);
-		free_comp_data (comp_data);
+			g_ptr_array_remove (priv->objects, comp_data);
+			free_comp_data (comp_data);
 		
-		e_table_model_row_deleted (E_TABLE_MODEL (model), pos);
+			e_table_model_row_deleted (E_TABLE_MODEL (model), pos);
+		}
 	}
 }
 
@@ -1460,7 +1562,6 @@ add_new_client (ECalModel *model, ECal *
 {
 	ECalModelPrivate *priv;
 	ECalModelClient *client_data;
-	ECal *existing_client;
 	
 	priv = model->priv;
 
Index: gui/e-cal-model.h
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-cal-model.h,v
retrieving revision 1.12
diff -u -p -r1.12 e-cal-model.h
--- gui/e-cal-model.h	14 Jul 2004 02:20:55 -0000	1.12
+++ gui/e-cal-model.h	29 Jul 2004 09:37:45 -0000
@@ -52,9 +52,16 @@ typedef enum {
 	E_CAL_MODEL_FIELD_LAST
 } ECalModelField;
 
+typedef enum {
+	E_CAL_MODEL_FLAGS_INVALID            = -1,
+	E_CAL_MODEL_FLAGS_EXPAND_RECURRENCES = 0x01
+} ECalModelFlags;
+
 typedef struct {
 	ECal *client;
 	icalcomponent *icalcomp;
+	time_t instance_start;
+	time_t instance_end;
 
 	/* private data */
 	ECellDateEditValue *dtstart;
@@ -91,6 +98,9 @@ GType               e_cal_model_get_type
 icalcomponent_kind  e_cal_model_get_component_kind             (ECalModel           *model);
 void                e_cal_model_set_component_kind             (ECalModel           *model,
 								icalcomponent_kind   kind);
+ECalModelFlags      e_cal_model_get_flags                      (ECalModel           *model);
+void                e_cal_model_set_flags                      (ECalModel           *model,
+								ECalModelFlags       flags);
 icaltimezone       *e_cal_model_get_timezone                   (ECalModel           *model);
 void                e_cal_model_set_timezone                   (ECalModel           *model,
 								icaltimezone        *zone);
@@ -99,11 +109,11 @@ void                e_cal_model_set_defa
 gboolean            e_cal_model_get_use_24_hour_format         (ECalModel           *model);
 void                e_cal_model_set_use_24_hour_format         (ECalModel           *model,
 								gboolean             use24);
-ECal          *     e_cal_model_get_default_client             (ECalModel           *model);
+ECal               *e_cal_model_get_default_client             (ECalModel           *model);
 void                e_cal_model_set_default_client             (ECalModel           *model,
 								ECal                *client);
 GList              *e_cal_model_get_client_list                (ECalModel           *model);
-ECal          *     e_cal_model_get_client_for_uri             (ECalModel           *model,
+ECal               *e_cal_model_get_client_for_uri             (ECalModel           *model,
 								const char          *uri);
 void                e_cal_model_add_client                     (ECalModel           *model,
 								ECal                *client);
@@ -116,7 +126,7 @@ void                e_cal_model_get_time
 void                e_cal_model_set_time_range                 (ECalModel           *model,
 								time_t               start,
 								time_t               end);
-const char *        e_cal_model_get_search_query               (ECalModel           *model);
+const char         *e_cal_model_get_search_query               (ECalModel           *model);
 void                e_cal_model_set_search_query               (ECalModel           *model,
 								const gchar         *sexp);
 icalcomponent      *e_cal_model_create_component_with_defaults (ECalModel           *model);


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