diff options
author | Not Zed <NotZed@HelixCode.com> | 2000-11-02 11:35:04 +0800 |
---|---|---|
committer | Michael Zucci <zucchi@src.gnome.org> | 2000-11-02 11:35:04 +0800 |
commit | f351369e5127337eb95185ac764b6744faf4b87f (patch) | |
tree | 57654b3a2d65743b8670b2f583f15639a368616a /camel/camel-folder.c | |
parent | 24e7b7d5fcfe1d98a912570c554b74ca1a9f0f64 (diff) | |
download | gsoc2013-evolution-f351369e5127337eb95185ac764b6744faf4b87f.tar.gz gsoc2013-evolution-f351369e5127337eb95185ac764b6744faf4b87f.tar.zst gsoc2013-evolution-f351369e5127337eb95185ac764b6744faf4b87f.zip |
Merged in camel-incremental-branch.
2000-11-02 Not Zed <NotZed@HelixCode.com>
* Merged in camel-incremental-branch.
svn path=/trunk/; revision=6336
Diffstat (limited to 'camel/camel-folder.c')
-rw-r--r-- | camel/camel-folder.c | 334 |
1 files changed, 284 insertions, 50 deletions
diff --git a/camel/camel-folder.c b/camel/camel-folder.c index 792d3c5d01..1d929fb4f0 100644 --- a/camel/camel-folder.c +++ b/camel/camel-folder.c @@ -157,15 +157,13 @@ camel_folder_init (gpointer object, gpointer klass) CamelFolder *folder = object; folder->frozen = 0; - folder->folder_changed = FALSE; - folder->messages_changed = NULL; + folder->changed_frozen = camel_folder_change_info_new(); } static void camel_folder_finalize (CamelObject *object) { CamelFolder *camel_folder = CAMEL_FOLDER (object); - GList *m; g_free (camel_folder->name); g_free (camel_folder->full_name); @@ -173,9 +171,7 @@ camel_folder_finalize (CamelObject *object) if (camel_folder->parent_store) camel_object_unref (CAMEL_OBJECT (camel_folder->parent_store)); - for (m = camel_folder->messages_changed; m; m = m->next) - g_free (m->data); - g_list_free (camel_folder->messages_changed); + camel_folder_change_info_free(camel_folder->changed_frozen); } CamelType @@ -979,45 +975,26 @@ camel_folder_freeze (CamelFolder * folder) static void thaw (CamelFolder * folder) { - GList *messages, *m; + int i; + CamelFolderChangeInfo *info; folder->frozen--; if (folder->frozen != 0) return; - /* Clear messages_changed now in case the signal handler ends - * up calling freeze and thaw itself. - */ - messages = folder->messages_changed; - folder->messages_changed = NULL; - - /* If the folder changed, emit that and ignore the individual - * messages (since the UIDs may no longer be valid). - */ - if (folder->folder_changed) { - folder->folder_changed = FALSE; - - camel_object_trigger_event (CAMEL_OBJECT (folder), - "folder_changed", NULL); - } else if (messages) { - /* FIXME: would be nice to not emit more than once for - * a given message - */ - for (m = messages; m; m = m->next) { - camel_object_trigger_event (CAMEL_OBJECT (folder), - "message_changed", - m->data); - g_free (m->data); + /* If we have more or less messages, do a folder changed, otherwise just + do a message changed for each one. + TODO: message_changed is now probably irrelevant and not required */ + info = folder->changed_frozen; + if (info->uid_added->len > 0 || info->uid_removed->len > 0) { + camel_object_trigger_event(CAMEL_OBJECT(folder), "folder_changed", info); + } else if (info->uid_changed->len > 0) { + for (i=0;i<info->uid_changed->len;i++) { + camel_object_trigger_event(CAMEL_OBJECT(folder), "message_changed", info->uid_changed->pdata[i]); } - g_list_free (messages); - return; } - if (messages) { - for (m = messages; m; m = m->next) - g_free (m->data); - g_list_free (messages); - } + camel_folder_change_info_clear(info); } /** @@ -1042,12 +1019,16 @@ static gboolean folder_changed (CamelObject *obj, gpointer event_data) { CamelFolder *folder = CAMEL_FOLDER (obj); + CamelFolderChangeInfo *changed = event_data; if (folder->frozen) { - folder->folder_changed = TRUE; + if (changed != NULL) + camel_folder_change_info_cat(folder->changed_frozen, changed); + else + g_warning("Class %s is passing NULL to folder_changed event", + camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder))); return FALSE; } - return TRUE; } @@ -1057,17 +1038,7 @@ message_changed (CamelObject *obj, /*const char *uid*/gpointer event_data) CamelFolder *folder = CAMEL_FOLDER (obj); if (folder->frozen) { - /* FIXME: if there are no hooks attached, we can just - * return here. - */ - - /* Only record the UID if it will be useful later. */ - if (!folder->folder_changed) { - folder->messages_changed = - g_list_prepend (folder->messages_changed, - g_strdup ((gchar *)event_data)); - } - + camel_folder_change_info_change_uid(folder->changed_frozen, (char *)event_data); return FALSE; } @@ -1124,3 +1095,266 @@ camel_folder_free_deep (CamelFolder *folder, GPtrArray *array) g_free (array->pdata[i]); g_ptr_array_free (array, TRUE); } + +/** + * camel_folder_change_info_new: + * @void: + * + * Create a new folder change info structure. + * + * Return value: + **/ +CamelFolderChangeInfo * +camel_folder_change_info_new(void) +{ + CamelFolderChangeInfo *info; + + info = g_malloc(sizeof(*info)); + info->uid_added = g_ptr_array_new(); + info->uid_removed = g_ptr_array_new(); + info->uid_changed = g_ptr_array_new(); + info->uid_source = NULL; + + return info; +} + +/** + * camel_folder_change_info_add_source: + * @info: + * @uid: + * + * Add a source uid for generating a changeset. + **/ +void +camel_folder_change_info_add_source(CamelFolderChangeInfo *info, const char *uid) +{ + if (info->uid_source == NULL) + info->uid_source = g_hash_table_new(g_str_hash, g_str_equal); + + if (g_hash_table_lookup(info->uid_source, uid) == NULL) + g_hash_table_insert(info->uid_source, g_strdup(uid), (void *)1); +} + +/** + * camel_folder_change_info_add_source_list: + * @info: + * @list: + * + * Add a list of source uid's for generating a changeset. + **/ +void +camel_folder_change_info_add_source_list(CamelFolderChangeInfo *info, const GPtrArray *list) +{ + int i; + + if (info->uid_source == NULL) + info->uid_source = g_hash_table_new(g_str_hash, g_str_equal); + + for (i=0;i<list->len;i++) { + char *uid = list->pdata[i]; + + if (g_hash_table_lookup(info->uid_source, uid) == NULL) + g_hash_table_insert(info->uid_source, g_strdup(uid), (void *)1); + } +} + +/** + * camel_folder_change_info_add_update: + * @info: + * @uid: + * + * Add a uid from the updated list, used to generate a changeset diff. + **/ +void +camel_folder_change_info_add_update(CamelFolderChangeInfo *info, const char *uid) +{ + char *key; + int value; + + if (info->uid_source == NULL) { + camel_folder_change_info_add_uid(info, uid); + return; + } + + if (g_hash_table_lookup_extended(info->uid_source, uid, (void **)&key, (void **)&value)) { + g_hash_table_remove(info->uid_source, key); + g_free(key); + } else { + camel_folder_change_info_add_uid(info, uid); + } +} + +/** + * camel_folder_change_info_add_update_list: + * @info: + * @list: + * + * Add a list of uid's from the updated list. + **/ +void +camel_folder_change_info_add_update_list(CamelFolderChangeInfo *info, const GPtrArray *list) +{ + int i; + + for (i=0;i<list->len;i++) { + camel_folder_change_info_add_update(info, list->pdata[i]); + } +} + +static void +change_info_remove(char *key, void *value, CamelFolderChangeInfo *info) +{ + camel_folder_change_info_remove_uid(info, key); + g_free(key); +} + +static void +change_info_free_update(char *key, void *value, CamelFolderChangeInfo *info) +{ + g_free(key); +} + +/** + * camel_folder_change_info_build_diff: + * @info: + * + * Compare the source uid set to the updated uid set and generate the differences + * into the added and removed lists. + **/ +void +camel_folder_change_info_build_diff(CamelFolderChangeInfo *info) +{ + if (info->uid_source) { + g_hash_table_foreach(info->uid_source, (GHFunc)change_info_remove, info); + g_hash_table_destroy(info->uid_source); + info->uid_source = NULL; + } +} + +static void +change_info_add_uid(CamelFolderChangeInfo *info, GPtrArray *uids, const char *uid) +{ + int i; + + /* TODO: Check that it is in the other arrays and remove it from them/etc? */ + for (i=0;i<uids->len;i++) { + if (!strcmp(uids->pdata[i], uid)) + return; + } + g_ptr_array_add(uids, g_strdup(uid)); +} + +static void +change_info_cat(CamelFolderChangeInfo *info, GPtrArray *uids, GPtrArray *source) +{ + int i; + + for (i=0;i<source->len;i++) { + change_info_add_uid(info, uids, source->pdata[i]); + } +} + +/** + * camel_folder_change_info_cat: + * @info: + * @source: + * + * Concatenate one change info onto antoher. Can be used to copy + * them too. + **/ +void +camel_folder_change_info_cat(CamelFolderChangeInfo *info, CamelFolderChangeInfo *source) +{ + change_info_cat(info, info->uid_added, source->uid_added); + change_info_cat(info, info->uid_removed, source->uid_removed); + change_info_cat(info, info->uid_changed, source->uid_changed); +} + +/** + * camel_folder_change_info_add_uid: + * @info: + * @uid: + * + * Add a new uid to the changeinfo. + **/ +void +camel_folder_change_info_add_uid(CamelFolderChangeInfo *info, const char *uid) +{ + change_info_add_uid(info, info->uid_added, uid); +} + +/** + * camel_folder_change_info_remove_uid: + * @info: + * @uid: + * + * Add a uid to the removed uid list. + **/ +void +camel_folder_change_info_remove_uid(CamelFolderChangeInfo *info, const char *uid) +{ + change_info_add_uid(info, info->uid_removed, uid); +} + +/** + * camel_folder_change_info_change_uid: + * @info: + * @uid: + * + * Add a uid to the changed uid list. + **/ +void +camel_folder_change_info_change_uid(CamelFolderChangeInfo *info, const char *uid) +{ + change_info_add_uid(info, info->uid_changed, uid); +} + +static void +change_info_clear(GPtrArray *uids) +{ + int i; + + for (i=0;i<uids->len;i++) { + g_free(uids->pdata[i]); + } + g_ptr_array_set_size(uids, 0); +} + +/** + * camel_folder_change_info_clear: + * @info: + * + * Empty out the change info; called after changes have been processed. + **/ +void +camel_folder_change_info_clear(CamelFolderChangeInfo *info) +{ + change_info_clear(info->uid_added); + change_info_clear(info->uid_removed); + change_info_clear(info->uid_changed); +} + +/** + * camel_folder_change_info_free: + * @info: + * + * Free memory associated with the folder change info lists. + **/ +void +camel_folder_change_info_free(CamelFolderChangeInfo *info) +{ + if (info->uid_source) { + g_hash_table_foreach(info->uid_source, (GHFunc)change_info_free_update, info); + g_hash_table_destroy(info->uid_source); + } + + camel_folder_change_info_clear(info); + + g_ptr_array_free(info->uid_added, TRUE); + g_ptr_array_free(info->uid_removed, TRUE); + g_ptr_array_free(info->uid_changed, TRUE); + g_free(info); +} + + + |