[evolution-data-server/treitter-factory-refactor] Factor out common EDataView code from EDataCalView and EDataBookView
- From: Travis Reitter <treitter src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [evolution-data-server/treitter-factory-refactor] Factor out common EDataView code from EDataCalView and EDataBookView
- Date: Tue, 26 Jan 2010 18:15:52 +0000 (UTC)
commit 3671f9599bdf63d46bcba4fc405e772338f4a171
Author: Travis Reitter <treitter gmail com>
Date: Tue Jan 26 09:35:03 2010 -0800
Factor out common EDataView code from EDataCalView and EDataBookView
addressbook/libedata-book/e-data-book-view.c | 195 +++++------------
calendar/libedata-cal/e-data-cal-view.c | 299 ++++++-------------------
libebackend/e-data-view.c | 288 ++++++++++++++++++++++++-
libebackend/e-data-view.h | 48 ++++-
4 files changed, 458 insertions(+), 372 deletions(-)
---
diff --git a/addressbook/libedata-book/e-data-book-view.c b/addressbook/libedata-book/e-data-book-view.c
index 5b715a7..46aaf0e 100644
--- a/addressbook/libedata-book/e-data-book-view.c
+++ b/addressbook/libedata-book/e-data-book-view.c
@@ -35,13 +35,9 @@ static gboolean impl_BookView_dispose (EDataBookView *view, GError **eror);
#include "e-data-book-view-glue.h"
-static void reset_array (GArray *array);
-
G_DEFINE_TYPE (EDataBookView, e_data_book_view, E_TYPE_DATA_VIEW);
#define E_DATA_BOOK_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_DATA_BOOK_VIEW, EDataBookViewPrivate))
-#define THRESHOLD 32
-
struct _EDataBookViewPrivate {
gchar* query;
gint max_results;
@@ -50,11 +46,6 @@ struct _EDataBookViewPrivate {
GMutex *pending_mutex;
- GArray *adds;
- GArray *changes;
- GArray *removes;
-
- GHashTable *ids;
guint idle_id;
};
@@ -70,6 +61,7 @@ enum {
CONTACTS_REMOVED,
STATUS_MESSAGE,
COMPLETE,
+ DONE,
LAST_SIGNAL
};
@@ -91,104 +83,24 @@ e_data_book_view_stop_if_running (EDataBookView *view)
}
static void
-send_pending_adds (EDataBookView *view)
-{
- EDataBookViewPrivate *priv = view->priv;
-
- if (priv->adds->len == 0)
- return;
-
- g_signal_emit (view, signals[CONTACTS_ADDED], 0, priv->adds->data);
- reset_array (priv->adds);
-}
-
-static void
-send_pending_changes (EDataBookView *view)
-{
- EDataBookViewPrivate *priv = view->priv;
-
- if (priv->changes->len == 0)
- return;
-
- g_signal_emit (view, signals[CONTACTS_CHANGED], 0, priv->changes->data);
- reset_array (priv->changes);
-}
-
-static void
-send_pending_removes (EDataBookView *view)
-{
- EDataBookViewPrivate *priv = view->priv;
-
- if (priv->removes->len == 0)
- return;
-
- g_signal_emit (view, signals[CONTACTS_REMOVED], 0, priv->removes->data);
- reset_array (priv->removes);
-}
-
-/*
- * Queue @vcard to be sent as a change notification. This takes ownership of
- * @vcard.
- */
-static void
-notify_change (EDataBookView *view, gchar *vcard)
-{
- EDataBookViewPrivate *priv = view->priv;
- send_pending_adds (view);
- send_pending_removes (view);
-
- g_array_append_val (priv->changes, vcard);
-}
-
-/*
- * Queue @id to be sent as a change notification. This takes ownership of @id.
- */
-static void
-notify_remove (EDataBookView *view, gchar *id)
+contacts_added (EDataView *view,
+ const gchar **objects)
{
- EDataBookViewPrivate *priv = view->priv;
-
- send_pending_adds (view);
- send_pending_changes (view);
-
- g_array_append_val (priv->removes, id);
- g_hash_table_remove (priv->ids, id);
+ g_signal_emit (view, signals[CONTACTS_ADDED], 0, objects);
}
-/*
- * Queue @id and @vcard to be sent as a change notification. This takes ownership of
- * @vcard but not @id.
- */
static void
-notify_add (EDataBookView *view, const gchar *id, gchar *vcard)
+contacts_changed (EDataView *view,
+ const gchar **objects)
{
- EDataBookViewPrivate *priv = view->priv;
- send_pending_changes (view);
- send_pending_removes (view);
-
- if (priv->adds->len == THRESHOLD) {
- send_pending_adds (view);
- }
- g_array_append_val (priv->adds, vcard);
- g_hash_table_insert (priv->ids, g_strdup (id),
- GUINT_TO_POINTER (1));
+ g_signal_emit (view, signals[CONTACTS_CHANGED], 0, objects);
}
static void
-reset_array (GArray *array)
+contacts_removed (EDataView *view,
+ const gchar **ids)
{
- gint i = 0;
- gchar *tmp = NULL;
-
- /* Free stored strings */
- for (i = 0; i < array->len; i++)
- {
- tmp = g_array_index (array, gchar *, i);
- g_free (tmp);
- }
-
- /* Force the array size to 0 */
- g_array_set_size (array, 0);
+ g_signal_emit (view, signals[CONTACTS_REMOVED], 0, ids);
}
/**
@@ -219,8 +131,7 @@ e_data_book_view_notify_update (EDataBookView *book_view,
id = e_contact_get_const (contact, E_CONTACT_UID);
- currently_in_view =
- g_hash_table_lookup (priv->ids, id) != NULL;
+ currently_in_view = e_data_view_contains_object (E_DATA_VIEW (book_view), (gpointer) id);
sexp = E_BOOK_BACKEND_SEXP (e_data_view_get_sexp (E_DATA_VIEW (book_view)));
want_in_view =
@@ -230,13 +141,15 @@ e_data_book_view_notify_update (EDataBookView *book_view,
vcard = e_vcard_to_string (E_VCARD (contact),
EVC_FORMAT_VCARD_30);
- if (currently_in_view)
- notify_change (book_view, vcard);
- else
- notify_add (book_view, id, vcard);
+ if (currently_in_view) {
+ e_data_view_notify_object_modification (E_DATA_VIEW (book_view), vcard);
+ } else {
+ e_data_view_notify_object_add (E_DATA_VIEW (book_view), (gpointer) g_strdup (id), vcard);
+ }
} else {
- if (currently_in_view)
- notify_remove (book_view, g_strdup (id));
+ if (currently_in_view) {
+ e_data_view_notify_object_remove (E_DATA_VIEW (book_view), (gpointer) id);
+ }
/* else nothing; we're removing a card that wasn't there */
}
@@ -272,24 +185,27 @@ e_data_book_view_notify_update_vcard (EDataBookView *book_view, gchar *vcard)
contact = e_contact_new_from_vcard (vcard);
id = e_contact_get_const (contact, E_CONTACT_UID);
- currently_in_view =
- g_hash_table_lookup (priv->ids, id) != NULL;
+ currently_in_view = e_data_view_contains_object (E_DATA_VIEW (book_view), (gpointer) id);
sexp = E_BOOK_BACKEND_SEXP (e_data_view_get_sexp (E_DATA_VIEW (book_view)));
want_in_view =
e_book_backend_sexp_match_contact (sexp, contact);
if (want_in_view) {
- if (currently_in_view)
- notify_change (book_view, vcard);
- else
- notify_add (book_view, id, vcard);
+ if (currently_in_view) {
+ e_data_view_notify_object_modification (E_DATA_VIEW (book_view), vcard);
+ } else {
+ e_data_view_notify_object_add (E_DATA_VIEW (book_view), (gpointer) g_strdup (id), vcard);
+ }
} else {
- if (currently_in_view)
- notify_remove (book_view, g_strdup (id));
- else
+ if (currently_in_view) {
+ e_data_view_notify_object_remove (E_DATA_VIEW (book_view), (gpointer) id);
+ } else {
/* else nothing; we're removing a card that wasn't there */
+ /* FIXME: this seems to not have been intended to be
+ * included in this else block, but it was */
g_free (vcard);
+ }
}
/* Do this last so that id is still valid when notify_ is called */
g_object_unref (contact);
@@ -328,13 +244,13 @@ e_data_book_view_notify_update_prefiltered_vcard (EDataBookView *book_view, cons
g_mutex_lock (priv->pending_mutex);
- currently_in_view =
- g_hash_table_lookup (priv->ids, id) != NULL;
+ currently_in_view = e_data_view_contains_object (E_DATA_VIEW (book_view), (gpointer) id);
- if (currently_in_view)
- notify_change (book_view, vcard);
- else
- notify_add (book_view, id, vcard);
+ if (currently_in_view) {
+ e_data_view_notify_object_modification (E_DATA_VIEW (book_view), vcard);
+ } else {
+ e_data_view_notify_object_add (E_DATA_VIEW (book_view), (gpointer) g_strdup (id), vcard);
+ }
g_mutex_unlock (priv->pending_mutex);
}
@@ -357,8 +273,9 @@ e_data_book_view_notify_remove (EDataBookView *book_view, const gchar *id)
g_mutex_lock (priv->pending_mutex);
- if (g_hash_table_lookup (priv->ids, id))
- notify_remove (book_view, g_strdup (id));
+ if (e_data_view_contains_object (E_DATA_VIEW (book_view), (gpointer) id)) {
+ e_data_view_notify_object_remove (E_DATA_VIEW (book_view), (gpointer) id);
+ }
g_mutex_unlock (priv->pending_mutex);
}
@@ -382,15 +299,17 @@ e_data_book_view_notify_complete (EDataBookView *book_view, EDataBookStatus stat
g_mutex_lock (priv->pending_mutex);
- send_pending_adds (book_view);
- send_pending_changes (book_view);
- send_pending_removes (book_view);
+ e_data_view_send_pending_adds (E_DATA_VIEW (book_view));
+ e_data_view_send_pending_modifications (E_DATA_VIEW (book_view));
+ e_data_view_send_pending_removes (E_DATA_VIEW (book_view));
g_mutex_unlock (priv->pending_mutex);
/* We're done now, so tell the backend to stop? TODO: this is a bit different to
how the CORBA backend works... */
+ e_data_view_notify_done (E_DATA_VIEW (book_view), status);
+ /* retained for backwards compatibility */
g_signal_emit (book_view, signals[COMPLETE], 0, status);
}
@@ -457,19 +376,9 @@ e_data_book_view_finalize (GObject *object)
EDataBookView *book_view = E_DATA_BOOK_VIEW (object);
EDataBookViewPrivate *priv = book_view->priv;
- reset_array (priv->adds);
- reset_array (priv->changes);
- reset_array (priv->removes);
- g_array_free (priv->adds, TRUE);
- g_array_free (priv->changes, TRUE);
- g_array_free (priv->removes, TRUE);
-
g_free (priv->query);
-
g_mutex_free (priv->pending_mutex);
- g_hash_table_destroy (priv->ids);
-
G_OBJECT_CLASS (e_data_book_view_parent_class)->finalize (object);
}
@@ -531,6 +440,9 @@ e_data_book_view_class_init (EDataBookViewClass *klass)
object_class->set_property = e_data_book_view_set_property;
parent_class->stop_if_running = (void (*)(EDataView*)) e_data_book_view_stop_if_running;
+ parent_class->objects_added = contacts_added;
+ parent_class->objects_modified = contacts_changed;
+ parent_class->objects_removed = contacts_removed;
signals[CONTACTS_ADDED] =
g_signal_new ("contacts-added",
@@ -564,6 +476,8 @@ e_data_book_view_class_init (EDataBookViewClass *klass)
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE, 1, G_TYPE_STRING);
+ /* this is meant to do the same thing as "done", but existed before it,
+ * so it's retained for compatibility */
signals[COMPLETE] =
g_signal_new ("complete",
G_OBJECT_CLASS_TYPE (klass),
@@ -572,6 +486,8 @@ e_data_book_view_class_init (EDataBookViewClass *klass)
g_cclosure_marshal_VOID__UINT,
G_TYPE_NONE, 1, G_TYPE_UINT);
+ signals[DONE] = g_signal_lookup ("done", E_TYPE_DATA_VIEW);
+
g_object_class_install_property
(object_class,
PROP_MAX_RESULTS,
@@ -607,13 +523,6 @@ e_data_book_view_init (EDataBookView *book_view)
priv->running = FALSE;
priv->pending_mutex = g_mutex_new ();
-
- priv->adds = g_array_sized_new (TRUE, TRUE, sizeof (gchar *), THRESHOLD);
- priv->changes = g_array_sized_new (TRUE, TRUE, sizeof (gchar *), THRESHOLD);
- priv->removes = g_array_sized_new (TRUE, TRUE, sizeof (gchar *), THRESHOLD);
-
- priv->ids = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, NULL);
}
static gboolean
diff --git a/calendar/libedata-cal/e-data-cal-view.c b/calendar/libedata-cal/e-data-cal-view.c
index 0120fc8..1f8cd96 100644
--- a/calendar/libedata-cal/e-data-cal-view.c
+++ b/calendar/libedata-cal/e-data-cal-view.c
@@ -46,29 +46,19 @@ static gboolean impl_EDataCalView_start (EDataCalView *query, GError **error);
struct _EDataCalViewPrivate {
gboolean started;
- gboolean done;
- EDataCalCallStatus done_status;
-
- GArray *adds;
- GArray *changes;
- GArray *removes;
-
- GHashTable *ids;
};
G_DEFINE_TYPE (EDataCalView, e_data_cal_view, E_TYPE_DATA_VIEW);
#define E_DATA_CAL_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), E_DATA_CAL_VIEW_TYPE, EDataCalViewPrivate))
-static void e_data_cal_view_finalize (GObject *object);
-
/* Signals */
enum {
- OBJECTS_ADDED,
- OBJECTS_MODIFIED,
- OBJECTS_REMOVED,
- PROGRESS,
- DONE,
- LAST_SIGNAL
+ OBJECTS_ADDED,
+ OBJECTS_MODIFIED,
+ OBJECTS_REMOVED,
+ PROGRESS,
+ DONE,
+ LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
@@ -79,6 +69,43 @@ e_data_cal_view_stop_if_running (EDataCalView *query)
/* Nothing for us to do here */
}
+static void
+e_data_cal_view_finalize (GObject *object)
+{
+ EDataCalView *query;
+ EDataCalViewPrivate *priv;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (IS_QUERY (object));
+
+ query = QUERY (object);
+ priv = query->priv;
+
+ (* G_OBJECT_CLASS (e_data_cal_view_parent_class)->finalize) (object);
+}
+
+static guint
+id_hash (gconstpointer key)
+{
+ const ECalComponentId *id = key;
+ return g_str_hash (id->uid) ^ (id->rid ? g_str_hash (id->rid) : 0);
+}
+
+static gboolean
+id_equal (gconstpointer a, gconstpointer b)
+{
+ const ECalComponentId *id_a = a, *id_b = b;
+
+ return (g_strcmp0 (id_a->uid, id_b->uid) == 0) &&
+ (g_strcmp0 (id_a->rid, id_b->rid) == 0);
+}
+
+static const gchar*
+id_get_str_id (ECalComponentId *id)
+{
+ return id->uid;
+}
+
/* Class init */
static void
e_data_cal_view_class_init (EDataCalViewClass *klass)
@@ -91,30 +118,15 @@ e_data_cal_view_class_init (EDataCalViewClass *klass)
object_class->finalize = e_data_cal_view_finalize;
parent_class->stop_if_running = (void (*)(EDataView*)) e_data_cal_view_stop_if_running;
+ parent_class->id_hash = (GHashFunc) id_hash;
+ parent_class->id_equal = (GEqualFunc) id_equal;
+ parent_class->id_destroy = (GDestroyNotify) e_cal_component_free_id;
+ parent_class->id_get_str_id = (const gchar* (*)(gconstpointer)) id_get_str_id;
- signals[OBJECTS_ADDED] =
- g_signal_new ("objects-added",
- G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL,
- g_cclosure_marshal_VOID__BOXED,
- G_TYPE_NONE, 1, G_TYPE_STRV);
-
- signals[OBJECTS_MODIFIED] =
- g_signal_new ("objects-modified",
- G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL,
- g_cclosure_marshal_VOID__BOXED,
- G_TYPE_NONE, 1, G_TYPE_STRV);
-
- signals[OBJECTS_REMOVED] =
- g_signal_new ("objects-removed",
- G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL,
- g_cclosure_marshal_VOID__BOXED,
- G_TYPE_NONE, 1, G_TYPE_STRV);
+ signals[OBJECTS_ADDED] = g_signal_lookup ("objects-added", E_TYPE_DATA_VIEW);
+ signals[OBJECTS_MODIFIED] = g_signal_lookup ("objects-modified", E_TYPE_DATA_VIEW);
+ signals[OBJECTS_REMOVED] = g_signal_lookup ("objects-removed", E_TYPE_DATA_VIEW);
+ signals[DONE] = g_signal_lookup ("done", E_TYPE_DATA_VIEW);
signals[PROGRESS] =
g_signal_new ("progress",
@@ -124,31 +136,9 @@ e_data_cal_view_class_init (EDataCalViewClass *klass)
e_data_cal_marshal_VOID__STRING_UINT,
G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_UINT);
- signals[DONE] =
- g_signal_new ("done",
- G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL,
- g_cclosure_marshal_VOID__UINT,
- G_TYPE_NONE, 1, G_TYPE_UINT);
-
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), &dbus_glib_e_data_cal_view_object_info);
}
-static guint
-id_hash (gconstpointer key)
-{
- const ECalComponentId *id = key;
- return g_str_hash (id->uid) ^ (id->rid ? g_str_hash (id->rid) : 0);
-}
-
-static gboolean
-id_equal (gconstpointer a, gconstpointer b)
-{
- const ECalComponentId *id_a = a, *id_b = b;
- return g_strcmp0 (id_a->uid, id_b->uid) == 0 && g_strcmp0 (id_a->rid, id_b->rid) == 0;
-}
-
/* Instance init */
static void
e_data_cal_view_init (EDataCalView *view)
@@ -158,15 +148,6 @@ e_data_cal_view_init (EDataCalView *view)
view->priv = priv;
priv->started = FALSE;
- priv->done = FALSE;
- priv->done_status = Success;
- priv->started = FALSE;
-
- priv->adds = g_array_sized_new (TRUE, TRUE, sizeof (gchar *), THRESHOLD);
- priv->changes = g_array_sized_new (TRUE, TRUE, sizeof (gchar *), THRESHOLD);
- priv->removes = g_array_sized_new (TRUE, TRUE, sizeof (gchar *), THRESHOLD);
-
- priv->ids = g_hash_table_new_full (id_hash, id_equal, (GDestroyNotify)e_cal_component_free_id, NULL);
}
EDataCalView *
@@ -198,119 +179,6 @@ e_data_cal_view_get_dbus_path (EDataCalView *view)
return e_data_view_get_dbus_path (E_DATA_VIEW (view));
}
-static void
-reset_array (GArray *array)
-{
- gint i = 0;
- gchar *tmp = NULL;
-
- /* Free stored strings */
- for (i = 0; i < array->len; i++) {
- tmp = g_array_index (array, gchar *, i);
- g_free (tmp);
- }
-
- /* Force the array size to 0 */
- g_array_set_size (array, 0);
-}
-
-static void
-send_pending_adds (EDataCalView *view)
-{
- EDataCalViewPrivate *priv = view->priv;
-
- if (priv->adds->len == 0)
- return;
-
- g_signal_emit (view, signals[OBJECTS_ADDED], 0, priv->adds->data);
- reset_array (priv->adds);
-}
-
-static void
-send_pending_changes (EDataCalView *view)
-{
- EDataCalViewPrivate *priv = view->priv;
-
- if (priv->changes->len == 0)
- return;
-
- g_signal_emit (view, signals[OBJECTS_MODIFIED], 0, priv->changes->data);
- reset_array (priv->changes);
-}
-
-static void
-send_pending_removes (EDataCalView *view)
-{
- EDataCalViewPrivate *priv = view->priv;
-
- if (priv->removes->len == 0)
- return;
-
- /* TODO: send ECalComponentIds as a list of pairs */
- g_signal_emit (view, signals[OBJECTS_REMOVED], 0, priv->removes->data);
- reset_array (priv->removes);
-}
-
-static void
-notify_add (EDataCalView *view, gchar *obj)
-{
- EDataCalViewPrivate *priv = view->priv;
- ECalComponent *comp;
-
- send_pending_changes (view);
- send_pending_removes (view);
-
- if (priv->adds->len == THRESHOLD) {
- send_pending_adds (view);
- }
- g_array_append_val (priv->adds, obj);
-
- comp = e_cal_component_new_from_string (obj);
- g_hash_table_insert (priv->ids,
- e_cal_component_get_id (comp),
- GUINT_TO_POINTER (1));
- g_object_unref (comp);
-}
-
-static void
-notify_change (EDataCalView *view, gchar *obj)
-{
- EDataCalViewPrivate *priv = view->priv;
-
- send_pending_adds (view);
- send_pending_removes (view);
-
- g_array_append_val (priv->changes, obj);
-}
-
-static void
-notify_remove (EDataCalView *view, ECalComponentId *id)
-{
- EDataCalViewPrivate *priv = view->priv;
- gchar *uid;
-
- send_pending_adds (view);
- send_pending_changes (view);
-
- /* TODO: store ECalComponentId instead of just uid*/
- uid = g_strdup (id->uid);
- g_array_append_val (priv->removes, uid);
-
- g_hash_table_remove (priv->ids, id);
-}
-
-static void
-notify_done (EDataCalView *view)
-{
- EDataCalViewPrivate *priv = view->priv;
-
- send_pending_adds (view);
- send_pending_changes (view);
- send_pending_removes (view);
-
- g_signal_emit (view, signals[DONE], 0, priv->done_status);
-}
-
static gboolean
impl_EDataCalView_start (EDataCalView *query, GError **error)
{
@@ -326,23 +194,6 @@ impl_EDataCalView_start (EDataCalView *query, GError **error)
return TRUE;
}
-static void
-e_data_cal_view_finalize (GObject *object)
-{
- EDataCalView *query;
- EDataCalViewPrivate *priv;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (IS_QUERY (object));
-
- query = QUERY (object);
- priv = query->priv;
-
- g_hash_table_destroy (priv->ids);
-
- (* G_OBJECT_CLASS (e_data_cal_view_parent_class)->finalize) (object);
-}
-
/**
* e_data_cal_view_get_backend:
* @query: A query object.
@@ -467,13 +318,7 @@ e_data_cal_view_is_started (EDataCalView *view)
gboolean
e_data_cal_view_is_done (EDataCalView *query)
{
- EDataCalViewPrivate *priv;
-
- g_return_val_if_fail (IS_QUERY (query), FALSE);
-
- priv = query->priv;
-
- return priv->done;
+ return e_data_view_is_done (E_DATA_VIEW (query));
}
/**
@@ -488,14 +333,8 @@ e_data_cal_view_is_done (EDataCalView *query)
EDataCalCallStatus
e_data_cal_view_get_done_status (EDataCalView *query)
{
- EDataCalViewPrivate *priv;
-
- g_return_val_if_fail (IS_QUERY (query), FALSE);
-
- priv = query->priv;
-
- if (priv->done)
- return priv->done_status;
+ if (e_data_view_is_done (E_DATA_VIEW (query)))
+ return e_data_view_get_done_status (E_DATA_VIEW (query));
return Success;
}
@@ -520,10 +359,18 @@ e_data_cal_view_notify_objects_added (EDataCalView *view, const GList *objects)
return;
for (l = objects; l; l = l->next) {
- notify_add (view, g_strdup (l->data));
+ gchar *object;
+ ECalComponent *comp;
+
+ object = g_strdup (l->data);
+ comp = e_cal_component_new_from_string (object);
+
+ e_data_view_notify_object_add (E_DATA_VIEW (view), e_cal_component_get_id (comp), object);
+
+ g_object_unref (comp);
}
- send_pending_adds (view);
+ e_data_view_send_pending_adds (E_DATA_VIEW (view));
}
/**
@@ -565,11 +412,10 @@ e_data_cal_view_notify_objects_modified (EDataCalView *view, const GList *object
return;
for (l = objects; l; l = l->next) {
- /* TODO: send add/remove/change as relevant, based on ->ids */
- notify_change (view, g_strdup (l->data));
+ e_data_view_notify_object_modification (E_DATA_VIEW (view), g_strdup (l->data));
}
- send_pending_changes (view);
+ e_data_view_send_pending_modifications (E_DATA_VIEW (view));
}
/**
@@ -612,11 +458,13 @@ e_data_cal_view_notify_objects_removed (EDataCalView *view, const GList *ids)
for (l = ids; l; l = l->next) {
ECalComponentId *id = l->data;
- if (g_hash_table_lookup (priv->ids, id))
- notify_remove (view, id);
+
+ if (e_data_view_contains_object (E_DATA_VIEW (view), id)) {
+ e_data_view_notify_object_remove (E_DATA_VIEW (view), id);
+ }
}
- send_pending_removes (view);
+ e_data_view_send_pending_removes (E_DATA_VIEW (view));
}
/**
@@ -679,8 +527,5 @@ e_data_cal_view_notify_done (EDataCalView *view, GNOME_Evolution_Calendar_CallSt
if (!priv->started)
return;
- priv->done = TRUE;
- priv->done_status = status;
-
- notify_done (view);
+ e_data_view_notify_done (E_DATA_VIEW (view), status);
}
diff --git a/libebackend/e-data-view.c b/libebackend/e-data-view.c
index 6aa47c6..8085ef6 100644
--- a/libebackend/e-data-view.c
+++ b/libebackend/e-data-view.c
@@ -45,6 +45,15 @@ struct _EDataViewPrivate {
EBackendSExp *sexp;
gchar *dbus_path;
+
+ GArray *adds;
+ GArray *modifications;
+ GArray *removes;
+
+ GHashTable *ids;
+
+ gboolean done;
+ guint done_status;
};
enum {
@@ -55,6 +64,16 @@ enum {
PROP_SEXP,
};
+enum {
+ OBJECTS_ADDED,
+ OBJECTS_MODIFIED,
+ OBJECTS_REMOVED,
+ DONE,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
static void
data_destroyed_cb (gpointer data, GObject *dead)
{
@@ -187,6 +206,21 @@ e_data_view_dispose (GObject *object)
priv->sexp = NULL;
}
+ if (priv->adds) {
+ g_array_unref (priv->adds);
+ priv->adds = NULL;
+ }
+
+ if (priv->modifications) {
+ g_array_unref (priv->modifications);
+ priv->modifications = NULL;
+ }
+
+ if (priv->removes) {
+ g_array_unref (priv->removes);
+ priv->removes = NULL;
+ }
+
G_OBJECT_CLASS (e_data_view_parent_class)->dispose (object);
}
@@ -198,6 +232,8 @@ e_data_view_finalize (GObject *object)
g_free (priv->dbus_path);
+ g_hash_table_destroy (priv->ids);
+
G_OBJECT_CLASS (e_data_view_parent_class)->finalize (object);
}
@@ -205,6 +241,18 @@ static void
e_data_view_constructed (GObject *object)
{
EDataView *view = E_DATA_VIEW (object);
+ EDataViewClass *klass;
+ GHashFunc id_hash;
+ GEqualFunc id_equal;
+ GDestroyNotify id_destroy;
+
+ klass = E_DATA_VIEW_GET_CLASS (view);
+
+ id_hash = klass->id_hash ? klass->id_hash : g_str_hash;
+ id_equal = klass->id_equal ? klass->id_equal : g_str_equal;
+ id_destroy = klass->id_destroy ? klass->id_destroy : g_free;
+
+ view->priv->ids = g_hash_table_new_full (id_hash, id_equal, id_destroy, NULL);
dbus_g_connection_register_g_object (connection, view->priv->dbus_path, G_OBJECT (view));
}
@@ -264,13 +312,58 @@ e_data_view_class_init (EDataViewClass *klass)
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
+ signals[OBJECTS_ADDED] =
+ g_signal_new ("objects-added",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EDataViewClass, objects_added),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1, G_TYPE_STRV);
+
+ signals[OBJECTS_MODIFIED] =
+ g_signal_new ("objects-modified",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EDataViewClass, objects_modified),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1, G_TYPE_STRV);
+
+ signals[OBJECTS_REMOVED] =
+ g_signal_new ("objects-removed",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EDataViewClass, objects_removed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1, G_TYPE_STRV);
+
+ signals[DONE] =
+ g_signal_new ("done",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
+
+
g_type_class_add_private (klass, sizeof (EDataViewPrivate));
}
static void
e_data_view_init (EDataView *view)
{
- view->priv = E_DATA_VIEW_GET_PRIVATE (view);
+ EDataViewPrivate *priv = E_DATA_VIEW_GET_PRIVATE (view);
+
+ view->priv = priv;
+
+ priv->adds = g_array_sized_new (TRUE, TRUE, sizeof (gchar *), THRESHOLD);
+ priv->modifications = g_array_sized_new (TRUE, TRUE, sizeof (gchar *), THRESHOLD);
+ priv->removes = g_array_sized_new (TRUE, TRUE, sizeof (gchar *), THRESHOLD);
+
+ priv->done = FALSE;
+ priv->done_status = 0;
}
/**
@@ -321,3 +414,196 @@ e_data_view_get_dbus_path (EDataView *view)
return view->priv->dbus_path;
}
+
+static void
+reset_array (GArray *array)
+{
+ gint i = 0;
+ gchar *tmp = NULL;
+
+ /* Free stored strings */
+ for (i = 0; i < array->len; i++) {
+ tmp = g_array_index (array, gchar *, i);
+ g_free (tmp);
+ }
+
+ /* Force the array size to 0 */
+ g_array_set_size (array, 0);
+}
+
+void
+e_data_view_send_pending_adds (EDataView *view)
+{
+ EDataViewPrivate *priv = view->priv;
+
+ if (priv->adds->len == 0)
+ return;
+
+ g_signal_emit (view, signals[OBJECTS_ADDED], 0, priv->adds->data);
+ reset_array (priv->adds);
+}
+
+void
+e_data_view_send_pending_modifications (EDataView *view)
+{
+ EDataViewPrivate *priv = view->priv;
+
+ if (priv->modifications->len == 0)
+ return;
+
+ g_signal_emit (view, signals[OBJECTS_MODIFIED], 0, priv->modifications->data);
+ reset_array (priv->modifications);
+}
+
+void
+e_data_view_send_pending_removes (EDataView *view)
+{
+ EDataViewPrivate *priv = view->priv;
+
+ if (priv->removes->len == 0)
+ return;
+
+ /* TODO: send ECalComponentIds as a list of pairs */
+ g_signal_emit (view, signals[OBJECTS_REMOVED], 0, priv->removes->data);
+ reset_array (priv->removes);
+}
+
+gboolean
+e_data_view_contains_object (EDataView *view,
+ gpointer id)
+{
+ g_return_val_if_fail (E_IS_DATA_VIEW (view), FALSE);
+
+ return g_hash_table_lookup (view->priv->ids, id) != NULL;
+}
+
+void
+e_data_view_notify_object_add (EDataView *view,
+ gpointer id,
+ const gchar *obj)
+{
+ EDataViewPrivate *priv;
+ EDataViewClass *klass;
+
+ g_return_if_fail (E_IS_DATA_VIEW (view));
+
+ priv = view->priv;
+ klass = E_DATA_VIEW_GET_CLASS (view);
+
+ e_data_view_send_pending_modifications (view);
+ e_data_view_send_pending_removes (view);
+
+ if (priv->adds->len == THRESHOLD) {
+ e_data_view_send_pending_adds (view);
+ }
+
+ if (e_data_view_contains_object (view, id)) {
+ if (klass->id_destroy) {
+ klass->id_destroy (id);
+ } else {
+ g_free (id);
+ }
+
+ return;
+ }
+
+ g_array_append_val (priv->adds, obj);
+
+ g_hash_table_insert (priv->ids, id, GUINT_TO_POINTER (1));
+}
+
+void
+e_data_view_notify_object_modification (EDataView *view,
+ gchar *obj)
+{
+ EDataViewPrivate *priv;
+
+ g_return_if_fail (E_IS_DATA_VIEW (view));
+
+ priv = view->priv;
+
+ e_data_view_send_pending_adds (view);
+ e_data_view_send_pending_removes (view);
+
+ g_array_append_val (priv->modifications, obj);
+}
+
+void
+e_data_view_notify_object_remove (EDataView *view,
+ gpointer id)
+{
+ EDataViewPrivate *priv;
+ gchar *uid;
+ EDataViewClass *klass;
+
+ g_return_if_fail (E_IS_DATA_VIEW (view));
+
+ priv = view->priv;
+ klass = E_DATA_VIEW_GET_CLASS (view);
+
+ if (!e_data_view_contains_object (view, id)) {
+ g_warning (G_STRLOC ": view does not contain id %p", id);
+ return;
+ }
+
+ e_data_view_send_pending_adds (view);
+ e_data_view_send_pending_modifications (view);
+
+ if (klass->id_get_str_id) {
+ uid = g_strdup (klass->id_get_str_id (id));
+ } else {
+ uid = g_strdup ((const gchar*) id);
+ }
+
+ g_array_append_val (priv->removes, uid);
+
+ g_hash_table_remove (priv->ids, id);
+}
+
+void
+e_data_view_notify_done (EDataView *view,
+ guint status)
+{
+ e_data_view_send_pending_adds (view);
+ e_data_view_send_pending_modifications (view);
+ e_data_view_send_pending_removes (view);
+
+ g_signal_emit (view, signals[DONE], 0, status);
+}
+
+/**
+ * e_data_view_is_done:
+ * @view: An #EDataView
+ *
+ * Checks whether the given view is already done. Being done means the initial
+ * matching of objects have been finished, not that no more notifications about
+ * changes will be sent. In fact, even after done, notifications will still be
+ * sent if there are changes in the objects matching the query search
+ * expression.
+ *
+ * Return value: TRUE if the view is done, FALSE if still in progress.
+ */
+gboolean
+e_data_view_is_done (EDataView *view)
+{
+ g_return_val_if_fail (E_IS_DATA_VIEW (view), FALSE);
+
+ return view->priv->done;
+}
+
+/**
+ * e_data_view_get_done_status:
+ * @view: An #EDataView
+ *
+ * Gets the status code obtained when the initial matching of objects was done
+ * for the given view.
+ *
+ * Return value: The view status.
+ */
+guint
+e_data_view_get_done_status (EDataView *view)
+{
+ g_return_val_if_fail (E_IS_DATA_VIEW (view), FALSE);
+
+ return view->priv->done_status;
+}
diff --git a/libebackend/e-data-view.h b/libebackend/e-data-view.h
index f83c54b..8f5ba4c 100644
--- a/libebackend/e-data-view.h
+++ b/libebackend/e-data-view.h
@@ -50,7 +50,29 @@ struct _EDataView {
struct _EDataViewClass {
GObjectClass parent;
- void (*stop_if_running) (EDataView *view);
+ void (*stop_if_running) (EDataView *view);
+
+ GHashFunc id_hash;
+
+ GEqualFunc id_equal;
+
+ GDestroyNotify id_destroy;
+
+ const gchar* (*id_get_str_id) (gconstpointer id);
+
+ /* Notification signals */
+ void (*objects_added) (EDataView *view,
+ const gchar **objects);
+
+ void (*objects_modified) (EDataView *view,
+ const gchar **objects);
+
+ void (*objects_removed) (EDataView *view,
+ const gchar **ids);
+/* FIXME: cut this
+ void (*done) (EDataView *view,
+ guint status);
+*/
};
GType e_data_view_get_type (void);
@@ -59,6 +81,30 @@ EBackendSExp* e_data_view_get_sexp (EDataView *view);
EBackend* e_data_view_get_backend (EDataView *view);
const gchar* e_data_view_get_dbus_path (EDataView *view);
+void e_data_view_send_pending_adds (EDataView *view);
+void e_data_view_send_pending_modifications (EDataView *view);
+void e_data_view_send_pending_removes (EDataView *view);
+
+gboolean e_data_view_contains_object (EDataView *view,
+ gpointer id);
+
+void e_data_view_notify_object_add (EDataView *view,
+ gpointer id,
+ const gchar *obj);
+
+void e_data_view_notify_object_modification (EDataView *view,
+ gchar *obj);
+
+void e_data_view_notify_object_remove (EDataView *view,
+ gpointer id);
+
+void e_data_view_notify_done (EDataView *view,
+ guint status);
+
+gboolean e_data_view_is_done (EDataView *view);
+
+guint e_data_view_get_done_status (EDataView *view);
+
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]