Re: [evolution-patches] calendar patch for #57622



On Thu, 2004-07-29 at 13:46 -0400, JP Rosevear wrote:
> On Thu, 2004-07-29 at 11:44 +0200, Rodrigo Moya wrote:
> > 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?
> 
> The only problem I see is that "Delete this Occurrence" in the list view
> adds an exdate of 1/1/1970 instead of the correct date.
> 
right, we were using in that function the ECalViewEvent's start time,
which was only filled in in the day and week views. The attached patch
makes all views fill in the ECalModelComponent's instance_start, and
that is what is used.
-- 
Rodrigo Moya <rodrigo novell com>
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/calendar/ChangeLog,v
retrieving revision 1.2465
diff -u -p -r1.2465 ChangeLog
--- ChangeLog	30 Jul 2004 07:37:02 -0000	1.2465
+++ ChangeLog	30 Jul 2004 11:56:18 -0000
@@ -1,3 +1,34 @@
+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.
+
+	* gui/e-week-view.c (e_week_view_add_event):
+	* gui/e-day-view.c (e_day_view_add_event): fill in the instance's
+	start and end times in the ECalModelComponent struct.
+
+	* gui/e-calendar-view.c (e_calendar_view_delete_selected_occurrence):
+	use the instance_start field to retrieve the RECUR-ID, now that all the
+	views fill it in.
+
 2004-07-28  Larry Ewing  <lewing novell com>
 
 	* gui/dialogs/calendar-setup.c (dialog_hide_unused_options): hide
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	30 Jul 2004 11:56:19 -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	30 Jul 2004 11:56:19 -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	30 Jul 2004 11:56:20 -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	30 Jul 2004 11:56:20 -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);
Index: gui/e-calendar-view.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-calendar-view.c,v
retrieving revision 1.60
diff -u -p -r1.60 e-calendar-view.c
--- gui/e-calendar-view.c	14 Jul 2004 02:20:55 -0000	1.60
+++ gui/e-calendar-view.c	30 Jul 2004 11:56:20 -0000
@@ -910,17 +910,13 @@ e_calendar_view_delete_selected_occurren
 			return;
 		}
 
-		/* get the RECUR-ID from the start date */
+		/* get the RECUR-ID from the instance start date */
 		e_cal_component_get_dtstart (comp, &dt);
-		if (dt.value) {
-			if (e_cal_get_timezone (event->comp_data->client, dt.tzid, &zone, NULL)) {
-				rid = icaltime_as_ical_string (
-					icaltime_from_timet_with_zone (event->start, TRUE, zone));
-			} else {
-				rid = icaltime_as_ical_string (
-					icaltime_from_timet (event->start, TRUE));
-			}
-		}
+		if (e_cal_get_timezone (event->comp_data->client, dt.tzid, &zone, NULL)) {
+			rid = icaltime_as_ical_string (
+				icaltime_from_timet_with_zone (event->comp_data->instance_start, TRUE, zone));
+		} else
+			rid = icaltime_as_ical_string (icaltime_from_timet (event->comp_data->instance_start, TRUE));
 
 		e_cal_component_free_datetime (&dt);
 	}
Index: gui/e-day-view.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-day-view.c,v
retrieving revision 1.250
diff -u -p -r1.250 e-day-view.c
--- gui/e-day-view.c	16 Jul 2004 14:30:49 -0000	1.250
+++ gui/e-day-view.c	30 Jul 2004 11:56:24 -0000
@@ -4131,6 +4131,8 @@ e_day_view_add_event (ECalComponent *com
 	event.start = start;
 	event.end = end;
 	event.canvas_item = NULL;
+	event.comp_data->instance_start = start;
+	event.comp_data->instance_end = end;
 
 	/* Calculate the start & end minute, relative to the top of the
 	   display. */
Index: gui/e-week-view.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-week-view.c,v
retrieving revision 1.220
diff -u -p -r1.220 e-week-view.c
--- gui/e-week-view.c	27 Jul 2004 02:29:11 -0000	1.220
+++ gui/e-week-view.c	30 Jul 2004 11:56:26 -0000
@@ -2437,6 +2437,8 @@ e_week_view_add_event (ECalComponent *co
 	event.end = end;
 	event.spans_index = 0;
 	event.num_spans = 0;
+	event.comp_data->instance_start = start;
+	event.comp_data->instance_end = end;
 
 	event.start_minute = start_tt.hour * 60 + start_tt.minute;
 	event.end_minute = end_tt.hour * 60 + end_tt.minute;


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