diff options
author | Federico Mena Quintero <federico@helixcode.com> | 2000-02-08 15:08:29 +0800 |
---|---|---|
committer | Arturo Espinosa <unammx@src.gnome.org> | 2000-02-08 15:08:29 +0800 |
commit | cc670cb2ca319599eebac658f1164dbb64d70c65 (patch) | |
tree | 55dc72c7ea1b1582158e8aa55eedb9d18a4ab4e4 | |
parent | c02660b4081a84c9ad5749a931f5458f08f634d3 (diff) | |
download | gsoc2013-evolution-cc670cb2ca319599eebac658f1164dbb64d70c65.tar gsoc2013-evolution-cc670cb2ca319599eebac658f1164dbb64d70c65.tar.gz gsoc2013-evolution-cc670cb2ca319599eebac658f1164dbb64d70c65.tar.bz2 gsoc2013-evolution-cc670cb2ca319599eebac658f1164dbb64d70c65.tar.lz gsoc2013-evolution-cc670cb2ca319599eebac658f1164dbb64d70c65.tar.xz gsoc2013-evolution-cc670cb2ca319599eebac658f1164dbb64d70c65.tar.zst gsoc2013-evolution-cc670cb2ca319599eebac658f1164dbb64d70c65.zip |
New struct to wrap instances of calendar objects for recurrencies and
2000-02-08 Federico Mena Quintero <federico@helixcode.com>
* evolution-calendar.idl (CalObjInstance): New struct to wrap
instances of calendar objects for recurrencies and alarms.
(Cal::get_events_in_range): New method to get ocurring and
recurring events by time range.
* cal-backend.c (cal_backend_get_events_in_range): New function to
get a list of event instances in a time range.
(string_from_ical_object): New internal function.
(cal_backend_get_object): Use string_from_ical_object() instead of
doing everything ourselves.
(cal_backend_get_events_in_range): New function to get a list of
the events that occur or recur in a specified time range.
* cal-client.c (cal_client_get_events_in_range): Implemented
client-side function.
* cal-util.h:
* cal-util.c: New files with utilities and types common to the
client and server parts.
(CalObjInstance): New structure to hold an instance of an actual
occurrence, recurrence, or alarm trigger of a calendar object.
(cal_obj_instance_list_free): New function to free a list of
calendar object instances.
* cal.c (Cal_get_events_in_range): Implemented new method.
* corba-cal.c (cal_repo_get_updated_objects): Free `str' with
free(), not g_free(), since calendar_get_as_vcal_string() uses
writeMemVObject(), which uses realloc(). Fixed in gnome-pim as
well.
svn path=/trunk/; revision=1693
-rw-r--r-- | calendar/ChangeLog | 33 | ||||
-rw-r--r-- | calendar/Makefile.am | 4 | ||||
-rw-r--r-- | calendar/cal-backend.c | 129 | ||||
-rw-r--r-- | calendar/cal-backend.h | 8 | ||||
-rw-r--r-- | calendar/cal-client.c | 54 | ||||
-rw-r--r-- | calendar/cal-client.h | 3 | ||||
-rw-r--r-- | calendar/cal-client/cal-client.c | 54 | ||||
-rw-r--r-- | calendar/cal-client/cal-client.h | 3 | ||||
-rw-r--r-- | calendar/cal.c | 58 | ||||
-rw-r--r-- | calendar/corba-cal.c | 2 | ||||
-rw-r--r-- | calendar/evolution-calendar.idl | 22 | ||||
-rw-r--r-- | calendar/gui/Makefile.am | 4 | ||||
-rw-r--r-- | calendar/gui/corba-cal.c | 2 | ||||
-rw-r--r-- | calendar/idl/evolution-calendar.idl | 22 | ||||
-rw-r--r-- | calendar/pcs/cal-backend.c | 129 | ||||
-rw-r--r-- | calendar/pcs/cal-backend.h | 8 | ||||
-rw-r--r-- | calendar/pcs/cal.c | 58 |
17 files changed, 567 insertions, 26 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog index 489b0f319c..7e5b0db773 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,36 @@ +2000-02-08 Federico Mena Quintero <federico@helixcode.com> + + * evolution-calendar.idl (CalObjInstance): New struct to wrap + instances of calendar objects for recurrencies and alarms. + (Cal::get_events_in_range): New method to get ocurring and + recurring events by time range. + + * cal-backend.c (cal_backend_get_events_in_range): New function to + get a list of event instances in a time range. + (string_from_ical_object): New internal function. + (cal_backend_get_object): Use string_from_ical_object() instead of + doing everything ourselves. + (cal_backend_get_events_in_range): New function to get a list of + the events that occur or recur in a specified time range. + + * cal-client.c (cal_client_get_events_in_range): Implemented + client-side function. + + * cal-util.h: + * cal-util.c: New files with utilities and types common to the + client and server parts. + (CalObjInstance): New structure to hold an instance of an actual + occurrence, recurrence, or alarm trigger of a calendar object. + (cal_obj_instance_list_free): New function to free a list of + calendar object instances. + + * cal.c (Cal_get_events_in_range): Implemented new method. + + * corba-cal.c (cal_repo_get_updated_objects): Free `str' with + free(), not g_free(), since calendar_get_as_vcal_string() uses + writeMemVObject(), which uses realloc(). Fixed in gnome-pim as + well. + 2000-02-04 Federico Mena Quintero <federico@helixcode.com> * cal-backend.c (get_calendar_base_vobject): New function to diff --git a/calendar/Makefile.am b/calendar/Makefile.am index 408f80dd76..5fa18ba0dd 100644 --- a/calendar/Makefile.am +++ b/calendar/Makefile.am @@ -62,6 +62,8 @@ gnomecal_SOURCES = \ cal-client.h \ cal-listener.c \ cal-listener.h \ + cal-util.c \ + cal-util.h \ calendar.c \ calendar.h \ calendar-conduit.h \ @@ -134,6 +136,8 @@ tlacuache_SOURCES = \ cal-common.h \ cal-factory.c \ cal-factory.h \ + cal-util.c \ + cal-util.h \ calobj.c \ calobj.h \ job.c \ diff --git a/calendar/cal-backend.c b/calendar/cal-backend.c index 72315e3882..2039c9c400 100644 --- a/calendar/cal-backend.c +++ b/calendar/cal-backend.c @@ -299,6 +299,30 @@ get_calendar_base_vobject (CalBackend *backend) return vobj; } +/* Builds the string representation of a complete calendar object wrapping the + * specified object --- a complete calendar is needed because of the timezone + * information. The return value must be freed with free(), not g_free(), since + * the internal implementation calls writeMemVObject() from libversit, which + * uses realloc() to allocate this string. + */ +static char * +string_from_ical_object (CalBackend *backend, iCalObject *ico) +{ + VObject *vcalobj, *vobj; + char *buf; + + vcalobj = get_calendar_base_vobject (backend); + vobj = ical_object_to_vobject (ico); + addVObjectProp (vcalobj, vobj); + + buf = writeMemVObject (NULL, NULL, vcalobj); + + cleanVObject (vcalobj); + cleanStrTbl (); + + return buf; +} + /** @@ -467,8 +491,7 @@ cal_backend_get_object (CalBackend *backend, const char *uid) { CalBackendPrivate *priv; iCalObject *ico; - VObject *vcalobj, *vobj; - char *buf; + char *buf, *retval; g_return_val_if_fail (backend != NULL, NULL); g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL); @@ -480,19 +503,105 @@ cal_backend_get_object (CalBackend *backend, const char *uid) g_assert (priv->object_hash != NULL); - ico = g_hash_table_lookup (priv->objec_hash, uid); + ico = g_hash_table_lookup (priv->object_hash, uid); if (!ico) return NULL; - vcalobj = get_calendar_base_vobject (backend); - vobj = ical_object_to_vobject (ico); - addVObjectProp (vcalobj, vobj); + /* string_from_ical_object() uses writeMemVObject(), which uses + * realloc(), so we must free its result with free() instead of + * g_free(). We take a copy of the result so that callers can use the + * normal glib function to free it. + */ - buf = writeMemVObject (NULL, NULL, vcalobj); + buf = string_from_ical_object (backend, ico); + retval = g_strdup (buf); + free (buf); - cleanVObject (vcalobj); - cleanStrTbl (); + return retval; +} - return buf; +struct build_event_list_closure { + CalBackend *backend; + GList *event_list; +}; + +/* Builds a sorted list of event object instances. Used as a callback from + * ical_object_generate_events(). + */ +static int +build_event_list (iCalObject *ico, time_t start, time_t end, void *data) +{ + CalObjInstance *icoi; + struct build_event_list_closure *c; + + c = data; + + icoi = g_new (CalObjInstance, 1); + icoi->calobj = string_from_ical_object (c->backend, ico); + icoi->start = start; + icoi->end = end; + + c->event_list = g_list_prepend (c->event_list, icoi); + + return TRUE; +} + +/* Compares two CalObjInstance structures by their start times. Called from + * g_list_sort(). + */ +static gint +compare_instance_func (gconstpointer a, gconstpointer b) +{ + const CalObjInstance *ca, *cb; + time_t diff; + + ca = a; + cb = b; + + diff = ca->start - cb->start; + return (diff < 0) ? -1 : (diff > 0) ? 1 : 0; +} + +/** + * cal_backend_get_events_in_range: + * @backend: A calendar backend. + * @start: Start time for query. + * @end: End time for query. + * + * Builds a sorted list of calendar event object instances that occur or recur + * within the specified time range. Each object instance contains the object + * itself and the start/end times at which it occurs or recurs. + * + * Return value: A list of calendar event object instances, sorted by their + * start times. + **/ +GList * +cal_backend_get_events_in_range (CalBackend *backend, time_t start, time_t end) +{ + CalBackendPrivate *priv; + struct build_event_list_closure c; + GList *l; + + g_return_val_if_fail (backend != NULL, NULL); + g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL); + + priv = backend->priv; + g_return_val_if_fail (priv->loaded, NULL); + + g_return_val_if_fail (start != -1 && end != -1, NULL); + g_return_val_if_fail (start <= end, NULL); + + c.backend = backend; + c.event_list = NULL; + + for (l = priv->events; l; l = l->next) { + iCalObject *ico; + + ico = l->data; + ical_object_generate_events (ico, start, end, build_event_list, &c); + } + + c.event_list = g_list_sort (c.event_list, compare_instance_func); + return c.event_list; } diff --git a/calendar/cal-backend.h b/calendar/cal-backend.h index e972cbd59e..aa54a3339d 100644 --- a/calendar/cal-backend.h +++ b/calendar/cal-backend.h @@ -27,6 +27,7 @@ #include "evolution-calendar.h" #include "cal-common.h" #include "cal.h" +#include "cal-util.h" BEGIN_GNOME_DECLS @@ -39,9 +40,10 @@ BEGIN_GNOME_DECLS #define IS_CAL_BACKEND(obj) (GTK_CHECK_TYPE ((obj), CAL_BACKEND_TYPE)) #define IS_CAL_BACKEND_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), CAL_BACKEND_TYPE)) +/* Load status values */ typedef enum { - CAL_BACKEND_LOAD_SUCCESS, /* Loading OK */ - CAL_BACKEND_LOAD_ERROR /* We need better error reporting in libversit */ + CAL_BACKEND_LOAD_SUCCESS, /* Loading OK */ + CAL_BACKEND_LOAD_ERROR /* We need better error reporting in libversit */ } CalBackendLoadStatus; struct _CalBackend { @@ -68,6 +70,8 @@ CalBackendLoadStatus cal_backend_load (CalBackend *backend, GnomeVFSURI *uri); char *cal_backend_get_object (CalBackend *backend, const char *uid); +GList *cal_backend_get_events_in_range (CalBackend *backend, time_t start, time_t end); + END_GNOME_DECLS diff --git a/calendar/cal-client.c b/calendar/cal-client.c index 63d33610f6..af8b83db34 100644 --- a/calendar/cal-client.c +++ b/calendar/cal-client.c @@ -471,3 +471,57 @@ cal_client_get_object (CalClient *client, const char *uid) CORBA_exception_free (&ev); return retval; } + +GList * +cal_client_get_events_in_range (CalClient *client, time_t start, time_t end) +{ + CalClientPrivate *priv; + CORBA_Environment ev; + Evolution_Calendar_CalObjInstanceSeq *seq; + GList *elist; + int i; + + g_return_val_if_fail (client != NULL, NULL); + g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + + priv = client->priv; + g_return_val_if_fail (priv->load_state == LOAD_STATE_LOADED, NULL); + + g_return_val_if_fail (start != -1 && end != -1, NULL); + g_return_val_if_fail (start <= end, NULL); + + priv = client->priv; + + CORBA_exception_init (&ev); + + seq = Evolution_Calendar_Cal_get_events_in_range (priv->cal, start, end, &ev); + if (ev._major != CORBA_NO_EXCEPTION) { + g_message ("cal_client_get_events_in_range(): could not get the event range"); + CORBA_exception_free (&ev); + return NULL; + } + CORBA_exception_free (&ev); + + /* Create the list in reverse order */ + + elist = NULL; + + for (i = 0; i < seq->_length; i++) { + Evolution_Calendar_CalObjInstance *corba_icoi; + CalObjInstance *icoi; + + corba_icoi = &seq->_buffer[i]; + icoi = g_new (CalObjInstance, 1); + + icoi->calobj = g_strdup (corba_icoi->calobj); + icoi->start = corba_icoi->start; + icoi->end = corba_icoi->end; + + elist = g_list_prepend (elist, icoi); + } + + CORBA_free (seq); + elist = g_list_reverse (elist); + + return elist; +} diff --git a/calendar/cal-client.h b/calendar/cal-client.h index 2f9ae5e1f8..e81ec8c13a 100644 --- a/calendar/cal-client.h +++ b/calendar/cal-client.h @@ -24,6 +24,7 @@ #include <libgnome/gnome-defs.h> #include <gtk/gtkobject.h> +#include "cal-util.h" BEGIN_GNOME_DECLS @@ -73,6 +74,8 @@ gboolean cal_client_load_calendar (CalClient *client, const char *str_uri); char *cal_client_get_object (CalClient *client, const char *uid); +GList *cal_client_get_events_in_range (CalClient *client, time_t start, time_t end); + END_GNOME_DECLS diff --git a/calendar/cal-client/cal-client.c b/calendar/cal-client/cal-client.c index 63d33610f6..af8b83db34 100644 --- a/calendar/cal-client/cal-client.c +++ b/calendar/cal-client/cal-client.c @@ -471,3 +471,57 @@ cal_client_get_object (CalClient *client, const char *uid) CORBA_exception_free (&ev); return retval; } + +GList * +cal_client_get_events_in_range (CalClient *client, time_t start, time_t end) +{ + CalClientPrivate *priv; + CORBA_Environment ev; + Evolution_Calendar_CalObjInstanceSeq *seq; + GList *elist; + int i; + + g_return_val_if_fail (client != NULL, NULL); + g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + + priv = client->priv; + g_return_val_if_fail (priv->load_state == LOAD_STATE_LOADED, NULL); + + g_return_val_if_fail (start != -1 && end != -1, NULL); + g_return_val_if_fail (start <= end, NULL); + + priv = client->priv; + + CORBA_exception_init (&ev); + + seq = Evolution_Calendar_Cal_get_events_in_range (priv->cal, start, end, &ev); + if (ev._major != CORBA_NO_EXCEPTION) { + g_message ("cal_client_get_events_in_range(): could not get the event range"); + CORBA_exception_free (&ev); + return NULL; + } + CORBA_exception_free (&ev); + + /* Create the list in reverse order */ + + elist = NULL; + + for (i = 0; i < seq->_length; i++) { + Evolution_Calendar_CalObjInstance *corba_icoi; + CalObjInstance *icoi; + + corba_icoi = &seq->_buffer[i]; + icoi = g_new (CalObjInstance, 1); + + icoi->calobj = g_strdup (corba_icoi->calobj); + icoi->start = corba_icoi->start; + icoi->end = corba_icoi->end; + + elist = g_list_prepend (elist, icoi); + } + + CORBA_free (seq); + elist = g_list_reverse (elist); + + return elist; +} diff --git a/calendar/cal-client/cal-client.h b/calendar/cal-client/cal-client.h index 2f9ae5e1f8..e81ec8c13a 100644 --- a/calendar/cal-client/cal-client.h +++ b/calendar/cal-client/cal-client.h @@ -24,6 +24,7 @@ #include <libgnome/gnome-defs.h> #include <gtk/gtkobject.h> +#include "cal-util.h" BEGIN_GNOME_DECLS @@ -73,6 +74,8 @@ gboolean cal_client_load_calendar (CalClient *client, const char *str_uri); char *cal_client_get_object (CalClient *client, const char *uid); +GList *cal_client_get_events_in_range (CalClient *client, time_t start, time_t end); + END_GNOME_DECLS diff --git a/calendar/cal.c b/calendar/cal.c index 1ce1d91716..664d9ef416 100644 --- a/calendar/cal.c +++ b/calendar/cal.c @@ -196,6 +196,63 @@ Cal_get_object (PortableServer_Servant servant, } } +/* Cal::get_events_in_range method */ +static Evolution_Calendar_CalObjInstanceSeq * +Cal_get_events_in_range (PortableServer_Servant servant, + const Evolution_Calendar_Time_t start, + const Evolution_Calendar_Time_t end, + CORBA_Environment *ev) +{ + Cal *cal; + CalPrivate *priv; + time_t t_start, t_end; + Evolution_Calendar_CalObjInstanceSeq *seq; + GList *elist, *l; + int n, i; + + cal = CAL (bonobo_object_from_servant (servant)); + priv = cal->priv; + + t_start = (time_t) start; + t_end = (time_t) end; + + if (t_start > t_end || t_start == -1 || t_end == -1) { + CORBA_exception_set (ev, CORBA_USER_EXCEPTION, + ex_Evolution_Calendar_Cal_InvalidRange, + NULL); + return NULL; + } + + /* Figure out the list and allocate the sequence */ + + elist = cal_backend_get_events_in_range (priv->backend, t_start, t_end); + n = g_list_length (elist); + + seq = Evolution_Calendar_CalObjInstanceSeq__alloc (); + seq->_length = n; + seq->_buffer = CORBA_sequence_Evolution_Calendar_CalObjInstance_allocbuf (n); + + /* Fill the sequence */ + + for (i = 0, l = elist; i < n; i++, l = l->next) { + CalObjInstance *icoi; + Evolution_Calendar_CalObjInstance *corba_icoi; + + icoi = l->data; + corba_icoi = &seq->_buffer[i]; + + corba_icoi->calobj = CORBA_string_dup (icoi->calobj); + corba_icoi->start = icoi->start; + corba_icoi->end = icoi->end; + } + + /* Done */ + + cal_obj_instance_list_free (elist); + + return seq; +} + /** * cal_get_epv: * @void: @@ -212,6 +269,7 @@ cal_get_epv (void) epv = g_new0 (POA_Evolution_Calendar_Cal__epv, 1); epv->_get_uri = Cal_get_uri; epv->get_object = Cal_get_object; + epv->get_events_in_range = Cal_get_events_in_range; return epv; } diff --git a/calendar/corba-cal.c b/calendar/corba-cal.c index 74afc0e76a..7b9878f875 100644 --- a/calendar/corba-cal.c +++ b/calendar/corba-cal.c @@ -295,7 +295,7 @@ cal_repo_get_updated_objects (PortableServer_Servant servant, } str = calendar_get_as_vcal_string (dirty_cal); res = CORBA_string_dup (str); - g_free (str); + free (str); /* calendar_get_as_vcal_string() uses writeMemVObject(), which uses realloc() */ calendar_destroy (dirty_cal); return res; diff --git a/calendar/evolution-calendar.idl b/calendar/evolution-calendar.idl index 6746eb66a1..8b9878d78e 100644 --- a/calendar/evolution-calendar.idl +++ b/calendar/evolution-calendar.idl @@ -23,11 +23,29 @@ module Calendar { /* An unique identifier for a calendar object */ typedef string CalObjUID; + /* Used to store a time_t */ + typedef unsigned long Time_t; + + /* An instance of a calendar object 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. + */ + struct CalObjInstance { + CalObj calobj; + Time_t start; + Time_t end; + }; + + typedef sequence<CalObjInstance> CalObjInstanceSeq; + interface Listener; /* Calendar client interface */ interface Cal : Bonobo::Unknown { exception NotFound {}; + exception InvalidRange {}; /* A calendar is identified by its URI */ readonly attribute string uri; @@ -35,6 +53,10 @@ module Calendar { /* Gets an object based on its URI */ CalObj get_object (in CalObjUID uid) raises (NotFound); + + /* Gets the events that occur or recur in the specified time range */ + CalObjInstanceSeq get_events_in_range (in Time_t start, in Time_t end) + raises (InvalidRange); }; /* Listener for changes in a calendar */ diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am index 408f80dd76..5fa18ba0dd 100644 --- a/calendar/gui/Makefile.am +++ b/calendar/gui/Makefile.am @@ -62,6 +62,8 @@ gnomecal_SOURCES = \ cal-client.h \ cal-listener.c \ cal-listener.h \ + cal-util.c \ + cal-util.h \ calendar.c \ calendar.h \ calendar-conduit.h \ @@ -134,6 +136,8 @@ tlacuache_SOURCES = \ cal-common.h \ cal-factory.c \ cal-factory.h \ + cal-util.c \ + cal-util.h \ calobj.c \ calobj.h \ job.c \ diff --git a/calendar/gui/corba-cal.c b/calendar/gui/corba-cal.c index 74afc0e76a..7b9878f875 100644 --- a/calendar/gui/corba-cal.c +++ b/calendar/gui/corba-cal.c @@ -295,7 +295,7 @@ cal_repo_get_updated_objects (PortableServer_Servant servant, } str = calendar_get_as_vcal_string (dirty_cal); res = CORBA_string_dup (str); - g_free (str); + free (str); /* calendar_get_as_vcal_string() uses writeMemVObject(), which uses realloc() */ calendar_destroy (dirty_cal); return res; diff --git a/calendar/idl/evolution-calendar.idl b/calendar/idl/evolution-calendar.idl index 6746eb66a1..8b9878d78e 100644 --- a/calendar/idl/evolution-calendar.idl +++ b/calendar/idl/evolution-calendar.idl @@ -23,11 +23,29 @@ module Calendar { /* An unique identifier for a calendar object */ typedef string CalObjUID; + /* Used to store a time_t */ + typedef unsigned long Time_t; + + /* An instance of a calendar object 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. + */ + struct CalObjInstance { + CalObj calobj; + Time_t start; + Time_t end; + }; + + typedef sequence<CalObjInstance> CalObjInstanceSeq; + interface Listener; /* Calendar client interface */ interface Cal : Bonobo::Unknown { exception NotFound {}; + exception InvalidRange {}; /* A calendar is identified by its URI */ readonly attribute string uri; @@ -35,6 +53,10 @@ module Calendar { /* Gets an object based on its URI */ CalObj get_object (in CalObjUID uid) raises (NotFound); + + /* Gets the events that occur or recur in the specified time range */ + CalObjInstanceSeq get_events_in_range (in Time_t start, in Time_t end) + raises (InvalidRange); }; /* Listener for changes in a calendar */ diff --git a/calendar/pcs/cal-backend.c b/calendar/pcs/cal-backend.c index 72315e3882..2039c9c400 100644 --- a/calendar/pcs/cal-backend.c +++ b/calendar/pcs/cal-backend.c @@ -299,6 +299,30 @@ get_calendar_base_vobject (CalBackend *backend) return vobj; } +/* Builds the string representation of a complete calendar object wrapping the + * specified object --- a complete calendar is needed because of the timezone + * information. The return value must be freed with free(), not g_free(), since + * the internal implementation calls writeMemVObject() from libversit, which + * uses realloc() to allocate this string. + */ +static char * +string_from_ical_object (CalBackend *backend, iCalObject *ico) +{ + VObject *vcalobj, *vobj; + char *buf; + + vcalobj = get_calendar_base_vobject (backend); + vobj = ical_object_to_vobject (ico); + addVObjectProp (vcalobj, vobj); + + buf = writeMemVObject (NULL, NULL, vcalobj); + + cleanVObject (vcalobj); + cleanStrTbl (); + + return buf; +} + /** @@ -467,8 +491,7 @@ cal_backend_get_object (CalBackend *backend, const char *uid) { CalBackendPrivate *priv; iCalObject *ico; - VObject *vcalobj, *vobj; - char *buf; + char *buf, *retval; g_return_val_if_fail (backend != NULL, NULL); g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL); @@ -480,19 +503,105 @@ cal_backend_get_object (CalBackend *backend, const char *uid) g_assert (priv->object_hash != NULL); - ico = g_hash_table_lookup (priv->objec_hash, uid); + ico = g_hash_table_lookup (priv->object_hash, uid); if (!ico) return NULL; - vcalobj = get_calendar_base_vobject (backend); - vobj = ical_object_to_vobject (ico); - addVObjectProp (vcalobj, vobj); + /* string_from_ical_object() uses writeMemVObject(), which uses + * realloc(), so we must free its result with free() instead of + * g_free(). We take a copy of the result so that callers can use the + * normal glib function to free it. + */ - buf = writeMemVObject (NULL, NULL, vcalobj); + buf = string_from_ical_object (backend, ico); + retval = g_strdup (buf); + free (buf); - cleanVObject (vcalobj); - cleanStrTbl (); + return retval; +} - return buf; +struct build_event_list_closure { + CalBackend *backend; + GList *event_list; +}; + +/* Builds a sorted list of event object instances. Used as a callback from + * ical_object_generate_events(). + */ +static int +build_event_list (iCalObject *ico, time_t start, time_t end, void *data) +{ + CalObjInstance *icoi; + struct build_event_list_closure *c; + + c = data; + + icoi = g_new (CalObjInstance, 1); + icoi->calobj = string_from_ical_object (c->backend, ico); + icoi->start = start; + icoi->end = end; + + c->event_list = g_list_prepend (c->event_list, icoi); + + return TRUE; +} + +/* Compares two CalObjInstance structures by their start times. Called from + * g_list_sort(). + */ +static gint +compare_instance_func (gconstpointer a, gconstpointer b) +{ + const CalObjInstance *ca, *cb; + time_t diff; + + ca = a; + cb = b; + + diff = ca->start - cb->start; + return (diff < 0) ? -1 : (diff > 0) ? 1 : 0; +} + +/** + * cal_backend_get_events_in_range: + * @backend: A calendar backend. + * @start: Start time for query. + * @end: End time for query. + * + * Builds a sorted list of calendar event object instances that occur or recur + * within the specified time range. Each object instance contains the object + * itself and the start/end times at which it occurs or recurs. + * + * Return value: A list of calendar event object instances, sorted by their + * start times. + **/ +GList * +cal_backend_get_events_in_range (CalBackend *backend, time_t start, time_t end) +{ + CalBackendPrivate *priv; + struct build_event_list_closure c; + GList *l; + + g_return_val_if_fail (backend != NULL, NULL); + g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL); + + priv = backend->priv; + g_return_val_if_fail (priv->loaded, NULL); + + g_return_val_if_fail (start != -1 && end != -1, NULL); + g_return_val_if_fail (start <= end, NULL); + + c.backend = backend; + c.event_list = NULL; + + for (l = priv->events; l; l = l->next) { + iCalObject *ico; + + ico = l->data; + ical_object_generate_events (ico, start, end, build_event_list, &c); + } + + c.event_list = g_list_sort (c.event_list, compare_instance_func); + return c.event_list; } diff --git a/calendar/pcs/cal-backend.h b/calendar/pcs/cal-backend.h index e972cbd59e..aa54a3339d 100644 --- a/calendar/pcs/cal-backend.h +++ b/calendar/pcs/cal-backend.h @@ -27,6 +27,7 @@ #include "evolution-calendar.h" #include "cal-common.h" #include "cal.h" +#include "cal-util.h" BEGIN_GNOME_DECLS @@ -39,9 +40,10 @@ BEGIN_GNOME_DECLS #define IS_CAL_BACKEND(obj) (GTK_CHECK_TYPE ((obj), CAL_BACKEND_TYPE)) #define IS_CAL_BACKEND_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), CAL_BACKEND_TYPE)) +/* Load status values */ typedef enum { - CAL_BACKEND_LOAD_SUCCESS, /* Loading OK */ - CAL_BACKEND_LOAD_ERROR /* We need better error reporting in libversit */ + CAL_BACKEND_LOAD_SUCCESS, /* Loading OK */ + CAL_BACKEND_LOAD_ERROR /* We need better error reporting in libversit */ } CalBackendLoadStatus; struct _CalBackend { @@ -68,6 +70,8 @@ CalBackendLoadStatus cal_backend_load (CalBackend *backend, GnomeVFSURI *uri); char *cal_backend_get_object (CalBackend *backend, const char *uid); +GList *cal_backend_get_events_in_range (CalBackend *backend, time_t start, time_t end); + END_GNOME_DECLS diff --git a/calendar/pcs/cal.c b/calendar/pcs/cal.c index 1ce1d91716..664d9ef416 100644 --- a/calendar/pcs/cal.c +++ b/calendar/pcs/cal.c @@ -196,6 +196,63 @@ Cal_get_object (PortableServer_Servant servant, } } +/* Cal::get_events_in_range method */ +static Evolution_Calendar_CalObjInstanceSeq * +Cal_get_events_in_range (PortableServer_Servant servant, + const Evolution_Calendar_Time_t start, + const Evolution_Calendar_Time_t end, + CORBA_Environment *ev) +{ + Cal *cal; + CalPrivate *priv; + time_t t_start, t_end; + Evolution_Calendar_CalObjInstanceSeq *seq; + GList *elist, *l; + int n, i; + + cal = CAL (bonobo_object_from_servant (servant)); + priv = cal->priv; + + t_start = (time_t) start; + t_end = (time_t) end; + + if (t_start > t_end || t_start == -1 || t_end == -1) { + CORBA_exception_set (ev, CORBA_USER_EXCEPTION, + ex_Evolution_Calendar_Cal_InvalidRange, + NULL); + return NULL; + } + + /* Figure out the list and allocate the sequence */ + + elist = cal_backend_get_events_in_range (priv->backend, t_start, t_end); + n = g_list_length (elist); + + seq = Evolution_Calendar_CalObjInstanceSeq__alloc (); + seq->_length = n; + seq->_buffer = CORBA_sequence_Evolution_Calendar_CalObjInstance_allocbuf (n); + + /* Fill the sequence */ + + for (i = 0, l = elist; i < n; i++, l = l->next) { + CalObjInstance *icoi; + Evolution_Calendar_CalObjInstance *corba_icoi; + + icoi = l->data; + corba_icoi = &seq->_buffer[i]; + + corba_icoi->calobj = CORBA_string_dup (icoi->calobj); + corba_icoi->start = icoi->start; + corba_icoi->end = icoi->end; + } + + /* Done */ + + cal_obj_instance_list_free (elist); + + return seq; +} + /** * cal_get_epv: * @void: @@ -212,6 +269,7 @@ cal_get_epv (void) epv = g_new0 (POA_Evolution_Calendar_Cal__epv, 1); epv->_get_uri = Cal_get_uri; epv->get_object = Cal_get_object; + epv->get_events_in_range = Cal_get_events_in_range; return epv; } |