diff options
-rw-r--r-- | calendar/ChangeLog | 14 | ||||
-rw-r--r-- | calendar/pcs/cal-backend-file.c | 93 |
2 files changed, 91 insertions, 16 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog index 8887a33474..a3d1372fb0 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,17 @@ +2001-08-29 Federico Mena Quintero <federico@ximian.com> + + * pcs/cal-backend-file.c (cal_backend_file_remove_object): See if + the set of categories changed by using the removed_categories hash + table. + (cal_backend_file_init): Create a table of removed categories. + This allows us to notify if and only if the set of category + changes when an object is updated/removed, instead of + unconditionally notifying if an object is updated. + (cal_backend_file_update_objects): Only notify if the set of + categories really changed. + (update_categories_from_comp): Shuffle the categories between the + priv->categories and priv->removed_categories lists. + 2001-08-28 Federico Mena Quintero <federico@ximian.com> Fixes bug #7879, a query may receive an update notification from diff --git a/calendar/pcs/cal-backend-file.c b/calendar/pcs/cal-backend-file.c index 3817382a71..1313b22f12 100644 --- a/calendar/pcs/cal-backend-file.c +++ b/calendar/pcs/cal-backend-file.c @@ -66,8 +66,9 @@ struct _CalBackendFilePrivate { GList *todos; GList *journals; - /* Hash table of live categories */ + /* Hash table of live categories, and a temporary hash of removed categories */ GHashTable *categories; + GHashTable *removed_categories; /* Idle handler for saving the calendar when it is dirty */ guint idle_id; @@ -201,6 +202,7 @@ cal_backend_file_init (CalBackendFile *cbfile) priv->journals = NULL; priv->categories = g_hash_table_new (g_str_hash, g_str_equal); + priv->removed_categories = g_hash_table_new (g_str_hash, g_str_equal); gtk_signal_connect (GTK_OBJECT (cbfile), "cal_added", GTK_SIGNAL_FUNC (cal_added_cb), NULL); @@ -331,6 +333,10 @@ cal_backend_file_destroy (GtkObject *object) g_hash_table_destroy (priv->categories); priv->categories = NULL; + g_hash_table_foreach (priv->removed_categories, free_category_cb, NULL); + g_hash_table_destroy (priv->removed_categories); + priv->removed_categories = NULL; + if (priv->icalcomp) { icalcomponent_free (priv->icalcomp); priv->icalcomp = NULL; @@ -513,11 +519,24 @@ update_categories_from_comp (CalBackendFile *cbfile, CalComponent *comp, gboolea 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); + /* See if it was in the removed categories */ + + c = g_hash_table_lookup (priv->removed_categories, name); + if (c) { + /* Move it to the set of live categories */ + g_assert (c->refcount == 0); + g_hash_table_remove (priv->removed_categories, c->name); + + c->refcount = 1; + g_hash_table_insert (priv->categories, c->name, c); + } else { + /* Create a new category */ + 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 */ @@ -529,8 +548,7 @@ update_categories_from_comp (CalBackendFile *cbfile, CalComponent *comp, gboolea if (c->refcount == 0) { g_hash_table_remove (priv->categories, c->name); - g_free (c->name); - g_free (c); + g_hash_table_insert (priv->removed_categories, c->name, c); } } } @@ -548,7 +566,7 @@ add_component (CalBackendFile *cbfile, CalComponent *comp, gboolean add_to_tople CalBackendFilePrivate *priv; GList **list; const char *uid; - + priv = cbfile->priv; switch (cal_component_get_vtype (comp)) { @@ -1449,6 +1467,32 @@ notify_remove (CalBackendFile *cbfile, const char *uid) } } +/* Used from g_hash_table_foreach_remove(); removes and frees a category */ +static gboolean +remove_category_cb (gpointer key, gpointer value, gpointer data) +{ + Category *c; + + c = value; + g_free (c->name); + g_free (c); + + return TRUE; +} + +/* Clears the table of removed categories */ +static void +clean_removed_categories (CalBackendFile *cbfile) +{ + CalBackendFilePrivate *priv; + + priv = cbfile->priv; + + g_hash_table_foreach_remove (priv->removed_categories, + remove_category_cb, + NULL); +} + /* Update_objects handler for the file backend. */ static gboolean cal_backend_file_update_objects (CalBackend *backend, const char *calobj) @@ -1460,6 +1504,7 @@ cal_backend_file_update_objects (CalBackend *backend, const char *calobj) CalComponent *old_comp; CalComponent *comp; const char *comp_uid; + int old_n_categories, new_n_categories; cbfile = CAL_BACKEND_FILE (backend); priv = cbfile->priv; @@ -1536,6 +1581,13 @@ cal_backend_file_update_objects (CalBackend *backend, const char *calobj) return FALSE; } + /* The list of removed categories must be empty because we are about to + * start a new scanning process. + */ + g_assert (g_hash_table_size (priv->removed_categories) == 0); + + old_n_categories = g_hash_table_size (priv->categories); + /* Update the component */ old_comp = lookup_component (cbfile, comp_uid); @@ -1557,11 +1609,17 @@ cal_backend_file_update_objects (CalBackend *backend, const char *calobj) add_component (cbfile, comp, TRUE); } + new_n_categories = g_hash_table_size (priv->categories); + mark_dirty (cbfile); - /* FIXME: do the notification asynchronously */ notify_update (cbfile, comp_uid); - notify_categories_changed (cbfile); + + if (old_n_categories != new_n_categories || + g_hash_table_size (priv->removed_categories) != 0) { + clean_removed_categories (cbfile); + notify_categories_changed (cbfile); + } return TRUE; } @@ -1573,7 +1631,6 @@ 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; @@ -1586,17 +1643,21 @@ cal_backend_file_remove_object (CalBackend *backend, const char *uid) if (!comp) return FALSE; - old_n_categories = g_hash_table_size (priv->categories); + /* The list of removed categories must be empty because we are about to + * start a new scanning process. + */ + g_assert (g_hash_table_size (priv->removed_categories) == 0); + 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) + if (g_hash_table_size (priv->removed_categories) != 0) { + clean_removed_categories (cbfile); notify_categories_changed (cbfile); + } return TRUE; } |