aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/pcs/cal-backend-file.c
diff options
context:
space:
mode:
authorFederico Mena Quintero <federico@helixcode.com>2000-12-19 07:47:52 +0800
committerFederico Mena Quintero <federico@src.gnome.org>2000-12-19 07:47:52 +0800
commit8d96fe16f15f653d0809603ccaecd677e5708d8d (patch)
tree56d1ccf4be7dcec8a7a09524f2d312ab1da004af /calendar/pcs/cal-backend-file.c
parenta1d12a819a73754b94eeaf558aefa91e77f169f3 (diff)
downloadgsoc2013-evolution-8d96fe16f15f653d0809603ccaecd677e5708d8d.tar
gsoc2013-evolution-8d96fe16f15f653d0809603ccaecd677e5708d8d.tar.gz
gsoc2013-evolution-8d96fe16f15f653d0809603ccaecd677e5708d8d.tar.bz2
gsoc2013-evolution-8d96fe16f15f653d0809603ccaecd677e5708d8d.tar.lz
gsoc2013-evolution-8d96fe16f15f653d0809603ccaecd677e5708d8d.tar.xz
gsoc2013-evolution-8d96fe16f15f653d0809603ccaecd677e5708d8d.tar.zst
gsoc2013-evolution-8d96fe16f15f653d0809603ccaecd677e5708d8d.zip
Alarm instance generation support for the Wombat.
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. svn path=/trunk/; revision=7076
Diffstat (limited to 'calendar/pcs/cal-backend-file.c')
-rw-r--r--calendar/pcs/cal-backend-file.c378
1 files changed, 358 insertions, 20 deletions
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 */