aboutsummaryrefslogtreecommitdiffstats
path: root/camel
diff options
context:
space:
mode:
Diffstat (limited to 'camel')
-rw-r--r--camel/ChangeLog15
-rw-r--r--camel/camel-folder-thread.c159
-rw-r--r--camel/camel-folder-thread.h3
-rw-r--r--camel/camel-folder.c28
-rw-r--r--camel/camel-folder.h2
5 files changed, 204 insertions, 3 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 65b72eb4de..5ba27929be 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,18 @@
+2001-03-17 Not Zed <NotZed@Ximian.com>
+
+ * camel-folder.c (camel_folder_ref_message_info): Implemented.
+ (ref_message_info): And default implementation.
+
+ * camel-folder.h: Added ref_message_info virtual method.
+
+2001-03-16 Not Zed <NotZed@Ximian.com>
+
+ * camel-folder-thread.c
+ (camel_folder_thread_messages_new_summary): New function to create
+ a thread tree from a supplied summary array.
+ (camel_folder_thread_messages_destroy): Handle thread trees
+ generated by the above function properly.
+
2001-03-16 Jeffrey Stedfast <fejj@ximian.com>
* camel-private.h: Same.
diff --git a/camel/camel-folder-thread.c b/camel/camel-folder-thread.c
index 3a1c4addde..53d381bead 100644
--- a/camel/camel-folder-thread.c
+++ b/camel/camel-folder-thread.c
@@ -432,6 +432,8 @@ static gint id_equal(void *a, void *b)
* Thread a (subset) of the messages in a folder. And sort the result
* in summary order.
*
+ * This function is probably to be removed soon.
+ *
* Return value: A CamelFolderThread contianing a tree of CamelFolderThreadNode's
* which represent the threaded structure of the messages.
**/
@@ -591,6 +593,157 @@ camel_folder_thread_messages_new(CamelFolder *folder, GPtrArray *uids)
}
/**
+ * camel_folder_thread_messages_new_summary:
+ * @summary: Array of CamelMessageInfo's to thread.
+ *
+ * Thread a list of MessageInfo's. The summary must remain valid for the
+ * life of the CamelFolderThread created by this function, and it is upto the
+ * caller to ensure this.
+ *
+ * Return value: A CamelFolderThread contianing a tree of CamelFolderThreadNode's
+ * which represent the threaded structure of the messages.
+ **/
+CamelFolderThread *
+camel_folder_thread_messages_new_summary(GPtrArray *summary)
+{
+ GHashTable *id_table, *no_id_table;
+ int i;
+ CamelFolderThreadNode *c, *child, *head;
+ CamelFolderThread *thread;
+
+#ifdef TIMEIT
+ struct timeval start, end;
+ unsigned long diff;
+
+ gettimeofday(&start, NULL);
+#endif
+
+ thread = g_malloc(sizeof(*thread));
+ thread->tree = NULL;
+ thread->node_chunks = e_memchunk_new(32, sizeof(CamelFolderThreadNode));
+ thread->folder = NULL;
+ thread->summary = NULL;
+
+ id_table = g_hash_table_new((GHashFunc)id_hash, (GCompareFunc)id_equal);
+ no_id_table = g_hash_table_new(NULL, NULL);
+ for (i=0;i<summary->len;i++) {
+ CamelMessageInfo *mi = summary->pdata[i];
+
+ if (mi->message_id.id.id) {
+ c = g_hash_table_lookup(id_table, &mi->message_id);
+ /* check for duplicate messages */
+ if (c) {
+ /* if duplicate, just make out it is a no-id message, but try and insert it
+ into the right spot in the tree */
+ d(printf("doing: (duplicate message id)\n"));
+ c = e_memchunk_alloc0(thread->node_chunks);
+ g_hash_table_insert(no_id_table, (void *)mi, c);
+ } else {
+ d(printf("doing : %08x%08x (%s)\n", mi->message_id.id.part.hi, mi->message_id.id.part.lo, camel_message_info_subject(mi)));
+ c = e_memchunk_alloc0(thread->node_chunks);
+ g_hash_table_insert(id_table, (void *)&mi->message_id, c);
+ }
+ } else {
+ d(printf("doing : (no message id)\n"));
+ c = e_memchunk_alloc0(thread->node_chunks);
+ g_hash_table_insert(no_id_table, (void *)mi, c);
+ }
+
+ c->message = mi;
+ c->order = i;
+ child = c;
+ if (mi->references) {
+ int j;
+
+ d(printf("references:\n"));
+ for (j=0;j<mi->references->size;j++) {
+ /* should never be empty, but just incase */
+ if (mi->references->references[j].id.id == 0)
+ continue;
+
+ c = g_hash_table_lookup(id_table, &mi->references->references[j]);
+ if (c == NULL) {
+ d(printf("not found\n"));
+ c = e_memchunk_alloc0(thread->node_chunks);
+ g_hash_table_insert(id_table, &mi->references->references[j], c);
+ }
+ if (c!=child)
+ container_parent_child(c, child);
+ child = c;
+ }
+ }
+ }
+
+ d(printf("\n\n"));
+ /* build a list of root messages (no parent) */
+ head = NULL;
+ g_hash_table_foreach(id_table, hashloop, &head);
+ g_hash_table_foreach(no_id_table, hashloop, &head);
+
+ g_hash_table_destroy(id_table);
+ g_hash_table_destroy(no_id_table);
+
+ /* remove empty parent nodes */
+ prune_empty(thread, &head);
+
+ /* find any siblings which missed out */
+ group_root_set(thread, &head);
+
+#if 0
+ printf("finished\n");
+ i = camel_folder_thread_messages_dump(head);
+ printf("%d count, %d items in tree\n", uids->len, i);
+#endif
+
+ sort_thread(&head);
+
+ /* remove any phantom nodes, this could possibly be put in group_root_set()? */
+ c = (CamelFolderThreadNode *)&head;
+ while (c && c->next) {
+ CamelFolderThreadNode *scan, *newtop;
+
+ child = c->next;
+ if (child->message == NULL) {
+ newtop = child->child;
+ /* unlink pseudo node */
+ c->next = newtop;
+
+ /* link its siblings onto the end of its children */
+ scan = (CamelFolderThreadNode *)&newtop->child;
+ while (scan->next)
+ scan = scan->next;
+ scan->next = newtop->next;
+ /* and link the now 'real' node into the list */
+ newtop->next = child->next;
+ c = newtop;
+ e_memchunk_free(thread->node_chunks, child);
+ } else {
+ c = child;
+ }
+ }
+
+ /* this is only debug assertion stuff */
+ c = (CamelFolderThreadNode *)&head;
+ while (c->next) {
+ c = c->next;
+ if (c->message == NULL)
+ g_warning("threading missed removing a pseudo node: %s\n", c->root_subject);
+ }
+
+ thread->tree = head;
+
+#ifdef TIMEIT
+ gettimeofday(&end, NULL);
+ diff = end.tv_sec * 1000 + end.tv_usec/1000;
+ diff -= start.tv_sec * 1000 + start.tv_usec/1000;
+ printf("Message threading %d messages took %ld.%03ld seconds\n",
+ summary->len, diff / 1000, diff % 1000);
+#endif
+
+ return thread;
+}
+
+/**
* camel_folder_thread_messages_destroy:
* @thread:
*
@@ -599,8 +752,10 @@ camel_folder_thread_messages_new(CamelFolder *folder, GPtrArray *uids)
void
camel_folder_thread_messages_destroy(CamelFolderThread *thread)
{
- camel_folder_free_summary(thread->folder, thread->summary);
- camel_object_unref((CamelObject *)thread->folder);
+ if (thread->folder) {
+ camel_folder_free_summary(thread->folder, thread->summary);
+ camel_object_unref((CamelObject *)thread->folder);
+ }
e_memchunk_destroy(thread->node_chunks);
g_free(thread);
}
diff --git a/camel/camel-folder-thread.h b/camel/camel-folder-thread.h
index 843ade0b56..d75fc35c54 100644
--- a/camel/camel-folder-thread.h
+++ b/camel/camel-folder-thread.h
@@ -43,6 +43,9 @@ typedef struct CamelFolderThread {
} CamelFolderThread;
CamelFolderThread *camel_folder_thread_messages_new(CamelFolder *folder, GPtrArray *uids);
+
+/* new improved interface (believe it or not!) */
+CamelFolderThread *camel_folder_thread_messages_new_summary(GPtrArray *summary);
/*
void camel_folder_thread_messages_add(CamelFolderThread *threads, CamelFolder *folder, GPtrArray *uids);
void camel_folder_thread_messages_remove(CamelFolderThread *threads, CamelFolder *folder, GPtrArray *uids);
diff --git a/camel/camel-folder.c b/camel/camel-folder.c
index b3d50e893d..b3a86c0f4f 100644
--- a/camel/camel-folder.c
+++ b/camel/camel-folder.c
@@ -35,7 +35,7 @@
#include "camel-private.h"
-#define d(x) x
+#define d(x)
static CamelObjectClass *parent_class = NULL;
@@ -87,6 +87,7 @@ static CamelMimeMessage *get_message (CamelFolder *folder,
static CamelMessageInfo *get_message_info (CamelFolder *folder, const char *uid);
static void free_message_info (CamelFolder *folder, CamelMessageInfo *info);
+static void ref_message_info (CamelFolder *folder, CamelMessageInfo *info);
static GPtrArray *search_by_expression (CamelFolder *folder,
const char *exp,
@@ -145,6 +146,7 @@ camel_folder_class_init (CamelFolderClass *camel_folder_class)
camel_folder_class->search_by_expression = search_by_expression;
camel_folder_class->search_free = search_free;
camel_folder_class->get_message_info = get_message_info;
+ camel_folder_class->ref_message_info = ref_message_info;
camel_folder_class->free_message_info = free_message_info;
camel_folder_class->copy_message_to = copy_message_to;
camel_folder_class->move_message_to = move_message_to;
@@ -801,6 +803,30 @@ camel_folder_free_message_info(CamelFolder *folder, CamelMessageInfo *info)
CF_CLASS (folder)->free_message_info(folder, info);
}
+static void
+ref_message_info (CamelFolder *folder, CamelMessageInfo *info)
+{
+ g_return_if_fail(folder->summary != NULL);
+
+ camel_folder_summary_info_ref(folder->summary, info);
+}
+
+/**
+ * camel_folder_ref_message_info:
+ * @folder:
+ * @info:
+ *
+ * Ref a CamelMessageInfo, previously obtained with get_message_info().
+ **/
+void
+camel_folder_ref_message_info(CamelFolder *folder, CamelMessageInfo *info)
+{
+ g_return_if_fail(CAMEL_IS_FOLDER (folder));
+ g_return_if_fail(info != NULL);
+
+ CF_CLASS (folder)->ref_message_info(folder, info);
+}
+
/* TODO: is this function required anyway? */
gboolean
camel_folder_has_summary_capability (CamelFolder *folder)
diff --git a/camel/camel-folder.h b/camel/camel-folder.h
index 53fa626e85..ab3483d1da 100644
--- a/camel/camel-folder.h
+++ b/camel/camel-folder.h
@@ -137,6 +137,7 @@ typedef struct {
void (*search_free) (CamelFolder *folder, GPtrArray *result);
CamelMessageInfo * (*get_message_info) (CamelFolder *, const char *uid);
+ void (*ref_message_info) (CamelFolder *, CamelMessageInfo *);
void (*free_message_info) (CamelFolder *, CamelMessageInfo *);
void (*copy_message_to) (CamelFolder *source,
@@ -252,6 +253,7 @@ void camel_folder_search_free (CamelFolder *folder, GPtrArray *);
/* summary info */
CamelMessageInfo *camel_folder_get_message_info (CamelFolder *folder, const char *uid);
void camel_folder_free_message_info (CamelFolder *folder, CamelMessageInfo *info);
+void camel_folder_ref_message_info (CamelFolder *folder, CamelMessageInfo *info);
void camel_folder_copy_message_to (CamelFolder *source,
const char *uid,