aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFederico Mena Quintero <federico@helixcode.com>2000-02-08 15:08:29 +0800
committerArturo Espinosa <unammx@src.gnome.org>2000-02-08 15:08:29 +0800
commitcc670cb2ca319599eebac658f1164dbb64d70c65 (patch)
tree55dc72c7ea1b1582158e8aa55eedb9d18a4ab4e4
parentc02660b4081a84c9ad5749a931f5458f08f634d3 (diff)
downloadgsoc2013-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/ChangeLog33
-rw-r--r--calendar/Makefile.am4
-rw-r--r--calendar/cal-backend.c129
-rw-r--r--calendar/cal-backend.h8
-rw-r--r--calendar/cal-client.c54
-rw-r--r--calendar/cal-client.h3
-rw-r--r--calendar/cal-client/cal-client.c54
-rw-r--r--calendar/cal-client/cal-client.h3
-rw-r--r--calendar/cal.c58
-rw-r--r--calendar/corba-cal.c2
-rw-r--r--calendar/evolution-calendar.idl22
-rw-r--r--calendar/gui/Makefile.am4
-rw-r--r--calendar/gui/corba-cal.c2
-rw-r--r--calendar/idl/evolution-calendar.idl22
-rw-r--r--calendar/pcs/cal-backend.c129
-rw-r--r--calendar/pcs/cal-backend.h8
-rw-r--r--calendar/pcs/cal.c58
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;
}