diff options
-rw-r--r-- | calendar/ChangeLog | 23 | ||||
-rw-r--r-- | calendar/cal-util/cal-component.c | 384 | ||||
-rw-r--r-- | calendar/cal-util/cal-component.h | 10 |
3 files changed, 326 insertions, 91 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog index 06518ca29f..94d0e17080 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,26 @@ +2000-06-30 Federico Mena Quintero <federico@helixcode.com> + + * cal-util/cal-component.c: Change of plans. We use an + icalcomponent from libical as our core representation so that we + can preserve extension fields and fields that we don't (yet) + support. CalComponent is just a wrapper with a nice API that + provides non-iterative, random access to the ical's fields. + (cal_component_destroy): Free the thing correctly. + (cal_component_get_vtype): Re-implement in terms of icalcomponent. + (cal_component_set_icalcomponent): New function to set the + CalComponent's data from an existing icalcomponent. + (cal_component_get_icalcomponent): New function. + (cal_component_set_new_vtype): New convenience function to create + an empty component. + (scan_icalcomponent): Core scanning function. + (scan_property): Another core scanning function. + (cal_component_get_uid): Use the property directly. + (cal_component_get_summary): Ditto. Handle the altrep parameter + as well. + (cal_component_set_summary): Ditto. Feel the pain, motherfucker. + It is ridiculous how much code this involves. + (scan_summary): Ditto. + 2000-06-29 Ettore Perazzoli <ettore@helixcode.com> * gui/component-factory.c (owner_set_cb): Get an diff --git a/calendar/cal-util/cal-component.c b/calendar/cal-util/cal-component.c index bb2fd1a50e..3370b8f9ea 100644 --- a/calendar/cal-util/cal-component.c +++ b/calendar/cal-util/cal-component.c @@ -28,14 +28,17 @@ /* Private part of the CalComponent structure */ typedef struct { - /* Type of this component */ - CalComponentVType type; + /* The icalcomponent we wrap */ + icalcomponent *icalcomp; - /* Summary string, optional */ - char *summary; + /* Properties */ - /* Unique identifier, MUST be present */ - char *uid; + icalproperty *uid_prop; + + struct { + icalproperty *prop; + icalparameter *altrep_param; + } summary; } CalComponentPrivate; @@ -102,7 +105,28 @@ cal_component_init (CalComponent *comp) priv = g_new0 (CalComponentPrivate, 1); comp->priv = priv; - priv->uid = cal_component_gen_uid (); + priv->uid_prop = cal_component_gen_uid (); +} + +/* Frees the internal icalcomponent only if it does not have a parent. If it + * does, it means we don't own it and we shouldn't free it. + */ +static void +free_icalcomponent (CalComponent *comp) +{ + CalComponentPrivate *priv; + + priv = comp->priv; + + if (!priv->icalcomp) + return; + + /* FIXME: remove the mappings! */ + + if (icalcomponent_get_parent (priv->icalcomp) != NULL) + icalcomponent_free (priv->icalcomp); + + priv->icalcomp = NULL; } /* Destroy handler for the calendar component object */ @@ -118,10 +142,7 @@ cal_component_destroy (GtkObject *object) comp = CAL_COMPONENT (object); priv = comp->priv; - if (priv->uid) { - g_free (priv->uid); - priv->uid = NULL; - } + free_icalcomponent (comp); g_free (priv); comp->priv = NULL; @@ -172,9 +193,9 @@ cal_component_gen_uid (void) * cal_component_new: * @void: * - * Creates a new empty calendar component object whose only set field is the - * unique identifier. You should set the type of this component as soon as - * possible by using cal_component_set_vtype(). + * Creates a new empty calendar component object. You should set it from an + * #icalcomponent structure by using cal_component_set_icalcomponent() or with a + * new empty component type by using cal_component_set_new_vtype(). * * Return value: A newly-created calendar component object. **/ @@ -184,119 +205,256 @@ cal_component_new (void) return CAL_COMPONENT (gtk_type_new (CAL_COMPONENT_TYPE)); } -/* Parses a property and stores it in the calendar component */ +/* Scans the summary property */ static void -load_property (CalComponent *comp, icalproperty *prop) +scan_summary (CalComponent *comp, icalproperty *prop) { + CalComponentPrivate *priv; + icalparameter *param; + + priv = comp->priv; + + priv->summary.prop = prop; + + for (param = icalproperty_get_first_parameter (prop, ICAL_ANY_PARAMETER); + param; + param = icalproperty_get_next_parameter (prop, ICAL_ANY_PARAMETER)) { + icalparameter_kind kind; + + kind = icalparameter_isa (param); + + switch (kind) { + case ICAL_ALTREP_PARAMETER: + priv->summary.altrep_param = param; + break; + + default: + break; + } + } +} + +/* Scans an icalproperty and adds its mapping to the component */ +static void +scan_property (CalComponent *comp, icalproperty *prop) +{ + CalComponentPrivate *priv; icalproperty_kind kind; - kind = icalproperty_isa (prop); + priv = comp->priv; + + switch (kind) { + case ICAL_SUMMARY_PROPERTY: + scan_summary (comp, prop); + + case ICAL_UID_PROPERTY: + priv->uid_prop = prop; + + default: + break; + } +} + +/* Scans an icalcomponent for its properties so that we can provide + * random-access to them. + */ +static void +scan_icalcomponent (CalComponent *comp) +{ + CalComponentPrivate *priv; + icalproperty *prop; + + priv = comp->priv; + + g_assert (priv->icalcomp != NULL); + + for (prop = icalcomponent_get_first_property (priv->icalcomp, ICAL_ANY_PROPERTY); + prop; + prop = icalcomponent_get_next_property (priv->icalcomp, ICAL_ANY_PROPERTY)) + scan_property (comp, prop); - /* FIXME */ + /* FIXME: parse ALARM subcomponents */ } /** - * cal_component_new_from_icalcomponent: - * @ical: An #icalcomponent structure with the component to parse. - * - * Creates a new calendar component object from an #icalcomponent from libical. - * This function only deals with VEVENT, VTODO, VJOURNAL, VFREEBUSY, AND - * VTIMEZONE components. + * cal_component_set_new_vtype: + * @comp: A calendar component object. + * @type: Type of calendar component to create. * - * Return value: A newly-created calendar component object. + * Clears any existing component data from a calendar component object and + * creates a new #icalcomponent of the specified type for it. The only property + * that will be set in the new component will be its unique identifier. **/ -CalComponent * -cal_component_new_from_icalcomponent (icalcomponent *ical) +void +cal_component_set_new_vtype (CalComponent *comp, CalComponentVType type) { - CalComponent *comp; + CalComponentPrivate *priv; + icalcomponent *icalcomp; icalcomponent_kind kind; - CalComponentVType type; + char *uid; icalproperty *prop; - g_return_val_if_fail (ical != NULL, NULL); + g_return_if_fail (comp != NULL); + g_return_if_fail (IS_CAL_COMPONENT (comp)); - kind = icalcomponent_isa (ical); + priv = comp->priv; - switch (kind) { - case ICAL_VEVENT_COMPONENT: - type = CAL_COMPONENT_EVENT; + free_icalcomponent (comp); + + if (type == CAL_COMPONENT_NO_TYPE) + return; + + /* Figure out the kind */ + + switch (type) { + case CAL_COMPONENT_EVENT: + kind = ICAL_VEVENT_COMPONENT; break; - case ICAL_VTODO_COMPONENT: - type = CAL_COMPONENT_TODO; + case CAL_COMPONENT_TODO: + kind = ICAL_VTODO_COMPONENT; break; - case ICAL_VJOURNAL_COMPONENT: - type = CAL_COMPONENT_JOURNAL; + case CAL_COMPONENT_JOURNAL: + kind = ICAL_VJOURNAL_COMPONENT; break; - case ICAL_VFREEBUSY_COMPONENT: - type = CAL_COMPONENT_FREEBUSY; + case CAL_COMPONENT_FREEBUSY: + kind = ICAL_VFREEBUSY_COMPONENT; break; - case ICAL_VTIMEZONE_COMPONENT: - type = CAL_COMPONENT_TIMEZONE; + case CAL_COMPONENT_TIMEZONE: + kind = ICAL_VTIMEZONE_COMPONENT; break; default: - g_message ("cal_component_new_from_icalcomponent(): Unsupported component type %d", - kind); - return NULL; + g_assert_not_reached (); + kind = ICAL_NO_COMPONENT; } - comp = cal_component_new (); - cal_component_set_vtype (comp, type); + /* Create an UID */ - for (prop = icalcomponent_get_first_property (ical, ICAL_ANY_PROPERTY); - prop; - prop = icalcomponent_get_next_property (ical, ICAL_ANY_PROPERTY)) - load_property (comp, prop); + icalcomp = icalcomponent_new (kind); + if (!icalcomp) { + g_message ("cal_component_set_new_vtype(): Could not create the icalcomponent!"); + return; + } - /* FIXME: parse ALARM subcomponents */ + uid = cal_component_gen_uid (); + prop = icalproperty_new_uid (uid); + g_free (uid); - return comp; + if (!prop) { + icalcomponent_free (icalcomp); + g_message ("cal_component_set_new_vtype(): Could not create the UID property!"); + return; + } + + icalcomponent_add_property (icalcomp, prop); + + /* Scan the component to build our mapping table */ + + priv->icalcomp = icalcomp; + scan_icalcomponent (comp); } /** - * cal_component_get_vtype: + * cal_component_set_icalcomponent: * @comp: A calendar component object. + * @icalcomp: An #icalcomponent. * - * Queries the type of a calendar component object. + * Sets the contents of a calendar component object from an #icalcomponent + * structure. If the @comp already had an #icalcomponent set into it, it will + * will be freed automatically if the #icalcomponent does not have a parent + * component itself. + **/ +void +cal_component_set_icalcomponent (CalComponent *comp, icalcomponent *icalcomp) +{ + CalComponentPrivate *priv; + + g_return_if_fail (comp != NULL); + g_return_if_fail (IS_CAL_COMPONENT (comp)); + + priv = comp->priv; + + if (priv->icalcomp == icalcomp) + return; + + free_icalcomponent (comp); + + priv->icalcomp = icalcomp; + + if (priv->icalcomp) + scan_icalcomponent (comp); +} + +/** + * cal_component_get_icalcomponent: + * @comp: A calendar component object. * - * Return value: The type of the component, as defined by RFC 2445. + * Queries the #icalcomponent structure that a calendar component object is + * wrapping. + * + * Return value: An #icalcomponent structure, or NULL if the @comp has no + * #icalcomponent set to it. **/ -CalComponentVType -cal_component_get_vtype (CalComponent *comp) +icalcomponent * +cal_component_get_icalcomponent (CalComponent *comp) { CalComponentPrivate *priv; - g_return_val_if_fail (comp != NULL, CAL_COMPONENT_NO_TYPE); - g_return_val_if_fail (IS_CAL_COMPONENT (comp), CAL_COMPONENT_NO_TYPE); + g_return_val_if_fail (comp != NULL, NULL); + g_return_val_if_fail (IS_CAL_COMPONENT (comp), NULL); priv = comp->priv; - return priv->type; + return priv->icalcomp; } /** - * cal_component_set_vtype: + * cal_component_get_vtype: * @comp: A calendar component object. - * @type: Type of the component, as defined by RFC 2445. * - * Sets the type of a calendar component object. This function should be used - * as soon as possible after creating a new calendar component so that its type - * can be known to the rest of the program. + * Queries the type of a calendar component object. + * + * Return value: The type of the component, as defined by RFC 2445. **/ -void -cal_component_set_vtype (CalComponent *comp, CalComponentVType type) +CalComponentVType +cal_component_get_vtype (CalComponent *comp) { CalComponentPrivate *priv; + icalcomponent_kind kind; - g_return_if_fail (comp != NULL); - g_return_if_fail (IS_CAL_COMPONENT (comp)); - g_return_if_fail (type != CAL_COMPONENT_NO_TYPE); + g_return_val_if_fail (comp != NULL, CAL_COMPONENT_NO_TYPE); + g_return_val_if_fail (IS_CAL_COMPONENT (comp), CAL_COMPONENT_NO_TYPE); priv = comp->priv; - priv->type = type; + + if (!priv->icalcomp) + return CAL_COMPONENT_NO_TYPE; + + kind = icalcomponent_isa (priv->icalcomp); + switch (kind) { + case ICAL_VEVENT_COMPONENT: + return CAL_COMPONENT_EVENT; + + case ICAL_VTODO_COMPONENT: + return CAL_COMPONENT_TODO; + + case ICAL_VJOURNAL_COMPONENT: + return CAL_COMPONENT_JOURNAL; + + case ICAL_VFREEBUSY_COMPONENT: + return CAL_COMPONENT_FREEBUSY; + + case ICAL_VTIMEZONE_COMPONENT: + return CAL_COMPONENT_TIMEZONE; + + default: + /* We should have been loaded with a supported type! */ + g_assert_not_reached (); + return CAL_COMPONENT_NO_TYPE; + } } /** @@ -316,7 +474,11 @@ cal_component_get_uid (CalComponent *comp) g_return_val_if_fail (IS_CAL_COMPONENT (comp), NULL); priv = comp->priv; - return priv->uid; + + /* This MUST exist, since we ensured that it did */ + g_assert (priv->uid_prop != NULL); + + return icalproperty_get_uid (priv->uid_prop); } /** @@ -336,30 +498,44 @@ cal_component_set_uid (CalComponent *comp, const char *uid) g_return_if_fail (uid != NULL); priv = comp->priv; - g_assert (priv->uid != NULL); - g_free (priv->uid); - priv->uid = g_strdup (uid); + /* This MUST exist, since we ensured that it did */ + g_assert (priv->uid_prop != NULL); + + icalproperty_set_uid (priv->uid_prop, (char *) uid); } /** * cal_component_get_summary: * @comp: A calendar component object. + * @summary: Return value for the summary string. + * @altrep: Return value for the alternate representation string. * * Queries the summary of a calendar component object. - * - * Return value: Summary string. **/ -const char * -cal_component_get_summary (CalComponent *comp) +void +cal_component_get_summary (CalComponent *comp, const char **summary, const char **altrep) { CalComponentPrivate *priv; - g_return_val_if_fail (comp != NULL, NULL); - g_return_val_if_fail (IS_CAL_COMPONENT (comp), NULL); + g_return_if_fail (comp != NULL); + g_return_if_fail (IS_CAL_COMPONENT (comp)); priv = comp->priv; - return priv->summary; + + if (summary) { + if (priv->summary.prop) + *summary = icalproperty_get_summary (priv->summary.prop); + else + *summary = NULL; + } + + if (altrep) { + if (priv->summary.altrep_param) + *altrep = icalparameter_get_altrep (priv->summary.altrep_param); + else + *altrep = NULL; + } } /** @@ -370,7 +546,7 @@ cal_component_get_summary (CalComponent *comp) * Sets the summary of a calendar component object. **/ void -cal_component_set_summary (CalComponent *comp, const char *summary) +cal_component_set_summary (CalComponent *comp, const char *summary, const char *altrep) { CalComponentPrivate *priv; @@ -379,8 +555,42 @@ cal_component_set_summary (CalComponent *comp, const char *summary) priv = comp->priv; - if (priv->summary) - g_free (priv->summary); + g_return_if_fail (priv->icalcomp != NULL); + + if (!summary) + g_return_if_fail (altrep == NULL); - priv->summary = g_strdup (summary); + if (summary) { + if (priv->summary.prop) + icalproperty_set_summary (priv->summary.prop, (char *) summary); + else { + priv->summary.prop = icalproperty_new_summary ((char *) summary); + icalcomponent_add_property (priv->icalcomp, priv->summary.prop); + } + } else if (priv->summary.prop) { + icalcomponent_remove_property (priv->icalcomp, priv->summary.prop); + icalproperty_free (priv->summary.prop); + + priv->summary.prop = NULL; + priv->summary.altrep_param = NULL; + } + + if (altrep) { + g_assert (priv->summary.prop != NULL); + + if (priv->summary.altrep_param) + icalparameter_set_altrep (priv->summary.altrep_param, (char *) altrep); + else { + priv->summary.altrep_param = icalparameter_new_altrep ((char *) altrep); + icalproperty_add_parameter (priv->summary.prop, priv->summary.altrep_param); + } + } else if (priv->summary.altrep_param) { +#if 0 + /* FIXME: this fucking routine will assert(0) since it is not implemented */ + icalproperty_remove_parameter (priv->summary.prop, ICAL_ALTREP_PARAMETER); + icalparameter_free (priv->summary.altrep_param); +#endif + + priv->summary.altrep_param = NULL; + } } diff --git a/calendar/cal-util/cal-component.h b/calendar/cal-util/cal-component.h index 1a5a271d9b..bc869670c8 100644 --- a/calendar/cal-util/cal-component.h +++ b/calendar/cal-util/cal-component.h @@ -71,16 +71,18 @@ char *cal_component_gen_uid (void); CalComponent *cal_component_new (void); -CalComponent *cal_component_new_from_icalcomponent (icalcomponent *ical); +void cal_component_set_new_vtype (CalComponent *comp, CalComponentVType type); + +void cal_component_set_icalcomponent (CalComponent *comp, icalcomponent *icalcomp); +icalcomponent *cal_component_get_icalcomponent (CalComponent *comp); CalComponentVType cal_component_get_vtype (CalComponent *comp); -void cal_component_set_vtype (CalComponent *comp, CalComponentVType type); const char *cal_component_get_uid (CalComponent *comp); void cal_component_set_uid (CalComponent *comp, const char *uid); -const char *cal_component_get_summary (CalComponent *comp); -void cal_component_set_summary (CalComponent *comp, const char *summary); +void cal_component_get_summary (CalComponent *comp, const char **summary, const char **altrep); +void cal_component_set_summary (CalComponent *comp, const char *summary, const char *altrep); |