aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/pcs
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/pcs')
-rw-r--r--calendar/pcs/cal-backend.c182
-rw-r--r--calendar/pcs/cal-backend.h2
-rw-r--r--calendar/pcs/cal-factory.c159
-rw-r--r--calendar/pcs/cal.c2
-rw-r--r--calendar/pcs/calobj.c2
-rw-r--r--calendar/pcs/tlacuache.c2
-rw-r--r--calendar/pcs/tlacuache.gnorba4
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