aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers
diff options
context:
space:
mode:
Diffstat (limited to 'camel/providers')
-rw-r--r--camel/providers/local/camel-mh-summary.c16
-rw-r--r--camel/providers/vee/camel-vee-folder.c228
-rw-r--r--camel/providers/vee/camel-vee-folder.h7
3 files changed, 221 insertions, 30 deletions
diff --git a/camel/providers/local/camel-mh-summary.c b/camel/providers/local/camel-mh-summary.c
index 2f3c829e8d..c28ee1f495 100644
--- a/camel/providers/local/camel-mh-summary.c
+++ b/camel/providers/local/camel-mh-summary.c
@@ -297,23 +297,32 @@ mh_summary_sync_message(CamelLocalSummary *cls, CamelMessageInfo *info, CamelExc
camel_mime_parser_init_with_fd(mp, fd);
if (camel_mime_parser_step(mp, 0, 0) != HSCAN_EOF) {
xev = camel_mime_parser_header(mp, "X-Evolution", &xevoffset);
+ d(printf("xev = '%s'\n", xev));
xevnew = camel_local_summary_encode_x_evolution(cls, info);
if (xev == NULL
|| camel_local_summary_decode_x_evolution(cls, xev, NULL) == -1
- || strlen(xev)+1 != strlen(xevnew)) {
+ || strlen(xev)-1 != strlen(xevnew)) {
+
+ d(printf("camel local summary_decode_xev = %d\n", camel_local_summary_decode_x_evolution(cls, xev, NULL)));
/* need to write a new copy/unlink old */
tmpname = g_strdup_printf("%s/.tmp.%d.%s", cls->folder_path, getpid(), info->uid);
+ d(printf("old xev was %d %s new xev is %d %s\n", strlen(xev), xev, strlen(xevnew), xevnew));
+ d(printf("creating new message %s\n", tmpname));
outfd = open(tmpname, O_CREAT|O_WRONLY|O_TRUNC, 0600);
if (outfd != -1) {
outlen = 0;
- if ( (len = camel_local_summary_write_headers(outfd, camel_mime_parser_headers_raw(mp), xevnew)) == 0) {
+ len = camel_local_summary_write_headers(outfd, camel_mime_parser_headers_raw(mp), xevnew);
+ if (len != -1) {
while (outlen != -1 && (len = camel_mime_parser_read(mp, &buffer, 10240)) > 0) {
+ d(printf("camel mime parser read, read %d bytes: %.*s\n", len, len, buffer));
do {
- outlen = write(fd, buffer, len);
+ outlen = write(outfd, buffer, len);
} while (outlen == -1 && errno == EINTR);
}
}
+
+ d(printf("len = %d outlen = %d, renaming/finishing\n", len, outlen));
if (close(outfd) == -1
|| len == -1
|| outlen == -1
@@ -326,6 +335,7 @@ mh_summary_sync_message(CamelLocalSummary *cls, CamelMessageInfo *info, CamelExc
}
g_free(tmpname);
} else {
+ d(printf("stamping in updated X-EV at %d\n", (int)xevoffset));
/* else, we can just update the flags field */
lseek(fd, xevoffset+strlen("X-Evolution: "), SEEK_SET);
do {
diff --git a/camel/providers/vee/camel-vee-folder.c b/camel/providers/vee/camel-vee-folder.c
index da47761754..77c3017179 100644
--- a/camel/providers/vee/camel-vee-folder.c
+++ b/camel/providers/vee/camel-vee-folder.c
@@ -24,6 +24,9 @@
#include "camel-vee-folder.h"
#include "camel-folder-summary.h"
#include "camel-mime-message.h"
+#ifdef DYNAMIC
+#include "camel-folder-search.h"
+#endif
#include <string.h>
@@ -128,6 +131,11 @@ camel_vee_folder_init (CamelVeeFolder *obj)
CAMEL_MESSAGE_DRAFT |
CAMEL_MESSAGE_FLAGGED |
CAMEL_MESSAGE_SEEN;
+
+ obj->changes = camel_folder_change_info_new();
+#ifdef DYNAMIC
+ obj->search = camel_folder_search_new();
+#endif
}
static void
@@ -137,12 +145,19 @@ camel_vee_folder_finalise (CamelObject *obj)
struct _CamelVeeFolderPrivate *p = _PRIVATE(vf);
GList *node;
+ /* FIXME: some leaks here, summary etc */
+
node = p->folders;
while (node) {
CamelFolder *f = node->data;
camel_object_unref((CamelObject *)f);
node = g_list_next(node);
}
+
+ camel_folder_change_info_free(vf->changes);
+#ifdef DYNAMIC
+ camel_object_unref((CamelObject *)vf->search);
+#endif
}
/**
@@ -156,8 +171,7 @@ camel_vee_folder_finalise (CamelObject *obj)
* Return value: A new CamelVeeFolder widget.
**/
CamelFolder *
-camel_vee_folder_new (CamelStore *parent_store, const char *name,
- CamelException *ex)
+camel_vee_folder_new (CamelStore *parent_store, const char *name, CamelException *ex)
{
CamelFolder *folder;
CamelVeeFolder *vf;
@@ -192,16 +206,136 @@ camel_vee_folder_new (CamelStore *parent_store, const char *name,
return folder;
}
+#ifdef DYNAMIC
+static void
+vfolder_remove_match(CamelVeeFolder *vf, CamelVeeMessageInfo *vinfo)
+{
+ printf("removing match %s\n", vinfo->info.uid);
+
+ g_hash_table_remove(vf->messages_uid, vinfo->info.uid);
+ g_ptr_array_remove_fast(vf->messages, vinfo);
+ camel_folder_change_info_remove_uid(vf->changes, vinfo->info.uid);
+ camel_message_info_free((CamelMessageInfo *)vinfo);
+}
+
+static CamelVeeMessageInfo *
+vfolder_add_match(CamelVeeFolder *vf, CamelFolder *f, const CamelMessageInfo *info)
+{
+ CamelVeeMessageInfo *mi;
+
+ mi = g_malloc0(sizeof(*mi));
+ camel_message_info_dup_to(info, (CamelMessageInfo*)mi);
+ g_free (mi->info.uid);
+ mi->info.uid = g_strdup_printf("%p:%s", f, info->uid);
+ mi->folder = f;
+ g_ptr_array_add(vf->messages, mi);
+ g_hash_table_insert(vf->messages_uid, mi->info.uid, mi);
+
+ printf("adding match %s\n", mi->info.uid);
+
+ camel_folder_change_info_add_uid(vf->changes, mi->info.uid);
+ return mi;
+}
+#endif
+
+static void
+vfolder_change_match(CamelVeeFolder *vf, CamelVeeMessageInfo *vinfo, const CamelMessageInfo *info)
+{
+ CamelFlag *flag;
+ CamelTag *tag;
+
+ printf("changing match %s\n", vinfo->info.uid);
+
+ vinfo->info.flags = info->flags;
+ camel_flag_list_free(&vinfo->info.user_flags);
+ flag = info->user_flags;
+ while (flag) {
+ camel_flag_set(&vinfo->info.user_flags, flag->name, TRUE);
+ flag = flag->next;
+ }
+ camel_tag_list_free(&vinfo->info.user_tags);
+ tag = info->user_tags;
+ while (tag) {
+ camel_tag_set(&vinfo->info.user_tags, tag->name, tag->value);
+ tag = tag->next;
+ }
+ camel_folder_change_info_change_uid(vf->changes, vinfo->info.uid);
+}
+
static void
folder_changed(CamelFolder *sub, gpointer type, CamelVeeFolder *vf)
{
CamelException *ex;
- ex = camel_exception_new();
- vee_folder_build_folder(vf, sub, ex);
- camel_exception_free(ex);
- /* FIXME: should only raise follow-on event if the result changed */
- camel_object_trigger_event( CAMEL_OBJECT(vf), "folder_changed", GINT_TO_POINTER(0));
+#ifdef DYNAMIC
+ CamelFolderChangeInfo *changes = type;
+
+ /* assume its faster to search a long list in whole, than by part */
+ if (changes && (changes->uid_added->len + changes->uid_changed->len) < 500) {
+ int i;
+ char *vuid;
+ CamelVeeMessageInfo *vinfo;
+ gboolean match;
+ const CamelMessageInfo *info;
+
+ ex = camel_exception_new();
+
+ /* see if added ones now match us */
+ for (i=0;i<changes->uid_added->len;i++) {
+ info = camel_folder_get_message_info(sub, changes->uid_added->pdata[i]);
+ if (info) {
+ camel_folder_search_set_folder(vf->search, sub);
+ match = camel_folder_search_match_expression(vf->search, vf->expression, info, ex);
+ if (match)
+ vinfo = vfolder_add_match(vf, sub, info);
+ }
+ }
+
+ /* check if changed ones still match */
+ for (i=0;i<changes->uid_changed->len;i++) {
+ info = camel_folder_get_message_info(sub, changes->uid_changed->pdata[i]);
+ vuid = g_strdup_printf("%p:%s", sub, (char *)changes->uid_changed->pdata[i]);
+ vinfo = (CamelVeeMessageInfo *)vee_get_message_info((CamelFolder *)vf, vuid);
+ if (info) {
+ camel_folder_search_set_folder(vf->search, sub);
+ match = camel_folder_search_match_expression(vf->search, vf->expression, info, ex);
+ if (vinfo) {
+ if (match)
+ vfolder_change_match(vf, vinfo, info);
+ else
+ vfolder_remove_match(vf, vinfo);
+ } else if (match)
+ vfolder_add_match(vf, sub, info);
+ } else if (vinfo)
+ vfolder_remove_match(vf, vinfo);
+
+ g_free(vuid);
+ }
+
+ camel_exception_free(ex);
+
+ /* mirror removes directly, if they used to match */
+ for (i=0;i<changes->uid_removed->len;i++) {
+ vuid = g_strdup_printf("%p:%s", sub, (char *)changes->uid_removed->pdata[i]);
+ vinfo = (CamelVeeMessageInfo *)vee_get_message_info((CamelFolder *)vf, vuid);
+ if (vinfo)
+ vfolder_remove_match(vf, vinfo);
+ g_free(vuid);
+ }
+ } else {
+#endif
+ ex = camel_exception_new();
+ vee_folder_build_folder(vf, sub, ex);
+ camel_exception_free(ex);
+#ifdef DYNAMIC
+ }
+#endif
+
+ /* cascade up, if we need to */
+ if (camel_folder_change_info_changed(vf->changes)) {
+ camel_object_trigger_event( CAMEL_OBJECT(vf), "folder_changed", vf->changes);
+ camel_folder_change_info_clear(vf->changes);
+ }
}
/* track flag changes in the summary */
@@ -209,24 +343,49 @@ static void
message_changed(CamelFolder *f, const char *uid, CamelVeeFolder *mf)
{
const CamelMessageInfo *info;
- CamelMessageInfo *vinfo;
- CamelFlag *flag;
+ CamelVeeMessageInfo *vinfo;
char *vuid;
+#ifdef DYNAMIC
+ gboolean match;
+ CamelException *ex;
+#endif
info = camel_folder_get_message_info(f, uid);
-
vuid = g_strdup_printf("%p:%s", f, uid);
- vinfo = (CamelMessageInfo *)vee_get_message_info((CamelFolder *)mf, vuid);
- if (info && vinfo) {
- vinfo->flags = info->flags;
- camel_flag_list_free(&vinfo->user_flags);
- flag = info->user_flags;
- while (flag) {
- camel_flag_set(&vinfo->user_flags, flag->name, TRUE);
- flag = flag->next;
- }
- camel_object_trigger_event( CAMEL_OBJECT(mf), "message_changed", vinfo->uid);
+ vinfo = (CamelVeeMessageInfo *)vee_get_message_info((CamelFolder *)mf, vuid);
+
+ /* see if this message now matches/doesn't match anymore */
+
+ /* Hmm, this might not work if the folder uses some weird search thing,
+ and/or can be slow since it wont use any index index, hmmm. */
+
+#ifdef DYNAMIC
+ camel_folder_search_set_folder(mf->search, f);
+ ex = camel_exception_new();
+ match = camel_folder_search_match_expression(mf->search, mf->expression, info, ex);
+ camel_exception_free(ex);
+ if (info) {
+ if (vinfo) {
+ if (match)
+ vfolder_change_match(mf, vinfo, info);
+ else
+ vfolder_remove_match(mf, vinfo);
+ } else if (match)
+ vfolder_add_match(mf, f, info);
+ } else if (vinfo)
+ vfolder_remove_match(mf, vinfo);
+#else
+ if (info && vinfo)
+ vfolder_change_match(mf, vinfo, info);
+#endif
+
+ /* cascade up, if required. This could probably be delayed,
+ but doesn't matter really, that is what freeze is for. */
+ if (camel_folder_change_info_changed(mf->changes)) {
+ camel_object_trigger_event( CAMEL_OBJECT(mf), "folder_changed", mf->changes);
+ camel_folder_change_info_clear(mf->changes);
}
+
g_free(vuid);
}
@@ -245,8 +404,18 @@ camel_vee_folder_add_folder(CamelVeeFolder *vf, CamelFolder *sub)
ex = camel_exception_new();
vee_folder_build_folder(vf, sub, ex);
camel_exception_free(ex);
- /* FIXME: should only raise follow-on event if the result changed */
- camel_object_trigger_event( CAMEL_OBJECT(vf), "folder_changed", GINT_TO_POINTER(0));
+
+ /* we'll assume the caller is going to update the whole list after they do this
+ this may or may not be the right thing to do, but it should be close enough */
+#if 0
+ if (camel_folder_change_info_changed(vf->changes)) {
+ camel_object_trigger_event( CAMEL_OBJECT(vf), "folder_changed", vf->changes);
+ camel_folder_change_info_clear(vf->changes);
+ }
+#else
+ camel_folder_change_info_clear(vf->changes);
+#endif
+
}
@@ -441,6 +610,11 @@ vee_folder_build(CamelVeeFolder *vf, CamelException *ex)
messages = g_ptr_array_new();
messages_uid = g_hash_table_new(g_str_hash, g_str_equal);
+ g_ptr_array_free(vf->messages, TRUE);
+ vf->messages = messages;
+ g_hash_table_destroy(vf->messages_uid);
+ vf->messages_uid = messages_uid;
+
node = p->folders;
while (node) {
GPtrArray *matches;
@@ -465,11 +639,6 @@ vee_folder_build(CamelVeeFolder *vf, CamelException *ex)
camel_folder_search_free(f, matches);
node = g_list_next(node);
}
-
- g_ptr_array_free(vf->messages, TRUE);
- vf->messages = messages;
- g_hash_table_destroy(vf->messages_uid);
- vf->messages_uid = messages_uid;
}
@@ -489,6 +658,7 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException
for (i=0;i<vf->messages->len;i++) {
CamelVeeMessageInfo *mi = g_ptr_array_index(vf->messages, i);
if (mi->folder == source) {
+ camel_folder_change_info_add_source(vf->changes, mi->info.uid);
g_hash_table_remove(vf->messages_uid, mi->info.uid);
g_ptr_array_remove_index_fast(vf->messages, i);
@@ -511,9 +681,13 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException
mi->folder = f;
g_ptr_array_add(messages, mi);
g_hash_table_insert(messages_uid, mi->info.uid, mi);
+
+ camel_folder_change_info_add_update(vf->changes, mi->info.uid);
}
}
camel_folder_search_free(f, matches);
+
+ camel_folder_change_info_build_diff(vf->changes);
}
diff --git a/camel/providers/vee/camel-vee-folder.h b/camel/providers/vee/camel-vee-folder.h
index 2263854912..8ea76a6227 100644
--- a/camel/providers/vee/camel-vee-folder.h
+++ b/camel/providers/vee/camel-vee-folder.h
@@ -24,6 +24,9 @@
#include <camel/camel-folder.h>
+/* try the dynamic update version */
+#define DYNAMIC
+
#define CAMEL_VEE_FOLDER(obj) CAMEL_CHECK_CAST (obj, camel_vee_folder_get_type (), CamelVeeFolder)
#define CAMEL_VEE_FOLDER_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_vee_folder_get_type (), CamelVeeFolderClass)
#define IS_CAMEL_VEE_FOLDER(obj) CAMEL_CHECK_TYPE (obj, camel_vee_folder_get_type ())
@@ -43,6 +46,10 @@ struct _CamelVeeFolder {
/* FIXME: Move this to a summary object??? */
GPtrArray *messages; /* message info's */
GHashTable *messages_uid;
+ CamelFolderChangeInfo *changes;
+#ifdef DYNAMIC
+ CamelFolderSearch *search;
+#endif
};
struct _CamelVeeFolderClass {