[libgdata] [calendar] Added recurrence support to GDataCalendarEvent
- From: Philip Withnall <pwithnall src gnome org>
- To: svn-commits-list gnome org
- Subject: [libgdata] [calendar] Added recurrence support to GDataCalendarEvent
- Date: Mon, 27 Apr 2009 14:33:40 -0400 (EDT)
commit 895a3f25756f0a368e6844c6caaf0b80c5612bef
Author: Philip Withnall <philip tecnocode co uk>
Date: Mon Apr 27 18:44:26 2009 +0100
[calendar] Added recurrence support to GDataCalendarEvent
Added gdata_calendar_event_[get|set]_recurrence,
gdata_calendar_event_get_original_event_details and
gdata_calendar_event_is_exception. Added a test case too.
---
docs/reference/gdata-sections.txt | 4 +
gdata/gdata-entry.c | 2 +-
gdata/gdata-feed.c | 2 +-
gdata/gdata.symbols | 4 +
gdata/services/calendar/gdata-calendar-event.c | 170 +++++++++++++++++++++++-
gdata/services/calendar/gdata-calendar-event.h | 4 +
gdata/tests/calendar.c | 64 +++++++++
7 files changed, 245 insertions(+), 5 deletions(-)
diff --git a/docs/reference/gdata-sections.txt b/docs/reference/gdata-sections.txt
index 535051d..9b01681 100644
--- a/docs/reference/gdata-sections.txt
+++ b/docs/reference/gdata-sections.txt
@@ -521,6 +521,10 @@ gdata_calendar_event_add_place
gdata_calendar_event_get_times
gdata_calendar_event_get_primary_time
gdata_calendar_event_add_time
+gdata_calendar_event_get_recurrence
+gdata_calendar_event_set_recurrence
+gdata_calendar_event_get_original_event_details
+gdata_calendar_event_is_exception
gdata_calendar_event_get_anyone_can_add_self
gdata_calendar_event_set_anyone_can_add_self
gdata_calendar_event_get_guests_can_invite_others
diff --git a/gdata/gdata-entry.c b/gdata/gdata-entry.c
index 20f670c..672462b 100644
--- a/gdata/gdata-entry.c
+++ b/gdata/gdata-entry.c
@@ -567,7 +567,7 @@ real_parse_xml (GDataEntry *self, xmlDoc *doc, xmlNode *node, GError **error)
buffer = xmlBufferCreate ();
xmlNodeDump (buffer, doc, node, 0, 0);
g_string_append (self->priv->extra_xml, (gchar*) xmlBufferContent (buffer));
- g_message ("Unhandled XML: %s", (gchar*) xmlBufferContent (buffer));
+ g_message ("Unhandled XML in <entry>: %s", (gchar*) xmlBufferContent (buffer));
xmlBufferFree (buffer);
/* Get the namespaces */
diff --git a/gdata/gdata-feed.c b/gdata/gdata-feed.c
index 2b042df..d4632d2 100644
--- a/gdata/gdata-feed.c
+++ b/gdata/gdata-feed.c
@@ -659,7 +659,7 @@ _gdata_feed_new_from_xml (const gchar *xml, gint length, GType entry_type,
xmlBuffer *buffer = xmlBufferCreate ();
xmlNodeDump (buffer, doc, node, 0, 0);
g_string_append (extra_xml, (gchar*) xmlBufferContent (buffer));
- g_message ("Unhandled XML: %s", (gchar*) xmlBufferContent (buffer));
+ g_message ("Unhandled XML in <feed>: %s", (gchar*) xmlBufferContent (buffer));
xmlBufferFree (buffer);
}
diff --git a/gdata/gdata.symbols b/gdata/gdata.symbols
index 769c485..ad0800a 100644
--- a/gdata/gdata.symbols
+++ b/gdata/gdata.symbols
@@ -198,6 +198,10 @@ gdata_calendar_event_get_places
gdata_calendar_event_add_time
gdata_calendar_event_get_times
gdata_calendar_event_get_primary_time
+gdata_calendar_event_get_recurrence
+gdata_calendar_event_set_recurrence
+gdata_calendar_event_get_original_event_details
+gdata_calendar_event_is_exception
gdata_calendar_query_get_type
gdata_calendar_query_new
gdata_calendar_query_new_with_limits
diff --git a/gdata/services/calendar/gdata-calendar-event.c b/gdata/services/calendar/gdata-calendar-event.c
index 35024b6..1ef5e30 100644
--- a/gdata/services/calendar/gdata-calendar-event.c
+++ b/gdata/services/calendar/gdata-calendar-event.c
@@ -64,6 +64,9 @@ struct _GDataCalendarEventPrivate {
guint anyone_can_add_self : 1;
GList *people; /* GDataGDWho */
GList *places; /* GDataGDWhere */
+ gchar *recurrence;
+ gchar *original_event_id;
+ gchar *original_event_uri;
};
enum {
@@ -76,7 +79,10 @@ enum {
PROP_GUESTS_CAN_MODIFY,
PROP_GUESTS_CAN_INVITE_OTHERS,
PROP_GUESTS_CAN_SEE_GUESTS,
- PROP_ANYONE_CAN_ADD_SELF
+ PROP_ANYONE_CAN_ADD_SELF,
+ PROP_RECURRENCE,
+ PROP_ORIGINAL_EVENT_ID,
+ PROP_ORIGINAL_EVENT_URI
};
G_DEFINE_TYPE (GDataCalendarEvent, gdata_calendar_event, GDATA_TYPE_ENTRY)
@@ -200,8 +206,8 @@ gdata_calendar_event_class_init (GDataCalendarEventClass *klass)
*
* Indicates whether event attendees may invite other people to the event.
*
- * For more information, see the <ulink type="http" url="http://code.google.com/apis/calendar/docs/2.0/reference.html#gCalguestsCanInviteOthers">
- * GData specification</ulink>.
+ * For more information, see the <ulink type="http"
+ * url="http://code.google.com/apis/calendar/docs/2.0/reference.html#gCalguestsCanInviteOthers">GData specification</ulink>.
**/
g_object_class_install_property (gobject_class, PROP_GUESTS_CAN_INVITE_OTHERS,
g_param_spec_boolean ("guests-can-invite-others",
@@ -233,6 +239,49 @@ gdata_calendar_event_class_init (GDataCalendarEventClass *klass)
"Anyone can add self", "Indicates whether anyone can add themselves to the attendee list of the event.",
FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GDataCalendarEvent:recurrence:
+ *
+ * Represents the dates and times when a recurring event takes place. The returned string is in iCal format, as a list of properties.
+ *
+ * For more information, see the <ulink type="http" url="http://code.google.com/apis/gdata/elements.html#gdRecurrence">
+ * GData specification</ulink>.
+ *
+ * Since: 0.3.0
+ **/
+ g_object_class_install_property (gobject_class, PROP_RECURRENCE,
+ g_param_spec_string ("recurrence",
+ "Recurrence", "Represents the dates and times when a recurring event takes place.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GDataCalendarEvent:original-event-id:
+ *
+ * The event ID for the original event, if this event is an exception to a recurring event.
+ *
+ * Since: 0.3.0
+ **/
+ g_object_class_install_property (gobject_class, PROP_ORIGINAL_EVENT_ID,
+ g_param_spec_string ("original-event-id",
+ "Original event ID", "The event ID for the original event, if this event is an exception to a recurring event.",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GDataCalendarEvent:original-event-uri:
+ *
+ * The event URI for the original event, if this event is an exception to a recurring event.
+ *
+ * Since: 0.3.0
+ **/
+ g_object_class_install_property (gobject_class, PROP_ORIGINAL_EVENT_URI,
+ g_param_spec_string ("original-event-uri",
+ "Original event URI", "The event URI for the original event, if this event is an exception"
+ " to a recurring event.",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
}
static void
@@ -256,6 +305,9 @@ gdata_calendar_event_finalize (GObject *object)
g_list_free (priv->people);
g_list_foreach (priv->places, (GFunc) gdata_gd_where_free, NULL);
g_list_free (priv->places);
+ g_free (priv->recurrence);
+ xmlFree ((xmlChar*) priv->original_event_id);
+ xmlFree ((xmlChar*) priv->original_event_uri);
/* Chain up to the parent class */
G_OBJECT_CLASS (gdata_calendar_event_parent_class)->finalize (object);
@@ -297,6 +349,15 @@ gdata_calendar_event_get_property (GObject *object, guint property_id, GValue *v
case PROP_ANYONE_CAN_ADD_SELF:
g_value_set_boolean (value, priv->anyone_can_add_self);
break;
+ case PROP_RECURRENCE:
+ g_value_set_string (value, priv->recurrence);
+ break;
+ case PROP_ORIGINAL_EVENT_ID:
+ g_value_set_string (value, priv->original_event_id);
+ break;
+ case PROP_ORIGINAL_EVENT_URI:
+ g_value_set_string (value, priv->original_event_uri);
+ break;
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -337,6 +398,9 @@ gdata_calendar_event_set_property (GObject *object, guint property_id, const GVa
case PROP_ANYONE_CAN_ADD_SELF:
gdata_calendar_event_set_anyone_can_add_self (self, g_value_get_boolean (value));
break;
+ case PROP_RECURRENCE:
+ gdata_calendar_event_set_recurrence (self, g_value_get_string (value));
+ break;
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -568,6 +632,19 @@ parse_xml (GDataEntry *entry, xmlDoc *doc, xmlNode *node, GError **error)
xmlFree (label);
gdata_calendar_event_add_place (self, where);
+ } else if (xmlStrcmp (node->name, (xmlChar*) "recurrence") == 0) {
+ /* gd:recurrence */
+ xmlChar *recurrence = xmlNodeListGetString (doc, node->xmlChildrenNode, TRUE);
+ gdata_calendar_event_set_recurrence (self, (gchar*) recurrence);
+ xmlFree (recurrence);
+ } else if (xmlStrcmp (node->name, (xmlChar*) "originalEvent") == 0) {
+ /* gd:originalEvent */
+ g_object_freeze_notify (G_OBJECT (self));
+ self->priv->original_event_id = (gchar*) xmlGetProp (node, (xmlChar*) "id");
+ g_object_notify (G_OBJECT (self), "original-event-id");
+ self->priv->original_event_uri = (gchar*) xmlGetProp (node, (xmlChar*) "href");
+ g_object_notify (G_OBJECT (self), "original-event-uri");
+ g_object_thaw_notify (G_OBJECT (self));
} else if (GDATA_ENTRY_CLASS (gdata_calendar_event_parent_class)->parse_xml (entry, doc, node, error) == FALSE) {
/* Error! */
return FALSE;
@@ -624,6 +701,9 @@ get_xml (GDataEntry *entry, GString *xml_string)
else
g_string_append (xml_string, "<gCal:anyoneCanAddSelf value='false'/>");
+ if (priv->recurrence != NULL)
+ g_string_append_printf (xml_string, "<gd:recurrence>%s</gd:recurrence>", priv->recurrence);
+
for (i = priv->times; i != NULL; i = i->next) {
gchar *start_time;
GDataGDWhen *when = (GDataGDWhen*) i->data;
@@ -1154,3 +1234,87 @@ gdata_calendar_event_get_primary_time (GDataCalendarEvent *self, GTimeVal *start
return TRUE;
}
+
+/**
+ * gdata_calendar_event_get_recurrence:
+ * @self: a #GDataCalendarEvent
+ *
+ * Gets the #GDataCalendarEvent:recurrence property.
+ *
+ * Return value: the event recurrence patterns, or %NULL
+ *
+ * Since: 0.3.0
+ **/
+const gchar *
+gdata_calendar_event_get_recurrence (GDataCalendarEvent *self)
+{
+ g_return_val_if_fail (GDATA_IS_CALENDAR_EVENT (self), NULL);
+ return self->priv->recurrence;
+}
+
+/**
+ * gdata_calendar_event_set_recurrence:
+ * @self: a #GDataCalendarEvent
+ * @recurrence: a new event recurrence, or %NULL
+ *
+ * Sets the #GDataCalendarEvent:recurrence property to the new recurrence, @recurrence.
+ *
+ * Set @recurrence to %NULL to unset the property in the event.
+ *
+ * Since: 0.3.0
+ **/
+void
+gdata_calendar_event_set_recurrence (GDataCalendarEvent *self, const gchar *recurrence)
+{
+ g_return_if_fail (GDATA_IS_CALENDAR_EVENT (self));
+
+ g_free (self->priv->recurrence);
+ self->priv->recurrence = g_strdup (recurrence);
+ g_object_notify (G_OBJECT (self), "recurrence");
+}
+
+/**
+ * gdata_calendar_event_get_original_event_details:
+ * @self: a #GDataCalendarEvent
+ * @event_id: return location for the original event's ID, or %NULL
+ * @event_uri: return location for the original event's URI, or %NULL
+ *
+ * Gets details of the original event, if this event is an exception to a recurring event. The original
+ * event's ID and the URI of the event's XML are returned in @event_id and @event_uri, respectively.
+ *
+ * If this event is not an exception to a recurring event, @event_id and @event_uri will be set to %NULL.
+ * See gdata_calendar_event_is_exception() to determine more simply whether an event is an exception to a
+ * recurring event.
+ *
+ * If both @event_id and @event_uri are %NULL, this function is a no-op.
+ *
+ * Since: 0.3.0
+ **/
+void
+gdata_calendar_event_get_original_event_details (GDataCalendarEvent *self, gchar **event_id, gchar **event_uri)
+{
+ g_return_if_fail (GDATA_IS_CALENDAR_EVENT (self));
+
+ if (event_id != NULL)
+ *event_id = g_strdup (self->priv->original_event_id);
+ if (event_uri != NULL)
+ *event_uri = g_strdup (self->priv->original_event_uri);
+}
+
+/**
+ * gdata_calendar_event_is_exception:
+ * @self: a #GDataCalendarEvent
+ *
+ * Determines whether the event is an exception to a recurring event. If it is, details of the original event
+ * can be retrieved using gdata_calendar_event_get_original_event_details().
+ *
+ * Return value: %TRUE if the event is an exception, %FALSE otherwise
+ *
+ * Since: 0.3.0.
+ **/
+gboolean
+gdata_calendar_event_is_exception (GDataCalendarEvent *self)
+{
+ g_return_val_if_fail (GDATA_IS_CALENDAR_EVENT (self), FALSE);
+ return (self->priv->original_event_id != NULL && self->priv->original_event_uri != NULL) ? TRUE : FALSE;
+}
diff --git a/gdata/services/calendar/gdata-calendar-event.h b/gdata/services/calendar/gdata-calendar-event.h
index f991697..aee82df 100644
--- a/gdata/services/calendar/gdata-calendar-event.h
+++ b/gdata/services/calendar/gdata-calendar-event.h
@@ -89,6 +89,10 @@ GList *gdata_calendar_event_get_places (GDataCalendarEvent *self);
void gdata_calendar_event_add_time (GDataCalendarEvent *self, GDataGDWhen *when);
GList *gdata_calendar_event_get_times (GDataCalendarEvent *self);
gboolean gdata_calendar_event_get_primary_time (GDataCalendarEvent *self, GTimeVal *start_time, GTimeVal *end_time, GDataGDWhen **when);
+const gchar *gdata_calendar_event_get_recurrence (GDataCalendarEvent *self);
+void gdata_calendar_event_set_recurrence (GDataCalendarEvent *self, const gchar *recurrence);
+void gdata_calendar_event_get_original_event_details (GDataCalendarEvent *self, gchar **event_id, gchar **event_uri);
+gboolean gdata_calendar_event_is_exception (GDataCalendarEvent *self);
G_END_DECLS
diff --git a/gdata/tests/calendar.c b/gdata/tests/calendar.c
index 451065b..dc006be 100644
--- a/gdata/tests/calendar.c
+++ b/gdata/tests/calendar.c
@@ -373,6 +373,69 @@ test_xml_dates (void)
}
static void
+test_xml_recurrence (void)
+{
+ GDataCalendarEvent *event;
+ gchar *xml;
+ GError *error = NULL;
+ gchar *id, *uri;
+
+ event = gdata_calendar_event_new_from_xml (
+ "<entry xmlns='http://www.w3.org/2005/Atom' "
+ "xmlns:gd='http://schemas.google.com/g/2005' "
+ "xmlns:gCal='http://schemas.google.com/gCal/2005' "
+ "xmlns:app='http://www.w3.org/2007/app'>"
+ "<id>http://www.google.com/calendar/feeds/libgdata test googlemail com/events/g5928e82rrch95b25f8ud0dlsg_20090429T153000Z</id>"
+ "<published>2009-04-25T15:22:47.000Z</published>"
+ "<updated>2009-04-27T17:54:10.000Z</updated>"
+ "<app:edited xmlns:app='http://www.w3.org/2007/app'>2009-04-27T17:54:10.000Z</app:edited>"
+ "<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'/>"
+ "<title>Test daily instance event</title>"
+ "<content></content>"
+ "<link rel='alternate' type='text/html' href='http://www.google.com/calendar/event?eid=ZzU5MjhlODJycmNoOTViMjVmOHVkMGRsc2dfMjAwOTA0MjlUMTUzMDAwWiBsaWJnZGF0YS50ZXN0QGdvb2dsZW1haWwuY29t' title='alternate'/>"
+ "<link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/libgdata test googlemail com/private/full/g5928e82rrch95b25f8ud0dlsg_20090429T153000Z'/>"
+ "<link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/libgdata test googlemail com/private/full/g5928e82rrch95b25f8ud0dlsg_20090429T153000Z'/>"
+ "<author>"
+ "<name>GData Test</name>"
+ "<email>libgdata test googlemail com</email>"
+ "</author>"
+ "<gd:originalEvent id='g5928e82rrch95b25f8ud0dlsg' href='http://www.google.com/calendar/feeds/libgdata test googlemail com/private/full/g5928e82rrch95b25f8ud0dlsg'>"
+ "<gd:when startTime='2009-04-29T16:30:00.000+01:00'/>"
+ "</gd:originalEvent>"
+ "<gCal:guestsCanModify value='false'/>"
+ "<gCal:guestsCanInviteOthers value='false'/>"
+ "<gCal:guestsCanSeeGuests value='false'/>"
+ "<gCal:anyoneCanAddSelf value='false'/>"
+ "<gd:comments>"
+ "<gd:feedLink href='http://www.google.com/calendar/feeds/libgdata test googlemail com/private/full/g5928e82rrch95b25f8ud0dlsg_20090429T153000Z/comments'/>"
+ "</gd:comments>"
+ "<gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'/>"
+ "<gd:visibility value='http://schemas.google.com/g/2005#event.private'/>"
+ "<gd:transparency value='http://schemas.google.com/g/2005#event.opaque'/>"
+ "<gCal:uid value='g5928e82rrch95b25f8ud0dlsg google com'/>"
+ "<gCal:sequence value='0'/>"
+ "<gd:when startTime='2009-04-29T17:30:00.000+01:00' endTime='2009-04-29T17:30:00.000+01:00'>"
+ "<gd:reminder minutes='10' method='email'/>"
+ "<gd:reminder minutes='10' method='alert'/>"
+ "</gd:when>"
+ "<gd:who rel='http://schemas.google.com/g/2005#event.organizer' valueString='GData Test' email='libgdata test googlemail com'/>"
+ "<gd:where valueString=''/>"
+ "</entry>", -1, &error);
+ g_assert_no_error (error);
+ g_assert (GDATA_IS_ENTRY (event));
+ g_clear_error (&error);
+
+ /* Check the original event */
+ g_assert (gdata_calendar_event_is_exception (event) == TRUE);
+
+ gdata_calendar_event_get_original_event_details (event, &id, &uri);
+ g_assert_cmpstr (id, ==, "g5928e82rrch95b25f8ud0dlsg");
+ g_assert_cmpstr (uri, ==, "http://www.google.com/calendar/feeds/libgdata test googlemail com/private/full/g5928e82rrch95b25f8ud0dlsg");
+
+ g_object_unref (event);
+}
+
+static void
test_query_uri (void)
{
GTimeVal time_val, time_val2;
@@ -466,6 +529,7 @@ main (int argc, char *argv[])
if (g_test_slow () == TRUE)
g_test_add_func ("/calendar/insert/simple", test_insert_simple);
g_test_add_func ("/calendar/xml/dates", test_xml_dates);
+ g_test_add_func ("/calendar/xml/recurrence", test_xml_recurrence);
g_test_add_func ("/calendar/query/uri", test_query_uri);
retval = g_test_run ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]