diff options
Diffstat (limited to 'calendar/pcs')
-rw-r--r-- | calendar/pcs/cal-backend.c | 182 | ||||
-rw-r--r-- | calendar/pcs/cal-backend.h | 2 | ||||
-rw-r--r-- | calendar/pcs/cal-factory.c | 159 | ||||
-rw-r--r-- | calendar/pcs/cal.c | 2 | ||||
-rw-r--r-- | calendar/pcs/calobj.c | 2 | ||||
-rw-r--r-- | calendar/pcs/tlacuache.c | 2 | ||||
-rw-r--r-- | calendar/pcs/tlacuache.gnorba | 4 |
7 files changed, 293 insertions, 60 deletions
diff --git a/calendar/pcs/cal-backend.c b/calendar/pcs/cal-backend.c index 17148cb048..18ed6a6c86 100644 --- a/calendar/pcs/cal-backend.c +++ b/calendar/pcs/cal-backend.c @@ -20,6 +20,7 @@ */ #include <config.h> +#include <gtk/gtksignal.h> #include "cal-backend.h" #include "calobj.h" #include "../libversit/vcc.h" @@ -36,7 +37,7 @@ typedef struct { /* URI where the calendar data is stored */ GnomeVFSURI *uri; - /* List of Cal client interface objects, each with its listener */ + /* List of Cal objects with their listeners */ GList *clients; /* All the iCalObject structures in the calendar, hashed by UID. The @@ -119,6 +120,55 @@ cal_backend_init (CalBackend *backend) backend->priv = priv; } +/* Saves a calendar */ +static void +save (CalBackend *backend) +{ + /* FIXME */ +} + +/* g_hash_table_foreach() callback to destroy an iCalObject */ +static void +free_ical_object (gpointer key, gpointer value, gpointer data) +{ + iCalObject *ico; + + ico = value; + ical_object_destroy (ico); +} + +/* Destroys a backend's data */ +static void +destroy (CalBackend *backend) +{ + CalBackendPrivate *priv; + + priv = backend->priv; + + if (priv->uri) { + gnome_vfs_uri_unref (priv->uri); + priv->uri = NULL; + } + + g_assert (priv->clients == NULL); + + if (priv->object_hash) { + g_hash_table_foreach (priv->object_hash, free_ical_object, NULL); + g_hash_table_destroy (priv->object_hash); + priv->object_hash = NULL; + } + + g_list_free (priv->events); + g_list_free (priv->todos); + g_list_free (priv->journals); + + priv->events = NULL; + priv->todos = NULL; + priv->journals = NULL; + + priv->loaded = FALSE; +} + /* Destroy handler for the calendar backend */ static void cal_backend_destroy (GtkObject *object) @@ -132,7 +182,10 @@ cal_backend_destroy (GtkObject *object) backend = CAL_BACKEND (object); priv = backend->priv; - /* FIXME: free stuff */ + if (priv->loaded) + save (backend); + + destroy (backend); g_free (priv); @@ -265,6 +318,11 @@ load_from_vobject (CalBackend *backend, VObject *vobject) ical = ical_object_create_from_vobject (this, object_name); + /* FIXME: some broken files may have duplicated UIDs. This is + * Bad(tm). Deal with it by creating new UIDs for them and + * spitting some messages to the console. + */ + if (ical) add_object (backend, ical); } @@ -364,45 +422,57 @@ cal_backend_get_uri (CalBackend *backend) return priv->uri; } -/** - * cal_backend_add_cal: - * @backend: A calendar backend. - * @cal: A calendar client interface object. - * - * Adds a calendar client interface object to a calendar @backend. The calendar - * backend must already have a loaded calendar. - **/ -void -cal_backend_add_cal (CalBackend *backend, Cal *cal) +/* Callback used when a Cal is destroyed */ +static void +cal_destroy_cb (GtkObject *object, gpointer data) { + Cal *cal; + Cal *lcal; + CalBackend *backend; CalBackendPrivate *priv; + GList *l; - g_return_if_fail (backend != NULL); - g_return_if_fail (IS_CAL_BACKEND (backend)); + cal = CAL (object); + backend = CAL_BACKEND (data); priv = backend->priv; - g_return_if_fail (priv->loaded); - g_return_if_fail (cal != NULL); - g_return_if_fail (IS_CAL (cal)); + /* Find the cal in the list of clients */ - gtk_object_ref (GTK_OBJECT (cal)); - priv->clients = g_list_prepend (priv->clients, cal); + for (l = priv->clients; l; l = l->next) { + lcal = CAL (l->data); + + if (lcal == cal) + break; + } + + g_assert (l != NULL); + + /* Disconnect */ + + priv->clients = g_list_remove_link (priv->clients, l); + g_list_free_1 (l); + + /* When all clients go away, the backend can go away, too. Commit + * suicide here. + */ + + if (!priv->clients) + gtk_object_unref (GTK_OBJECT (backend)); } /** - * cal_backend_remove_cal: + * cal_backend_add_cal: * @backend: A calendar backend. * @cal: A calendar client interface object. - * - * Removes a calendar client interface object from a calendar backend. The - * calendar backend must already have a loaded calendar. + * + * Adds a calendar client interface object to a calendar @backend. The calendar + * backend must already have a loaded calendar. **/ void -cal_backend_remove_cal (CalBackend *backend, Cal *cal) +cal_backend_add_cal (CalBackend *backend, Cal *cal) { CalBackendPrivate *priv; - GList *l; g_return_if_fail (backend != NULL); g_return_if_fail (IS_CAL_BACKEND (backend)); @@ -413,13 +483,15 @@ cal_backend_remove_cal (CalBackend *backend, Cal *cal) g_return_if_fail (cal != NULL); g_return_if_fail (IS_CAL (cal)); - l = g_list_find (priv->clients, cal); - if (!l) - return; + /* We do not keep a reference to the Cal since the calendar user agent + * owns it. + */ + + gtk_signal_connect (GTK_OBJECT (cal), "destroy", + GTK_SIGNAL_FUNC (cal_destroy_cb), + backend); - gtk_object_unref (GTK_OBJECT (cal)); - priv->clients = g_list_remove_link (priv->clients, l); - g_list_free_1 (l); + priv->clients = g_list_prepend (priv->clients, cal); } /** @@ -441,11 +513,12 @@ cal_backend_load (CalBackend *backend, GnomeVFSURI *uri) g_return_val_if_fail (backend != NULL, CAL_BACKEND_LOAD_ERROR); g_return_val_if_fail (IS_CAL_BACKEND (backend), CAL_BACKEND_LOAD_ERROR); - g_return_val_if_fail (uri != NULL, CAL_BACKEND_LOAD_ERROR); priv = backend->priv; g_return_val_if_fail (!priv->loaded, CAL_BACKEND_LOAD_ERROR); + g_return_val_if_fail (uri != NULL, CAL_BACKEND_LOAD_ERROR); + /* FIXME: this looks rather bad; maybe we should check for local files * and fail if they are remote. */ @@ -475,13 +548,46 @@ cal_backend_load (CalBackend *backend, GnomeVFSURI *uri) } /** + * cal_backend_create: + * @backend: A calendar backend. + * @uri: URI that will contain the calendar data. + * + * Creates a new empty calendar in a calendar backend. + **/ +void +cal_backend_create (CalBackend *backend, GnomeVFSURI *uri) +{ + CalBackendPrivate *priv; + + g_return_if_fail (backend != NULL); + g_return_if_fail (IS_CAL_BACKEND (backend)); + + priv = backend->priv; + g_return_if_fail (!priv->loaded); + + g_return_if_fail (uri != NULL); + + /* Create the new calendar information */ + + g_assert (priv->object_hash == NULL); + priv->object_hash = g_hash_table_new (g_str_hash, g_str_equal); + + /* Done */ + + gnome_vfs_uri_ref (uri); + + priv->uri = uri; + priv->loaded = TRUE; +} + +/** * cal_backend_get_object: * @backend: A calendar backend. * @uid: Unique identifier for a calendar object. - * + * * Queries a calendar backend for a calendar object based on its unique * identifier. - * + * * Return value: The string representation of a complete calendar wrapping the * the sought object, or NULL if no object had the specified UID. A complete * calendar is returned because you also need the timezone data. @@ -560,10 +666,10 @@ build_uids_list (gpointer key, gpointer value, gpointer data) * cal_backend_get_uids: * @backend: A calendar backend. * @type: Bitmask with types of objects to return. - * + * * Builds a list of unique identifiers corresponding to calendar objects whose * type matches one of the types specified in the @type flags. - * + * * Return value: A list of strings that are the sought UIDs. **/ GList * @@ -639,11 +745,11 @@ compare_instance_func (gconstpointer a, gconstpointer b) * @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. **/ diff --git a/calendar/pcs/cal-backend.h b/calendar/pcs/cal-backend.h index 55c414d5f7..41b2b9186d 100644 --- a/calendar/pcs/cal-backend.h +++ b/calendar/pcs/cal-backend.h @@ -68,6 +68,8 @@ void cal_backend_remove_cal (CalBackend *backend, Cal *cal); CalBackendLoadStatus cal_backend_load (CalBackend *backend, GnomeVFSURI *uri); +void cal_backend_create (CalBackend *backend, GnomeVFSURI *uri); + char *cal_backend_get_object (CalBackend *backend, const char *uid); GList *cal_backend_get_uids (CalBackend *backend, CalObjType type); diff --git a/calendar/pcs/cal-factory.c b/calendar/pcs/cal-factory.c index d5b79ef423..14b7ac9cb6 100644 --- a/calendar/pcs/cal-factory.c +++ b/calendar/pcs/cal-factory.c @@ -244,9 +244,24 @@ lookup_backend (CalFactory *factory, GnomeVFSURI *uri) return backend; } +/* Adds a backend to the calendar factory's hash table */ +static void +add_backend (CalFactory *factory, GnomeVFSURI *uri, CalBackend *backend) +{ + CalFactoryPrivate *priv; + + priv = factory->priv; + + gnome_vfs_uri_ref (uri); + g_hash_table_insert (priv->backends, uri, backend); + /* FIXME: connect to destroy on the backend and remove it from + * the hash table when it dies. + */ +} + /* Loads a calendar backend and puts it in the factory's backend hash table */ static CalBackend * -load_backend (CalFactory *factory, GnomeVFSURI *uri, Evolution_Calendar_Listener listener) +load_backend (CalFactory *factory, GnomeVFSURI *uri) { CalFactoryPrivate *priv; CalBackend *backend; @@ -264,9 +279,7 @@ load_backend (CalFactory *factory, GnomeVFSURI *uri, Evolution_Calendar_Listener switch (status) { case CAL_BACKEND_LOAD_SUCCESS: - gnome_vfs_uri_ref (uri); - g_hash_table_insert (priv->backends, uri, backend); - + add_backend (factory, uri, backend); return backend; case CAL_BACKEND_LOAD_ERROR: @@ -279,6 +292,27 @@ load_backend (CalFactory *factory, GnomeVFSURI *uri, Evolution_Calendar_Listener } } +/* Creates a calendar backend and puts it in the factory's backend hash table */ +static CalBackend * +create_backend (CalFactory *factory, GnomeVFSURI *uri) +{ + CalFactoryPrivate *priv; + CalBackend *backend; + + priv = factory->priv; + + backend = cal_backend_new (); + if (!backend) { + g_message ("create_backend(): could not create the backend"); + return NULL; + } + + cal_backend_create (backend, uri); + add_backend (factory, uri, backend); + + return backend; +} + /* Adds a listener to a calendar backend by creating a calendar client interface * object. */ @@ -314,10 +348,8 @@ add_calendar_client (CalFactory *factory, CalBackend *backend, Evolution_Calenda if (ev._major != CORBA_NO_EXCEPTION) { g_message ("add_calendar_client(): could not notify the listener"); - cal_backend_remove_cal (backend, cal); + bonobo_object_unref (BONOBO_OBJECT (cal)); } - - gtk_object_unref (GTK_OBJECT (cal)); } /* Job handler for the load calendar command */ @@ -342,15 +374,14 @@ load_fn (gpointer data) listener = jd->listener; g_free (jd); + /* Look up the backend and create it if needed */ + backend = lookup_backend (factory, uri); if (!backend) - backend = load_backend (factory, uri, listener); - - gnome_vfs_uri_unref (uri); + backend = load_backend (factory, uri); if (!backend) { - g_message ("load_fn(): could not load the backend"); CORBA_exception_init (&ev); Evolution_Calendar_Listener_cal_loaded (listener, Evolution_Calendar_Listener_ERROR, @@ -368,6 +399,8 @@ load_fn (gpointer data) out: + gnome_vfs_uri_unref (uri); + CORBA_exception_init (&ev); CORBA_Object_release (listener, &ev); @@ -377,6 +410,78 @@ load_fn (gpointer data) CORBA_exception_free (&ev); } +/* Job handler for the create calendar command */ +static void +create_fn (gpointer data) +{ + LoadCreateJobData *jd; + CalFactory *factory; + GnomeVFSURI *uri; + Evolution_Calendar_Listener listener; + CalBackend *backend; + CORBA_Environment ev; + + jd = data; + factory = jd->factory; + + uri = gnome_vfs_uri_new (jd->uri); + g_free (jd->uri); + + factory = jd->factory; + listener = jd->listener; + g_free (jd); + + /* Check that the backend is not in use */ + + backend = lookup_backend (factory, uri); + + if (backend) { + CORBA_exception_init (&ev); + Evolution_Calendar_Listener_cal_loaded (listener, + Evolution_Calendar_Listener_IN_USE, + CORBA_OBJECT_NIL, + &ev); + + if (ev._major != CORBA_NO_EXCEPTION) + g_message ("create_fn(): could not notify the listener"); + + CORBA_exception_free (&ev); + goto out; + } + + /* Create the backend */ + + backend = create_backend (factory, uri); + + if (!backend) { + CORBA_exception_init (&ev); + Evolution_Calendar_Listener_cal_loaded (listener, + Evolution_Calendar_Listener_ERROR, + CORBA_OBJECT_NIL, + &ev); + + if (ev._major != CORBA_NO_EXCEPTION) + g_message ("create_fn(): could not notify the listener"); + + CORBA_exception_free (&ev); + goto out; + } + + add_calendar_client (factory, backend, listener); + + out: + + gnome_vfs_uri_unref (uri); + + CORBA_exception_init (&ev); + CORBA_Object_release (listener, &ev); + + if (ev._major != CORBA_NO_EXCEPTION) + g_message ("create_fn(): could not release the listener"); + + CORBA_exception_free (&ev); +} + /** @@ -470,8 +575,10 @@ cal_factory_new (void) return cal_factory_construct (factory, corba_factory); } -void -cal_factory_load (CalFactory *factory, const char *uri, Evolution_Calendar_Listener listener) +/* Queues a load or create request */ +static void +queue_load_create_job (CalFactory *factory, const char *uri, Evolution_Calendar_Listener listener, + JobFunc func) { LoadCreateJobData *jd; CORBA_Environment ev; @@ -481,21 +588,21 @@ cal_factory_load (CalFactory *factory, const char *uri, Evolution_Calendar_Liste CORBA_exception_init (&ev); result = CORBA_Object_is_nil (listener, &ev); if (ev._major != CORBA_NO_EXCEPTION) { - g_message ("cal_factory_load(): could not see if the listener was NIL"); + g_message ("queue_load_create_job(): could not see if the listener was NIL"); CORBA_exception_free (&ev); return; } CORBA_exception_free (&ev); if (result) { - g_message ("cal_factory_load(): cannot operate on a NIL listener!"); + g_message ("queue_load_create_job(): cannot operate on a NIL listener!"); return; } listener_copy = CORBA_Object_duplicate (listener, &ev); if (ev._major != CORBA_NO_EXCEPTION) { - g_message ("cal_factory_load(): could not duplicate the listener"); + g_message ("queue_load_create_job(): could not duplicate the listener"); CORBA_exception_free (&ev); return; } @@ -507,11 +614,27 @@ cal_factory_load (CalFactory *factory, const char *uri, Evolution_Calendar_Liste jd->uri = g_strdup (uri); jd->listener = listener_copy; - job_add (load_fn, jd); + job_add (func, jd); +} + +/** + * cal_factory_load: + * @factory: A calendar factory. + * @uri: URI of calendar to load. + * @listener: Listener for notification of the load result. + * + * Initiates a load request in a calendar factory. A calendar will be loaded + * asynchronously and the result code will be reported to the specified + * listener. + **/ +void +cal_factory_load (CalFactory *factory, const char *uri, Evolution_Calendar_Listener listener) +{ + queue_load_create_job (factory, uri, listener, load_fn); } void cal_factory_create (CalFactory *factory, const char *uri, Evolution_Calendar_Listener listener) { - /* FIXME */ + queue_load_create_job (factory, uri, listener, create_fn); } diff --git a/calendar/pcs/cal.c b/calendar/pcs/cal.c index 74badc7013..358f08167d 100644 --- a/calendar/pcs/cal.c +++ b/calendar/pcs/cal.c @@ -127,6 +127,8 @@ cal_destroy (GtkObject *object) cal = CAL (object); priv = cal->priv; + priv->backend = NULL; + CORBA_exception_init (&ev); CORBA_Object_release (priv->listener, &ev); if (ev._major != CORBA_NO_EXCEPTION) diff --git a/calendar/pcs/calobj.c b/calendar/pcs/calobj.c index 8d3e68edcc..01e90e3b50 100644 --- a/calendar/pcs/calobj.c +++ b/calendar/pcs/calobj.c @@ -677,7 +677,7 @@ ical_object_create_from_vobject (VObject *o, const char *object_name) ical->class = g_strdup (str_val (vo)); free (the_str); } else - ical->class = "PUBLIC"; + ical->class = g_strdup ("PUBLIC"); /* categories */ if (has (o, VCCategoriesProp)){ diff --git a/calendar/pcs/tlacuache.c b/calendar/pcs/tlacuache.c index b11b5030d8..602cbfbe27 100644 --- a/calendar/pcs/tlacuache.c +++ b/calendar/pcs/tlacuache.c @@ -73,7 +73,7 @@ create_cal_factory (void) CORBA_exception_init (&ev); result = goad_server_register (CORBA_OBJECT_NIL, object, - "calendar:cal-factory", + "evolution:calendar-factory", "object", &ev); diff --git a/calendar/pcs/tlacuache.gnorba b/calendar/pcs/tlacuache.gnorba index acf2289229..da0f4ed552 100644 --- a/calendar/pcs/tlacuache.gnorba +++ b/calendar/pcs/tlacuache.gnorba @@ -1,5 +1,5 @@ -[calendar:cal-factory] +[evolution:calendar-factory] type=exe -repo_id=IDL:GNOME/Calendar/CalFactory:1.0 +repo_id=IDL:Evolution/Calendar/CalFactory:1.0 description=Calendar factory for the Personal Calendar Server location_info=tlacuache |