From 642d32d63f226cd1ba049a9d979132e1a1cef94d Mon Sep 17 00:00:00 2001 From: Damon Chaplin Date: Tue, 3 Jul 2001 04:21:37 +0000 Subject: cal-client/cal-client.[hc] cal-util/cal-component.c 2001-07-03 Damon Chaplin * cal-client/cal-client.[hc] * cal-util/cal-component.c * cal-util/cal-recur.[hc] * cal-util/test-recur.c * cal-util/timeutil.c * gui/calendar-config.c * gui/calendar-model.[hc] * gui/comp-util.[hc] * gui/e-calendar-table.c * gui/e-day-view-main-item.c * gui/e-day-view-top-item.c * gui/e-day-view.[hc] * gui/e-itip-control.c * gui/e-timezone-entry.[hc] * gui/e-week-view.[hc] * gui/gnome-cal.[hc] * gui/goto.c * gui/tag-calendar.[hc] * gui/dialogs/cal-prefs-dialog.c * gui/dialogs/comp-editor-page.[hc] * gui/dialogs/comp-editor-util.[hc] * gui/dialogs/comp-editor.c * gui/dialogs/e-timezone-dialog.[hc] * gui/dialogs/event-page.c * gui/dialogs/meeting-page.c * gui/dialogs/recurrence-page.c * gui/dialogs/task-details-page.c * gui/dialogs/task-details-page.glade * gui/dialogs/task-page.c * idl/evolution-calendar.idl * pcs/cal-backend-file.c * pcs/cal-backend.c * pcs/cal-backend.h * pcs/cal.c * pcs/query.c: timezone changes everywhere. There's still quite a few things to update, and its not working well at present. svn path=/trunk/; revision=10729 --- calendar/pcs/cal-backend-file.c | 119 +++++++++++++++++++++++++++++++++++++--- calendar/pcs/cal-backend.c | 23 ++++++++ calendar/pcs/cal-backend.h | 3 + calendar/pcs/cal.c | 30 ++++++++++ calendar/pcs/query.c | 23 +++++++- 5 files changed, 190 insertions(+), 8 deletions(-) (limited to 'calendar/pcs') diff --git a/calendar/pcs/cal-backend-file.c b/calendar/pcs/cal-backend-file.c index 79a6018ec0..17765f918c 100644 --- a/calendar/pcs/cal-backend-file.c +++ b/calendar/pcs/cal-backend-file.c @@ -73,6 +73,7 @@ static gboolean cal_backend_file_is_loaded (CalBackend *backend); static int cal_backend_file_get_n_objects (CalBackend *backend, CalObjType type); static char *cal_backend_file_get_object (CalBackend *backend, const char *uid); +static char *cal_backend_file_get_timezone_object (CalBackend *backend, const char *tzid); static CalObjType cal_backend_file_get_type_by_uid (CalBackend *backend, const char *uid); static GList *cal_backend_file_get_uids (CalBackend *backend, CalObjType type); static GList *cal_backend_file_get_objects_in_range (CalBackend *backend, CalObjType type, @@ -148,6 +149,7 @@ cal_backend_file_class_init (CalBackendFileClass *class) backend_class->is_loaded = cal_backend_file_is_loaded; backend_class->get_n_objects = cal_backend_file_get_n_objects; backend_class->get_object = cal_backend_file_get_object; + backend_class->get_timezone_object = cal_backend_file_get_timezone_object; backend_class->get_type_by_uid = cal_backend_file_get_type_by_uid; backend_class->get_uids = cal_backend_file_get_uids; backend_class->get_objects_in_range = cal_backend_file_get_objects_in_range; @@ -812,6 +814,40 @@ cal_backend_file_get_object (CalBackend *backend, const char *uid) return cal_component_get_as_string (comp); } +/* Get_object handler for the file backend */ +static char * +cal_backend_file_get_timezone_object (CalBackend *backend, const char *tzid) +{ + CalBackendFile *cbfile; + CalBackendFilePrivate *priv; + icaltimezone *icaltz; + icalcomponent *icalcomp; + char *ical_string; + + cbfile = CAL_BACKEND_FILE (backend); + priv = cbfile->priv; + + g_return_val_if_fail (tzid != NULL, NULL); + + g_return_val_if_fail (priv->icalcomp != NULL, NULL); + g_assert (priv->comp_uid_hash != NULL); + + icaltz = icalcomponent_get_timezone (priv->icalcomp, tzid); + if (!icaltz) + return NULL; + + icalcomp = icaltimezone_get_component (icaltz); + if (!icalcomp) + return NULL; + + ical_string = icalcomponent_as_ical_string (icalcomp); + /* We dup the string; libical owns that memory. */ + if (ical_string) + return g_strdup (ical_string); + else + return NULL; +} + static CalObjType cal_backend_file_get_type_by_uid (CalBackend *backend, const char *uid) { @@ -910,6 +946,20 @@ add_instance (CalComponent *comp, time_t start, time_t end, gpointer data) return FALSE; } + +/* FIXME */ +static icaltimezone* +resolve_tzid (const char *tzid, gpointer data) +{ + icalcomponent *vcalendar_comp = data; + + if (!strcmp (tzid, "UTC")) + return icaltimezone_get_utc_timezone (); + else + return icalcomponent_get_timezone (vcalendar_comp, tzid); +} + + /* Populates a hash table with the UIDs of the components that occur or recur * within a specific time range. */ @@ -920,9 +970,17 @@ get_instances_in_range (GHashTable *uid_hash, GList *components, time_t start, t for (l = components; l; l = l->next) { CalComponent *comp; + icalcomponent *icalcomp, *vcalendar_comp; comp = CAL_COMPONENT (l->data); - cal_recur_generate_instances (comp, start, end, add_instance, uid_hash); + + /* Get the parent VCALENDAR component, so we can resolve + TZIDs. */ + icalcomp = cal_component_get_icalcomponent (comp); + vcalendar_comp = icalcomponent_get_parent (icalcomp); + g_assert (vcalendar_comp != NULL); + + cal_recur_generate_instances (comp, start, end, add_instance, uid_hash, resolve_tzid, vcalendar_comp); } } @@ -1346,7 +1404,7 @@ generate_alarms_for_comp (CalComponent *comp, time_t start, time_t end) aod.end = end; aod.triggers = NULL; aod.n_triggers = 0; - cal_recur_generate_instances (comp, alarm_start, alarm_end, add_alarm_occurrences_cb, &aod); + cal_recur_generate_instances (comp, alarm_start, alarm_end, add_alarm_occurrences_cb, &aod, resolve_tzid, NULL); /* We add the ABSOLUTE triggers separately */ generate_absolute_triggers (comp, &aod); @@ -1564,7 +1622,7 @@ cal_backend_file_update_object (CalBackend *backend, const char *uid, const char { CalBackendFile *cbfile; CalBackendFilePrivate *priv; - icalcomponent *icalcomp; + icalcomponent *icalcomp, *vcalendar_comp = NULL; icalcomponent_kind kind; CalComponent *old_comp; CalComponent *comp; @@ -1580,16 +1638,51 @@ cal_backend_file_update_object (CalBackend *backend, const char *uid, const char /* Pull the component from the string and ensure that it is sane */ + fprintf (stderr, "cal_backend_file: Parsing string:\n%s\n", calobj); icalcomp = icalparser_parse_string ((char *) calobj); if (!icalcomp) return FALSE; + fprintf (stderr, "cal_backend_file: Parsed OK.\n"); + kind = icalcomponent_isa (icalcomp); - if (!(kind == ICAL_VEVENT_COMPONENT - || kind == ICAL_VTODO_COMPONENT - || kind == ICAL_VJOURNAL_COMPONENT)) { + if (kind == ICAL_VCALENDAR_COMPONENT) { + int num_found = 0; + icalcomponent_kind child_kind; + icalcomponent *subcomp; + + fprintf (stderr, "cal_backend_file: VCALENDAR found\n"); + + /* We have a VCALENDAR containing the VEVENT/VTODO and the + related timezone data, so we have to step through it to + find the actual VEVENT/VTODO component. */ + vcalendar_comp = icalcomp; + + subcomp = icalcomponent_get_first_component (vcalendar_comp, + ICAL_ANY_COMPONENT); + while (subcomp) { + child_kind = icalcomponent_isa (subcomp); + if (kind == ICAL_VEVENT_COMPONENT + || kind == ICAL_VTODO_COMPONENT + || kind == ICAL_VJOURNAL_COMPONENT) { + icalcomp = subcomp; + num_found++; + } + subcomp = icalcomponent_get_next_component (vcalendar_comp, + ICAL_ANY_COMPONENT); + } + + /* If we didn't find exactly 1 VEVENT/VTODO it is an error. */ + if (num_found != 1) { + icalcomponent_free (icalcomp); + return FALSE; + } + + } else if (!(kind == ICAL_VEVENT_COMPONENT + || kind == ICAL_VTODO_COMPONENT + || kind == ICAL_VJOURNAL_COMPONENT)) { /* We don't support this type of component */ icalcomponent_free (icalcomp); return FALSE; @@ -1618,7 +1711,19 @@ cal_backend_file_update_object (CalBackend *backend, const char *uid, const char if (old_comp) remove_component (cbfile, old_comp); - add_component (cbfile, comp, TRUE); + if (kind == ICAL_VCALENDAR_COMPONENT) { + /* If we have a VCALENDAR component with child VTIMEZONEs and + the VEVENT/VTODO, we have to merge it into the existing + VCALENDAR, resolving any conflicting TZIDs. */ + icalcomponent_merge_component (priv->icalcomp, vcalendar_comp); + + /* Now we add the component to our local cache, but we pass + FALSE as the last argument, since we have already added + the libical component when merging above.*/ + add_component (cbfile, comp, FALSE); + } else { + add_component (cbfile, comp, TRUE); + } mark_dirty (cbfile); diff --git a/calendar/pcs/cal-backend.c b/calendar/pcs/cal-backend.c index 2b14e291db..a9eae9f212 100644 --- a/calendar/pcs/cal-backend.c +++ b/calendar/pcs/cal-backend.c @@ -138,6 +138,7 @@ cal_backend_class_init (CalBackendClass *class) class->is_loaded = NULL; class->get_n_objects = NULL; class->get_object = NULL; + class->get_timezone_object = NULL; class->get_type_by_uid = NULL; class->get_uids = NULL; class->get_objects_in_range = NULL; @@ -280,6 +281,28 @@ cal_backend_get_object (CalBackend *backend, const char *uid) return (* CLASS (backend)->get_object) (backend, uid); } +/** + * cal_backend_get_timezone_object: + * @backend: A calendar backend. + * @tzid: Unique identifier for a calendar VTIMEZONE object. + * + * Queries a calendar backend for a VTIMEZONE calendar object based on its + * unique TZID identifier. + * + * Return value: The string representation of a VTIMEZONE component, or NULL + * if no VTIMEZONE object had the specified TZID. + **/ +char * +cal_backend_get_timezone_object (CalBackend *backend, const char *tzid) +{ + g_return_val_if_fail (backend != NULL, NULL); + g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL); + g_return_val_if_fail (tzid != NULL, NULL); + + g_assert (CLASS (backend)->get_timezone_object != NULL); + return (* CLASS (backend)->get_timezone_object) (backend, tzid); +} + /** * cal_backend_get_uids: * @backend: A calendar backend. diff --git a/calendar/pcs/cal-backend.h b/calendar/pcs/cal-backend.h index c59be8d808..e5d475452b 100644 --- a/calendar/pcs/cal-backend.h +++ b/calendar/pcs/cal-backend.h @@ -84,6 +84,7 @@ struct _CalBackendClass { /* General object acquirement and information related virtual methods */ int (* get_n_objects) (CalBackend *backend, CalObjType type); char *(* get_object) (CalBackend *backend, const char *uid); + char *(* get_timezone_object) (CalBackend *backend, const char *tzid); CalObjType(* get_type_by_uid) (CalBackend *backend, const char *uid); GList *(* get_uids) (CalBackend *backend, CalObjType type); @@ -122,6 +123,8 @@ int cal_backend_get_n_objects (CalBackend *backend, CalObjType type); char *cal_backend_get_object (CalBackend *backend, const char *uid); +char *cal_backend_get_timezone_object (CalBackend *backend, const char *tzid); + GList *cal_backend_get_uids (CalBackend *backend, CalObjType type); GList *cal_backend_get_objects_in_range (CalBackend *backend, CalObjType type, diff --git a/calendar/pcs/cal.c b/calendar/pcs/cal.c index ab815cb3e2..9cd5b5b219 100644 --- a/calendar/pcs/cal.c +++ b/calendar/pcs/cal.c @@ -424,6 +424,35 @@ impl_Cal_get_query (PortableServer_Servant servant, return query_copy; } +/* Cal::get_timezone_object method */ +static GNOME_Evolution_Calendar_CalObj +impl_Cal_get_timezone_object (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CalTimezoneObjUID tzid, + CORBA_Environment *ev) +{ + Cal *cal; + CalPrivate *priv; + char *calobj; + + cal = CAL (bonobo_object_from_servant (servant)); + priv = cal->priv; + + calobj = cal_backend_get_timezone_object (priv->backend, tzid); + + if (calobj) { + CORBA_char *calobj_copy; + + calobj_copy = CORBA_string_dup (calobj); + g_free (calobj); + return calobj_copy; + } else { + CORBA_exception_set (ev, CORBA_USER_EXCEPTION, + ex_GNOME_Evolution_Calendar_Cal_NotFound, + NULL); + return NULL; + } +} + /** * cal_construct: * @cal: A calendar client interface. @@ -556,6 +585,7 @@ cal_class_init (CalClass *klass) epv->_get_uri = impl_Cal_get_uri; epv->countObjects = impl_Cal_get_n_objects; epv->getObject = impl_Cal_get_object; + epv->getTimezoneObject = impl_Cal_get_timezone_object; epv->getUIDs = impl_Cal_get_uids; epv->getChanges = impl_Cal_get_changes; epv->getObjectsInRange = impl_Cal_get_objects_in_range; diff --git a/calendar/pcs/query.c b/calendar/pcs/query.c index ed391ee667..237b2524e1 100644 --- a/calendar/pcs/query.c +++ b/calendar/pcs/query.c @@ -442,6 +442,20 @@ instance_occur_cb (CalComponent *comp, time_t start, time_t end, gpointer data) return FALSE; } +/* FIXME. This is the same as the function in cal-backend-file.c. It needs + to be added to the backend interface, I think. */ +static icaltimezone* +resolve_tzid (const char *tzid, gpointer data) +{ + icalcomponent *vcalendar_comp = data; + + if (!strcmp (tzid, "UTC")) + return icaltimezone_get_utc_timezone (); + else + return icalcomponent_get_timezone (vcalendar_comp, tzid); +} + + /* (occur-in-time-range? START END) * * START - time_t, start of the time range @@ -459,6 +473,7 @@ func_occur_in_time_range (ESExp *esexp, int argc, ESExpResult **argv, void *data time_t start, end; gboolean occurs; ESExpResult *result; + icalcomponent *icalcomp, *vcalendar_comp; query = QUERY (data); priv = query->priv; @@ -490,7 +505,13 @@ func_occur_in_time_range (ESExp *esexp, int argc, ESExpResult **argv, void *data /* See if there is at least one instance in that range */ occurs = FALSE; - cal_recur_generate_instances (comp, start, end, instance_occur_cb, &occurs); + + /* Get the parent VCALENDAR component, so we can resolve TZIDs. */ + icalcomp = cal_component_get_icalcomponent (comp); + vcalendar_comp = icalcomponent_get_parent (icalcomp); + g_assert (vcalendar_comp != NULL); + + cal_recur_generate_instances (comp, start, end, instance_occur_cb, &occurs, resolve_tzid, vcalendar_comp); result = e_sexp_result_new (esexp, ESEXP_RES_BOOL); result->value.bool = occurs; -- cgit v1.2.3