From 96d24f1297eaa5a6333b9fcfdf35420d273703af Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Wed, 1 Aug 2001 03:41:51 +0000 Subject: The Wombat now keeps track of which categories are present in the objects 2001-07-31 Federico Mena Quintero The Wombat now keeps track of which categories are present in the objects of a calendar. It will notify the clients of changes in this set. This is to make the category drop-down menus in the calendar/tasks views be always up to date. * idl/evolution-calendar.idl (Listener): Added a notifyCategoriesChanged() method. The Wombat now keeps track of the categories within a calendar. * cal-client/cal-listener.[ch]: Switched it to use BonoboXObject. Also added the notifyCategoriesChanged implementation. * cal-client/cal-client.[ch]: Added a "categories_changed" signal. * pcs/cal-backend-file.c: Maintain a list of the live categories. (update_categories_from_comp): New function to maintain the set of live categories. (add_component): Update the set of categories. (remove_component): Likewise. (open_cal): Notify about changes in the set of categories. (create_cal): Likewise. (cal_backend_file_update_objects): Likewise. (cal_backend_file_remove_object): Likewise. (notify_categories_changed): New function to notify the clients about the current set of categories. * pcs/cal.c (cal_notify_categories_changed): New function. svn path=/trunk/; revision=11536 --- calendar/ChangeLog | 30 ++++++ calendar/cal-client/cal-client.c | 38 +++++++ calendar/cal-client/cal-client.h | 2 + calendar/cal-client/cal-listener.c | 203 ++++++++++++------------------------ calendar/cal-client/cal-listener.h | 35 +++---- calendar/idl/evolution-calendar.idl | 6 ++ calendar/pcs/cal-backend-file.c | 147 +++++++++++++++++++++++++- calendar/pcs/cal.c | 31 ++++++ calendar/pcs/cal.h | 2 + 9 files changed, 339 insertions(+), 155 deletions(-) (limited to 'calendar') diff --git a/calendar/ChangeLog b/calendar/ChangeLog index f5e999af8d..ef7b73a460 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,33 @@ +2001-07-31 Federico Mena Quintero + + The Wombat now keeps track of which categories are present in the + objects of a calendar. It will notify the clients of changes in + this set. This is to make the category drop-down menus in the + calendar/tasks views be always up to date. + + * idl/evolution-calendar.idl (Listener): Added a + notifyCategoriesChanged() method. The Wombat now keeps track of + the categories within a calendar. + + * cal-client/cal-listener.[ch]: Switched it to use BonoboXObject. + Also added the notifyCategoriesChanged implementation. + + * cal-client/cal-client.[ch]: Added a "categories_changed" signal. + + * pcs/cal-backend-file.c: Maintain a list of the live categories. + (update_categories_from_comp): New function to maintain the set of + live categories. + (add_component): Update the set of categories. + (remove_component): Likewise. + (open_cal): Notify about changes in the set of categories. + (create_cal): Likewise. + (cal_backend_file_update_objects): Likewise. + (cal_backend_file_remove_object): Likewise. + (notify_categories_changed): New function to notify the clients + about the current set of categories. + + * pcs/cal.c (cal_notify_categories_changed): New function. + 2001-07-31 Rodrigo Moya * gui/e-day-view.c (selection_received): diff --git a/calendar/cal-client/cal-client.c b/calendar/cal-client/cal-client.c index 007466ddad..bb888e6205 100644 --- a/calendar/cal-client/cal-client.c +++ b/calendar/cal-client/cal-client.c @@ -71,6 +71,7 @@ enum { CAL_OPENED, OBJ_UPDATED, OBJ_REMOVED, + CATEGORIES_CHANGED, FORGET_PASSWORD, LAST_SIGNAL }; @@ -160,6 +161,14 @@ cal_client_class_init (CalClientClass *class) gtk_marshal_NONE__STRING, GTK_TYPE_NONE, 1, GTK_TYPE_STRING); + cal_client_signals[CATEGORIES_CHANGED] = + gtk_signal_new ("categories_changed", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (CalClientClass, categories_changed), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, + GTK_TYPE_POINTER); cal_client_signals[FORGET_PASSWORD] = gtk_signal_new ("forget_password", GTK_RUN_FIRST, @@ -171,6 +180,12 @@ cal_client_class_init (CalClientClass *class) gtk_object_class_add_signals (object_class, cal_client_signals, LAST_SIGNAL); + class->cal_opened = NULL; + class->obj_updated = NULL; + class->obj_removed = NULL; + class->categories_changed = NULL; + class->forget_password = NULL; + object_class->destroy = cal_client_destroy; } @@ -455,6 +470,28 @@ obj_removed_cb (CalListener *listener, const GNOME_Evolution_Calendar_CalObjUID gtk_signal_emit (GTK_OBJECT (client), cal_client_signals[OBJ_REMOVED], uid); } +/* Handle the categories_changed signal from the listener */ +static void +categories_changed_cb (CalListener *listener, const GNOME_Evolution_Calendar_StringSeq *categories, + gpointer data) +{ + CalClient *client; + GPtrArray *cats; + int i; + + client = CAL_CLIENT (data); + + cats = g_ptr_array_new (); + g_ptr_array_set_size (cats, categories->_length); + + for (i = 0; i < categories->_length; i++) + cats->pdata[i] = categories->_buffer[i]; + + gtk_signal_emit (GTK_OBJECT (client), cal_client_signals[CATEGORIES_CHANGED], cats); + + g_ptr_array_free (cats, TRUE); +} + /* Handle the get_password signal from the Wombatclient */ static gchar * client_get_password_cb (WombatClient *w_client, @@ -626,6 +663,7 @@ cal_client_open_calendar (CalClient *client, const char *str_uri, gboolean only_ priv->listener = cal_listener_new (cal_opened_cb, obj_updated_cb, obj_removed_cb, + categories_changed_cb, client); if (!priv->listener) { g_message ("cal_client_open_calendar(): could not create the listener"); diff --git a/calendar/cal-client/cal-client.h b/calendar/cal-client/cal-client.h index 4681574289..a5facbd1c6 100644 --- a/calendar/cal-client/cal-client.h +++ b/calendar/cal-client/cal-client.h @@ -82,6 +82,8 @@ struct _CalClientClass { void (* obj_updated) (CalClient *client, const char *uid); void (* obj_removed) (CalClient *client, const char *uid); + void (* categories_changed) (CalClient *client, GPtrArray *categories); + void (* forget_password) (CalClient *client, const char *key); }; diff --git a/calendar/cal-client/cal-listener.c b/calendar/cal-client/cal-listener.c index aeeccef7dc..087d5e9c00 100644 --- a/calendar/cal-client/cal-listener.c +++ b/calendar/cal-client/cal-listener.c @@ -1,7 +1,6 @@ /* Evolution calendar listener * - * Copyright (C) 2000 Ximian, Inc. - * Copyright (C) 2000 Ximian, Inc. + * Copyright (C) 2001 Ximian, Inc. * * Author: Federico Mena-Quintero * @@ -26,7 +25,7 @@ /* Private part of the CalListener structure */ -struct _CalListenerPrivate { +struct CalListenerPrivate { /* The calendar this listener refers to */ GNOME_Evolution_Calendar_Cal cal; @@ -34,6 +33,7 @@ struct _CalListenerPrivate { CalListenerCalOpenedFn cal_opened_fn; CalListenerObjUpdatedFn obj_updated_fn; CalListenerObjRemovedFn obj_removed_fn; + CalListenerCategoriesChangedFn categories_changed_fn; gpointer fn_data; }; @@ -43,51 +43,28 @@ static void cal_listener_class_init (CalListenerClass *class); static void cal_listener_init (CalListener *listener); static void cal_listener_destroy (GtkObject *object); -static POA_GNOME_Evolution_Calendar_Listener__vepv cal_listener_vepv; - -static BonoboObjectClass *parent_class; +static void impl_notifyCalOpened (PortableServer_Servant servant, + GNOME_Evolution_Calendar_Listener_OpenStatus status, + GNOME_Evolution_Calendar_Cal cal, + CORBA_Environment *ev); +static void impl_notifyObjUpdated (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CalObjUID uid, + CORBA_Environment *ev); +static void impl_notifyObjRemoved (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CalObjUID uid, + CORBA_Environment *ev); +static void impl_notifyCategoriesChanged (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_StringSeq *categories, + CORBA_Environment *ev); + +static BonoboXObjectClass *parent_class; -/** - * cal_listener_get_type: - * @void: - * - * Registers the #CalListener class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the #CalListener class. - **/ -GtkType -cal_listener_get_type (void) -{ - static GtkType cal_listener_type = 0; - - if (!cal_listener_type) { - static const GtkTypeInfo cal_listener_info = { - "CalListener", - sizeof (CalListener), - sizeof (CalListenerClass), - (GtkClassInitFunc) cal_listener_class_init, - (GtkObjectInitFunc) cal_listener_init, - NULL, /* reserved_1 */ - NULL, /* reserved_2 */ - (GtkClassInitFunc) NULL - }; - - cal_listener_type = gtk_type_unique (bonobo_object_get_type (), &cal_listener_info); - } - - return cal_listener_type; -} - -/* CORBA class initialization function for the calendar listener */ -static void -init_cal_listener_corba_class (void) -{ - cal_listener_vepv.Bonobo_Unknown_epv = bonobo_object_get_epv (); - cal_listener_vepv.GNOME_Evolution_Calendar_Listener_epv = cal_listener_get_epv (); -} +BONOBO_X_TYPE_FUNC_FULL (CalListener, + GNOME_Evolution_Calendar_Listener, + BONOBO_X_OBJECT_TYPE, + cal_listener); /* Class initialization function for the calendar listener */ static void @@ -97,11 +74,14 @@ cal_listener_class_init (CalListenerClass *class) object_class = (GtkObjectClass *) class; - parent_class = gtk_type_class (bonobo_object_get_type ()); + parent_class = gtk_type_class (BONOBO_X_OBJECT_TYPE); - object_class->destroy = cal_listener_destroy; + class->epv.notifyCalOpened = impl_notifyCalOpened; + class->epv.notifyObjUpdated = impl_notifyObjUpdated; + class->epv.notifyObjRemoved = impl_notifyObjRemoved; + class->epv.notifyCategoriesChanged = impl_notifyCategoriesChanged; - init_cal_listener_corba_class (); + object_class->destroy = cal_listener_destroy; } /* Object initialization function for the calendar listener */ @@ -117,6 +97,7 @@ cal_listener_init (CalListener *listener) priv->cal_opened_fn = NULL; priv->obj_updated_fn = NULL; priv->obj_removed_fn = NULL; + priv->categories_changed_fn = NULL; } /* Destroy handler for the calendar listener */ @@ -163,12 +144,12 @@ cal_listener_destroy (GtkObject *object) /* CORBA servant implementation */ -/* Listener::notifyCalOpened method */ +/* ::notifyCalOpened method */ static void -Listener_notifyCalOpened (PortableServer_Servant servant, - GNOME_Evolution_Calendar_Listener_OpenStatus status, - GNOME_Evolution_Calendar_Cal cal, - CORBA_Environment *ev) +impl_notifyCalOpened (PortableServer_Servant servant, + GNOME_Evolution_Calendar_Listener_OpenStatus status, + GNOME_Evolution_Calendar_Cal cal, + CORBA_Environment *ev) { CalListener *listener; CalListenerPrivate *priv; @@ -199,11 +180,11 @@ Listener_notifyCalOpened (PortableServer_Servant servant, (* priv->cal_opened_fn) (listener, status, cal, priv->fn_data); } -/* Listener::notifyObjUpdated method */ +/* ::notifyObjUpdated method */ static void -Listener_notifyObjUpdated (PortableServer_Servant servant, - GNOME_Evolution_Calendar_CalObjUID uid, - CORBA_Environment *ev) +impl_notifyObjUpdated (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CalObjUID uid, + CORBA_Environment *ev) { CalListener *listener; CalListenerPrivate *priv; @@ -215,11 +196,11 @@ Listener_notifyObjUpdated (PortableServer_Servant servant, (* priv->obj_updated_fn) (listener, uid, priv->fn_data); } -/* Listener::notifyObjRemoved method */ +/* ::notifyObjRemoved method */ static void -Listener_notifyObjRemoved (PortableServer_Servant servant, - GNOME_Evolution_Calendar_CalObjUID uid, - CORBA_Environment *ev) +impl_notifyObjRemoved (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CalObjUID uid, + CORBA_Environment *ev) { CalListener *listener; CalListenerPrivate *priv; @@ -231,24 +212,20 @@ Listener_notifyObjRemoved (PortableServer_Servant servant, (* priv->obj_removed_fn) (listener, uid, priv->fn_data); } -/** - * cal_listener_get_epv: - * @void: - * - * Creates an EPV for the Listener CORBA class. - * - * Return value: A newly-allocated EPV. - **/ -POA_GNOME_Evolution_Calendar_Listener__epv * -cal_listener_get_epv (void) +/* ::notifyCategoriesChanged method */ +static void +impl_notifyCategoriesChanged (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_StringSeq *categories, + CORBA_Environment *ev) { - POA_GNOME_Evolution_Calendar_Listener__epv *epv; + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; - epv = g_new0 (POA_GNOME_Evolution_Calendar_Listener__epv, 1); - epv->notifyCalOpened = Listener_notifyCalOpened; - epv->notifyObjUpdated = Listener_notifyObjUpdated; - epv->notifyObjRemoved = Listener_notifyObjRemoved; - return epv; + g_assert (priv->categories_changed_fn != NULL); + (* priv->categories_changed_fn) (listener, categories, priv->fn_data); } @@ -256,27 +233,28 @@ cal_listener_get_epv (void) /** * cal_listener_construct: * @listener: A calendar listener. - * @corba_listener: CORBA object for the calendar listener. * @cal_opened_fn: Function that will be called to notify that a calendar was * opened. * @obj_updated_fn: Function that will be called to notify that an object in the * calendar was updated. * @obj_removed_fn: Function that will be called to notify that an object in the * calendar was removed. + * @categories_changed_fn: Function that will be called to notify that the list + * of categories that are present in the calendar's objects has changed. * @fn_data: Closure data pointer that will be passed to the notification * functions. * - * Constructs a calendar listener by binding the corresponding CORBA object to - * it. + * Constructs a calendar listener by setting the callbacks that it will use for + * notification from the calendar server. * * Return value: the same object as the @listener argument. **/ CalListener * cal_listener_construct (CalListener *listener, - GNOME_Evolution_Calendar_Listener corba_listener, CalListenerCalOpenedFn cal_opened_fn, CalListenerObjUpdatedFn obj_updated_fn, CalListenerObjRemovedFn obj_removed_fn, + CalListenerCategoriesChangedFn categories_changed_fn, gpointer fn_data) { CalListenerPrivate *priv; @@ -286,52 +264,19 @@ cal_listener_construct (CalListener *listener, g_return_val_if_fail (cal_opened_fn != NULL, NULL); g_return_val_if_fail (obj_updated_fn != NULL, NULL); g_return_val_if_fail (obj_removed_fn != NULL, NULL); + g_return_val_if_fail (categories_changed_fn != NULL, NULL); priv = listener->priv; priv->cal_opened_fn = cal_opened_fn; priv->obj_updated_fn = obj_updated_fn; priv->obj_removed_fn = obj_removed_fn; + priv->categories_changed_fn = categories_changed_fn; priv->fn_data = fn_data; - bonobo_object_construct (BONOBO_OBJECT (listener), corba_listener); return listener; } -/** - * cal_listener_corba_object_create: - * @object: #BonoboObject that will wrap the CORBA object. - * - * Creates and activates the CORBA object that is wrapped by the specified - * calendar listener @object. - * - * Return value: An activated object reference or #CORBA_OBJECT_NIL in case of - * failure. - **/ -GNOME_Evolution_Calendar_Listener -cal_listener_corba_object_create (BonoboObject *object) -{ - POA_GNOME_Evolution_Calendar_Listener *servant; - CORBA_Environment ev; - - g_return_val_if_fail (object != NULL, CORBA_OBJECT_NIL); - g_return_val_if_fail (IS_CAL_LISTENER (object), CORBA_OBJECT_NIL); - - servant = (POA_GNOME_Evolution_Calendar_Listener *) g_new0 (BonoboObjectServant, 1); - servant->vepv = &cal_listener_vepv; - - CORBA_exception_init (&ev); - POA_GNOME_Evolution_Calendar_Listener__init ((PortableServer_Servant) servant, &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - g_free (servant); - CORBA_exception_free (&ev); - return CORBA_OBJECT_NIL; - } - - CORBA_exception_free (&ev); - return (GNOME_Evolution_Calendar_Listener) bonobo_object_activate_servant (object, servant); -} - /** * cal_listener_new: * @cal_opened_fn: Function that will be called to notify that a calendar was @@ -340,48 +285,34 @@ cal_listener_corba_object_create (BonoboObject *object) * calendar was updated. * @obj_removed_fn: Function that will be called to notify that an object in the * calendar was removed. + * @categories_changed_fn: Function that will be called to notify that the list + * of categories that are present in the calendar's objects has changed. * @fn_data: Closure data pointer that will be passed to the notification * functions. * * Creates a new #CalListener object. * - * Return value: A newly-created #CalListener, or NULL if its corresponding - * CORBA object could not be created. + * Return value: A newly-created #CalListener object. **/ CalListener * cal_listener_new (CalListenerCalOpenedFn cal_opened_fn, CalListenerObjUpdatedFn obj_updated_fn, CalListenerObjRemovedFn obj_removed_fn, + CalListenerCategoriesChangedFn categories_changed_fn, gpointer fn_data) { CalListener *listener; - CORBA_Environment ev; - GNOME_Evolution_Calendar_Listener corba_listener; - gboolean result; g_return_val_if_fail (cal_opened_fn != NULL, NULL); g_return_val_if_fail (obj_updated_fn != NULL, NULL); g_return_val_if_fail (obj_removed_fn != NULL, NULL); + g_return_val_if_fail (categories_changed_fn != NULL, NULL); listener = gtk_type_new (CAL_LISTENER_TYPE); - - corba_listener = cal_listener_corba_object_create (BONOBO_OBJECT (listener)); - - CORBA_exception_init (&ev); - result = CORBA_Object_is_nil (corba_listener, &ev); - - if (ev._major != CORBA_NO_EXCEPTION || result) { - g_message ("cal_listener_new(): could not create the CORBA listener"); - bonobo_object_unref (BONOBO_OBJECT (listener)); - CORBA_exception_free (&ev); - return NULL; - } - CORBA_exception_free (&ev); - return cal_listener_construct (listener, - corba_listener, cal_opened_fn, obj_updated_fn, obj_removed_fn, + categories_changed_fn, fn_data); } diff --git a/calendar/cal-client/cal-listener.h b/calendar/cal-client/cal-listener.h index fa9209cc79..4cbbd8b8c9 100644 --- a/calendar/cal-client/cal-listener.h +++ b/calendar/cal-client/cal-listener.h @@ -1,7 +1,6 @@ /* Evolution calendar listener * - * Copyright (C) 2000 Ximian, Inc. - * Copyright (C) 2000 Ximian, Inc. + * Copyright (C) 2001 Ximian, Inc. * * Author: Federico Mena-Quintero * @@ -24,7 +23,7 @@ #define CAL_LISTENER_H #include -#include +#include #include "evolution-calendar.h" BEGIN_GNOME_DECLS @@ -38,21 +37,20 @@ BEGIN_GNOME_DECLS #define IS_CAL_LISTENER(obj) (GTK_CHECK_TYPE ((obj), CAL_LISTENER_TYPE)) #define IS_CAL_LISTENER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), CAL_LISTENER_TYPE)) -typedef struct _CalListener CalListener; -typedef struct _CalListenerClass CalListenerClass; +typedef struct CalListenerPrivate CalListenerPrivate; -typedef struct _CalListenerPrivate CalListenerPrivate; - -struct _CalListener { - BonoboObject object; +typedef struct { + BonoboXObject xobject; /* Private data */ CalListenerPrivate *priv; -}; +} CalListener; + +typedef struct { + BonoboXObjectClass parent_class; -struct _CalListenerClass { - BonoboObjectClass parent_class; -}; + POA_GNOME_Evolution_Calendar_Listener__epv epv; +} CalListenerClass; /* Notification functions */ typedef void (* CalListenerCalOpenedFn) (CalListener *listener, @@ -67,25 +65,26 @@ typedef void (* CalListenerObjRemovedFn) (CalListener *listener, const GNOME_Evolution_Calendar_CalObjUID uid, gpointer data); +typedef void (* CalListenerCategoriesChangedFn) (CalListener *listener, + const GNOME_Evolution_Calendar_StringSeq *categories, + gpointer data); + GtkType cal_listener_get_type (void); CalListener *cal_listener_construct (CalListener *listener, - GNOME_Evolution_Calendar_Listener corba_listener, CalListenerCalOpenedFn cal_opened_fn, CalListenerObjUpdatedFn obj_updated_fn, CalListenerObjRemovedFn obj_removed_fn, + CalListenerCategoriesChangedFn categories_changed_fn, gpointer fn_data); -GNOME_Evolution_Calendar_Listener cal_listener_corba_object_create (BonoboObject *object); - CalListener *cal_listener_new (CalListenerCalOpenedFn cal_opened_fn, CalListenerObjUpdatedFn obj_updated_fn, CalListenerObjRemovedFn obj_removed_fn, + CalListenerCategoriesChangedFn categories_changed_fn, gpointer fn_data); -POA_GNOME_Evolution_Calendar_Listener__epv *cal_listener_get_epv (void); - END_GNOME_DECLS diff --git a/calendar/idl/evolution-calendar.idl b/calendar/idl/evolution-calendar.idl index ef3f59e629..7f4a850ecb 100644 --- a/calendar/idl/evolution-calendar.idl +++ b/calendar/idl/evolution-calendar.idl @@ -25,6 +25,9 @@ module Calendar { /* A unique identifier for a calendar component */ typedef string CalObjUID; + /* Simple sequence of strings */ + typedef sequence StringSeq; + /* Sequence of unique identifiers */ typedef sequence CalObjUIDSeq; @@ -212,6 +215,9 @@ module Calendar { /* Called from a Calendar when a component is removed */ void notifyObjRemoved (in CalObjUID uid); + + /* Called from a Calendar when the list of categories changes */ + void notifyCategoriesChanged (in StringSeq categories); }; /* Handle to a live query on a calendar */ diff --git a/calendar/pcs/cal-backend-file.c b/calendar/pcs/cal-backend-file.c index 219683e4f9..0c87760204 100644 --- a/calendar/pcs/cal-backend-file.c +++ b/calendar/pcs/cal-backend-file.c @@ -29,6 +29,15 @@ +/* A category that exists in some of the objects of the calendar */ +typedef struct { + /* Category name, also used as the key in the categories hash table */ + char *name; + + /* Number of objects that have this category */ + int refcount; +} Category; + /* Private part of the CalBackendFile structure */ struct _CalBackendFilePrivate { /* URI where the calendar data is stored */ @@ -56,6 +65,9 @@ struct _CalBackendFilePrivate { GList *todos; GList *journals; + /* Hash table of live categories */ + GHashTable *categories; + /* Idle handler for saving the calendar when it is dirty */ guint idle_id; }; @@ -181,6 +193,8 @@ cal_backend_file_init (CalBackendFile *cbfile) priv->events = NULL; priv->todos = NULL; priv->journals = NULL; + + priv->categories = g_hash_table_new (g_str_hash, g_str_equal); } /* g_hash_table_foreach() callback to destroy a CalComponent */ @@ -247,6 +261,17 @@ save (CalBackendFile *cbfile) return; } +/* Used from g_hash_table_foreach(), frees a Category structure */ +static void +free_category_cb (gpointer key, gpointer value, gpointer data) +{ + Category *c; + + c = value; + g_free (c->name); + g_free (c); +} + /* Destroy handler for the file backend */ static void cal_backend_file_destroy (GtkObject *object) @@ -287,11 +312,14 @@ cal_backend_file_destroy (GtkObject *object) g_list_free (priv->events); g_list_free (priv->todos); g_list_free (priv->journals); - priv->events = NULL; priv->todos = NULL; priv->journals = NULL; + g_hash_table_foreach (priv->categories, free_category_cb, NULL); + g_hash_table_destroy (priv->categories); + priv->categories = NULL; + if (priv->icalcomp) { icalcomponent_free (priv->icalcomp); priv->icalcomp = NULL; @@ -465,6 +493,56 @@ check_dup_uid (CalBackendFile *cbfile, CalComponent *comp) mark_dirty (cbfile); } +/* Updates the hash table of categories by adding or removing those in the + * component. + */ +static void +update_categories_from_comp (CalBackendFile *cbfile, CalComponent *comp, gboolean add) +{ + CalBackendFilePrivate *priv; + GSList *categories, *l; + + priv = cbfile->priv; + + cal_component_get_categories_list (comp, &categories); + + for (l = categories; l; l = l->next) { + const char *name; + Category *c; + + name = l->data; + c = g_hash_table_lookup (priv->categories, name); + + if (add) { + /* Add the category to the set */ + if (c) + c->refcount++; + else { + c = g_new (Category, 1); + c->name = g_strdup (name); + c->refcount = 1; + + g_hash_table_insert (priv->categories, c->name, c); + } + } else { + /* Remove the category from the set --- it *must* have existed */ + + g_assert (c != NULL); + g_assert (c->refcount > 0); + + c->refcount--; + + if (c->refcount == 0) { + g_hash_table_remove (priv->categories, c->name); + g_free (c->name); + g_free (c); + } + } + } + + cal_component_free_categories_list (categories); +} + /* Tries to add an icalcomponent to the file backend. We only store the objects * of the types we support; all others just remain in the toplevel component so * that we don't lose them. @@ -515,6 +593,10 @@ add_component (CalBackendFile *cbfile, CalComponent *comp, gboolean add_to_tople icalcomponent_add_component (priv->icalcomp, icalcomp); } + + /* Update the set of categories */ + + update_categories_from_comp (cbfile, comp, TRUE); } /* Removes a component from the backend's hash and lists. Does not perform @@ -568,6 +650,10 @@ remove_component (CalBackendFile *cbfile, CalComponent *comp) *list = g_list_remove_link (*list, l); g_list_free_1 (l); + /* Update the set of categories */ + + update_categories_from_comp (cbfile, comp, FALSE); + gtk_object_unref (GTK_OBJECT (comp)); } @@ -607,6 +693,53 @@ scan_vcalendar (CalBackendFile *cbfile) } } +/* Used from g_hash_table_foreach(), adds a category name to the sequence */ +static void +add_category_cb (gpointer key, gpointer value, gpointer data) +{ + Category *c; + GNOME_Evolution_Calendar_StringSeq *seq; + + c = value; + seq = data; + + seq->_buffer[seq->_length] = CORBA_string_dup (c->name); + seq->_length++; +} + +/* Notifies the clients with the current list of categories */ +static void +notify_categories_changed (CalBackendFile *cbfile) +{ + CalBackendFilePrivate *priv; + GNOME_Evolution_Calendar_StringSeq *seq; + GList *l; + + priv = cbfile->priv; + + /* Build the sequence of category names */ + + seq = GNOME_Evolution_Calendar_StringSeq__alloc (); + seq->_length = 0; + seq->_maximum = g_hash_table_size (priv->categories); + seq->_buffer = CORBA_sequence_CORBA_string_allocbuf (seq->_maximum); + CORBA_sequence_set_release (seq, TRUE); + + g_hash_table_foreach (priv->categories, add_category_cb, seq); + g_assert (seq->_length == seq->_maximum); + + /* Notify the clients */ + + for (l = priv->clients; l; l = l->next) { + Cal *cal; + + cal = CAL (l->data); + cal_notify_categories_changed (cal, seq); + } + + CORBA_free (seq); +} + /* Callback used from icalparser_parse() */ static char * get_line_fn (char *s, size_t size, void *data) @@ -671,6 +804,8 @@ open_cal (CalBackendFile *cbfile, GnomeVFSURI *uri, FILE *file) gnome_vfs_uri_ref (uri); priv->uri = uri; + notify_categories_changed (cbfile); + return CAL_BACKEND_OPEN_SUCCESS; } @@ -692,6 +827,8 @@ create_cal (CalBackendFile *cbfile, GnomeVFSURI *uri) mark_dirty (cbfile); + notify_categories_changed (cbfile); + return CAL_BACKEND_OPEN_SUCCESS; } @@ -1786,6 +1923,7 @@ cal_backend_file_update_objects (CalBackend *backend, const char *calobj) /* FIXME: do the notification asynchronously */ notify_update (cbfile, comp_uid); + notify_categories_changed (cbfile); return TRUE; } @@ -1797,6 +1935,7 @@ cal_backend_file_remove_object (CalBackend *backend, const char *uid) CalBackendFile *cbfile; CalBackendFilePrivate *priv; CalComponent *comp; + int old_n_categories, new_n_categories; cbfile = CAL_BACKEND_FILE (backend); priv = cbfile->priv; @@ -1809,12 +1948,18 @@ cal_backend_file_remove_object (CalBackend *backend, const char *uid) if (!comp) return FALSE; + old_n_categories = g_hash_table_size (priv->categories); remove_component (cbfile, comp); + new_n_categories = g_hash_table_size (priv->categories); + mark_dirty (cbfile); /* FIXME: do the notification asynchronously */ notify_remove (cbfile, uid); + if (old_n_categories != new_n_categories) + notify_categories_changed (cbfile); + return TRUE; } diff --git a/calendar/pcs/cal.c b/calendar/pcs/cal.c index f89d5c820f..cb92f391b5 100644 --- a/calendar/pcs/cal.c +++ b/calendar/pcs/cal.c @@ -673,6 +673,37 @@ cal_notify_remove (Cal *cal, const char *uid) CORBA_exception_free (&ev); } +/** + * cal_notify_categories_changed: + * @cal: A calendar client interface. + * @categories: List of categories. + * + * Notifies a listener attached to a calendar client interface object about the + * current set of categories in a calendar backend. + **/ +void +cal_notify_categories_changed (Cal *cal, GNOME_Evolution_Calendar_StringSeq *categories) +{ + CalPrivate *priv; + CORBA_Environment ev; + + g_return_if_fail (cal != NULL); + g_return_if_fail (IS_CAL (cal)); + g_return_if_fail (categories != NULL); + + priv = cal->priv; + g_return_if_fail (priv->listener != CORBA_OBJECT_NIL); + + CORBA_exception_init (&ev); + GNOME_Evolution_Calendar_Listener_notifyCategoriesChanged (priv->listener, categories, &ev); + + if (ev._major != CORBA_NO_EXCEPTION) + g_message ("cal_notify_categories_changed(): Could not notify the listener " + "about the current set of categories"); + + CORBA_exception_free (&ev); +} + /** * cal_get_password: * @cal: A calendar client interface. diff --git a/calendar/pcs/cal.h b/calendar/pcs/cal.h index 35e870739c..6797b5df25 100644 --- a/calendar/pcs/cal.h +++ b/calendar/pcs/cal.h @@ -65,6 +65,8 @@ Cal *cal_new (CalBackend *backend, GNOME_Evolution_Calendar_Listener listener); void cal_notify_update (Cal *cal, const char *uid); void cal_notify_remove (Cal *cal, const char *uid); +void cal_notify_categories_changed (Cal *cal, GNOME_Evolution_Calendar_StringSeq *categories); + char *cal_get_password (Cal *cal, const char *prompt, const char *key); void cal_forget_password (Cal *cal, const char *key); -- cgit v1.2.3