From 4d41e52eecf1810cbec3d371fe5dbe42e6167a05 Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Fri, 31 Jul 2009 18:50:18 +0200 Subject: Bug #539334 - Postpone processing event when called recursively --- calendar/gui/e-cal-model.c | 131 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 125 insertions(+), 6 deletions(-) diff --git a/calendar/gui/e-cal-model.c b/calendar/gui/e-cal-model.c index d5a922625f..04a81a8697 100644 --- a/calendar/gui/e-cal-model.c +++ b/calendar/gui/e-cal-model.c @@ -91,6 +91,16 @@ struct _ECalModelPrivate { /* callback, to retrieve start time for newly added rows by click-to-add */ ECalModelDefaultTimeFunc get_default_time; gpointer get_default_time_user_data; + + gboolean in_added; + gboolean in_modified; + gboolean in_removed; + + GList *notify_added; + GList *notify_modified; + GList *notify_removed; + + GMutex *notify_lock; }; static gint ecm_column_count (ETableModel *etm); @@ -267,6 +277,8 @@ cal_model_finalize (GObject *object) } g_ptr_array_free (priv->objects, FALSE); + g_mutex_free (priv->notify_lock); + /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -417,6 +429,14 @@ e_cal_model_init (ECalModel *model) model->priv->accounts = itip_addresses_get (); model->priv->use_24_hour_format = TRUE; + + model->priv->in_added = FALSE; + model->priv->in_modified = FALSE; + model->priv->in_removed = FALSE; + model->priv->notify_added = NULL; + model->priv->notify_modified = NULL; + model->priv->notify_removed = NULL; + model->priv->notify_lock = g_mutex_new (); } /* ETableModel methods */ @@ -1625,10 +1645,11 @@ ensure_dates_are_in_default_zone (ECalModel *model, } } +static void e_cal_view_objects_added_cb (ECalView *query, GList *objects, ECalModel *model); + static void -e_cal_view_objects_added_cb (ECalView *query, GList *objects, gpointer user_data) +process_added (ECalView *query, GList *objects, ECalModel *model) { - ECalModel *model = (ECalModel *) user_data; ECalModelPrivate *priv; GList *l; @@ -1699,9 +1720,8 @@ e_cal_view_objects_added_cb (ECalView *query, GList *objects, gpointer user_data } static void -e_cal_view_objects_modified_cb (ECalView *query, GList *objects, gpointer user_data) +process_modified (ECalView *query, GList *objects, ECalModel *model) { - ECalModel *model = (ECalModel *) user_data; ECalModelPrivate *priv; GList *l, *list = NULL; @@ -1782,10 +1802,9 @@ e_cal_view_objects_modified_cb (ECalView *query, GList *objects, gpointer user_d } static void -e_cal_view_objects_removed_cb (ECalView *query, GList *ids, gpointer user_data) +process_removed (ECalView *query, GList *ids, ECalModel *model) { ECalModelPrivate *priv; - ECalModel *model = (ECalModel *) user_data; GList *l; priv = model->priv; @@ -1819,6 +1838,106 @@ e_cal_view_objects_removed_cb (ECalView *query, GList *ids, gpointer user_data) e_table_model_changed (E_TABLE_MODEL (model)); } +static gpointer +copy_comp_id (gpointer id) +{ + ECalComponentId *comp_id = (ECalComponentId *) id, *copy; + + g_return_val_if_fail (comp_id != NULL, NULL); + + copy = g_new0 (ECalComponentId, 1); + copy->uid = g_strdup (comp_id->uid); + copy->rid = g_strdup (comp_id->rid); + + return copy; +} + +static void +free_comp_id (gpointer id) +{ + ECalComponentId *comp_id = (ECalComponentId *) id; + + g_return_if_fail (comp_id != NULL); + + g_free (comp_id->uid); + g_free (comp_id->rid); + g_free (comp_id); +} + +static void +process_event (ECalView *query, GList *objects, ECalModel *model, + void (*process_fn) (ECalView *query, GList *objects, ECalModel *model), + gboolean *in, GList **save_list, gpointer (*copy_fn) (gpointer data), void (*free_fn)(gpointer data)) +{ + gboolean skip = FALSE; + GList *l; + + g_mutex_lock (model->priv->notify_lock); + if (*in) { + skip = TRUE; + for (l = objects; l; l = l->next) { + if (l->data) + *save_list = g_list_append (*save_list, copy_fn (l->data)); + } + } else { + *in = TRUE; + } + + g_mutex_unlock (model->priv->notify_lock); + + if (skip) + return; + + /* do it */ + process_fn (query, objects, model); + + g_mutex_lock (model->priv->notify_lock); + while (*save_list) { + GList *copy = *save_list; + *save_list = NULL; + g_mutex_unlock (model->priv->notify_lock); + + /* do it */ + process_fn (query, copy, model); + + for (l = copy; l; l = l->next) { + if (l->data) { + free_fn (l->data); + } + } + g_list_free (copy); + + g_mutex_lock (model->priv->notify_lock); + } + + *in = FALSE; + g_mutex_unlock (model->priv->notify_lock); +} + +static void +e_cal_view_objects_added_cb (ECalView *query, GList *objects, ECalModel *model) +{ + process_event (query, objects, model, + process_added, &model->priv->in_added, &model->priv->notify_added, + (gpointer (*)(gpointer)) icalcomponent_new_clone, (void (*)(gpointer)) icalcomponent_free); +} + +static void +e_cal_view_objects_modified_cb (ECalView *query, GList *objects, ECalModel *model) +{ + process_event (query, objects, model, + process_modified, &model->priv->in_modified, &model->priv->notify_modified, + (gpointer (*)(gpointer)) icalcomponent_new_clone, (void (*)(gpointer)) icalcomponent_free); +} + +static void +e_cal_view_objects_removed_cb (ECalView *query, GList *ids, ECalModel *model) +{ + process_event (query, ids, model, + process_removed, &model->priv->in_removed, &model->priv->notify_removed, + copy_comp_id, free_comp_id); +} + static void e_cal_view_progress_cb (ECalView *query, const gchar *message, gint percent, gpointer user_data) { -- cgit v1.2.3