diff options
Diffstat (limited to 'calendar')
-rw-r--r-- | calendar/ChangeLog | 70 | ||||
-rw-r--r-- | calendar/cal-client/cal-client.c | 146 | ||||
-rw-r--r-- | calendar/cal-client/cal-client.h | 6 | ||||
-rw-r--r-- | calendar/cal-util/cal-component.c | 190 | ||||
-rw-r--r-- | calendar/cal-util/cal-component.h | 95 | ||||
-rw-r--r-- | calendar/cal-util/cal-util.c | 25 | ||||
-rw-r--r-- | calendar/cal-util/cal-util.h | 12 | ||||
-rw-r--r-- | calendar/gui/gnome-cal.c | 12 | ||||
-rw-r--r-- | calendar/idl/evolution-calendar.idl | 64 | ||||
-rw-r--r-- | calendar/pcs/cal-backend-file.c | 378 | ||||
-rw-r--r-- | calendar/pcs/cal-backend.c | 58 | ||||
-rw-r--r-- | calendar/pcs/cal-backend.h | 31 | ||||
-rw-r--r-- | calendar/pcs/cal.c | 109 |
13 files changed, 828 insertions, 368 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog index e1af0879af..5219852ecf 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,73 @@ +2000-12-18 Federico Mena Quintero <federico@helixcode.com> + + Alarm instance generation support for the Wombat. + + * idl/evolution-calendar.idl (Cal::CalAlarmInstance): Changed to + have an alarm UID, the trigger time, and the actual occurrence + time. + (Cal::CalComponentAlarms): New structure to hold a pair of a + component and its alarms that trigger in a particular range of + time. + (Cal::getAlarmsInRange): Changed to return a CalComponentAlarmsSeq. + + * cal-util/cal-component.h (CalAlarmInstance): New C-side + structure to match the one on the IDL. + (CalComponentAlarms): Ditto. + (CalAlarmAction): Renamed from CalComponentAlarmAction. + (CalAlarmTriggerType): Renamed from CalComponentAlarmTriggerType. + Encoded the START and END parameters for the RELATED parameter in + this enum, too. Added a NONE value for invalid or missing trigger + specifications. + (CalComponentAlarmTriggerRelated): Removed. + (CalAlarmTrigger): Renamed from CalComponentAlarmTrigger. Renamed + the duration/time fields to rel_duration/abs_time, respectively. + + * cal-util/cal-component.c (cal_component_alarm_get_trigger): + Changed to use the new trigger structure. + (cal_component_alarm_set_trigger): Likewise. + (cal_component_alarm_free_trigger): Removed function. + (cal_component_has_alarms): Count the elements in the + alarm_uid_hash instead of trying to fetch the first alarm subcomponent. + (cal_component_alarms_free): New function to free a + CalComponentAlarms structure. + (CalComponentAlarmPrivate): Added an uid property pointer. + (scan_alarm_property): Scan for the our extension UID property. + (cal_component_alarm_get_uid): New function. + + * pcs/cal-backend.h (CalBackendClass): Changed the signatures of + the ::get_alarms_in_range() and ::get_alarms_for_object() methods. + + * pcs/cal-backend.c (cal_backend_get_alarms_in_range): Changed + signature; use the new method. + (cal_backend_get_alarms_for_object): Likewise. + + * pcs/cal-backend-file.c (compute_alarm_range): New spiffy + function to compute a range of time for alarm occurrences. + (add_alarm_occurrences_cb): New function to add alarms for a + particular occurrence of the component. + (generate_absolute_triggers): New function to add the absolute + alarm triggers. + (generate_alarms_for_comp): New function to generate all the alarm + instances for a component. + (cal_backend_file_get_alarms_in_range): Implemented. + + * pcs/cal.c (Cal_get_alarms_in_range): Use the new CalBackend API. + (Cal_get_alarms_for_object): Likewise. + (build_alarm_instance_seq): Removed old function. + + * cal-util/cal-util.c (cal_alarm_instance_list_free): Removed + function. + + * cal-client/cal-client.c (build_component_alarms_list): New + function to demarshal the component alarms sequence. + (build_alarm_instance_list): New function to demarshal the alarm + instances sequence. + (cal_client_get_alarms_in_range): Updated for the new API. + (cal_client_get_alarms_for_object): Updated for the new API. + + * gui/gnome-cal.c: Temporary #ifdef-ing out of alarm-related stuff + to make it build. + 2000-12-15 Federico Mena Quintero <federico@helixcode.com> * cal-util/timeutil.[ch] (time_from_isodate): Removed unused diff --git a/calendar/cal-client/cal-client.c b/calendar/cal-client/cal-client.c index a75912275f..b3e8cd507d 100644 --- a/calendar/cal-client/cal-client.c +++ b/calendar/cal-client/cal-client.c @@ -622,7 +622,7 @@ cal_client_get_object (CalClient *client, const char *uid, CalComponent **comp) { CalClientPrivate *priv; CORBA_Environment ev; - GNOME_Evolution_Calendar_CalObj calobj_str; + GNOME_Evolution_Calendar_CalObj comp_str; CalClientGetStatus retval; icalcomponent *icalcomp; @@ -639,7 +639,7 @@ cal_client_get_object (CalClient *client, const char *uid, CalComponent **comp) *comp = NULL; CORBA_exception_init (&ev); - calobj_str = GNOME_Evolution_Calendar_Cal_getObject (priv->cal, (char *) uid, &ev); + comp_str = GNOME_Evolution_Calendar_Cal_getObject (priv->cal, (char *) uid, &ev); if (ev._major == CORBA_USER_EXCEPTION && strcmp (CORBA_exception_id (&ev), ex_GNOME_Evolution_Calendar_Cal_NotFound) == 0) @@ -649,8 +649,8 @@ cal_client_get_object (CalClient *client, const char *uid, CalComponent **comp) goto out; } - icalcomp = icalparser_parse_string (calobj_str); - CORBA_free (calobj_str); + icalcomp = icalparser_parse_string (comp_str); + CORBA_free (comp_str); if (!icalcomp) { retval = CAL_CLIENT_GET_SYNTAX_ERROR; @@ -1160,61 +1160,81 @@ cal_client_generate_instances (CalClient *client, CalObjType type, g_list_free (instances); } - -#if 0 -/* Translates the CORBA representation of an AlarmType */ -static enum AlarmType -uncorba_alarm_type (Evolution_Calendar_AlarmType corba_type) +/* Builds a list of CalAlarmInstance structures */ +static GSList * +build_alarm_instance_list (CalComponent *comp, GNOME_Evolution_Calendar_CalAlarmInstanceSeq *seq) { - switch (corba_type) { - case Evolution_Calendar_MAIL: - return ALARM_MAIL; + GSList *alarms; + int i; - case Evolution_Calendar_PROGRAM: - return ALARM_PROGRAM; + alarms = NULL; - case Evolution_Calendar_DISPLAY: - return ALARM_DISPLAY; + for (i = 0; i < seq->_length; i++) { + GNOME_Evolution_Calendar_CalAlarmInstance *corba_instance; + CalComponentAlarm *alarm; + const char *auid; + CalAlarmInstance *instance; - case Evolution_Calendar_AUDIO: - return ALARM_AUDIO; + corba_instance = seq->_buffer + i; - default: - g_assert_not_reached (); - return ALARM_DISPLAY; + /* Since we want the in-commponent auid, we look for the alarm + * in the component and fetch its "real" auid. + */ + + alarm = cal_component_get_alarm (comp, corba_instance->auid); + if (!alarm) + continue; + + auid = cal_component_alarm_get_uid (alarm); + cal_component_alarm_free (alarm); + + instance = g_new (CalAlarmInstance, 1); + instance->auid = auid; + instance->trigger = corba_instance->trigger; + instance->occur = corba_instance->occur; + + alarms = g_slist_prepend (alarms, instance); } + + return g_slist_reverse (alarms); } -#endif -/* Builds a GList of CalAlarmInstance structures from the CORBA sequence */ -static GList * -build_alarm_instance_list (GNOME_Evolution_Calendar_CalAlarmInstanceSeq *seq) +/* Builds a list of CalComponentAlarms structures */ +static GSList * +build_component_alarms_list (GNOME_Evolution_Calendar_CalComponentAlarmsSeq *seq) { - GList *list; + GSList *comp_alarms; int i; - /* Create the list in reverse order */ + comp_alarms = NULL; - list = NULL; for (i = 0; i < seq->_length; i++) { - GNOME_Evolution_Calendar_CalAlarmInstance *corba_ai; - CalAlarmInstance *ai; + GNOME_Evolution_Calendar_CalComponentAlarms *corba_alarms; + CalComponent *comp; + CalComponentAlarms *alarms; + icalcomponent *icalcomp; - corba_ai = &seq->_buffer[i]; - ai = g_new (CalAlarmInstance, 1); + corba_alarms = seq->_buffer + i; - ai->uid = g_strdup (corba_ai->uid); -#if 0 - ai->type = uncorba_alarm_type (corba_ai->type); -#endif - ai->trigger = corba_ai->trigger; - ai->occur = corba_ai->occur; + icalcomp = icalparser_parse_string (corba_alarms->calobj); + if (!icalcomp) + continue; + + comp = cal_component_new (); + if (!cal_component_set_icalcomponent (comp, icalcomp)) { + icalcomponent_free (icalcomp); + gtk_object_unref (GTK_OBJECT (comp)); + continue; + } + + alarms = g_new (CalComponentAlarms, 1); + alarms->comp = comp; + alarms->alarms = build_alarm_instance_list (comp, &corba_alarms->alarms); - list = g_list_prepend (list, ai); + comp_alarms = g_slist_prepend (comp_alarms, alarms); } - list = g_list_reverse (list); - return list; + return comp_alarms; } /** @@ -1226,15 +1246,16 @@ build_alarm_instance_list (GNOME_Evolution_Calendar_CalAlarmInstanceSeq *seq) * Queries a calendar for the alarms that trigger in the specified range of * time. * - * Return value: A list of #CalAlarmInstance structures. + * Return value: A list of #CalComponentAlarms structures. This should be freed + * using the cal_client_free_alarms() function. **/ -GList * +GSList * cal_client_get_alarms_in_range (CalClient *client, time_t start, time_t end) { CalClientPrivate *priv; CORBA_Environment ev; - GNOME_Evolution_Calendar_CalAlarmInstanceSeq *seq; - GList *alarms; + GNOME_Evolution_Calendar_CalComponentAlarmsSeq *seq; + GSList *alarms; g_return_val_if_fail (client != NULL, NULL); g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); @@ -1255,7 +1276,7 @@ cal_client_get_alarms_in_range (CalClient *client, time_t start, time_t end) } CORBA_exception_free (&ev); - alarms = build_alarm_instance_list (seq); + alarms = build_component_alarms_list (seq); CORBA_free (seq); return alarms; @@ -1264,10 +1285,11 @@ cal_client_get_alarms_in_range (CalClient *client, time_t start, time_t end) /** * cal_client_get_alarms_for_object: * @client: A calendar client. - * @uid: Unique identifier for a calendar object. + * @uid: Unique identifier for a calendar component. * @start: Start time for query. * @end: End time for query. - * @alarms: Return value for the list of alarm instances. + * @alarms: Return value for the component's alarm instances. Will return NULL + * if no instances occur within the specified time range. * * Queries a calendar for the alarms of a particular object that trigger in the * specified range of time. @@ -1277,12 +1299,14 @@ cal_client_get_alarms_in_range (CalClient *client, time_t start, time_t end) gboolean cal_client_get_alarms_for_object (CalClient *client, const char *uid, time_t start, time_t end, - GList **alarms) + CalComponentAlarms **alarms) { CalClientPrivate *priv; CORBA_Environment ev; - GNOME_Evolution_Calendar_CalAlarmInstanceSeq *seq; + GNOME_Evolution_Calendar_CalComponentAlarms *corba_alarms; gboolean retval; + icalcomponent *icalcomp; + CalComponent *comp; g_return_val_if_fail (client != NULL, FALSE); g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); @@ -1300,7 +1324,8 @@ cal_client_get_alarms_for_object (CalClient *client, const char *uid, CORBA_exception_init (&ev); - seq = GNOME_Evolution_Calendar_Cal_getAlarmsForObject (priv->cal, (char *) uid, start, end, &ev); + corba_alarms = GNOME_Evolution_Calendar_Cal_getAlarmsForObject (priv->cal, (char *) uid, + start, end, &ev); if (ev._major == CORBA_USER_EXCEPTION && strcmp (CORBA_exception_id (&ev), ex_GNOME_Evolution_Calendar_Cal_NotFound) == 0) goto out; @@ -1309,14 +1334,27 @@ cal_client_get_alarms_for_object (CalClient *client, const char *uid, goto out; } + icalcomp = icalparser_parse_string (corba_alarms->calobj); + if (!icalcomp) + goto out; + + comp = cal_component_new (); + if (!cal_component_set_icalcomponent (comp, icalcomp)) { + icalcomponent_free (icalcomp); + gtk_object_unref (GTK_OBJECT (comp)); + goto out; + } + retval = TRUE; - *alarms = build_alarm_instance_list (seq); - CORBA_free (seq); + + *alarms = g_new (CalComponentAlarms, 1); + (*alarms)->comp = comp; + (*alarms)->alarms = build_alarm_instance_list (comp, &corba_alarms->alarms); + CORBA_free (corba_alarms); out: CORBA_exception_free (&ev); return retval; - } /** diff --git a/calendar/cal-client/cal-client.h b/calendar/cal-client/cal-client.h index b30c0a7d32..ecf714a9a4 100644 --- a/calendar/cal-client/cal-client.h +++ b/calendar/cal-client/cal-client.h @@ -102,11 +102,13 @@ void cal_client_generate_instances (CalClient *client, CalObjType type, time_t start, time_t end, CalRecurInstanceFn cb, gpointer cb_data); -GList *cal_client_get_alarms_in_range (CalClient *client, time_t start, time_t end); +GSList *cal_client_get_alarms_in_range (CalClient *client, time_t start, time_t end); + +void cal_client_free_alarms (GSList *alarms); gboolean cal_client_get_alarms_for_object (CalClient *client, const char *uid, time_t start, time_t end, - GList **alarms); + CalComponentAlarms **alarms); gboolean cal_client_update_object (CalClient *client, CalComponent *comp); diff --git a/calendar/cal-util/cal-component.c b/calendar/cal-util/cal-component.c index c7a1e6e324..1ece361da7 100644 --- a/calendar/cal-util/cal-component.c +++ b/calendar/cal-util/cal-component.c @@ -118,6 +118,9 @@ struct _CalComponentAlarm { /* Alarm icalcomponent we wrap */ icalcomponent *icalcomp; + /* Our extension UID property */ + icalproperty *uid; + /* Properties */ icalproperty *action; @@ -3433,7 +3436,6 @@ gboolean cal_component_has_alarms (CalComponent *comp) { CalComponentPrivate *priv; - icalcomponent *subcomp; g_return_val_if_fail (comp != NULL, FALSE); g_return_val_if_fail (IS_CAL_COMPONENT (comp), FALSE); @@ -3441,9 +3443,7 @@ cal_component_has_alarms (CalComponent *comp) priv = comp->priv; g_return_val_if_fail (priv->icalcomp != NULL, FALSE); - subcomp = icalcomponent_get_first_component (priv->icalcomp, ICAL_VALARM_COMPONENT); - - return subcomp != NULL ? TRUE : FALSE; + return g_hash_table_size (priv->alarm_uid_hash) != 0; } /* Scans an icalproperty from a calendar component and adds its mapping to our @@ -3453,6 +3453,7 @@ static void scan_alarm_property (CalComponentAlarm *alarm, icalproperty *prop) { icalproperty_kind kind; + const char *xname; kind = icalproperty_isa (prop); @@ -3465,6 +3466,15 @@ scan_alarm_property (CalComponentAlarm *alarm, icalproperty *prop) alarm->trigger = prop; break; + case ICAL_X_PROPERTY: + xname = icalproperty_get_x_name (prop); + g_assert (xname != NULL); + + if (strcmp (xname, EVOLUTION_ALARM_UID_PROPERTY) == 0) + alarm->uid = prop; + + break; + default: break; } @@ -3481,12 +3491,15 @@ make_alarm (CalComponent *comp, icalcomponent *subcomp) alarm->parent = comp; alarm->icalcomp = subcomp; + alarm->uid = NULL; for (prop = icalcomponent_get_first_property (subcomp, ICAL_ANY_PROPERTY); prop; prop = icalcomponent_get_next_property (subcomp, ICAL_ANY_PROPERTY)) scan_alarm_property (alarm, prop); + g_assert (alarm->uid != NULL); + return alarm; } @@ -3589,6 +3602,50 @@ cal_component_alarm_free (CalComponentAlarm *alarm) } /** + * cal_component_alarms_free: + * @alarms: Component alarms structure. + * + * Frees a #CalComponentAlarms structure. + **/ +void +cal_component_alarms_free (CalComponentAlarms *alarms) +{ + GSList *l; + + g_return_if_fail (alarms != NULL); + + g_assert (alarms->comp != NULL); + gtk_object_unref (GTK_OBJECT (alarms->comp)); + + for (l = alarms->alarms; l; l = l->next) { + CalAlarmInstance *instance; + + instance = l->data; + g_assert (instance != NULL); + g_free (instance); + } + + g_free (alarms->alarms); + g_free (alarms); +} + +/** + * cal_component_alarm_get_uid: + * @alarm: An alarm subcomponent. + * + * Queries the unique identifier of an alarm subcomponent. + * + * Return value: UID of the alarm. + **/ +const char * +cal_component_alarm_get_uid (CalComponentAlarm *alarm) +{ + g_return_val_if_fail (alarm != NULL, NULL); + + return alarm_uid_from_prop (alarm->uid); +} + +/** * cal_component_alarm_get_action: * @alarm: An alarm. * @action: Return value for the alarm's action type. @@ -3596,7 +3653,7 @@ cal_component_alarm_free (CalComponentAlarm *alarm) * Queries the action type of an alarm. **/ void -cal_component_alarm_get_action (CalComponentAlarm *alarm, CalComponentAlarmAction *action) +cal_component_alarm_get_action (CalComponentAlarm *alarm, CalAlarmAction *action) { const char *str; @@ -3606,22 +3663,22 @@ cal_component_alarm_get_action (CalComponentAlarm *alarm, CalComponentAlarmActio g_assert (alarm->icalcomp != NULL); if (!alarm->action) { - *action = CAL_COMPONENT_ALARM_NONE; + *action = CAL_ALARM_NONE; return; } str = icalproperty_get_action (alarm->action); if (strcasecmp (str, "AUDIO") == 0) - *action = CAL_COMPONENT_ALARM_AUDIO; + *action = CAL_ALARM_AUDIO; else if (strcasecmp (str, "DISPLAY") == 0) - *action = CAL_COMPONENT_ALARM_DISPLAY; + *action = CAL_ALARM_DISPLAY; else if (strcasecmp (str, "EMAIL") == 0) - *action = CAL_COMPONENT_ALARM_EMAIL; + *action = CAL_ALARM_EMAIL; else if (strcasecmp (str, "PROCEDURE") == 0) - *action = CAL_COMPONENT_ALARM_PROCEDURE; + *action = CAL_ALARM_PROCEDURE; else - *action = CAL_COMPONENT_ALARM_UNKNOWN; + *action = CAL_ALARM_UNKNOWN; } /** @@ -3632,30 +3689,30 @@ cal_component_alarm_get_action (CalComponentAlarm *alarm, CalComponentAlarmActio * Sets the action type for an alarm. **/ void -cal_component_alarm_set_action (CalComponentAlarm *alarm, CalComponentAlarmAction action) +cal_component_alarm_set_action (CalComponentAlarm *alarm, CalAlarmAction action) { char *str; g_return_if_fail (alarm != NULL); - g_return_if_fail (action != CAL_COMPONENT_ALARM_NONE); - g_return_if_fail (action != CAL_COMPONENT_ALARM_UNKNOWN); + g_return_if_fail (action != CAL_ALARM_NONE); + g_return_if_fail (action != CAL_ALARM_UNKNOWN); g_assert (alarm->icalcomp != NULL); switch (action) { - case CAL_COMPONENT_ALARM_AUDIO: + case CAL_ALARM_AUDIO: str = "AUDIO"; break; - case CAL_COMPONENT_ALARM_DISPLAY: + case CAL_ALARM_DISPLAY: str = "DISPLAY"; break; - case CAL_COMPONENT_ALARM_EMAIL: + case CAL_ALARM_EMAIL: str = "EMAIL"; break; - case CAL_COMPONENT_ALARM_PROCEDURE: + case CAL_ALARM_PROCEDURE: str = "PROCEDURE"; break; @@ -3675,16 +3732,16 @@ cal_component_alarm_set_action (CalComponentAlarm *alarm, CalComponentAlarmActio /** * cal_component_alarm_get_trigger: * @alarm: An alarm. - * @trigger: Return value for the trigger time. This should be freed using the - * cal_component_alarm_free_trigger() function. + * @trigger: Return value for the trigger time. * * Queries the trigger time for an alarm. **/ void -cal_component_alarm_get_trigger (CalComponentAlarm *alarm, CalComponentAlarmTrigger **trigger) +cal_component_alarm_get_trigger (CalComponentAlarm *alarm, CalAlarmTrigger *trigger) { icalparameter *param; union icaltriggertype t; + gboolean relative; g_return_if_fail (alarm != NULL); g_return_if_fail (trigger != NULL); @@ -3692,16 +3749,13 @@ cal_component_alarm_get_trigger (CalComponentAlarm *alarm, CalComponentAlarmTrig g_assert (alarm->icalcomp != NULL); if (!alarm->trigger) { - *trigger = NULL; + trigger->type = CAL_ALARM_TRIGGER_NONE; return; } - *trigger = g_new (CalComponentAlarmTrigger, 1); - /* Get trigger type */ param = icalproperty_get_first_parameter (alarm->trigger, ICAL_VALUE_PARAMETER); - if (param) { icalparameter_value value; @@ -3709,30 +3763,29 @@ cal_component_alarm_get_trigger (CalComponentAlarm *alarm, CalComponentAlarmTrig switch (value) { case ICAL_VALUE_DURATION: - (*trigger)->type = CAL_COMPONENT_ALARM_TRIGGER_RELATIVE; + relative = TRUE; break; case ICAL_VALUE_DATETIME: - (*trigger)->type = CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE; + relative = FALSE; break; default: g_message ("cal_component_alarm_get_trigger(): Unknown value for trigger " "value %d; using RELATIVE", value); - (*trigger)->type = CAL_COMPONENT_ALARM_TRIGGER_RELATIVE; + relative = TRUE; break; } } else - (*trigger)->type = CAL_COMPONENT_ALARM_TRIGGER_RELATIVE; + relative = TRUE; /* Get trigger value and the RELATED parameter */ t = icalproperty_get_trigger (alarm->trigger); - switch ((*trigger)->type) { - case CAL_COMPONENT_ALARM_TRIGGER_RELATIVE: - (*trigger)->u.relative.duration = t.duration; + if (relative) { + trigger->u.rel_duration = t.duration; param = icalproperty_get_first_parameter (alarm->trigger, ICAL_RELATED_PARAMETER); if (param) { @@ -3742,29 +3795,21 @@ cal_component_alarm_get_trigger (CalComponentAlarm *alarm, CalComponentAlarmTrig switch (rel) { case ICAL_RELATED_START: - (*trigger)->u.relative.related = - CAL_COMPONENT_ALARM_TRIGGER_RELATED_START; + trigger->type = CAL_ALARM_TRIGGER_RELATIVE_START; break; case ICAL_RELATED_END: - (*trigger)->u.relative.related = - CAL_COMPONENT_ALARM_TRIGGER_RELATED_END; + trigger->type = CAL_ALARM_TRIGGER_RELATIVE_END; break; default: g_assert_not_reached (); } } else - (*trigger)->u.relative.related = CAL_COMPONENT_ALARM_TRIGGER_RELATED_START; - - break; - - case CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE: - (*trigger)->u.absolute = t.time; - break; - - default: - g_assert_not_reached (); + trigger->type = CAL_ALARM_TRIGGER_RELATIVE_START; + } else { + trigger->u.abs_time = t.time; + trigger->type = CAL_ALARM_TRIGGER_ABSOLUTE; } } @@ -3776,7 +3821,7 @@ cal_component_alarm_get_trigger (CalComponentAlarm *alarm, CalComponentAlarmTrig * Sets the trigger time of an alarm. **/ void -cal_component_alarm_set_trigger (CalComponentAlarm *alarm, CalComponentAlarmTrigger *trigger) +cal_component_alarm_set_trigger (CalComponentAlarm *alarm, CalAlarmTrigger trigger) { union icaltriggertype t; icalparameter *param; @@ -3784,7 +3829,7 @@ cal_component_alarm_set_trigger (CalComponentAlarm *alarm, CalComponentAlarmTrig icalparameter_related related; g_return_if_fail (alarm != NULL); - g_return_if_fail (trigger != NULL); + g_return_if_fail (trigger.type != CAL_ALARM_TRIGGER_NONE); g_assert (alarm->icalcomp != NULL); @@ -3798,32 +3843,23 @@ cal_component_alarm_set_trigger (CalComponentAlarm *alarm, CalComponentAlarmTrig /* Set the value */ - value_type = ICAL_DURATION_VALUE; /* Keep GCC happy */ - related = ICAL_RELATED_START; /* Ditto */ + related = ICAL_RELATED_START; /* Keep GCC happy */ - switch (trigger->type) { - case CAL_COMPONENT_ALARM_TRIGGER_RELATIVE: - t.duration = trigger->u.relative.duration; + switch (trigger.type) { + case CAL_ALARM_TRIGGER_RELATIVE_START: + t.duration = trigger.u.rel_duration; value_type = ICAL_DURATION_VALUE; + related = ICAL_RELATED_START; + break; - switch (trigger->u.relative.related) { - case CAL_COMPONENT_ALARM_TRIGGER_RELATED_START: - related = ICAL_RELATED_START; - break; - - case CAL_COMPONENT_ALARM_TRIGGER_RELATED_END: - related = ICAL_RELATED_END; - break; - - default: - g_assert_not_reached (); - return; - } - + case CAL_ALARM_TRIGGER_RELATIVE_END: + t.duration = trigger.u.rel_duration; + value_type = ICAL_DURATION_VALUE; + related = ICAL_RELATED_END; break; - case CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE: - t.time = trigger->u.absolute; + case CAL_ALARM_TRIGGER_ABSOLUTE: + t.time = trigger.u.abs_time; value_type = ICAL_DATETIME_VALUE; break; @@ -3847,7 +3883,7 @@ cal_component_alarm_set_trigger (CalComponentAlarm *alarm, CalComponentAlarmTrig /* Related parameter */ - if (trigger->type == CAL_COMPONENT_ALARM_TRIGGER_RELATIVE) { + if (trigger.type != CAL_ALARM_TRIGGER_ABSOLUTE) { param = icalproperty_get_first_parameter (alarm->trigger, ICAL_RELATED_PARAMETER); if (param) @@ -3858,17 +3894,3 @@ cal_component_alarm_set_trigger (CalComponentAlarm *alarm, CalComponentAlarmTrig } } } - -/** - * cal_component_alarm_free_trigger: - * @trigger: A #CalComponentAlarmTrigger structure. - * - * Frees a #CalComponentAlarmTrigger structure. - **/ -void -cal_component_alarm_free_trigger (CalComponentAlarmTrigger *trigger) -{ - g_return_if_fail (trigger != NULL); - - g_free (trigger); -} diff --git a/calendar/cal-util/cal-component.h b/calendar/cal-util/cal-component.h index f59bb33a7b..893e066f52 100644 --- a/calendar/cal-util/cal-component.h +++ b/calendar/cal-util/cal-component.h @@ -51,7 +51,9 @@ typedef enum { CAL_COMPONENT_TIMEZONE } CalComponentVType; -/* Field identifiers for a calendar component */ +/* Field identifiers for a calendar component; these are used by the data model + * for ETable. + */ typedef enum { CAL_COMPONENT_FIELD_CATEGORIES, /* concatenation of the categories list */ CAL_COMPONENT_FIELD_CLASSIFICATION, @@ -74,8 +76,9 @@ typedef enum { CAL_COMPONENT_FIELD_NUM_FIELDS } CalComponentField; -/* Structures to return properties and their parameters */ +/* Structures and enumerations to return properties and their parameters */ +/* CLASSIFICATION property */ typedef enum { CAL_COMPONENT_CLASS_NONE, CAL_COMPONENT_CLASS_PUBLIC, @@ -84,6 +87,7 @@ typedef enum { CAL_COMPONENT_CLASS_UNKNOWN } CalComponentClassification; +/* Properties that have time and timezone information */ typedef struct { /* Actual date/time value */ struct icaltimetype *value; @@ -92,11 +96,13 @@ typedef struct { const char *tzid; } CalComponentDateTime; +/* Way in which a period of time is specified */ typedef enum { CAL_COMPONENT_PERIOD_DATETIME, CAL_COMPONENT_PERIOD_DURATION } CalComponentPeriodType; +/* Period of time, can have explicit start/end times or start/duration instead */ typedef struct { CalComponentPeriodType type; @@ -108,6 +114,7 @@ typedef struct { } u; } CalComponentPeriod; +/* Text properties */ typedef struct { /* Description string */ const char *value; @@ -116,6 +123,7 @@ typedef struct { const char *altrep; } CalComponentText; +/* Time transparency */ typedef enum { CAL_COMPONENT_TRANSP_NONE, CAL_COMPONENT_TRANSP_TRANSPARENT, @@ -123,7 +131,7 @@ typedef enum { CAL_COMPONENT_TRANSP_UNKNOWN } CalComponentTransparency; -typedef struct _CalComponentAlarm CalComponentAlarm; +/* Main calendar component object */ typedef struct _CalComponent CalComponent; typedef struct _CalComponentClass CalComponentClass; @@ -262,37 +270,58 @@ void cal_component_free_text_list (GSList *text_list); /* Alarms */ -typedef enum { - CAL_COMPONENT_ALARM_NONE, - CAL_COMPONENT_ALARM_AUDIO, - CAL_COMPONENT_ALARM_DISPLAY, - CAL_COMPONENT_ALARM_EMAIL, - CAL_COMPONENT_ALARM_PROCEDURE, - CAL_COMPONENT_ALARM_UNKNOWN -} CalComponentAlarmAction; +/* Opaque structure used to represent alarm subcomponents */ +typedef struct _CalComponentAlarm CalComponentAlarm; -typedef enum { - CAL_COMPONENT_ALARM_TRIGGER_RELATIVE, - CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE -} CalComponentAlarmTriggerType; +/* An alarm occurrence, i.e. a trigger instance */ +typedef struct { + /* UID of the alarm that triggered */ + const char *auid; + + /* Trigger time, i.e. "5 minutes before the appointment" */ + time_t trigger; + /* Actual event occurrence to which this trigger corresponds */ + time_t occur; +} CalAlarmInstance; + +/* Alarm trigger instances for a particular component */ +typedef struct { + /* The actual component */ + CalComponent *comp; + + /* List of CalAlarmInstance structures */ + GSList *alarms; +} CalComponentAlarms; + +/* Alarm types */ +typedef enum { + CAL_ALARM_NONE, + CAL_ALARM_AUDIO, + CAL_ALARM_DISPLAY, + CAL_ALARM_EMAIL, + CAL_ALARM_PROCEDURE, + CAL_ALARM_UNKNOWN +} CalAlarmAction; + +/* Whether a trigger is relative to the start or end of an event occurrence, or + * whether it is specified to occur at an absolute time. + */ typedef enum { - CAL_COMPONENT_ALARM_TRIGGER_RELATED_START, - CAL_COMPONENT_ALARM_TRIGGER_RELATED_END -} CalComponentAlarmTriggerRelated; + CAL_ALARM_TRIGGER_NONE, + CAL_ALARM_TRIGGER_RELATIVE_START, + CAL_ALARM_TRIGGER_RELATIVE_END, + CAL_ALARM_TRIGGER_ABSOLUTE +} CalAlarmTriggerType; typedef struct { - CalComponentAlarmTriggerType type; + CalAlarmTriggerType type; union { - struct { - struct icaldurationtype duration; - CalComponentAlarmTriggerRelated related; - } relative; - - struct icaltimetype absolute; + struct icaldurationtype rel_duration; + struct icaltimetype abs_time; } u; -} CalComponentAlarmTrigger; +} CalAlarmTrigger; gboolean cal_component_has_alarms (CalComponent *comp); GList *cal_component_get_alarm_uids (CalComponent *comp); @@ -300,12 +329,16 @@ CalComponentAlarm *cal_component_get_alarm (CalComponent *comp, const char *auid void cal_component_alarm_free (CalComponentAlarm *alarm); -void cal_component_alarm_get_action (CalComponentAlarm *alarm, CalComponentAlarmAction *action); -void cal_component_alarm_set_action (CalComponentAlarm *alarm, CalComponentAlarmAction action); +void cal_component_alarms_free (CalComponentAlarms *alarms); + +const char *cal_component_alarm_get_uid (CalComponentAlarm *alarm); + +void cal_component_alarm_get_action (CalComponentAlarm *alarm, CalAlarmAction *action); +void cal_component_alarm_set_action (CalComponentAlarm *alarm, CalAlarmAction action); + +void cal_component_alarm_get_trigger (CalComponentAlarm *alarm, CalAlarmTrigger *trigger); +void cal_component_alarm_set_trigger (CalComponentAlarm *alarm, CalAlarmTrigger trigger); -void cal_component_alarm_get_trigger (CalComponentAlarm *alarm, CalComponentAlarmTrigger **trigger); -void cal_component_alarm_set_trigger (CalComponentAlarm *alarm, CalComponentAlarmTrigger *trigger); -void cal_component_alarm_free_trigger (CalComponentAlarmTrigger *trigger); diff --git a/calendar/cal-util/cal-util.c b/calendar/cal-util/cal-util.c index 092fd79889..c75a65d7d5 100644 --- a/calendar/cal-util/cal-util.c +++ b/calendar/cal-util/cal-util.c @@ -51,31 +51,6 @@ cal_obj_instance_list_free (GList *list) } /** - * cal_alarm_instance_list_free: - * @list: List of #CalAlarmInstance structures. - * - * Frees a list of #CalAlarmInstance structures. - **/ -void -cal_alarm_instance_list_free (GList *list) -{ - CalAlarmInstance *i; - GList *l; - - for (l = list; l; l = l->next) { - i = l->data; - - g_assert (i != NULL); - g_assert (i->uid != NULL); - - g_free (i->uid); - g_free (i); - } - - g_list_free (list); -} - -/** * cal_obj_uid_list_free: * @list: List of strings with unique identifiers. * diff --git a/calendar/cal-util/cal-util.h b/calendar/cal-util/cal-util.h index 5c640a2d89..ac7838885e 100644 --- a/calendar/cal-util/cal-util.h +++ b/calendar/cal-util/cal-util.h @@ -41,18 +41,6 @@ typedef struct { void cal_obj_instance_list_free (GList *list); -/* Instance of an alarm trigger */ -typedef struct { - char *uid; /* UID of object */ -#if 0 - enum AlarmType type; /* Type of alarm */ -#endif - time_t trigger; /* Alarm trigger time */ - time_t occur; /* Occurrence time */ -} CalAlarmInstance; - -void cal_alarm_instance_list_free (GList *list); - /* Used for multiple UID queries */ typedef enum { CALOBJ_TYPE_EVENT = 1 << 0, diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c index e64ecbe706..ac43fbe438 100644 --- a/calendar/gui/gnome-cal.c +++ b/calendar/gui/gnome-cal.c @@ -786,8 +786,6 @@ program_notification (char *command, int close_standard) sigaction (SIGQUIT, &save_quit, NULL); } -#endif - /* Queues a snooze alarm */ static void snooze (GnomeCalendar *gcal, CalComponent *comp, time_t occur, int snooze_mins, gboolean audio) @@ -1040,10 +1038,13 @@ midnight_refresh_cb (gpointer alarm_id, time_t trigger, gpointer data) load_alarms (cal); } +#endif + /* Loads and queues the alarms from the current time up to midnight. */ static void load_alarms (GnomeCalendar *gcal) { +#if 0 GnomeCalendarPrivate *priv; time_t now; time_t end_of_day; @@ -1070,6 +1071,7 @@ load_alarms (GnomeCalendar *gcal) g_message ("load_alarms(): Could not set up the midnight refresh alarm!"); /* FIXME: what to do? */ } +#endif } /* Loads the initial data into the calendar; this should be called right after @@ -1086,6 +1088,7 @@ initial_load (GnomeCalendar *gcal) tag_calendar_by_client (priv->date_navigator, priv->client); } +#if 0 /* Removes any queued alarms for the specified UID */ static void remove_alarms_for_object (GnomeCalendar *gcal, const char *uid) @@ -1142,6 +1145,7 @@ add_alarms_for_object (GnomeCalendar *gcal, const char *uid) cal_alarm_instance_list_free (alarms); } +#endif /* Displays an error to indicate that loading a calendar failed */ static void @@ -1276,8 +1280,10 @@ obj_updated_cb (CalClient *client, const char *uid, gpointer data) gcal = GNOME_CALENDAR (data); priv = gcal->priv; +#if 0 remove_alarms_for_object (gcal, uid); add_alarms_for_object (gcal, uid); +#endif tag_calendar_by_client (priv->date_navigator, priv->client); } @@ -1292,7 +1298,9 @@ obj_removed_cb (CalClient *client, const char *uid, gpointer data) gcal = GNOME_CALENDAR (data); priv = gcal->priv; +#if 0 remove_alarms_for_object (gcal, uid); +#endif tag_calendar_by_client (priv->date_navigator, priv->client); } diff --git a/calendar/idl/evolution-calendar.idl b/calendar/idl/evolution-calendar.idl index bee377c76a..3e64e07888 100644 --- a/calendar/idl/evolution-calendar.idl +++ b/calendar/idl/evolution-calendar.idl @@ -16,17 +16,20 @@ module GNOME { module Evolution { module Calendar { - /* A calendar object (event/todo/journal/etc), represented as an + /* A calendar component (event/todo/journal/etc), represented as an * iCalendar string. */ typedef string CalObj; - /* An unique identifier for a calendar object */ + /* A unique identifier for a calendar component */ typedef string CalObjUID; /* Sequence of unique identifiers */ typedef sequence<CalObjUID> CalObjUIDSeq; + /* A unique identifier for an alarm subcomponent */ + typedef string CalAlarmUID; + /* Flags for getting UID sequences */ typedef long CalObjType; const CalObjType TYPE_EVENT = 1 << 0; @@ -51,11 +54,11 @@ module Calendar { /* Used to store a time_t */ typedef unsigned long Time_t; - /* An instance of a calendar object that actually occurs. These are + /* An instance of a calendar component that actually occurs. These are * "virtual" objects in that they are used to represent instances of * recurring events and alarms. "Real" objects just contain the * information required to figure out the times at which they recur or - * trigger. + * trigger. */ struct CalObjInstance { CalObjUID uid; @@ -63,6 +66,7 @@ module Calendar { Time_t end; }; + /* Used to transfer a list of component occurrences */ typedef sequence<CalObjInstance> CalObjInstanceSeq; /* An object change */ @@ -71,18 +75,28 @@ module Calendar { CalObjChangeType type; }; + /* Used to transfer a list of changed components */ typedef sequence<CalObjChange> CalObjChangeSeq; /* An alarm trigger instance */ struct CalAlarmInstance { - CalObjUID uid; - AlarmType type; + CalAlarmUID auid; Time_t trigger; Time_t occur; }; + /* Used to represent a list of alarm triggers for a single component */ typedef sequence<CalAlarmInstance> CalAlarmInstanceSeq; + /* Alarms for a component */ + struct CalComponentAlarms { + CalObj calobj; + CalAlarmInstanceSeq alarms; + }; + + /* Used to represent a list of components plus their triggers */ + typedef sequence<CalComponentAlarms> CalComponentAlarmsSeq; + interface Listener; /* Calendar client interface */ @@ -94,48 +108,46 @@ module Calendar { /* A calendar is identified by its URI */ readonly attribute string uri; - /* Gets the number of objects of the specified types */ + /* Gets the number of components of the specified types */ long countObjects (in CalObjType type); - /* Gets an object based on its URI */ + /* Gets a component based on its URI */ CalObj getObject (in CalObjUID uid) raises (NotFound); - /* Gets a list of UIDs based on object type */ + /* Gets a list of UIDs based on component type */ CalObjUIDSeq getUIds (in CalObjType type); - /* Gets a list of objects that changed based on object type */ + /* Gets a list of components that changed based on object type */ CalObjChangeSeq getChanges (in CalObjType type, in string change_id); - /* Gets a list of objects that occur or recur in the specified time range */ + /* Gets a list of components that occur or recur in the specified time range */ CalObjUIDSeq getObjectsInRange (in CalObjType type, in Time_t start, in Time_t end) raises (InvalidRange); - /* - * Gets the objects whose alarms trigger in the specified time - * range. + /* Gets a list of the components that have alarms that trigger + * in the specified range of time, and the trigger/occurrence + * structures themselves. */ - CalAlarmInstanceSeq getAlarmsInRange (in Time_t start, in Time_t end) + CalComponentAlarmsSeq getAlarmsInRange (in Time_t start, in Time_t end) raises (InvalidRange); - /* - * Gets the alarms for the specified object that trigger in the - * specified time range. + /* Gets the alarms for the specified component that trigger in + * the specified time range. */ - CalAlarmInstanceSeq getAlarmsForObject (in CalObjUID uid, - in Time_t start, in Time_t end) + CalComponentAlarms getAlarmsForObject (in CalObjUID uid, + in Time_t start, in Time_t end) raises (NotFound, InvalidRange); - /* - * Updates an object by adding it if it does not exist or by - * changing an existing one. + /* Updates a component by adding it if it does not exist or by + * changing an existing one. */ void updateObject (in CalObjUID uid, in CalObj calobj) raises (InvalidObject); - /* Removes an object */ + /* Removes a component */ void removeObject (in CalObjUID uid) raises (NotFound); }; @@ -157,10 +169,10 @@ module Calendar { */ void notifyCalLoaded (in LoadStatus status, in Cal cal); - /* Called from a Calendar when an object is added or changed */ + /* Called from a Calendar when a component is added or changed */ void notifyObjUpdated (in CalObjUID uid); - /* Called from a Calendar when an object is removed */ + /* Called from a Calendar when a component is removed */ void notifyObjRemoved (in CalObjUID uid); }; diff --git a/calendar/pcs/cal-backend-file.c b/calendar/pcs/cal-backend-file.c index c63e690246..85026a861a 100644 --- a/calendar/pcs/cal-backend-file.c +++ b/calendar/pcs/cal-backend-file.c @@ -74,10 +74,14 @@ static CalObjType cal_backend_file_get_type_by_uid (CalBackend *backend, const c static GList *cal_backend_file_get_uids (CalBackend *backend, CalObjType type); static GList *cal_backend_file_get_objects_in_range (CalBackend *backend, CalObjType type, time_t start, time_t end); -static GList *cal_backend_file_get_alarms_in_range (CalBackend *backend, time_t start, time_t end); -static gboolean cal_backend_file_get_alarms_for_object (CalBackend *backend, const char *uid, - time_t start, time_t end, - GList **alarms); + +static GNOME_Evolution_Calendar_CalComponentAlarmsSeq *cal_backend_file_get_alarms_in_range ( + CalBackend *backend, time_t start, time_t end); + +static GNOME_Evolution_Calendar_CalComponentAlarms *cal_backend_file_get_alarms_for_object ( + CalBackend *backend, const char *uid, + time_t start, time_t end, gboolean *object_found); + static gboolean cal_backend_file_update_object (CalBackend *backend, const char *uid, const char *calobj); static gboolean cal_backend_file_remove_object (CalBackend *backend, const char *uid); @@ -922,12 +926,300 @@ cal_backend_file_get_objects_in_range (CalBackend *backend, CalObjType type, return event_list; } +/* Computes the range of time in which recurrences should be generated for a + * component in order to compute alarm trigger times. + */ +static void +compute_alarm_range (CalComponent *comp, GList *alarm_uids, time_t start, time_t end, + time_t *alarm_start, time_t *alarm_end) +{ + GList *l; + + *alarm_start = start; + *alarm_end = end; + + for (l = alarm_uids; l; l = l->next) { + const char *auid; + CalComponentAlarm *alarm; + CalAlarmTrigger trigger; + struct icaldurationtype *dur; + time_t dur_time; + + auid = l->data; + alarm = cal_component_get_alarm (comp, auid); + g_assert (alarm != NULL); + + cal_component_alarm_get_trigger (alarm, &trigger); + cal_component_alarm_free (alarm); + + switch (trigger.type) { + case CAL_ALARM_TRIGGER_NONE: + case CAL_ALARM_TRIGGER_ABSOLUTE: + continue; + + case CAL_ALARM_TRIGGER_RELATIVE_START: + dur = &trigger.u.rel_duration; + dur_time = icaldurationtype_as_timet (*dur); + + if (dur->is_neg) + *alarm_start = MIN (*alarm_start, start - dur_time); + else + *alarm_end = MAX (*alarm_end, start + dur_time); + + break; + + case CAL_ALARM_TRIGGER_RELATIVE_END: + dur = &trigger.u.rel_duration; + dur_time = icaldurationtype_as_timet (*dur); + + if (dur->is_neg) + *alarm_start = MIN (*alarm_start, end - dur_time); + else + *alarm_end = MAX (*alarm_end, end + dur_time); + + break; + + default: + g_assert_not_reached (); + } + } + + g_assert (*alarm_start <= *alarm_end); +} + +/* Closure data to generate alarm occurrences */ +struct alarm_occurrence_data { + /* These are the info we have */ + GList *alarm_uids; + time_t start; + time_t end; + + /* This is what we compute */ + GSList *triggers; + int n_triggers; +}; + +/* Callback used from cal_recur_generate_instances(); generates triggers for all + * of a component's RELATIVE alarms. + */ +static gboolean +add_alarm_occurrences_cb (CalComponent *comp, time_t start, time_t end, gpointer data) +{ + struct alarm_occurrence_data *aod; + GList *l; + + aod = data; + + for (l = aod->alarm_uids; l; l = l->next) { + const char *auid; + CalComponentAlarm *alarm; + CalAlarmTrigger trigger; + struct icaldurationtype *dur; + time_t dur_time; + time_t occur_time, trigger_time; + CalAlarmInstance *instance; + + auid = l->data; + alarm = cal_component_get_alarm (comp, auid); + g_assert (alarm != NULL); + + cal_component_alarm_get_trigger (alarm, &trigger); + cal_component_alarm_free (alarm); + + if (trigger.type != CAL_ALARM_TRIGGER_RELATIVE_START + && trigger.type != CAL_ALARM_TRIGGER_RELATIVE_END) + continue; + + dur = &trigger.u.rel_duration; + dur_time = icaldurationtype_as_timet (*dur); + + if (trigger.type == CAL_ALARM_TRIGGER_RELATIVE_START) + occur_time = start; + else + occur_time = end; + + if (dur->is_neg) + trigger_time = occur_time - dur_time; + else + trigger_time = occur_time + dur_time; + + if (trigger_time < aod->start || trigger_time >= aod->end) + continue; + + instance = g_new (CalAlarmInstance, 1); + instance->auid = auid; + instance->trigger = trigger_time; + instance->occur = occur_time; + + aod->triggers = g_slist_prepend (aod->triggers, instance); + aod->n_triggers++; + } + + return TRUE; +} + +/* Generates the absolute triggers for a component */ +static void +generate_absolute_triggers (CalComponent *comp, struct alarm_occurrence_data *aod) +{ + GList *l; + + for (l = aod->alarm_uids; l; l = l->next) { + const char *auid; + CalComponentAlarm *alarm; + CalAlarmTrigger trigger; + time_t abs_time; + CalAlarmInstance *instance; + + auid = l->data; + alarm = cal_component_get_alarm (comp, auid); + g_assert (alarm != NULL); + + cal_component_alarm_get_trigger (alarm, &trigger); + cal_component_alarm_free (alarm); + + if (trigger.type != CAL_ALARM_TRIGGER_ABSOLUTE) + continue; + + abs_time = icaltime_as_timet (trigger.u.abs_time); + + if (abs_time < aod->start || abs_time >= aod->end) + continue; + + instance = g_new (CalAlarmInstance, 1); + instance->auid = auid; + instance->trigger = abs_time; + instance->occur = abs_time; /* No particular occurrence, so just use the same time */ + + aod->triggers = g_slist_prepend (aod->triggers, instance); + aod->n_triggers++; + } +} + +/* Compares two alarm instances; called from g_slist_sort() */ +static gint +compare_alarm_instance (gconstpointer a, gconstpointer b) +{ + const CalAlarmInstance *aia, *aib; + + aia = a; + aib = b; + + if (aia->trigger < aib->trigger) + return -1; + else if (aia->trigger > aib->trigger) + return 1; + else + return 0; +} + +/* Generates alarm instances for a calendar component. Returns the instances + * structure, or NULL if no alarm instances occurred in the specified time + * range. + */ +static CalComponentAlarms * +generate_alarms_for_comp (CalComponent *comp, time_t start, time_t end) +{ + GList *alarm_uids; + time_t alarm_start, alarm_end; + struct alarm_occurrence_data aod; + CalComponentAlarms *alarms; + + if (!cal_component_has_alarms (comp)) + return NULL; + + alarm_uids = cal_component_get_alarm_uids (comp); + compute_alarm_range (comp, alarm_uids, start, end, &alarm_start, &alarm_end); + + aod.alarm_uids = alarm_uids; + aod.start = start; + aod.end = end; + aod.triggers = NULL; + aod.n_triggers = 0; + cal_recur_generate_instances (comp, alarm_start, alarm_end, add_alarm_occurrences_cb, &aod); + + /* We add the ABSOLUTE triggers separately */ + generate_absolute_triggers (comp, &aod); + + if (aod.n_triggers == 0) + return NULL; + + /* Create the component alarm instances structure */ + + alarms = g_new (CalComponentAlarms, 1); + alarms->comp = comp; + gtk_object_ref (GTK_OBJECT (alarms->comp)); + alarms->alarms = g_slist_sort (aod.triggers, compare_alarm_instance); + + return alarms; +} + +/* Iterates through all the components in the comps list and generates alarm + * instances for them; putting them in the comp_alarms list. Returns the number + * of elements it added to that list. + */ +static int +generate_alarms_for_list (GList *comps, time_t start, time_t end, GSList **comp_alarms) +{ + GList *l; + int n; + + n = 0; + + for (l = comps; l; l = l->next) { + CalComponent *comp; + CalComponentAlarms *alarms; + + comp = CAL_COMPONENT (l->data); + alarms = generate_alarms_for_comp (comp, start, end); + + if (alarms) { + *comp_alarms = g_slist_prepend (*comp_alarms, alarms); + n++; + } + } + + return n; +} + +/* Fills a CORBA sequence of alarm instances */ +static void +fill_alarm_instances_seq (GNOME_Evolution_Calendar_CalAlarmInstanceSeq *seq, GSList *alarms) +{ + int n_alarms; + GSList *l; + int i; + + n_alarms = g_slist_length (alarms); + + CORBA_sequence_set_release (seq, TRUE); + seq->_length = n_alarms; + seq->_buffer = CORBA_sequence_GNOME_Evolution_Calendar_CalAlarmInstance_allocbuf (n_alarms); + + for (l = alarms, i = 0; l; l = l->next, i++) { + CalAlarmInstance *instance; + GNOME_Evolution_Calendar_CalAlarmInstance *corba_instance; + + instance = l->data; + corba_instance = seq->_buffer + i; + + corba_instance->auid = CORBA_string_dup (instance->auid); + corba_instance->trigger = (long) instance->trigger; + corba_instance->occur = (long) instance->occur; + } +} + /* Get_alarms_in_range handler for the file backend */ -static GList * +static GNOME_Evolution_Calendar_CalComponentAlarmsSeq * cal_backend_file_get_alarms_in_range (CalBackend *backend, time_t start, time_t end) { CalBackendFile *cbfile; CalBackendFilePrivate *priv; + int n_comp_alarms; + GSList *comp_alarms; + GSList *l; + int i; + GNOME_Evolution_Calendar_CalComponentAlarmsSeq *seq; cbfile = CAL_BACKEND_FILE (backend); priv = cbfile->priv; @@ -937,35 +1229,81 @@ cal_backend_file_get_alarms_in_range (CalBackend *backend, time_t start, time_t g_return_val_if_fail (start != -1 && end != -1, NULL); g_return_val_if_fail (start <= end, NULL); - /* FIXME: have to deal with an unknown number of alarms; we can't just - * do the same thing as in cal-backend-imc. - */ - return NULL; + /* Per RFC 2445, only VEVENTs and VTODOs can have alarms */ + + n_comp_alarms = 0; + comp_alarms = NULL; + + n_comp_alarms += generate_alarms_for_list (priv->events, start, end, &comp_alarms); + n_comp_alarms += generate_alarms_for_list (priv->todos, start, end, &comp_alarms); + + seq = GNOME_Evolution_Calendar_CalComponentAlarmsSeq__alloc (); + CORBA_sequence_set_release (seq, TRUE); + seq->_length = n_comp_alarms; + seq->_buffer = CORBA_sequence_GNOME_Evolution_Calendar_CalComponentAlarms_allocbuf ( + n_comp_alarms); + + for (l = comp_alarms, i = 0; l; l = l->next, i++) { + CalComponentAlarms *alarms; + char *comp_str; + + alarms = l->data; + + comp_str = cal_component_get_as_string (alarms->comp); + seq->_buffer[i].calobj = CORBA_string_dup (comp_str); + g_free (comp_str); + + fill_alarm_instances_seq (&seq->_buffer[i].alarms, alarms->alarms); + + cal_component_alarms_free (alarms); + } + + g_slist_free (comp_alarms); + + return seq; } /* Get_alarms_for_object handler for the file backend */ -static gboolean +static GNOME_Evolution_Calendar_CalComponentAlarms * cal_backend_file_get_alarms_for_object (CalBackend *backend, const char *uid, - time_t start, time_t end, - GList **alarms) + time_t start, time_t end, gboolean *object_found) { CalBackendFile *cbfile; CalBackendFilePrivate *priv; + CalComponent *comp; + char *comp_str; + GNOME_Evolution_Calendar_CalComponentAlarms *corba_alarms; + CalComponentAlarms *alarms; cbfile = CAL_BACKEND_FILE (backend); priv = cbfile->priv; - g_return_val_if_fail (priv->icalcomp != NULL, FALSE); + g_return_val_if_fail (priv->icalcomp != NULL, NULL); - g_return_val_if_fail (uid != NULL, FALSE); - g_return_val_if_fail (start != -1 && end != -1, FALSE); - g_return_val_if_fail (start <= end, FALSE); - g_return_val_if_fail (alarms != NULL, FALSE); + g_return_val_if_fail (uid != NULL, NULL); + g_return_val_if_fail (start != -1 && end != -1, NULL); + g_return_val_if_fail (start <= end, NULL); + g_return_val_if_fail (object_found != NULL, NULL); - /* FIXME */ + comp = lookup_component (cbfile, uid); + if (!comp) { + *object_found = FALSE; + return NULL; + } - *alarms = NULL; - return FALSE; + *object_found = TRUE; + + comp_str = cal_component_get_as_string (comp); + corba_alarms = GNOME_Evolution_Calendar_CalComponentAlarms__alloc (); + + corba_alarms->calobj = CORBA_string_dup (comp_str); + g_free (comp_str); + + alarms = generate_alarms_for_comp (comp, start, end); + fill_alarm_instances_seq (&corba_alarms->alarms, alarms->alarms); + cal_component_alarms_free (alarms); + + return corba_alarms; } /* Notifies a backend's clients that an object was updated */ diff --git a/calendar/pcs/cal-backend.c b/calendar/pcs/cal-backend.c index ce9604e418..9570b85d7f 100644 --- a/calendar/pcs/cal-backend.c +++ b/calendar/pcs/cal-backend.c @@ -464,21 +464,29 @@ cal_backend_get_objects_in_range (CalBackend *backend, CalObjType type, * @backend: A calendar backend. * @start: Start time for query. * @end: End time for query. + * @valid_range: Return value that says whether the range is valid or not. * * Builds a sorted list of the alarms that trigger in the specified time range. * - * Return value: A list of #CalAlarmInstance structures, sorted by trigger time. + * Return value: A sequence of component alarm instances structures, or NULL + * if @valid_range returns FALSE. **/ -GList * -cal_backend_get_alarms_in_range (CalBackend *backend, time_t start, time_t end) +GNOME_Evolution_Calendar_CalComponentAlarmsSeq * +cal_backend_get_alarms_in_range (CalBackend *backend, time_t start, time_t end, gboolean *valid_range) { g_return_val_if_fail (backend != NULL, NULL); g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL); - g_return_val_if_fail (start != -1 && end != -1, NULL); - g_return_val_if_fail (start <= end, NULL); + g_return_val_if_fail (valid_range != NULL, NULL); g_assert (CLASS (backend)->get_alarms_in_range != NULL); - return (* CLASS (backend)->get_alarms_in_range) (backend, start, end); + + if (!(start != -1 && end != -1 && start <= end)) { + *valid_range = FALSE; + return NULL; + } else { + *valid_range = TRUE; + return (* CLASS (backend)->get_alarms_in_range) (backend, start, end); + } } /** @@ -487,27 +495,43 @@ cal_backend_get_alarms_in_range (CalBackend *backend, time_t start, time_t end) * @uid: Unique identifier for a calendar object. * @start: Start time for query. * @end: End time for query. - * @alarms: Return value for the list of alarm instances. + * @result: Return value for the result code for the operation. * * Builds a sorted list of the alarms of the specified event that trigger in a * particular time range. * - * Return value: TRUE on success, FALSE if the object was not found. + * Return value: A structure of the component's alarm instances, or NULL if @result + * returns something other than #CAL_BACKEND_GET_ALARMS_SUCCESS. **/ -gboolean +GNOME_Evolution_Calendar_CalComponentAlarms * cal_backend_get_alarms_for_object (CalBackend *backend, const char *uid, time_t start, time_t end, - GList **alarms) + CalBackendGetAlarmsForObjectResult *result) { - g_return_val_if_fail (backend != NULL, FALSE); - g_return_val_if_fail (IS_CAL_BACKEND (backend), FALSE); - g_return_val_if_fail (uid != NULL, FALSE); - g_return_val_if_fail (start != -1 && end != -1, FALSE); - g_return_val_if_fail (start <= end, FALSE); - g_return_val_if_fail (alarms != NULL, FALSE); + g_return_val_if_fail (backend != NULL, NULL); + g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL); + g_return_val_if_fail (uid != NULL, NULL); + g_return_val_if_fail (result != NULL, NULL); g_assert (CLASS (backend)->get_alarms_for_object != NULL); - return (* CLASS (backend)->get_alarms_for_object) (backend, uid, start, end, alarms); + + if (!(start != -1 && end != -1 && start <= end)) { + *result = CAL_BACKEND_GET_ALARMS_INVALID_RANGE; + return NULL; + } else { + gboolean object_found; + GNOME_Evolution_Calendar_CalComponentAlarms *alarms; + + alarms = (* CLASS (backend)->get_alarms_for_object) (backend, uid, start, end, + &object_found); + + if (object_found) + *result = CAL_BACKEND_GET_ALARMS_SUCCESS; + else + *result = CAL_BACKEND_GET_ALARMS_NOT_FOUND; + + return alarms; + } } /** diff --git a/calendar/pcs/cal-backend.h b/calendar/pcs/cal-backend.h index e2d5c6c880..6194630b43 100644 --- a/calendar/pcs/cal-backend.h +++ b/calendar/pcs/cal-backend.h @@ -27,7 +27,7 @@ #include <libgnomevfs/gnome-vfs.h> #include <cal-util/cal-util.h> #include <cal-util/cal-component.h> -#include "calendar/pcs/evolution-calendar.h" +#include "evolution-calendar.h" #include "cal-common.h" #include "cal.h" @@ -48,6 +48,13 @@ typedef enum { CAL_BACKEND_LOAD_ERROR /* We need better error reporting in libversit */ } CalBackendLoadStatus; +/* Result codes for ::get_alarms_in_range() */ +typedef enum { + CAL_BACKEND_GET_ALARMS_SUCCESS, + CAL_BACKEND_GET_ALARMS_NOT_FOUND, + CAL_BACKEND_GET_ALARMS_INVALID_RANGE +} CalBackendGetAlarmsForObjectResult; + struct _CalBackend { GtkObject object; @@ -70,12 +77,16 @@ struct _CalBackendClass { char *(* get_object) (CalBackend *backend, const char *uid); CalObjType(* get_type_by_uid) (CalBackend *backend, const char *uid); GList *(* get_uids) (CalBackend *backend, CalObjType type); + GList *(* get_objects_in_range) (CalBackend *backend, CalObjType type, time_t start, time_t end); - GList *(* get_alarms_in_range) (CalBackend *backend, time_t start, time_t end); - gboolean (* get_alarms_for_object) (CalBackend *backend, const char *uid, - time_t start, time_t end, - GList **alarms); + + GNOME_Evolution_Calendar_CalComponentAlarmsSeq *(* get_alarms_in_range) ( + CalBackend *backend, time_t start, time_t end); + GNOME_Evolution_Calendar_CalComponentAlarms *(* get_alarms_for_object) ( + CalBackend *backend, const char *uid, + time_t start, time_t end, gboolean *object_found); + gboolean (* update_object) (CalBackend *backend, const char *uid, const char *calobj); gboolean (* remove_object) (CalBackend *backend, const char *uid); }; @@ -101,11 +112,13 @@ GNOME_Evolution_Calendar_CalObjChangeSeq * cal_backend_get_changes (CalBackend * GList *cal_backend_get_objects_in_range (CalBackend *backend, CalObjType type, time_t start, time_t end); -GList *cal_backend_get_alarms_in_range (CalBackend *backend, time_t start, time_t end); +GNOME_Evolution_Calendar_CalComponentAlarmsSeq *cal_backend_get_alarms_in_range ( + CalBackend *backend, time_t start, time_t end, gboolean *valid_range); -gboolean cal_backend_get_alarms_for_object (CalBackend *backend, const char *uid, - time_t start, time_t end, - GList **alarms); +GNOME_Evolution_Calendar_CalComponentAlarms *cal_backend_get_alarms_for_object ( + CalBackend *backend, const char *uid, + time_t start, time_t end, + CalBackendGetAlarmsForObjectResult *result); gboolean cal_backend_update_object (CalBackend *backend, const char *uid, const char *calobj); diff --git a/calendar/pcs/cal.c b/calendar/pcs/cal.c index 179c850475..77f18806d9 100644 --- a/calendar/pcs/cal.c +++ b/calendar/pcs/cal.c @@ -334,68 +334,8 @@ Cal_get_objects_in_range (PortableServer_Servant servant, return seq; } -#if 0 -/* Translates an enum AlarmType to its CORBA representation */ -static Evolution_Calendar_AlarmType -corba_alarm_type (enum AlarmType type) -{ - switch (type) { - case ALARM_MAIL: - return Evolution_Calendar_MAIL; - - case ALARM_PROGRAM: - return Evolution_Calendar_PROGRAM; - - case ALARM_DISPLAY: - return Evolution_Calendar_DISPLAY; - - case ALARM_AUDIO: - return Evolution_Calendar_AUDIO; - - default: - g_assert_not_reached (); - return Evolution_Calendar_DISPLAY; - } -} -#endif - -/* Builds a CORBA sequence of alarm instances from a CalAlarmInstance list. */ -static GNOME_Evolution_Calendar_CalAlarmInstanceSeq * -build_alarm_instance_seq (GList *alarms) -{ - GList *l; - int n, i; - GNOME_Evolution_Calendar_CalAlarmInstanceSeq *seq; - - n = g_list_length (alarms); - - seq = GNOME_Evolution_Calendar_CalAlarmInstanceSeq__alloc (); - CORBA_sequence_set_release (seq, TRUE); - seq->_length = n; - seq->_buffer = CORBA_sequence_GNOME_Evolution_Calendar_CalAlarmInstance_allocbuf (n); - - /* Fill the sequence */ - - for (i = 0, l = alarms; l; i++, l = l->next) { - CalAlarmInstance *ai; - GNOME_Evolution_Calendar_CalAlarmInstance *corba_ai; - - ai = l->data; - corba_ai = &seq->_buffer[i]; - - corba_ai->uid = CORBA_string_dup (ai->uid); -#if 0 - corba_ai->type = corba_alarm_type (ai->type); -#endif - corba_ai->trigger = ai->trigger; - corba_ai->occur = ai->occur; - } - - return seq; -} - /* Cal::get_alarms_in_range method */ -static GNOME_Evolution_Calendar_CalAlarmInstanceSeq * +static GNOME_Evolution_Calendar_CalComponentAlarmsSeq * Cal_get_alarms_in_range (PortableServer_Servant servant, GNOME_Evolution_Calendar_Time_t start, GNOME_Evolution_Calendar_Time_t end, @@ -404,8 +344,8 @@ Cal_get_alarms_in_range (PortableServer_Servant servant, Cal *cal; CalPrivate *priv; time_t t_start, t_end; - GNOME_Evolution_Calendar_CalAlarmInstanceSeq *seq; - GList *alarms; + gboolean valid_range; + GNOME_Evolution_Calendar_CalComponentAlarmsSeq *seq; cal = CAL (bonobo_object_from_servant (servant)); priv = cal->priv; @@ -413,36 +353,30 @@ Cal_get_alarms_in_range (PortableServer_Servant servant, t_start = (time_t) start; t_end = (time_t) end; - if (t_start > t_end || t_start == -1 || t_end == -1) { + seq = cal_backend_get_alarms_in_range (priv->backend, t_start, t_end, &valid_range); + if (!valid_range) { CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_GNOME_Evolution_Calendar_Cal_InvalidRange, NULL); return NULL; } - /* Figure out the list and allocate the sequence */ - - alarms = cal_backend_get_alarms_in_range (priv->backend, t_start, t_end); - seq = build_alarm_instance_seq (alarms); - cal_alarm_instance_list_free (alarms); - return seq; } /* Cal::get_alarms_for_object method */ -static GNOME_Evolution_Calendar_CalAlarmInstanceSeq * +static GNOME_Evolution_Calendar_CalComponentAlarms * Cal_get_alarms_for_object (PortableServer_Servant servant, const GNOME_Evolution_Calendar_CalObjUID uid, GNOME_Evolution_Calendar_Time_t start, GNOME_Evolution_Calendar_Time_t end, - CORBA_Environment *ev) + CORBA_Environment * ev) { Cal *cal; CalPrivate *priv; time_t t_start, t_end; - GNOME_Evolution_Calendar_CalAlarmInstanceSeq *seq; - GList *alarms; - gboolean result; + GNOME_Evolution_Calendar_CalComponentAlarms *alarms; + CalBackendGetAlarmsForObjectResult result; cal = CAL (bonobo_object_from_servant (servant)); priv = cal->priv; @@ -450,25 +384,28 @@ Cal_get_alarms_for_object (PortableServer_Servant servant, t_start = (time_t) start; t_end = (time_t) end; - if (t_start > t_end || t_start == -1 || t_end == -1) { + alarms = cal_backend_get_alarms_for_object (priv->backend, uid, t_start, t_end, &result); + + switch (result) { + case CAL_BACKEND_GET_ALARMS_SUCCESS: + return alarms; + + case CAL_BACKEND_GET_ALARMS_NOT_FOUND: CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_GNOME_Evolution_Calendar_Cal_InvalidRange, + ex_GNOME_Evolution_Calendar_Cal_NotFound, NULL); return NULL; - } - result = cal_backend_get_alarms_for_object (priv->backend, uid, t_start, t_end, &alarms); - if (!result) { + case CAL_BACKEND_GET_ALARMS_INVALID_RANGE: CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_GNOME_Evolution_Calendar_Cal_NotFound, + ex_GNOME_Evolution_Calendar_Cal_InvalidRange, NULL); return NULL; - } - - seq = build_alarm_instance_seq (alarms); - cal_alarm_instance_list_free (alarms); - return seq; + default: + g_assert_not_reached (); + return NULL; + } } /* Cal::update_object method */ |