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.

Apps/Evolution/Camel.FolderThread (last edited 2013-08-08 22:50:10 by WilliamJonMcCann)