Camel.FolderThread
From Evolution
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.
