aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--calendar/ChangeLog41
-rw-r--r--calendar/cal-backend.c139
-rw-r--r--calendar/cal-backend.h4
-rw-r--r--calendar/cal-client.c93
-rw-r--r--calendar/cal-client.h5
-rw-r--r--calendar/cal-client/cal-client.c93
-rw-r--r--calendar/cal-client/cal-client.h5
-rw-r--r--calendar/cal-client/cal-listener.c46
-rw-r--r--calendar/cal-client/cal-listener.h3
-rw-r--r--calendar/cal-client/client-test.c16
-rw-r--r--calendar/cal-factory.c49
-rw-r--r--calendar/cal-listener.c46
-rw-r--r--calendar/cal-listener.h3
-rw-r--r--calendar/cal.c57
-rw-r--r--calendar/cal.h2
-rw-r--r--calendar/evolution-calendar.idl24
-rw-r--r--calendar/gui/layout.c1
-rw-r--r--calendar/idl/evolution-calendar.idl24
-rw-r--r--calendar/layout.c1
-rw-r--r--calendar/pcs/cal-backend.c139
-rw-r--r--calendar/pcs/cal-backend.h4
-rw-r--r--calendar/pcs/cal-factory.c49
-rw-r--r--calendar/pcs/cal.c57
-rw-r--r--calendar/pcs/cal.h2
-rw-r--r--calendar/pcs/tlacuache.c19
-rw-r--r--calendar/tl-test.c16
-rw-r--r--calendar/tlacuache.c19
27 files changed, 769 insertions, 188 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index 2982d7d689..e81315c966 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,3 +1,44 @@
+2000-02-11 Federico Mena Quintero <federico@helixcode.com>
+
+ * cal-client.c (cal_client_update_object): Implemented.
+
+ * cal.c (cal_notify_update): New function to notify the listener
+ about an updated object.
+ (Cal_update_object): Implemented.
+ (Cal_get_uids): set_release() the sequence to TRUE.
+ (Cal_get_events_in_range): Likewise.
+
+ * cal-backend.c (remove_object): New function to remove objects
+ from a calendar backend.
+ (cal_backend_update_object): New public function to update an
+ object and notify clients about it.
+
+ * evolution-calendar.idl (Cal): Added update_object() and
+ delete_object() methods.
+ (Listener): Removed the obj_changed method and renamed obj_added
+ to obj_updated. We now only have updated and removed notifiers.
+
+ * cal-listener.[ch]: Removed the "changed" notification code.
+ Changed the "added" notification code to the "updated"
+ notification.
+
+ * cal-client.c: Likewise.
+
+ * tlacuache.c (create_cal_factory): Connect to "destroy" on the
+ factory and exit the main loop when the factory is destroyed.
+
+ * cal-factory.c (backend_destroy_cb): New callback used when a
+ backend is destroyed. Removes the backend from the factory's hash
+ table and unrefs the factory if all backends go away.
+ (add_calendar_client): Free the environment.
+
+ * cal.c (cal_new): Use bonobo_object_unref() if we fail to
+ initialize.
+
+ * cal-listener.c (cal_listener_new): Likewise.
+
+ * layout.c (layout_events): Plug li.partition memory leak.
+
2000-02-10 Federico Mena Quintero <federico@helixcode.com>
* cal-backend.c (cal_backend_add_cal): Connect to the Cal's
diff --git a/calendar/cal-backend.c b/calendar/cal-backend.c
index 18ed6a6c86..1ce4b615c3 100644
--- a/calendar/cal-backend.c
+++ b/calendar/cal-backend.c
@@ -197,6 +197,19 @@ cal_backend_destroy (GtkObject *object)
/* iCalObject manipulation functions */
+/* Looks up an object by its UID in the backend's object hash table */
+static iCalObject *
+lookup_object (CalBackend *backend, const char *uid)
+{
+ CalBackendPrivate *priv;
+ iCalObject *ico;
+
+ priv = backend->priv;
+ ico = g_hash_table_lookup (priv->object_hash, uid);
+
+ return ico;
+}
+
/* Ensures that an iCalObject has a unique identifier. If it doesn't have one,
* it will create one for it. Returns whether an UID was created or not.
*/
@@ -275,6 +288,49 @@ add_object (CalBackend *backend, iCalObject *ico)
#endif
}
+/* Removes an object from the backend's hash and lists. Does not perform
+ * notification on the clients.
+ */
+static void
+remove_object (CalBackend *backend, iCalObject *ico)
+{
+ CalBackendPrivate *priv;
+ GList **list, *l;
+
+ priv = backend->priv;
+
+ g_assert (ico->uid != NULL);
+ g_hash_table_remove (priv->object_hash, ico->uid);
+
+ switch (ico->type) {
+ case ICAL_EVENT:
+ list = &priv->events;
+ break;
+
+ case ICAL_TODO:
+ list = &priv->todos;
+ break;
+
+ case ICAL_JOURNAL:
+ list = &priv->journals;
+ break;
+
+ default:
+ list = NULL;
+ }
+
+ if (!list)
+ return;
+
+ l = g_list_find (*list, ico);
+ g_assert (l != NULL);
+
+ *list = g_list_remove_link (*list, l);
+ g_list_free_1 (l);
+
+ ical_object_destroy (ico);
+}
+
/* Load a calendar from a VObject */
static void
load_from_vobject (CalBackend *backend, VObject *vobject)
@@ -609,7 +665,7 @@ cal_backend_get_object (CalBackend *backend, const char *uid)
g_assert (priv->object_hash != NULL);
- ico = g_hash_table_lookup (priv->object_hash, uid);
+ ico = lookup_object (backend, uid);
if (!ico)
return NULL;
@@ -782,3 +838,84 @@ cal_backend_get_events_in_range (CalBackend *backend, time_t start, time_t end)
c.event_list = g_list_sort (c.event_list, compare_instance_func);
return c.event_list;
}
+
+/* Notifies a backend's clients that an object was updated */
+static void
+notify_update (CalBackend *backend, const char *uid)
+{
+ CalBackendPrivate *priv;
+ GList *l;
+
+ priv = backend->priv;
+
+ for (l = priv->clients; l; l = l->next) {
+ Cal *cal;
+
+ cal = CAL (l->data);
+ cal_notify_update (cal, uid);
+ }
+}
+
+/**
+ * cal_backend_update_object:
+ * @backend: A calendar backend.
+ * @uid: Unique identifier of the object to update.
+ * @calobj: String representation of the new calendar object.
+ *
+ * Updates an object in a calendar backend. It will replace any existing object
+ * that has the same UID as the specified one. The backend will in turn notify
+ * all of its clients about the change.
+ *
+ * Return value: TRUE on success, FALSE on being passed an invalid object.
+ **/
+gboolean
+cal_backend_update_object (CalBackend *backend, const char *uid, const char *calobj)
+{
+ CalBackendPrivate *priv;
+ iCalObject *ico, *new_ico;
+ CalObjFindStatus status;
+
+ g_return_val_if_fail (backend != NULL, FALSE);
+ g_return_val_if_fail (IS_CAL_BACKEND (backend), FALSE);
+
+ priv = backend->priv;
+ g_return_val_if_fail (priv->loaded, FALSE);
+
+ g_return_val_if_fail (uid != NULL, FALSE);
+ g_return_val_if_fail (calobj != NULL, FALSE);
+
+ /* Pull the object from the string */
+
+ status = ical_object_find_in_string (uid, calobj, &new_ico);
+
+ if (status != CAL_OBJ_FIND_SUCCESS)
+ return FALSE;
+
+ /* Update the object */
+
+ ico = lookup_object (backend, uid);
+
+ if (ico)
+ remove_object (backend, ico);
+
+ add_object (backend, new_ico);
+
+ notify_update (backend, new_ico->uid);
+ return TRUE;
+}
+
+void
+cal_backend_remove_object (CalBackend *backend, const char *uid)
+{
+ 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 (uid != NULL);
+
+ /* FIXME */
+}
diff --git a/calendar/cal-backend.h b/calendar/cal-backend.h
index 41b2b9186d..fab83e4b82 100644
--- a/calendar/cal-backend.h
+++ b/calendar/cal-backend.h
@@ -76,6 +76,10 @@ GList *cal_backend_get_uids (CalBackend *backend, CalObjType type);
GList *cal_backend_get_events_in_range (CalBackend *backend, time_t start, time_t end);
+gboolean cal_backend_update_object (CalBackend *backend, const char *uid, const char *calobj);
+
+void cal_backend_remove_object (CalBackend *backend, const char *uid);
+
END_GNOME_DECLS
diff --git a/calendar/cal-client.c b/calendar/cal-client.c
index aa8cdcf50c..9b25740318 100644
--- a/calendar/cal-client.c
+++ b/calendar/cal-client.c
@@ -54,9 +54,8 @@ typedef struct {
/* Signal IDs */
enum {
CAL_LOADED,
- OBJ_ADDED,
+ OBJ_UPDATED,
OBJ_REMOVED,
- OBJ_CHANGED,
LAST_SIGNAL
};
@@ -120,11 +119,11 @@ cal_client_class_init (CalClientClass *class)
gtk_marshal_NONE__ENUM,
GTK_TYPE_NONE, 1,
GTK_TYPE_ENUM);
- cal_client_signals[OBJ_ADDED] =
- gtk_signal_new ("obj_added",
+ cal_client_signals[OBJ_UPDATED] =
+ gtk_signal_new ("obj_updated",
GTK_RUN_FIRST,
object_class->type,
- GTK_SIGNAL_OFFSET (CalClientClass, obj_added),
+ GTK_SIGNAL_OFFSET (CalClientClass, obj_updated),
gtk_marshal_NONE__STRING,
GTK_TYPE_NONE, 1,
GTK_TYPE_STRING);
@@ -136,14 +135,6 @@ cal_client_class_init (CalClientClass *class)
gtk_marshal_NONE__STRING,
GTK_TYPE_NONE, 1,
GTK_TYPE_STRING);
- cal_client_signals[OBJ_CHANGED] =
- gtk_signal_new ("obj_changed",
- GTK_RUN_FIRST,
- object_class->type,
- GTK_SIGNAL_OFFSET (CalClientClass, obj_changed),
- gtk_marshal_NONE__STRING,
- GTK_TYPE_NONE, 1,
- GTK_TYPE_STRING);
gtk_object_class_add_signals (object_class, cal_client_signals, LAST_SIGNAL);
@@ -215,7 +206,7 @@ static void
destroy_cal (CalClient *client)
{
CalClientPrivate *priv;
- CORBA_Environment ev;
+ CORBA_Environment ev;
int result;
priv = client->priv;
@@ -233,7 +224,7 @@ destroy_cal (CalClient *client)
if (result)
return;
-
+
CORBA_exception_init (&ev);
Evolution_Calendar_Cal_unref (priv->cal, &ev);
if (ev._major != CORBA_NO_EXCEPTION)
@@ -343,14 +334,14 @@ cal_loaded_cb (CalListener *listener,
client_status);
}
-/* Handle the obj_added signal from the listener */
+/* Handle the obj_updated signal from the listener */
static void
-obj_added_cb (CalListener *listener, const Evolution_Calendar_CalObjUID uid, gpointer data)
+obj_updated_cb (CalListener *listener, const Evolution_Calendar_CalObjUID uid, gpointer data)
{
CalClient *client;
client = CAL_CLIENT (data);
- gtk_signal_emit (GTK_OBJECT (client), cal_client_signals[OBJ_ADDED], uid);
+ gtk_signal_emit (GTK_OBJECT (client), cal_client_signals[OBJ_UPDATED], uid);
}
/* Handle the obj_removed signal from the listener */
@@ -363,16 +354,6 @@ obj_removed_cb (CalListener *listener, const Evolution_Calendar_CalObjUID uid, g
gtk_signal_emit (GTK_OBJECT (client), cal_client_signals[OBJ_REMOVED], uid);
}
-/* Handle the obj_changed signal from the listener */
-static void
-obj_changed_cb (CalListener *listener, const Evolution_Calendar_CalObjUID uid, gpointer data)
-{
- CalClient *client;
-
- client = CAL_CLIENT (data);
- gtk_signal_emit (GTK_OBJECT (client), cal_client_signals[OBJ_CHANGED], uid);
-}
-
/**
@@ -484,15 +465,12 @@ load_or_create (CalClient *client, const char *str_uri, gboolean load)
gtk_signal_connect (GTK_OBJECT (priv->listener), "cal_loaded",
GTK_SIGNAL_FUNC (cal_loaded_cb),
client);
- gtk_signal_connect (GTK_OBJECT (priv->listener), "obj_added",
- GTK_SIGNAL_FUNC (obj_added_cb),
+ gtk_signal_connect (GTK_OBJECT (priv->listener), "obj_updated",
+ GTK_SIGNAL_FUNC (obj_updated_cb),
client);
gtk_signal_connect (GTK_OBJECT (priv->listener), "obj_removed",
GTK_SIGNAL_FUNC (obj_removed_cb),
client);
- gtk_signal_connect (GTK_OBJECT (priv->listener), "obj_changed",
- GTK_SIGNAL_FUNC (obj_changed_cb),
- client);
corba_listener = (Evolution_Calendar_Listener) bonobo_object_corba_objref (
BONOBO_OBJECT (priv->listener));
@@ -719,3 +697,52 @@ cal_client_get_events_in_range (CalClient *client, time_t start, time_t end)
return elist;
}
+
+/**
+ * cal_client_update_object:
+ * @client: A calendar client.
+ * @uid: Unique identifier of object to update.
+ * @calobj: String representation of the new calendar object.
+ *
+ * Asks a calendar to update an object based on its UID. Any existing object
+ * with the specified UID will be replaced. The client program should not
+ * assume that the object is actually in the server's storage until it has
+ * received the "obj_updated" notification signal.
+ *
+ * Return value: TRUE on success, FALSE on specifying an invalid object.
+ **/
+gboolean
+cal_client_update_object (CalClient *client, const char *uid, const char *calobj)
+{
+ CalClientPrivate *priv;
+ CORBA_Environment ev;
+ gboolean retval;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE);
+
+ priv = client->priv;
+ g_return_val_if_fail (priv->load_state == LOAD_STATE_LOADED, FALSE);
+
+ g_return_val_if_fail (uid != NULL, FALSE);
+ g_return_val_if_fail (calobj != NULL, FALSE);
+
+ retval = FALSE;
+
+ CORBA_exception_init (&ev);
+ Evolution_Calendar_Cal_update_object (priv->cal, uid, calobj, &ev);
+
+ if (ev._major == CORBA_USER_EXCEPTION &&
+ strcmp (CORBA_exception_id (&ev), ex_Evolution_Calendar_Cal_InvalidObject) == 0)
+ goto out;
+ else if (ev._major != CORBA_NO_EXCEPTION) {
+ g_message ("cal_client_update_object(): could not update the object");
+ goto out;
+ }
+
+ retval = TRUE;
+
+ out:
+ CORBA_exception_free (&ev);
+ return retval;
+}
diff --git a/calendar/cal-client.h b/calendar/cal-client.h
index 0c4c3e4406..7baad2c733 100644
--- a/calendar/cal-client.h
+++ b/calendar/cal-client.h
@@ -60,9 +60,8 @@ struct _CalClientClass {
void (* cal_loaded) (CalClient *client, CalClientLoadStatus status);
- void (* obj_added) (CalClient *client, const char *uid);
+ void (* obj_updated) (CalClient *client, const char *uid);
void (* obj_removed) (CalClient *client, const char *uid);
- void (* obj_changed) (CalClient *client, const char *uid);
};
GtkType cal_client_get_type (void);
@@ -80,6 +79,8 @@ GList *cal_client_get_uids (CalClient *client, CalObjType type);
GList *cal_client_get_events_in_range (CalClient *client, time_t start, time_t end);
+gboolean cal_client_update_object (CalClient *client, const char *uid, const char *calobj);
+
END_GNOME_DECLS
diff --git a/calendar/cal-client/cal-client.c b/calendar/cal-client/cal-client.c
index aa8cdcf50c..9b25740318 100644
--- a/calendar/cal-client/cal-client.c
+++ b/calendar/cal-client/cal-client.c
@@ -54,9 +54,8 @@ typedef struct {
/* Signal IDs */
enum {
CAL_LOADED,
- OBJ_ADDED,
+ OBJ_UPDATED,
OBJ_REMOVED,
- OBJ_CHANGED,
LAST_SIGNAL
};
@@ -120,11 +119,11 @@ cal_client_class_init (CalClientClass *class)
gtk_marshal_NONE__ENUM,
GTK_TYPE_NONE, 1,
GTK_TYPE_ENUM);
- cal_client_signals[OBJ_ADDED] =
- gtk_signal_new ("obj_added",
+ cal_client_signals[OBJ_UPDATED] =
+ gtk_signal_new ("obj_updated",
GTK_RUN_FIRST,
object_class->type,
- GTK_SIGNAL_OFFSET (CalClientClass, obj_added),
+ GTK_SIGNAL_OFFSET (CalClientClass, obj_updated),
gtk_marshal_NONE__STRING,
GTK_TYPE_NONE, 1,
GTK_TYPE_STRING);
@@ -136,14 +135,6 @@ cal_client_class_init (CalClientClass *class)
gtk_marshal_NONE__STRING,
GTK_TYPE_NONE, 1,
GTK_TYPE_STRING);
- cal_client_signals[OBJ_CHANGED] =
- gtk_signal_new ("obj_changed",
- GTK_RUN_FIRST,
- object_class->type,
- GTK_SIGNAL_OFFSET (CalClientClass, obj_changed),
- gtk_marshal_NONE__STRING,
- GTK_TYPE_NONE, 1,
- GTK_TYPE_STRING);
gtk_object_class_add_signals (object_class, cal_client_signals, LAST_SIGNAL);
@@ -215,7 +206,7 @@ static void
destroy_cal (CalClient *client)
{
CalClientPrivate *priv;
- CORBA_Environment ev;
+ CORBA_Environment ev;
int result;
priv = client->priv;
@@ -233,7 +224,7 @@ destroy_cal (CalClient *client)
if (result)
return;
-
+
CORBA_exception_init (&ev);
Evolution_Calendar_Cal_unref (priv->cal, &ev);
if (ev._major != CORBA_NO_EXCEPTION)
@@ -343,14 +334,14 @@ cal_loaded_cb (CalListener *listener,
client_status);
}
-/* Handle the obj_added signal from the listener */
+/* Handle the obj_updated signal from the listener */
static void
-obj_added_cb (CalListener *listener, const Evolution_Calendar_CalObjUID uid, gpointer data)
+obj_updated_cb (CalListener *listener, const Evolution_Calendar_CalObjUID uid, gpointer data)
{
CalClient *client;
client = CAL_CLIENT (data);
- gtk_signal_emit (GTK_OBJECT (client), cal_client_signals[OBJ_ADDED], uid);
+ gtk_signal_emit (GTK_OBJECT (client), cal_client_signals[OBJ_UPDATED], uid);
}
/* Handle the obj_removed signal from the listener */
@@ -363,16 +354,6 @@ obj_removed_cb (CalListener *listener, const Evolution_Calendar_CalObjUID uid, g
gtk_signal_emit (GTK_OBJECT (client), cal_client_signals[OBJ_REMOVED], uid);
}
-/* Handle the obj_changed signal from the listener */
-static void
-obj_changed_cb (CalListener *listener, const Evolution_Calendar_CalObjUID uid, gpointer data)
-{
- CalClient *client;
-
- client = CAL_CLIENT (data);
- gtk_signal_emit (GTK_OBJECT (client), cal_client_signals[OBJ_CHANGED], uid);
-}
-
/**
@@ -484,15 +465,12 @@ load_or_create (CalClient *client, const char *str_uri, gboolean load)
gtk_signal_connect (GTK_OBJECT (priv->listener), "cal_loaded",
GTK_SIGNAL_FUNC (cal_loaded_cb),
client);
- gtk_signal_connect (GTK_OBJECT (priv->listener), "obj_added",
- GTK_SIGNAL_FUNC (obj_added_cb),
+ gtk_signal_connect (GTK_OBJECT (priv->listener), "obj_updated",
+ GTK_SIGNAL_FUNC (obj_updated_cb),
client);
gtk_signal_connect (GTK_OBJECT (priv->listener), "obj_removed",
GTK_SIGNAL_FUNC (obj_removed_cb),
client);
- gtk_signal_connect (GTK_OBJECT (priv->listener), "obj_changed",
- GTK_SIGNAL_FUNC (obj_changed_cb),
- client);
corba_listener = (Evolution_Calendar_Listener) bonobo_object_corba_objref (
BONOBO_OBJECT (priv->listener));
@@ -719,3 +697,52 @@ cal_client_get_events_in_range (CalClient *client, time_t start, time_t end)
return elist;
}
+
+/**
+ * cal_client_update_object:
+ * @client: A calendar client.
+ * @uid: Unique identifier of object to update.
+ * @calobj: String representation of the new calendar object.
+ *
+ * Asks a calendar to update an object based on its UID. Any existing object
+ * with the specified UID will be replaced. The client program should not
+ * assume that the object is actually in the server's storage until it has
+ * received the "obj_updated" notification signal.
+ *
+ * Return value: TRUE on success, FALSE on specifying an invalid object.
+ **/
+gboolean
+cal_client_update_object (CalClient *client, const char *uid, const char *calobj)
+{
+ CalClientPrivate *priv;
+ CORBA_Environment ev;
+ gboolean retval;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE);
+
+ priv = client->priv;
+ g_return_val_if_fail (priv->load_state == LOAD_STATE_LOADED, FALSE);
+
+ g_return_val_if_fail (uid != NULL, FALSE);
+ g_return_val_if_fail (calobj != NULL, FALSE);
+
+ retval = FALSE;
+
+ CORBA_exception_init (&ev);
+ Evolution_Calendar_Cal_update_object (priv->cal, uid, calobj, &ev);
+
+ if (ev._major == CORBA_USER_EXCEPTION &&
+ strcmp (CORBA_exception_id (&ev), ex_Evolution_Calendar_Cal_InvalidObject) == 0)
+ goto out;
+ else if (ev._major != CORBA_NO_EXCEPTION) {
+ g_message ("cal_client_update_object(): could not update the object");
+ goto out;
+ }
+
+ retval = TRUE;
+
+ out:
+ CORBA_exception_free (&ev);
+ return retval;
+}
diff --git a/calendar/cal-client/cal-client.h b/calendar/cal-client/cal-client.h
index 0c4c3e4406..7baad2c733 100644
--- a/calendar/cal-client/cal-client.h
+++ b/calendar/cal-client/cal-client.h
@@ -60,9 +60,8 @@ struct _CalClientClass {
void (* cal_loaded) (CalClient *client, CalClientLoadStatus status);
- void (* obj_added) (CalClient *client, const char *uid);
+ void (* obj_updated) (CalClient *client, const char *uid);
void (* obj_removed) (CalClient *client, const char *uid);
- void (* obj_changed) (CalClient *client, const char *uid);
};
GtkType cal_client_get_type (void);
@@ -80,6 +79,8 @@ GList *cal_client_get_uids (CalClient *client, CalObjType type);
GList *cal_client_get_events_in_range (CalClient *client, time_t start, time_t end);
+gboolean cal_client_update_object (CalClient *client, const char *uid, const char *calobj);
+
END_GNOME_DECLS
diff --git a/calendar/cal-client/cal-listener.c b/calendar/cal-client/cal-listener.c
index 32024d04f5..2c875c4c38 100644
--- a/calendar/cal-client/cal-listener.c
+++ b/calendar/cal-client/cal-listener.c
@@ -36,9 +36,8 @@ typedef struct {
/* Signal IDs */
enum {
CAL_LOADED,
- OBJ_ADDED,
+ OBJ_UPDATED,
OBJ_REMOVED,
- OBJ_CHANGED,
LAST_SIGNAL
};
@@ -115,11 +114,11 @@ cal_listener_class_init (CalListenerClass *class)
GTK_TYPE_NONE, 2,
GTK_TYPE_ENUM,
GTK_TYPE_POINTER);
- cal_listener_signals[OBJ_ADDED] =
- gtk_signal_new ("obj_added",
+ cal_listener_signals[OBJ_UPDATED] =
+ gtk_signal_new ("obj_updated",
GTK_RUN_FIRST,
object_class->type,
- GTK_SIGNAL_OFFSET (CalListenerClass, obj_added),
+ GTK_SIGNAL_OFFSET (CalListenerClass, obj_updated),
gtk_marshal_NONE__POINTER,
GTK_TYPE_NONE, 1,
GTK_TYPE_POINTER);
@@ -131,14 +130,6 @@ cal_listener_class_init (CalListenerClass *class)
gtk_marshal_NONE__POINTER,
GTK_TYPE_NONE, 1,
GTK_TYPE_POINTER);
- cal_listener_signals[OBJ_CHANGED] =
- gtk_signal_new ("obj_changed",
- GTK_RUN_FIRST,
- object_class->type,
- GTK_SIGNAL_OFFSET (CalListenerClass, obj_changed),
- gtk_marshal_NONE__POINTER,
- GTK_TYPE_NONE, 1,
- GTK_TYPE_POINTER);
gtk_object_class_add_signals (object_class, cal_listener_signals, LAST_SIGNAL);
@@ -272,16 +263,16 @@ Listener_cal_loaded (PortableServer_Servant servant,
load_status, cal);
}
-/* Listener::obj_added method */
+/* Listener::obj_updated method */
static void
-Listener_obj_added (PortableServer_Servant servant,
- Evolution_Calendar_CalObjUID uid,
- CORBA_Environment *ev)
+Listener_obj_updated (PortableServer_Servant servant,
+ Evolution_Calendar_CalObjUID uid,
+ CORBA_Environment *ev)
{
CalListener *listener;
listener = CAL_LISTENER (bonobo_object_from_servant (servant));
- gtk_signal_emit (GTK_OBJECT (listener), cal_listener_signals[OBJ_ADDED],
+ gtk_signal_emit (GTK_OBJECT (listener), cal_listener_signals[OBJ_UPDATED],
uid);
}
@@ -298,19 +289,6 @@ Listener_obj_removed (PortableServer_Servant servant,
uid);
}
-/* Listener::obj_changed method */
-static void
-Listener_obj_changed (PortableServer_Servant servant,
- Evolution_Calendar_CalObjUID uid,
- CORBA_Environment *ev)
-{
- CalListener *listener;
-
- listener = CAL_LISTENER (bonobo_object_from_servant (servant));
- gtk_signal_emit (GTK_OBJECT (listener), cal_listener_signals[OBJ_CHANGED],
- uid);
-}
-
/**
* cal_listener_get_epv:
* @void:
@@ -326,10 +304,8 @@ cal_listener_get_epv (void)
epv = g_new0 (POA_Evolution_Calendar_Listener__epv, 1);
epv->cal_loaded = Listener_cal_loaded;
- epv->obj_added = Listener_obj_added;
+ epv->obj_updated = Listener_obj_updated;
epv->obj_removed = Listener_obj_removed;
- epv->obj_changed = Listener_obj_changed;
-
return epv;
}
@@ -415,7 +391,7 @@ cal_listener_new (void)
if (ev._major != CORBA_NO_EXCEPTION || result) {
g_message ("cal_listener_new(): could not create the CORBA listener");
- gtk_object_unref (GTK_OBJECT (listener));
+ bonobo_object_unref (BONOBO_OBJECT (listener));
CORBA_exception_free (&ev);
return NULL;
}
diff --git a/calendar/cal-client/cal-listener.h b/calendar/cal-client/cal-listener.h
index 52b934e774..23590e6ff8 100644
--- a/calendar/cal-client/cal-listener.h
+++ b/calendar/cal-client/cal-listener.h
@@ -62,9 +62,8 @@ struct _CalListenerClass {
void (* cal_loaded) (CalListener *listener,
CalListenerLoadStatus status,
Evolution_Calendar_Cal cal);
- void (* obj_added) (CalListener *listener, const Evolution_Calendar_CalObjUID uid);
+ void (* obj_updated) (CalListener *listener, const Evolution_Calendar_CalObjUID uid);
void (* obj_removed) (CalListener *listener, const Evolution_Calendar_CalObjUID uid);
- void (* obj_changed) (CalListener *listener, const Evolution_Calendar_CalObjUID uid);
};
GtkType cal_listener_get_type (void);
diff --git a/calendar/cal-client/client-test.c b/calendar/cal-client/client-test.c
index bebaa42d87..d2374db275 100644
--- a/calendar/cal-client/client-test.c
+++ b/calendar/cal-client/client-test.c
@@ -57,13 +57,15 @@ list_uids (gpointer data)
printf ("------------------------------\n%s", calobj);
printf ("------------------------------\n");
+ cal_client_update_object (client, uid, calobj);
+
g_free (calobj);
}
}
cal_obj_uid_list_free (uids);
- gtk_object_unref (GTK_OBJECT (client));
+/* gtk_object_unref (GTK_OBJECT (client)); */
return FALSE;
}
@@ -84,6 +86,13 @@ cal_loaded (CalClient *client, CalClientLoadStatus status, gpointer data)
gtk_object_unref (GTK_OBJECT (client));
}
+/* Callback used when an object is updated */
+static void
+obj_updated (CalClient *client, const char *uid, gpointer data)
+{
+ cl_printf (client, "Object updated: %s\n", uid);
+}
+
/* Creates a calendar client and tries to load the specified URI into it */
static CalClient *
create_client (const char *uri, gboolean load)
@@ -100,13 +109,16 @@ create_client (const char *uri, gboolean load)
gtk_signal_connect (GTK_OBJECT (client), "cal_loaded",
GTK_SIGNAL_FUNC (cal_loaded),
NULL);
+ gtk_signal_connect (GTK_OBJECT (client), "obj_updated",
+ GTK_SIGNAL_FUNC (obj_updated),
+ NULL);
printf ("Calendar loading `%s'...\n", uri);
if (load)
result = cal_client_load_calendar (client, uri);
else
- result = cal_client_create_calendar (client, uri);
+ result = cal_client_load_calendar (client, uri);
if (!result) {
g_message ("create_client(): failure when issuing calendar load/create request `%s'",
diff --git a/calendar/cal-factory.c b/calendar/cal-factory.c
index 14b7ac9cb6..a170718678 100644
--- a/calendar/cal-factory.c
+++ b/calendar/cal-factory.c
@@ -20,6 +20,7 @@
*/
#include <config.h>
+#include <gtk/gtksignal.h>
#include "cal.h"
#include "cal-backend.h"
#include "cal-factory.h"
@@ -139,6 +140,8 @@ cal_factory_destroy (GtkObject *object)
factory = CAL_FACTORY (object);
priv = factory->priv;
+ /* Should we assert that there are no more backends? */
+
g_hash_table_foreach (priv->backends, free_backend, NULL);
g_hash_table_destroy (priv->backends);
priv->backends = NULL;
@@ -244,6 +247,41 @@ lookup_backend (CalFactory *factory, GnomeVFSURI *uri)
return backend;
}
+/* Callback used when a backend is destroyed */
+static void
+backend_destroy_cb (GtkObject *object, gpointer data)
+{
+ CalFactory *factory;
+ CalFactoryPrivate *priv;
+ CalBackend *backend;
+ GnomeVFSURI *uri;
+ gpointer orig_key;
+ gboolean result;
+ GnomeVFSURI *orig_uri;
+
+ factory = CAL_FACTORY (data);
+ priv = factory->priv;
+
+ /* Remove the backend from the hash table */
+
+ backend = CAL_BACKEND (object);
+ uri = cal_backend_get_uri (backend);
+ g_assert (uri != NULL);
+
+ result = g_hash_table_lookup_extended (priv->backends, uri, &orig_key, NULL);
+ g_assert (result != FALSE);
+
+ orig_uri = orig_key;
+
+ g_hash_table_remove (priv->backends, orig_uri);
+ gnome_vfs_uri_unref (orig_uri);
+
+ /* If there are no more backends, then the factory can go away */
+
+ if (g_hash_table_size (priv->backends) == 0)
+ bonobo_object_unref (BONOBO_OBJECT (factory));
+}
+
/* Adds a backend to the calendar factory's hash table */
static void
add_backend (CalFactory *factory, GnomeVFSURI *uri, CalBackend *backend)
@@ -254,9 +292,10 @@ add_backend (CalFactory *factory, GnomeVFSURI *uri, CalBackend *backend)
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.
- */
+
+ gtk_signal_connect (GTK_OBJECT (backend), "destroy",
+ GTK_SIGNAL_FUNC (backend_destroy_cb),
+ factory);
}
/* Loads a calendar backend and puts it in the factory's backend hash table */
@@ -350,6 +389,8 @@ add_calendar_client (CalFactory *factory, CalBackend *backend, Evolution_Calenda
g_message ("add_calendar_client(): could not notify the listener");
bonobo_object_unref (BONOBO_OBJECT (cal));
}
+
+ CORBA_exception_free (&ev);
}
/* Job handler for the load calendar command */
@@ -566,7 +607,7 @@ cal_factory_new (void)
if (ev._major != CORBA_NO_EXCEPTION || retval) {
g_message ("cal_factory_new(): could not create the CORBA factory");
- gtk_object_unref (GTK_OBJECT (factory));
+ bonobo_object_unref (BONOBO_OBJECT (factory));
CORBA_exception_free (&ev);
return NULL;
}
diff --git a/calendar/cal-listener.c b/calendar/cal-listener.c
index 32024d04f5..2c875c4c38 100644
--- a/calendar/cal-listener.c
+++ b/calendar/cal-listener.c
@@ -36,9 +36,8 @@ typedef struct {
/* Signal IDs */
enum {
CAL_LOADED,
- OBJ_ADDED,
+ OBJ_UPDATED,
OBJ_REMOVED,
- OBJ_CHANGED,
LAST_SIGNAL
};
@@ -115,11 +114,11 @@ cal_listener_class_init (CalListenerClass *class)
GTK_TYPE_NONE, 2,
GTK_TYPE_ENUM,
GTK_TYPE_POINTER);
- cal_listener_signals[OBJ_ADDED] =
- gtk_signal_new ("obj_added",
+ cal_listener_signals[OBJ_UPDATED] =
+ gtk_signal_new ("obj_updated",
GTK_RUN_FIRST,
object_class->type,
- GTK_SIGNAL_OFFSET (CalListenerClass, obj_added),
+ GTK_SIGNAL_OFFSET (CalListenerClass, obj_updated),
gtk_marshal_NONE__POINTER,
GTK_TYPE_NONE, 1,
GTK_TYPE_POINTER);
@@ -131,14 +130,6 @@ cal_listener_class_init (CalListenerClass *class)
gtk_marshal_NONE__POINTER,
GTK_TYPE_NONE, 1,
GTK_TYPE_POINTER);
- cal_listener_signals[OBJ_CHANGED] =
- gtk_signal_new ("obj_changed",
- GTK_RUN_FIRST,
- object_class->type,
- GTK_SIGNAL_OFFSET (CalListenerClass, obj_changed),
- gtk_marshal_NONE__POINTER,
- GTK_TYPE_NONE, 1,
- GTK_TYPE_POINTER);
gtk_object_class_add_signals (object_class, cal_listener_signals, LAST_SIGNAL);
@@ -272,16 +263,16 @@ Listener_cal_loaded (PortableServer_Servant servant,
load_status, cal);
}
-/* Listener::obj_added method */
+/* Listener::obj_updated method */
static void
-Listener_obj_added (PortableServer_Servant servant,
- Evolution_Calendar_CalObjUID uid,
- CORBA_Environment *ev)
+Listener_obj_updated (PortableServer_Servant servant,
+ Evolution_Calendar_CalObjUID uid,
+ CORBA_Environment *ev)
{
CalListener *listener;
listener = CAL_LISTENER (bonobo_object_from_servant (servant));
- gtk_signal_emit (GTK_OBJECT (listener), cal_listener_signals[OBJ_ADDED],
+ gtk_signal_emit (GTK_OBJECT (listener), cal_listener_signals[OBJ_UPDATED],
uid);
}
@@ -298,19 +289,6 @@ Listener_obj_removed (PortableServer_Servant servant,
uid);
}
-/* Listener::obj_changed method */
-static void
-Listener_obj_changed (PortableServer_Servant servant,
- Evolution_Calendar_CalObjUID uid,
- CORBA_Environment *ev)
-{
- CalListener *listener;
-
- listener = CAL_LISTENER (bonobo_object_from_servant (servant));
- gtk_signal_emit (GTK_OBJECT (listener), cal_listener_signals[OBJ_CHANGED],
- uid);
-}
-
/**
* cal_listener_get_epv:
* @void:
@@ -326,10 +304,8 @@ cal_listener_get_epv (void)
epv = g_new0 (POA_Evolution_Calendar_Listener__epv, 1);
epv->cal_loaded = Listener_cal_loaded;
- epv->obj_added = Listener_obj_added;
+ epv->obj_updated = Listener_obj_updated;
epv->obj_removed = Listener_obj_removed;
- epv->obj_changed = Listener_obj_changed;
-
return epv;
}
@@ -415,7 +391,7 @@ cal_listener_new (void)
if (ev._major != CORBA_NO_EXCEPTION || result) {
g_message ("cal_listener_new(): could not create the CORBA listener");
- gtk_object_unref (GTK_OBJECT (listener));
+ bonobo_object_unref (BONOBO_OBJECT (listener));
CORBA_exception_free (&ev);
return NULL;
}
diff --git a/calendar/cal-listener.h b/calendar/cal-listener.h
index 52b934e774..23590e6ff8 100644
--- a/calendar/cal-listener.h
+++ b/calendar/cal-listener.h
@@ -62,9 +62,8 @@ struct _CalListenerClass {
void (* cal_loaded) (CalListener *listener,
CalListenerLoadStatus status,
Evolution_Calendar_Cal cal);
- void (* obj_added) (CalListener *listener, const Evolution_Calendar_CalObjUID uid);
+ void (* obj_updated) (CalListener *listener, const Evolution_Calendar_CalObjUID uid);
void (* obj_removed) (CalListener *listener, const Evolution_Calendar_CalObjUID uid);
- void (* obj_changed) (CalListener *listener, const Evolution_Calendar_CalObjUID uid);
};
GtkType cal_listener_get_type (void);
diff --git a/calendar/cal.c b/calendar/cal.c
index 358f08167d..158e4c493c 100644
--- a/calendar/cal.c
+++ b/calendar/cal.c
@@ -226,6 +226,7 @@ Cal_get_uids (PortableServer_Servant servant,
n = g_list_length (uids);
seq = Evolution_Calendar_CalObjUIDSeq__alloc ();
+ CORBA_sequence_set_release (seq, TRUE);
seq->_length = n;
seq->_buffer = CORBA_sequence_Evolution_Calendar_CalObjUID_allocbuf (n);
@@ -279,6 +280,7 @@ Cal_get_events_in_range (PortableServer_Servant servant,
n = g_list_length (elist);
seq = Evolution_Calendar_CalObjInstanceSeq__alloc ();
+ CORBA_sequence_set_release (seq, TRUE);
seq->_length = n;
seq->_buffer = CORBA_sequence_Evolution_Calendar_CalObjInstance_allocbuf (n);
@@ -304,6 +306,25 @@ Cal_get_events_in_range (PortableServer_Servant servant,
return seq;
}
+/* Cal::update_object method */
+static void
+Cal_update_object (PortableServer_Servant servant,
+ const Evolution_Calendar_CalObjUID uid,
+ const Evolution_Calendar_CalObj calobj,
+ CORBA_Environment *ev)
+{
+ Cal *cal;
+ CalPrivate *priv;
+
+ cal = CAL (bonobo_object_from_servant (servant));
+ priv = cal->priv;
+
+ if (!cal_backend_update_object (priv->backend, uid, calobj))
+ CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
+ ex_Evolution_Calendar_Cal_InvalidObject,
+ NULL);
+}
+
/**
* cal_get_epv:
* @void:
@@ -322,6 +343,7 @@ cal_get_epv (void)
epv->get_object = Cal_get_object;
epv->get_uids = Cal_get_uids;
epv->get_events_in_range = Cal_get_events_in_range;
+ epv->update_object = Cal_update_object;
return epv;
}
@@ -438,7 +460,7 @@ cal_new (CalBackend *backend, Evolution_Calendar_Listener listener)
ret = CORBA_Object_is_nil ((CORBA_Object) corba_cal, &ev);
if (ev._major != CORBA_NO_EXCEPTION || ret) {
g_message ("cal_new(): could not create the CORBA object");
- gtk_object_unref (GTK_OBJECT (cal));
+ bonobo_object_unref (BONOBO_OBJECT (cal));
CORBA_exception_free (&ev);
return NULL;
}
@@ -448,9 +470,40 @@ cal_new (CalBackend *backend, Evolution_Calendar_Listener listener)
retval = cal_construct (cal, corba_cal, backend, listener);
if (!retval) {
g_message ("cal_new(): could not construct the calendar client interface");
- gtk_object_unref (GTK_OBJECT (cal));
+ bonobo_object_unref (BONOBO_OBJECT (cal));
return NULL;
}
return retval;
}
+
+/**
+ * cal_notify_update:
+ * @cal: A calendar client interface.
+ * @uid: UID of object that was updated.
+ *
+ * Notifies a listener attached to a calendar client interface object about an
+ * update to a calendar object.
+ **/
+void
+cal_notify_update (Cal *cal, const char *uid)
+{
+ CalPrivate *priv;
+ CORBA_Environment ev;
+
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
+ g_return_if_fail (uid != NULL);
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
+ Evolution_Calendar_Listener_obj_updated (priv->listener, uid, &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION)
+ g_message ("cal_notify_update(): could not notify the listener "
+ "about an updated object");
+
+ CORBA_exception_free (&ev);
+}
diff --git a/calendar/cal.h b/calendar/cal.h
index b866470437..18f38f5655 100644
--- a/calendar/cal.h
+++ b/calendar/cal.h
@@ -58,6 +58,8 @@ Evolution_Calendar_Cal cal_corba_object_create (BonoboObject *object);
Cal *cal_new (CalBackend *backend, Evolution_Calendar_Listener listener);
+void cal_notify_update (Cal *cal, const char *uid);
+
POA_Evolution_Calendar_Cal__epv *cal_get_epv (void);
diff --git a/calendar/evolution-calendar.idl b/calendar/evolution-calendar.idl
index d4b87e9825..bc4266c3ae 100644
--- a/calendar/evolution-calendar.idl
+++ b/calendar/evolution-calendar.idl
@@ -41,7 +41,7 @@ module Calendar {
* "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.
+ * trigger.
*/
struct CalObjInstance {
CalObjUID uid;
@@ -58,6 +58,7 @@ module Calendar {
interface Cal : Bonobo::Unknown {
exception NotFound {};
exception InvalidRange {};
+ exception InvalidObject {};
/* A calendar is identified by its URI */
readonly attribute string uri;
@@ -72,6 +73,16 @@ module Calendar {
/* 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);
+
+ /* Updates an object by adding it if it does not exist or by
+ * changing an existing one.
+ */
+ void update_object (in CalObjUID uid, in CalObj calobj)
+ raises (InvalidObject);
+
+ /* Removes an object */
+ void remove_object (in CalObjUID uid)
+ raises (NotFound);
};
/* Listener for changes in a calendar */
@@ -81,23 +92,20 @@ module Calendar {
SUCCESS, /* All OK */
ERROR, /* Generic error */
IN_USE /* Requested create while a calendar
- * with the same URI was in use.
+ * with the same URI was in use.
*/
};
/* Called from a CalFactory when a calendar is initially loaded
- * or created. The listener must remember the cal object.
+ * or created. The listener must remember the cal object.
*/
void cal_loaded (in LoadStatus status, in Cal cal);
- /* Called from a Calendar when an object is added */
- void obj_added (in CalObjUID uid);
+ /* Called from a Calendar when an object is added or changed */
+ void obj_updated (in CalObjUID uid);
/* Called from a Calendar when an object is removed */
void obj_removed (in CalObjUID uid);
-
- /* Called from a Calendar when an object is changed */
- void obj_changed (in CalObjUID uid);
};
/* A calendar factory, can load and create calendars */
diff --git a/calendar/gui/layout.c b/calendar/gui/layout.c
index 7042071056..4195c464ae 100644
--- a/calendar/gui/layout.c
+++ b/calendar/gui/layout.c
@@ -279,6 +279,7 @@ layout_events (GList *events, LayoutQueryTimeFunc func, int *num_slots, int **al
/* Clean up and return values */
+ g_free (li.partition);
g_free (li.array);
*num_slots = li.num_slots;
diff --git a/calendar/idl/evolution-calendar.idl b/calendar/idl/evolution-calendar.idl
index d4b87e9825..bc4266c3ae 100644
--- a/calendar/idl/evolution-calendar.idl
+++ b/calendar/idl/evolution-calendar.idl
@@ -41,7 +41,7 @@ module Calendar {
* "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.
+ * trigger.
*/
struct CalObjInstance {
CalObjUID uid;
@@ -58,6 +58,7 @@ module Calendar {
interface Cal : Bonobo::Unknown {
exception NotFound {};
exception InvalidRange {};
+ exception InvalidObject {};
/* A calendar is identified by its URI */
readonly attribute string uri;
@@ -72,6 +73,16 @@ module Calendar {
/* 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);
+
+ /* Updates an object by adding it if it does not exist or by
+ * changing an existing one.
+ */
+ void update_object (in CalObjUID uid, in CalObj calobj)
+ raises (InvalidObject);
+
+ /* Removes an object */
+ void remove_object (in CalObjUID uid)
+ raises (NotFound);
};
/* Listener for changes in a calendar */
@@ -81,23 +92,20 @@ module Calendar {
SUCCESS, /* All OK */
ERROR, /* Generic error */
IN_USE /* Requested create while a calendar
- * with the same URI was in use.
+ * with the same URI was in use.
*/
};
/* Called from a CalFactory when a calendar is initially loaded
- * or created. The listener must remember the cal object.
+ * or created. The listener must remember the cal object.
*/
void cal_loaded (in LoadStatus status, in Cal cal);
- /* Called from a Calendar when an object is added */
- void obj_added (in CalObjUID uid);
+ /* Called from a Calendar when an object is added or changed */
+ void obj_updated (in CalObjUID uid);
/* Called from a Calendar when an object is removed */
void obj_removed (in CalObjUID uid);
-
- /* Called from a Calendar when an object is changed */
- void obj_changed (in CalObjUID uid);
};
/* A calendar factory, can load and create calendars */
diff --git a/calendar/layout.c b/calendar/layout.c
index 7042071056..4195c464ae 100644
--- a/calendar/layout.c
+++ b/calendar/layout.c
@@ -279,6 +279,7 @@ layout_events (GList *events, LayoutQueryTimeFunc func, int *num_slots, int **al
/* Clean up and return values */
+ g_free (li.partition);
g_free (li.array);
*num_slots = li.num_slots;
diff --git a/calendar/pcs/cal-backend.c b/calendar/pcs/cal-backend.c
index 18ed6a6c86..1ce4b615c3 100644
--- a/calendar/pcs/cal-backend.c
+++ b/calendar/pcs/cal-backend.c
@@ -197,6 +197,19 @@ cal_backend_destroy (GtkObject *object)
/* iCalObject manipulation functions */
+/* Looks up an object by its UID in the backend's object hash table */
+static iCalObject *
+lookup_object (CalBackend *backend, const char *uid)
+{
+ CalBackendPrivate *priv;
+ iCalObject *ico;
+
+ priv = backend->priv;
+ ico = g_hash_table_lookup (priv->object_hash, uid);
+
+ return ico;
+}
+
/* Ensures that an iCalObject has a unique identifier. If it doesn't have one,
* it will create one for it. Returns whether an UID was created or not.
*/
@@ -275,6 +288,49 @@ add_object (CalBackend *backend, iCalObject *ico)
#endif
}
+/* Removes an object from the backend's hash and lists. Does not perform
+ * notification on the clients.
+ */
+static void
+remove_object (CalBackend *backend, iCalObject *ico)
+{
+ CalBackendPrivate *priv;
+ GList **list, *l;
+
+ priv = backend->priv;
+
+ g_assert (ico->uid != NULL);
+ g_hash_table_remove (priv->object_hash, ico->uid);
+
+ switch (ico->type) {
+ case ICAL_EVENT:
+ list = &priv->events;
+ break;
+
+ case ICAL_TODO:
+ list = &priv->todos;
+ break;
+
+ case ICAL_JOURNAL:
+ list = &priv->journals;
+ break;
+
+ default:
+ list = NULL;
+ }
+
+ if (!list)
+ return;
+
+ l = g_list_find (*list, ico);
+ g_assert (l != NULL);
+
+ *list = g_list_remove_link (*list, l);
+ g_list_free_1 (l);
+
+ ical_object_destroy (ico);
+}
+
/* Load a calendar from a VObject */
static void
load_from_vobject (CalBackend *backend, VObject *vobject)
@@ -609,7 +665,7 @@ cal_backend_get_object (CalBackend *backend, const char *uid)
g_assert (priv->object_hash != NULL);
- ico = g_hash_table_lookup (priv->object_hash, uid);
+ ico = lookup_object (backend, uid);
if (!ico)
return NULL;
@@ -782,3 +838,84 @@ cal_backend_get_events_in_range (CalBackend *backend, time_t start, time_t end)
c.event_list = g_list_sort (c.event_list, compare_instance_func);
return c.event_list;
}
+
+/* Notifies a backend's clients that an object was updated */
+static void
+notify_update (CalBackend *backend, const char *uid)
+{
+ CalBackendPrivate *priv;
+ GList *l;
+
+ priv = backend->priv;
+
+ for (l = priv->clients; l; l = l->next) {
+ Cal *cal;
+
+ cal = CAL (l->data);
+ cal_notify_update (cal, uid);
+ }
+}
+
+/**
+ * cal_backend_update_object:
+ * @backend: A calendar backend.
+ * @uid: Unique identifier of the object to update.
+ * @calobj: String representation of the new calendar object.
+ *
+ * Updates an object in a calendar backend. It will replace any existing object
+ * that has the same UID as the specified one. The backend will in turn notify
+ * all of its clients about the change.
+ *
+ * Return value: TRUE on success, FALSE on being passed an invalid object.
+ **/
+gboolean
+cal_backend_update_object (CalBackend *backend, const char *uid, const char *calobj)
+{
+ CalBackendPrivate *priv;
+ iCalObject *ico, *new_ico;
+ CalObjFindStatus status;
+
+ g_return_val_if_fail (backend != NULL, FALSE);
+ g_return_val_if_fail (IS_CAL_BACKEND (backend), FALSE);
+
+ priv = backend->priv;
+ g_return_val_if_fail (priv->loaded, FALSE);
+
+ g_return_val_if_fail (uid != NULL, FALSE);
+ g_return_val_if_fail (calobj != NULL, FALSE);
+
+ /* Pull the object from the string */
+
+ status = ical_object_find_in_string (uid, calobj, &new_ico);
+
+ if (status != CAL_OBJ_FIND_SUCCESS)
+ return FALSE;
+
+ /* Update the object */
+
+ ico = lookup_object (backend, uid);
+
+ if (ico)
+ remove_object (backend, ico);
+
+ add_object (backend, new_ico);
+
+ notify_update (backend, new_ico->uid);
+ return TRUE;
+}
+
+void
+cal_backend_remove_object (CalBackend *backend, const char *uid)
+{
+ 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 (uid != NULL);
+
+ /* FIXME */
+}
diff --git a/calendar/pcs/cal-backend.h b/calendar/pcs/cal-backend.h
index 41b2b9186d..fab83e4b82 100644
--- a/calendar/pcs/cal-backend.h
+++ b/calendar/pcs/cal-backend.h
@@ -76,6 +76,10 @@ GList *cal_backend_get_uids (CalBackend *backend, CalObjType type);
GList *cal_backend_get_events_in_range (CalBackend *backend, time_t start, time_t end);
+gboolean cal_backend_update_object (CalBackend *backend, const char *uid, const char *calobj);
+
+void cal_backend_remove_object (CalBackend *backend, const char *uid);
+
END_GNOME_DECLS
diff --git a/calendar/pcs/cal-factory.c b/calendar/pcs/cal-factory.c
index 14b7ac9cb6..a170718678 100644
--- a/calendar/pcs/cal-factory.c
+++ b/calendar/pcs/cal-factory.c
@@ -20,6 +20,7 @@
*/
#include <config.h>
+#include <gtk/gtksignal.h>
#include "cal.h"
#include "cal-backend.h"
#include "cal-factory.h"
@@ -139,6 +140,8 @@ cal_factory_destroy (GtkObject *object)
factory = CAL_FACTORY (object);
priv = factory->priv;
+ /* Should we assert that there are no more backends? */
+
g_hash_table_foreach (priv->backends, free_backend, NULL);
g_hash_table_destroy (priv->backends);
priv->backends = NULL;
@@ -244,6 +247,41 @@ lookup_backend (CalFactory *factory, GnomeVFSURI *uri)
return backend;
}
+/* Callback used when a backend is destroyed */
+static void
+backend_destroy_cb (GtkObject *object, gpointer data)
+{
+ CalFactory *factory;
+ CalFactoryPrivate *priv;
+ CalBackend *backend;
+ GnomeVFSURI *uri;
+ gpointer orig_key;
+ gboolean result;
+ GnomeVFSURI *orig_uri;
+
+ factory = CAL_FACTORY (data);
+ priv = factory->priv;
+
+ /* Remove the backend from the hash table */
+
+ backend = CAL_BACKEND (object);
+ uri = cal_backend_get_uri (backend);
+ g_assert (uri != NULL);
+
+ result = g_hash_table_lookup_extended (priv->backends, uri, &orig_key, NULL);
+ g_assert (result != FALSE);
+
+ orig_uri = orig_key;
+
+ g_hash_table_remove (priv->backends, orig_uri);
+ gnome_vfs_uri_unref (orig_uri);
+
+ /* If there are no more backends, then the factory can go away */
+
+ if (g_hash_table_size (priv->backends) == 0)
+ bonobo_object_unref (BONOBO_OBJECT (factory));
+}
+
/* Adds a backend to the calendar factory's hash table */
static void
add_backend (CalFactory *factory, GnomeVFSURI *uri, CalBackend *backend)
@@ -254,9 +292,10 @@ add_backend (CalFactory *factory, GnomeVFSURI *uri, CalBackend *backend)
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.
- */
+
+ gtk_signal_connect (GTK_OBJECT (backend), "destroy",
+ GTK_SIGNAL_FUNC (backend_destroy_cb),
+ factory);
}
/* Loads a calendar backend and puts it in the factory's backend hash table */
@@ -350,6 +389,8 @@ add_calendar_client (CalFactory *factory, CalBackend *backend, Evolution_Calenda
g_message ("add_calendar_client(): could not notify the listener");
bonobo_object_unref (BONOBO_OBJECT (cal));
}
+
+ CORBA_exception_free (&ev);
}
/* Job handler for the load calendar command */
@@ -566,7 +607,7 @@ cal_factory_new (void)
if (ev._major != CORBA_NO_EXCEPTION || retval) {
g_message ("cal_factory_new(): could not create the CORBA factory");
- gtk_object_unref (GTK_OBJECT (factory));
+ bonobo_object_unref (BONOBO_OBJECT (factory));
CORBA_exception_free (&ev);
return NULL;
}
diff --git a/calendar/pcs/cal.c b/calendar/pcs/cal.c
index 358f08167d..158e4c493c 100644
--- a/calendar/pcs/cal.c
+++ b/calendar/pcs/cal.c
@@ -226,6 +226,7 @@ Cal_get_uids (PortableServer_Servant servant,
n = g_list_length (uids);
seq = Evolution_Calendar_CalObjUIDSeq__alloc ();
+ CORBA_sequence_set_release (seq, TRUE);
seq->_length = n;
seq->_buffer = CORBA_sequence_Evolution_Calendar_CalObjUID_allocbuf (n);
@@ -279,6 +280,7 @@ Cal_get_events_in_range (PortableServer_Servant servant,
n = g_list_length (elist);
seq = Evolution_Calendar_CalObjInstanceSeq__alloc ();
+ CORBA_sequence_set_release (seq, TRUE);
seq->_length = n;
seq->_buffer = CORBA_sequence_Evolution_Calendar_CalObjInstance_allocbuf (n);
@@ -304,6 +306,25 @@ Cal_get_events_in_range (PortableServer_Servant servant,
return seq;
}
+/* Cal::update_object method */
+static void
+Cal_update_object (PortableServer_Servant servant,
+ const Evolution_Calendar_CalObjUID uid,
+ const Evolution_Calendar_CalObj calobj,
+ CORBA_Environment *ev)
+{
+ Cal *cal;
+ CalPrivate *priv;
+
+ cal = CAL (bonobo_object_from_servant (servant));
+ priv = cal->priv;
+
+ if (!cal_backend_update_object (priv->backend, uid, calobj))
+ CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
+ ex_Evolution_Calendar_Cal_InvalidObject,
+ NULL);
+}
+
/**
* cal_get_epv:
* @void:
@@ -322,6 +343,7 @@ cal_get_epv (void)
epv->get_object = Cal_get_object;
epv->get_uids = Cal_get_uids;
epv->get_events_in_range = Cal_get_events_in_range;
+ epv->update_object = Cal_update_object;
return epv;
}
@@ -438,7 +460,7 @@ cal_new (CalBackend *backend, Evolution_Calendar_Listener listener)
ret = CORBA_Object_is_nil ((CORBA_Object) corba_cal, &ev);
if (ev._major != CORBA_NO_EXCEPTION || ret) {
g_message ("cal_new(): could not create the CORBA object");
- gtk_object_unref (GTK_OBJECT (cal));
+ bonobo_object_unref (BONOBO_OBJECT (cal));
CORBA_exception_free (&ev);
return NULL;
}
@@ -448,9 +470,40 @@ cal_new (CalBackend *backend, Evolution_Calendar_Listener listener)
retval = cal_construct (cal, corba_cal, backend, listener);
if (!retval) {
g_message ("cal_new(): could not construct the calendar client interface");
- gtk_object_unref (GTK_OBJECT (cal));
+ bonobo_object_unref (BONOBO_OBJECT (cal));
return NULL;
}
return retval;
}
+
+/**
+ * cal_notify_update:
+ * @cal: A calendar client interface.
+ * @uid: UID of object that was updated.
+ *
+ * Notifies a listener attached to a calendar client interface object about an
+ * update to a calendar object.
+ **/
+void
+cal_notify_update (Cal *cal, const char *uid)
+{
+ CalPrivate *priv;
+ CORBA_Environment ev;
+
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
+ g_return_if_fail (uid != NULL);
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
+ Evolution_Calendar_Listener_obj_updated (priv->listener, uid, &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION)
+ g_message ("cal_notify_update(): could not notify the listener "
+ "about an updated object");
+
+ CORBA_exception_free (&ev);
+}
diff --git a/calendar/pcs/cal.h b/calendar/pcs/cal.h
index b866470437..18f38f5655 100644
--- a/calendar/pcs/cal.h
+++ b/calendar/pcs/cal.h
@@ -58,6 +58,8 @@ Evolution_Calendar_Cal cal_corba_object_create (BonoboObject *object);
Cal *cal_new (CalBackend *backend, Evolution_Calendar_Listener listener);
+void cal_notify_update (Cal *cal, const char *uid);
+
POA_Evolution_Calendar_Cal__epv *cal_get_epv (void);
diff --git a/calendar/pcs/tlacuache.c b/calendar/pcs/tlacuache.c
index 602cbfbe27..35bb585862 100644
--- a/calendar/pcs/tlacuache.c
+++ b/calendar/pcs/tlacuache.c
@@ -28,11 +28,6 @@
-/* The calendar factory */
-static CalFactory *factory;
-
-
-
/* Stuff that the un-converted alarm code needs to build */
int debug_alarms = FALSE;
@@ -54,10 +49,18 @@ calendar_notify (time_t time, CalendarAlarm *which, void *data)
+/* Callback used when the calendar factory is destroyed */
+static void
+factory_destroy_cb (GtkObject *object, gpointer data)
+{
+ gtk_main_quit ();
+}
+
/* Creates and registers the calendar factory */
static gboolean
create_cal_factory (void)
{
+ CalFactory *factory;
CORBA_Object object;
CORBA_Environment ev;
int result;
@@ -79,14 +82,20 @@ create_cal_factory (void)
if (ev._major != CORBA_NO_EXCEPTION || result == -1) {
g_message ("create_cal_factory(): could not register the calendar factory");
+ bonobo_object_unref (BONOBO_OBJECT (factory));
CORBA_exception_free (&ev);
return FALSE;
} else if (result == -2) {
g_message ("create_cal_factory(): a calendar factory is already registered");
+ bonobo_object_unref (BONOBO_OBJECT (factory));
CORBA_exception_free (&ev);
return FALSE;
}
+ gtk_signal_connect (GTK_OBJECT (factory), "destroy",
+ GTK_SIGNAL_FUNC (factory_destroy_cb),
+ NULL);
+
CORBA_exception_free (&ev);
return TRUE;
}
diff --git a/calendar/tl-test.c b/calendar/tl-test.c
index bebaa42d87..d2374db275 100644
--- a/calendar/tl-test.c
+++ b/calendar/tl-test.c
@@ -57,13 +57,15 @@ list_uids (gpointer data)
printf ("------------------------------\n%s", calobj);
printf ("------------------------------\n");
+ cal_client_update_object (client, uid, calobj);
+
g_free (calobj);
}
}
cal_obj_uid_list_free (uids);
- gtk_object_unref (GTK_OBJECT (client));
+/* gtk_object_unref (GTK_OBJECT (client)); */
return FALSE;
}
@@ -84,6 +86,13 @@ cal_loaded (CalClient *client, CalClientLoadStatus status, gpointer data)
gtk_object_unref (GTK_OBJECT (client));
}
+/* Callback used when an object is updated */
+static void
+obj_updated (CalClient *client, const char *uid, gpointer data)
+{
+ cl_printf (client, "Object updated: %s\n", uid);
+}
+
/* Creates a calendar client and tries to load the specified URI into it */
static CalClient *
create_client (const char *uri, gboolean load)
@@ -100,13 +109,16 @@ create_client (const char *uri, gboolean load)
gtk_signal_connect (GTK_OBJECT (client), "cal_loaded",
GTK_SIGNAL_FUNC (cal_loaded),
NULL);
+ gtk_signal_connect (GTK_OBJECT (client), "obj_updated",
+ GTK_SIGNAL_FUNC (obj_updated),
+ NULL);
printf ("Calendar loading `%s'...\n", uri);
if (load)
result = cal_client_load_calendar (client, uri);
else
- result = cal_client_create_calendar (client, uri);
+ result = cal_client_load_calendar (client, uri);
if (!result) {
g_message ("create_client(): failure when issuing calendar load/create request `%s'",
diff --git a/calendar/tlacuache.c b/calendar/tlacuache.c
index 602cbfbe27..35bb585862 100644
--- a/calendar/tlacuache.c
+++ b/calendar/tlacuache.c
@@ -28,11 +28,6 @@
-/* The calendar factory */
-static CalFactory *factory;
-
-
-
/* Stuff that the un-converted alarm code needs to build */
int debug_alarms = FALSE;
@@ -54,10 +49,18 @@ calendar_notify (time_t time, CalendarAlarm *which, void *data)
+/* Callback used when the calendar factory is destroyed */
+static void
+factory_destroy_cb (GtkObject *object, gpointer data)
+{
+ gtk_main_quit ();
+}
+
/* Creates and registers the calendar factory */
static gboolean
create_cal_factory (void)
{
+ CalFactory *factory;
CORBA_Object object;
CORBA_Environment ev;
int result;
@@ -79,14 +82,20 @@ create_cal_factory (void)
if (ev._major != CORBA_NO_EXCEPTION || result == -1) {
g_message ("create_cal_factory(): could not register the calendar factory");
+ bonobo_object_unref (BONOBO_OBJECT (factory));
CORBA_exception_free (&ev);
return FALSE;
} else if (result == -2) {
g_message ("create_cal_factory(): a calendar factory is already registered");
+ bonobo_object_unref (BONOBO_OBJECT (factory));
CORBA_exception_free (&ev);
return FALSE;
}
+ gtk_signal_connect (GTK_OBJECT (factory), "destroy",
+ GTK_SIGNAL_FUNC (factory_destroy_cb),
+ NULL);
+
CORBA_exception_free (&ev);
return TRUE;
}