aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/pcs/query-backend.c
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/pcs/query-backend.c')
-rw-r--r--calendar/pcs/query-backend.c269
1 files changed, 269 insertions, 0 deletions
diff --git a/calendar/pcs/query-backend.c b/calendar/pcs/query-backend.c
new file mode 100644
index 0000000000..d3ec5a761d
--- /dev/null
+++ b/calendar/pcs/query-backend.c
@@ -0,0 +1,269 @@
+/* Evolution calendar - Backend cache for calendar queries.
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Author: Rodrigo Moya <rodrigo@ximian.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <libgnome/gnome-defs.h>
+#include <libgnome/gnome-i18n.h>
+#include <gtk/gtksignal.h>
+#include <cal-util/cal-component.h>
+#include "query.h"
+#include "query-backend.h"
+
+static void query_backend_class_init (QueryBackendClass *klass);
+static void query_backend_init (QueryBackend *qb);
+static void query_backend_destroy (GtkObject *object);
+
+typedef struct {
+ CalComponent *comp;
+} QueryBackendComponent;
+
+/* Private part of the QueryBackend structure */
+struct _QueryBackendPrivate {
+ char *uri;
+ CalBackend *backend;
+ GHashTable *components;
+ GList *queries;
+};
+
+static GHashTable *loaded_backends = NULL;
+static GtkObjectClass *parent_class = NULL;
+
+/* Class initialization function for the backend cache */
+static void
+query_backend_class_init (QueryBackendClass *klass)
+{
+ GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
+
+ parent_class = gtk_type_class (GTK_TYPE_OBJECT);
+
+ object_class->destroy = query_backend_destroy;
+}
+
+/* Object initialization function for the backend cache */
+static void
+query_backend_init (QueryBackend *qb)
+{
+ QueryBackendPrivate *priv;
+
+ priv = g_new0 (QueryBackendPrivate, 1);
+ qb->priv = priv;
+
+ priv->uri = NULL;
+ priv->backend = NULL;
+ priv->components = g_hash_table_new (g_str_hash, g_str_equal);
+ priv->queries = NULL;
+}
+
+/* Destroy handler for the backend cache */
+static void
+query_backend_destroy (GtkObject *object)
+{
+ QueryBackend *qb = (QueryBackend *) object;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (IS_QUERY_BACKEND (qb));
+
+ /* remove the QueryBackend from the internal hash table */
+ g_hash_table_remove (loaded_backends, qb->priv->uri);
+
+ /* free memory */
+ qb->priv->backend = NULL;
+
+ g_free (qb->priv->uri);
+ qb->priv->uri = NULL;
+
+ g_hash_table_destroy (qb->priv->components);
+ qb->priv->components = NULL;
+
+ g_list_free (qb->priv->queries);
+ qb->priv->queries = NULL;
+
+ g_free (qb->priv);
+ qb->priv = NULL;
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+/**
+ * query_backend_get_type:
+ * @void:
+ *
+ * Registers the #QueryBackend class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the #QueryBackend class.
+ **/
+GtkType
+query_backend_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type) {
+ static const GtkTypeInfo info = {
+ "QueryBackend",
+ sizeof (QueryBackend),
+ sizeof (QueryBackendClass),
+ (GtkClassInitFunc) query_backend_class_init,
+ (GtkObjectInitFunc) query_backend_init,
+ NULL, /* reserved_1 */
+ NULL, /* reserved_2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (GTK_TYPE_OBJECT, &info);
+ }
+
+ return type;
+}
+
+static void
+backend_destroyed_cb (GtkObject *object, gpointer user_data)
+{
+ CalBackend *backend = (CalBackend *) object;
+ QueryBackend *qb = (QueryBackend *) user_data;
+
+ g_return_if_fail (IS_CAL_BACKEND (backend));
+ g_return_if_fail (IS_QUERY_BACKEND (qb));
+
+ gtk_object_unref (GTK_OBJECT (qb));
+}
+
+static void
+object_updated_cb (CalBackend *backend, const char *uid, gpointer user_data)
+{
+ gpointer orig_key, orig_value;
+ char *tmp_uid;
+ CalComponent *comp;
+ QueryBackend *qb = (QueryBackend *) user_data;
+
+ g_return_if_fail (IS_QUERY_BACKEND (qb));
+
+ if (g_hash_table_lookup_extended (qb->priv->components, uid, &orig_key, &orig_value)) {
+ g_hash_table_remove (qb->priv->components, uid);
+ }
+
+ comp = cal_backend_get_object_component (qb->priv->backend, uid);
+ if (IS_CAL_COMPONENT (comp)) {
+ cal_component_get_uid (comp, &tmp_uid);
+ g_hash_table_insert (qb->priv->components, tmp_uid, comp);
+ }
+}
+
+static void
+object_removed_cb (CalBackend *backend, const char *uid, gpointer user_data)
+{
+ gpointer orig_key, orig_value;
+ QueryBackend *qb = (QueryBackend *) user_data;
+
+ g_return_if_fail (IS_QUERY_BACKEND (qb));
+
+ if (g_hash_table_lookup_extended (qb->priv->components, uid, &orig_key, &orig_value)) {
+ g_hash_table_remove (qb->priv->components, uid);
+ }
+}
+
+static void
+query_destroyed_cb (GtkObject *object, gpointer user_data)
+{
+ Query *query = (Query *) object;
+ QueryBackend *qb = (QueryBackend *) user_data;
+
+ g_return_if_fail (IS_QUERY (query));
+ g_return_if_fail (IS_QUERY_BACKEND (qb));
+
+ qb->priv->queries = g_list_remove (qb->priv->queries, query);
+}
+
+static void
+foreach_uid_cb (gpointer data, gpointer user_data)
+{
+ CalComponent *comp;
+ char *uid;
+ QueryBackend *qb = (QueryBackend *) user_data;
+
+ g_return_if_fail (data != NULL);
+ g_return_if_fail (IS_QUERY_BACKEND (qb));
+
+ comp = cal_backend_get_object_component (qb->priv->backend, (const char *) data);
+ if (IS_CAL_COMPONENT (comp)) {
+ cal_component_get_uid (comp, &uid);
+ g_hash_table_insert (qb->priv->components, uid, comp);
+ }
+ else
+ g_warning (_("Could not get component with UID = %s"), (const char *) data);
+}
+
+/**
+ * query_backend_new
+ * @query: The #Query object that issues the query.
+ * @backend: A #CalBackend object.
+ *
+ * Create a new #QueryBackend instance, which is a class to
+ * have a cache of objects for the calendar queries, so that
+ * we don't have to ask the calendar backend to get the objects
+ * everytime.
+ *
+ * Returns: the newly-created object.
+ */
+QueryBackend *
+query_backend_new (Query *query, CalBackend *backend)
+{
+ QueryBackend *qb = NULL;
+
+ g_return_val_if_fail (IS_QUERY (query), NULL);
+ g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
+
+ /* see if we already have the backend loaded */
+ qb = g_hash_table_lookup (loaded_backends,
+ cal_backend_get_uri (backend));
+ if (!qb) {
+ GList *uidlist;
+
+ qb = gtk_type_new (QUERY_BACKEND_TYPE);
+
+ qb->priv->uri = g_strdup (cal_backend_get_uri (backend));
+ qb->priv->backend = backend;
+
+ /* load all UIDs */
+ uidlist = cal_backend_get_uids (backend, CALOBJ_TYPE_ANY);
+ g_list_foreach (uidlist, foreach_uid_cb, qb);
+ cal_obj_uid_list_free (uidlist);
+
+ gtk_signal_connect (GTK_OBJECT (backend), "destroy",
+ GTK_SIGNAL_FUNC (backend_destroyed_cb), qb);
+ gtk_signal_connect (GTK_OBJECT (backend), "obj_updated",
+ GTK_SIGNAL_FUNC (object_updated_cb), qb);
+ gtk_signal_connect (GTK_OBJECT (backend), "obj_removed",
+ GTK_SIGNAL_FUNC (object_removed_cb), qb);
+
+ g_hash_table_insert (loaded_backends, qb->priv->uri, qb);
+ }
+
+ qb->priv->queries = g_list_append (qb->priv->queries, query);
+ gtk_signal_connect (GTK_OBJECT (query), "destroy",
+ GTK_SIGNAL_FUNC (query_destroyed_cb), qb);
+
+ return qb;
+}