Contents
Camel.FolderThread
CamelFolderThread is a helper processing object that can take a list of messages from a folder, and calculate the conversations contained in the messages, based on the NNTP and RFC822 headers, In-Reply-To and References.
The algorithm is based on one from Jamie Zawinksi, a developer on Netscape 3 Mail. The threading is quite robust and reliable (despite what some Mutt users have claimed over the years). Because it is also based on pre-calculated hashes from the CamelMessageInfo, it is also very fast.
Base object
The base object contains some internal working data and the tree pointer which points to a tree of nodes representing the conversation threads.
typedef struct _CamelFolderThread { guint32 refcount : 31; guint32 subject : 1; struct _CamelFolderThreadNode *tree; struct _EMemChunk *node_chunks; CamelFolder *folder; GPtrArray *summary; } CamelFolderThread; typedef struct _CamelFolderThreadNode { struct _CamelFolderThreadNode *next, *parent, *child; const CamelMessageInfo *message; char *root_subject; guint32 order:31; guint32 re:1; } CamelFolderThreadNode;
CamelFolderThreadNode is the important bit, where a description of the structure of the conversation is created. This can be used to directly build a model for use in a tree-view widget, or even used directly as a read-only model.
Methods
The new function creates the base object, threading all messages appropriately. the thread_subject option enables an additional algorithm which will fall-back to using "Re: " before subject lines to try to find conversation parts, when there are no other headers present.
CamelFolderThread *camel_folder_thread_messages_new(CamelFolder *folder, GPtrArray *uids, gboolean thread_subject);
The apply function can be used to re-calculate the thread tree. It is a bit more efficient than re-building a full tree, and it changes the algorithm slightly. If nodes with children are removed, those children are not re-sorted to their proper ordered location in the tree, they just remain where they are. This can prevent strange jumping as messages are deleted.
void camel_folder_thread_messages_apply(CamelFolderThread *thread, GPtrArray *uids);
Some reference counting:
void camel_folder_thread_messages_ref(CamelFolderThread *threads); void camel_folder_thread_messages_unref(CamelFolderThread *threads);
And a debug function which dumps the tree structure generated.
int camel_folder_threaded_messages_dump(CamelFolderThreadNode *c);
Notes
The disksummary branch code has its own independent implementation of these algorithms, one which works incrementally much more efficiently than these are.
Should reference the algorithm, from JWZ's site.