From 8e212824134c1740d05fb36799f78716c5059801 Mon Sep 17 00:00:00 2001 From: Not Zed Date: Fri, 12 Nov 2004 05:53:12 +0000 Subject: ** Merge in notzed-messageinfo-branch, fix some minor conflicts. 2004-11-12 Not Zed ** Merge in notzed-messageinfo-branch, fix some minor conflicts. svn path=/trunk/; revision=27898 --- camel/camel-vtrash-folder.c | 418 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 397 insertions(+), 21 deletions(-) (limited to 'camel/camel-vtrash-folder.c') diff --git a/camel/camel-vtrash-folder.c b/camel/camel-vtrash-folder.c index 91e4b8a3a1..63656f438f 100644 --- a/camel/camel-vtrash-folder.c +++ b/camel/camel-vtrash-folder.c @@ -1,6 +1,7 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Authors: Jeffrey Stedfast + * Michael Zucchi * * Copyright 2001 Ximian, Inc. (www.ximian.com) * @@ -28,6 +29,7 @@ #include "camel-vee-store.h" #include "camel-mime-message.h" #include "camel-i18n.h" +#include "camel-private.h" #include @@ -49,23 +51,7 @@ static struct { static CamelVeeFolderClass *camel_vtrash_folder_parent; -static void vtrash_append_message (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **appended_uid, - CamelException *ex); -static void vtrash_transfer_messages_to (CamelFolder *folder, GPtrArray *uids, - CamelFolder *dest, GPtrArray **transferred_uids, - gboolean delete_originals, CamelException *ex); - -static void -camel_vtrash_folder_class_init (CamelVTrashFolderClass *klass) -{ - CamelFolderClass *folder_class = (CamelFolderClass *) klass; - - camel_vtrash_folder_parent = CAMEL_VEE_FOLDER_CLASS(camel_vee_folder_get_type()); - - folder_class->append_message = vtrash_append_message; - folder_class->transfer_messages_to = vtrash_transfer_messages_to; -} +static void camel_vtrash_folder_class_init (CamelVTrashFolderClass *klass); static void camel_vtrash_folder_init (CamelVTrashFolder *vtrash) @@ -121,6 +107,77 @@ camel_vtrash_folder_new (CamelStore *parent_store, enum _camel_vtrash_folder_t t return (CamelFolder *)vtrash; } +static int +vtrash_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args) +{ + CamelFolder *folder = (CamelFolder *)object; + int i; + guint32 tag; + int unread = -1, deleted = 0, junked = 0, visible = 0, count = -1; + + for (i=0;iargc;i++) { + CamelArgGet *arg = &args->argv[i]; + + tag = arg->tag; + + /* NB: this is a copy of camel-folder.c with the unread count logic altered. + makes sure its still atomically calculated */ + switch (tag & CAMEL_ARG_TAG) { + case CAMEL_FOLDER_ARG_UNREAD: + case CAMEL_FOLDER_ARG_DELETED: + case CAMEL_FOLDER_ARG_JUNKED: + case CAMEL_FOLDER_ARG_VISIBLE: + /* This is so we can get the values atomically, and also so we can calculate them only once */ + if (unread == -1) { + int j; + CamelMessageInfo *info; + + unread = 0; + count = camel_folder_summary_count(folder->summary); + for (j=0; jsummary, j))) { + guint32 flags = camel_message_info_flags(info); + + if ((flags & (CAMEL_MESSAGE_SEEN)) == 0) + unread++; + if (flags & CAMEL_MESSAGE_DELETED) + deleted++; + if (flags & CAMEL_MESSAGE_JUNK) + junked++; + if ((flags & (CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_JUNK)) == 0) + visible++; + camel_message_info_free(info); + } + } + } + + switch (tag & CAMEL_ARG_TAG) { + case CAMEL_FOLDER_ARG_UNREAD: + count = unread; + break; + case CAMEL_FOLDER_ARG_DELETED: + count = deleted; + break; + case CAMEL_FOLDER_ARG_JUNKED: + count = junked; + break; + case CAMEL_FOLDER_ARG_VISIBLE: + count = visible; + break; + } + + *arg->ca_int = count; + break; + default: + continue; + } + + arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE; + } + + return ((CamelObjectClass *)camel_vtrash_folder_parent)->getv(object, ex, args); +} + static void vtrash_append_message (CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, char **appended_uid, @@ -199,20 +256,20 @@ vtrash_transfer_messages_to (CamelFolder *source, GPtrArray *uids, continue; } - if (dest == mi->folder) { + if (dest == mi->real->summary->folder) { /* Just unset the flag on the original message */ camel_folder_set_message_flags (source, uids->pdata[i], sbit, 0); } else { if (batch == NULL) batch = g_hash_table_new(NULL, NULL); - md = g_hash_table_lookup(batch, mi->folder); + md = g_hash_table_lookup(batch, mi->real->summary->folder); if (md == NULL) { md = g_malloc0(sizeof(*md)); - md->folder = mi->folder; + md->folder = mi->real->summary->folder; camel_object_ref((CamelObject *)md->folder); md->uids = g_ptr_array_new(); md->dest = dest; - g_hash_table_insert(batch, mi->folder, md); + g_hash_table_insert(batch, mi->real->summary->folder, md); } tuid = uids->pdata[i]; @@ -228,3 +285,322 @@ vtrash_transfer_messages_to (CamelFolder *source, GPtrArray *uids, g_hash_table_destroy(batch); } } + +static GPtrArray * +vtrash_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex) +{ + GList *node; + GPtrArray *matches, *result = g_ptr_array_new(), *uids = g_ptr_array_new(); + struct _CamelVeeFolderPrivate *p = ((CamelVeeFolder *)folder)->priv; + + /* we optimise the search by only searching for messages which we have anyway */ + CAMEL_VEE_FOLDER_LOCK(folder, subfolder_lock); + node = p->folders; + while (node) { + CamelFolder *f = node->data; + int i; + char hash[8]; + GPtrArray *infos = camel_folder_get_summary(f); + + camel_vee_folder_hash_folder(f, hash); + + for (i=0;ilen;i++) { + CamelMessageInfo *mi = infos->pdata[i]; + + if (camel_message_info_flags(mi) & ((CamelVTrashFolder *)folder)->bit) + g_ptr_array_add(uids, (void *)camel_message_info_uid(mi)); + } + + if (uids->len > 0 + && (matches = camel_folder_search_by_uids(f, expression, uids, NULL))) { + for (i = 0; i < matches->len; i++) { + char *uid = matches->pdata[i], *vuid; + + vuid = g_malloc(strlen(uid)+9); + memcpy(vuid, hash, 8); + strcpy(vuid+8, uid); + g_ptr_array_add(result, vuid); + } + camel_folder_search_free(f, matches); + } + g_ptr_array_set_size(uids, 0); + camel_folder_free_summary(f, infos); + + node = g_list_next(node); + } + CAMEL_VEE_FOLDER_UNLOCK(folder, subfolder_lock); + + g_ptr_array_free(uids, TRUE); + + return result; +} + +static GPtrArray * +vtrash_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex) +{ + GList *node; + GPtrArray *matches, *result = g_ptr_array_new(), *folder_uids = g_ptr_array_new(); + struct _CamelVeeFolderPrivate *p = ((CamelVeeFolder *)folder)->priv; + + CAMEL_VEE_FOLDER_LOCK(folder, subfolder_lock); + + node = p->folders; + while (node) { + CamelFolder *f = node->data; + int i; + char hash[8]; + + camel_vee_folder_hash_folder(f, hash); + + /* map the vfolder uid's to the source folder uid's first */ + g_ptr_array_set_size(uids, 0); + for (i=0;ilen;i++) { + char *uid = uids->pdata[i]; + + if (strlen(uid) >= 8 && strncmp(uid, hash, 8) == 0) { + CamelMessageInfo *mi; + + mi = camel_folder_get_message_info(f, uid+8); + if (mi) { + if(camel_message_info_flags(mi) & ((CamelVTrashFolder *)folder)->bit) + g_ptr_array_add(folder_uids, uid+8); + camel_folder_free_message_info(f, mi); + } + } + } + + if (folder_uids->len > 0 + && (matches = camel_folder_search_by_uids(f, expression, folder_uids, ex))) { + for (i = 0; i < matches->len; i++) { + char *uid = matches->pdata[i], *vuid; + + vuid = g_malloc(strlen(uid)+9); + memcpy(vuid, hash, 8); + strcpy(vuid+8, uid); + g_ptr_array_add(result, vuid); + } + camel_folder_search_free(f, matches); + } + node = g_list_next(node); + } + + CAMEL_VEE_FOLDER_UNLOCK(folder, subfolder_lock); + + g_ptr_array_free(folder_uids, TRUE); + + return result; +} + +static void +vtrash_uid_removed(CamelVTrashFolder *vf, const char *uid, char hash[8]) +{ + char *vuid; + CamelVeeMessageInfo *vinfo; + + vuid = g_alloca(strlen(uid)+9); + memcpy(vuid, hash, 8); + strcpy(vuid+8, uid); + vinfo = (CamelVeeMessageInfo *)camel_folder_summary_uid(((CamelFolder *)vf)->summary, vuid); + if (vinfo) { + camel_folder_change_info_remove_uid(((CamelVeeFolder *)vf)->changes, vuid); + camel_folder_summary_remove(((CamelFolder *)vf)->summary, (CamelMessageInfo *)vinfo); + camel_message_info_free(vinfo); + } +} + +static void +vtrash_uid_added(CamelVTrashFolder *vf, const char *uid, CamelMessageInfo *info, char hash[8]) +{ + char *vuid; + CamelVeeMessageInfo *vinfo; + + vuid = g_alloca(strlen(uid)+9); + memcpy(vuid, hash, 8); + strcpy(vuid+8, uid); + vinfo = (CamelVeeMessageInfo *)camel_folder_summary_uid(((CamelFolder *)vf)->summary, vuid); + if (vinfo == NULL) { + camel_vee_summary_add((CamelVeeSummary *)((CamelFolder *)vf)->summary, info, hash); + camel_folder_change_info_add_uid(((CamelVeeFolder *)vf)->changes, vuid); + } else { + camel_folder_change_info_change_uid(((CamelVeeFolder *)vf)->changes, vuid); + camel_message_info_free(vinfo); + } +} + +static void +vtrash_folder_changed(CamelVeeFolder *vf, CamelFolder *sub, CamelFolderChangeInfo *changes) +{ + CamelMessageInfo *info; + char hash[8]; + CamelFolderChangeInfo *vf_changes = NULL; + int i; + + camel_vee_folder_hash_folder(sub, hash); + + CAMEL_VEE_FOLDER_LOCK(vf, summary_lock); + + /* remove any removed that we also have */ + for (i=0;iuid_removed->len;i++) + vtrash_uid_removed((CamelVTrashFolder *)vf, (const char *)changes->uid_removed->pdata[i], hash); + + /* check any changed still deleted/junked */ + for (i=0;iuid_changed->len;i++) { + const char *uid = changes->uid_changed->pdata[i]; + + info = camel_folder_get_message_info(sub, uid); + if (info == NULL) + continue; + + if ((camel_message_info_flags(info) & ((CamelVTrashFolder *)vf)->bit) == 0) + vtrash_uid_removed((CamelVTrashFolder *)vf, uid, hash); + else + vtrash_uid_added((CamelVTrashFolder *)vf, uid, info, hash); + + camel_message_info_free(info); + } + + /* add any new ones which are already matching */ + for (i=0;iuid_added->len;i++) { + const char *uid = changes->uid_added->pdata[i]; + + info = camel_folder_get_message_info(sub, uid); + if (info == NULL) + continue; + + if ((camel_message_info_flags(info) & ((CamelVTrashFolder *)vf)->bit) != 0) + vtrash_uid_added((CamelVTrashFolder *)vf, uid, info, hash); + + camel_message_info_free(info); + } + + if (camel_folder_change_info_changed(((CamelVeeFolder *)vf)->changes)) { + vf_changes = ((CamelVeeFolder *)vf)->changes; + ((CamelVeeFolder *)vf)->changes = camel_folder_change_info_new(); + } + + CAMEL_VEE_FOLDER_UNLOCK(vf, summary_lock); + + if (vf_changes) { + camel_object_trigger_event(vf, "folder_changed", vf_changes); + camel_folder_change_info_free(vf_changes); + } +} + +static void +vtrash_add_folder(CamelVeeFolder *vf, CamelFolder *sub) +{ + GPtrArray *infos; + int i; + char hash[8]; + CamelFolderChangeInfo *vf_changes = NULL; + + camel_vee_folder_hash_folder(sub, hash); + + CAMEL_VEE_FOLDER_LOCK(vf, summary_lock); + + infos = camel_folder_get_summary(sub); + for (i=0;ilen;i++) { + CamelMessageInfo *info = infos->pdata[i]; + + if ((camel_message_info_flags(info) & ((CamelVTrashFolder *)vf)->bit)) + vtrash_uid_added((CamelVTrashFolder *)vf, camel_message_info_uid(info), info, hash); + } + camel_folder_free_summary(sub, infos); + + if (camel_folder_change_info_changed(vf->changes)) { + vf_changes = vf->changes; + vf->changes = camel_folder_change_info_new(); + } + + CAMEL_VEE_FOLDER_UNLOCK(vf, summary_lock); + + if (vf_changes) { + camel_object_trigger_event(vf, "folder_changed", vf_changes); + camel_folder_change_info_free(vf_changes); + } +} + +static void +vtrash_remove_folder(CamelVeeFolder *vf, CamelFolder *sub) +{ + GPtrArray *infos; + int i; + char hash[8]; + CamelFolderChangeInfo *vf_changes = NULL; + CamelFolderSummary *ssummary = sub->summary; + int start, last; + + camel_vee_folder_hash_folder(sub, hash); + + CAMEL_VEE_FOLDER_LOCK(vf, summary_lock); + + start = -1; + last = -1; + infos = camel_folder_get_summary(sub); + for (i=0;ilen;i++) { + CamelVeeMessageInfo *mi = infos->pdata[i]; + + if (mi == NULL) + continue; + + if (mi->real->summary == ssummary) { + const char *uid = camel_message_info_uid(mi); + + camel_folder_change_info_remove_uid(vf->changes, uid); + + if (last == -1) { + last = start = i; + } else if (last+1 == i) { + last = i; + } else { + camel_folder_summary_remove_range(((CamelFolder *)vf)->summary, start, last); + i -= (last-start)+1; + start = last = i; + } + } + } + camel_folder_free_summary(sub, infos); + + if (last != -1) + camel_folder_summary_remove_range(((CamelFolder *)vf)->summary, start, last); + + if (camel_folder_change_info_changed(vf->changes)) { + vf_changes = vf->changes; + vf->changes = camel_folder_change_info_new(); + } + + CAMEL_VEE_FOLDER_UNLOCK(vf, summary_lock); + + if (vf_changes) { + camel_object_trigger_event(vf, "folder_changed", vf_changes); + camel_folder_change_info_free(vf_changes); + } +} + +static int +vtrash_rebuild_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException *ex) +{ + /* we should always be in sync */ + return 0; +} + +static void +camel_vtrash_folder_class_init (CamelVTrashFolderClass *klass) +{ + CamelFolderClass *folder_class = (CamelFolderClass *) klass; + + camel_vtrash_folder_parent = CAMEL_VEE_FOLDER_CLASS(camel_vee_folder_get_type()); + + ((CamelObjectClass *)klass)->getv = vtrash_getv; + + folder_class->append_message = vtrash_append_message; + folder_class->transfer_messages_to = vtrash_transfer_messages_to; + folder_class->search_by_expression = vtrash_search_by_expression; + folder_class->search_by_uids = vtrash_search_by_uids; + + ((CamelVeeFolderClass *)klass)->add_folder = vtrash_add_folder; + ((CamelVeeFolderClass *)klass)->remove_folder = vtrash_remove_folder; + ((CamelVeeFolderClass *)klass)->rebuild_folder = vtrash_rebuild_folder; + + ((CamelVeeFolderClass *)klass)->folder_changed = vtrash_folder_changed; +} -- cgit v1.2.3