From 31eb98be3b45881d6208b58982d42aa575e67a1f Mon Sep 17 00:00:00 2001 From: Rodrigo Moya Date: Mon, 2 Aug 2004 07:33:38 +0000 Subject: Fixes #57622 2004-07-30 Rodrigo Moya 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. svn path=/trunk/; revision=26790 --- calendar/ChangeLog | 31 ++++++ calendar/gui/e-cal-list-view.c | 1 + calendar/gui/e-cal-model-calendar.c | 20 +++- calendar/gui/e-cal-model.c | 205 +++++++++++++++++++++++++++--------- calendar/gui/e-cal-model.h | 16 ++- calendar/gui/e-calendar-view.c | 16 ++- calendar/gui/e-day-view.c | 2 + calendar/gui/e-week-view.c | 2 + 8 files changed, 224 insertions(+), 69 deletions(-) diff --git a/calendar/ChangeLog b/calendar/ChangeLog index 6487a72351..49816845e4 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,34 @@ +2004-07-30 Rodrigo Moya + + 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-29 JP Rosevear * gui/e-calendar-view.c: creating new items no longer needs to be diff --git a/calendar/gui/e-cal-list-view.c b/calendar/gui/e-cal-list-view.c index ab1feefa7c..db194895fd 100644 --- a/calendar/gui/e-cal-list-view.c +++ b/calendar/gui/e-cal-list-view.c @@ -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)) { diff --git a/calendar/gui/e-cal-model-calendar.c b/calendar/gui/e-cal-model-calendar.c index 3649352372..4754927bbd 100644 --- a/calendar/gui/e-cal-model-calendar.c +++ b/calendar/gui/e-cal-model-calendar.c @@ -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, int row) 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 : diff --git a/calendar/gui/e-cal-model.c b/calendar/gui/e-cal-model.c index e5f0f8c418..64b8d6e328 100644 --- a/calendar/gui/e-cal-model.c +++ b/calendar/gui/e-cal-model.c @@ -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, ECalModelClass *klass) 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, ECalModelComponent *comp_data) 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; @@ -1036,6 +1045,34 @@ e_cal_model_set_component_kind (ECalModel *model, icalcomponent_kind kind) priv->kind = kind; } +/** + * 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 */ @@ -1263,6 +1300,36 @@ get_position_in_array (GPtrArray *objects, gpointer item) 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 *query, GList *objects, gpointer user_data 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 *query, GList *objects, gpointer user_d 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; - comp_data = search_by_uid_and_client (priv, e_cal_view_get_client (query), icalcomponent_get_uid (l->data)); - if (!comp_data) - continue; + /* 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; + + 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 *query, GList *uids, gpointer user_data) 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; + /* 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); - 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 *client, gboolean do_query) { ECalModelPrivate *priv; ECalModelClient *client_data; - ECal *existing_client; priv = model->priv; diff --git a/calendar/gui/e-cal-model.h b/calendar/gui/e-cal-model.h index 846d7b4acd..69feef8842 100644 --- a/calendar/gui/e-cal-model.h +++ b/calendar/gui/e-cal-model.h @@ -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 (void); 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_default_category (ECalModel 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_range (ECalModel 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); diff --git a/calendar/gui/e-calendar-view.c b/calendar/gui/e-calendar-view.c index e95bc458ff..0cb5cb9f3d 100644 --- a/calendar/gui/e-calendar-view.c +++ b/calendar/gui/e-calendar-view.c @@ -910,17 +910,13 @@ e_calendar_view_delete_selected_occurrence (ECalendarView *cal_view) 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); } diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c index cf60e91fcc..4830bbda89 100644 --- a/calendar/gui/e-day-view.c +++ b/calendar/gui/e-day-view.c @@ -4131,6 +4131,8 @@ e_day_view_add_event (ECalComponent *comp, 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. */ diff --git a/calendar/gui/e-week-view.c b/calendar/gui/e-week-view.c index d53918ae5e..ee884db3de 100644 --- a/calendar/gui/e-week-view.c +++ b/calendar/gui/e-week-view.c @@ -2437,6 +2437,8 @@ e_week_view_add_event (ECalComponent *comp, 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; -- cgit