aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--calendar/ChangeLog30
-rw-r--r--calendar/cal-client/cal-client.c38
-rw-r--r--calendar/cal-client/cal-client.h2
-rw-r--r--calendar/cal-client/cal-listener.c203
-rw-r--r--calendar/cal-client/cal-listener.h35
-rw-r--r--calendar/idl/evolution-calendar.idl6
-rw-r--r--calendar/pcs/cal-backend-file.c147
-rw-r--r--calendar/pcs/cal.c31
-rw-r--r--calendar/pcs/cal.h2
9 files changed, 339 insertions, 155 deletions
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 <federico@ximian.com>
+
+ 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 <rodrigo@ximian.com>
* 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 <federico@ximian.com>
*
@@ -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,53 +264,20 @@ 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
* opened.
@@ -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 <federico@ximian.com>
*
@@ -24,7 +23,7 @@
#define CAL_LISTENER_H
#include <libgnome/gnome-defs.h>
-#include <bonobo/bonobo-object.h>
+#include <bonobo/bonobo-xobject.h>
#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<string> StringSeq;
+
/* Sequence of unique identifiers */
typedef sequence<CalObjUID> 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
@@ -674,6 +674,37 @@ cal_notify_remove (Cal *cal, const char *uid)
}
/**
+ * 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.
* @prompt: The message to show to the user when asking for the password.
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);