Set threaded view before setting the folder (cleanup some flash ons

2000-11-30  Not Zed  <NotZed@HelixCode.com>

	* mail-ops.c (cleanup_load_folder): Set threaded view before
	setting the folder (cleanup some flash ons tartup).

	* message-list.c (message_list_init): Initialise a mempool for uid
	string storage.
	(new_id_from_uid): Added messagelist arg, allocate strings from
	uid_pool.
	(new_id_from_subject): Same.  Fixed all callers.
	(remove_node_diff): Dont free uid here.
	(build_flat_diff): Nor here.
	(clear_tree): Flush the mempool, rather than freeing the id's
	directly.
	(free_tree_ids): Removed, no longer required.
	(free_tree_ids): Likewise.
	(message_list_init): Dont connect to the table destroy signal
	anymore to free the uid table.
	(message_list_destroy): Free the uid pool here.
	(*): Use accessors for messageid stuff.
	(content_is_attachment): Removed, no longer required.
	(ml_tree_value_at): Get the attachment flag directly from the
	summary.
	(ml_tree_value_at): For 'fake' nodes, try and do something better
	than "?" for from, to, and size.
	(subtree_size): New function, add up the total size of a subtree.
	(subtree_earliest): Get the earliest date from a subtree.
	(ml_tree_value_at): Return earliest date sent/received for fake
	nodes.
	(ml_tree_value_at): Return something to mark a fake subject line
	as a fake subject, although i dont know, i guess this buggers up
	sorting ...
	(subtree_size): Check the info node is still there.
	(subtree_earliest): Same here.
	(subtree_unread): And here.  The info node might vanish if the
	folder has changed/is changing and we try and redraw stuff while
	its doing it.
	(message_list_drag_data_get): Use accessors.

svn path=/trunk/; revision=6732
This commit is contained in:
Not Zed
2000-11-30 11:32:50 +00:00
committed by Michael Zucci
parent 1fbfdbd43e
commit 9b49b3e25a
4 changed files with 176 additions and 104 deletions

View File

@ -1,3 +1,42 @@
2000-11-30 Not Zed <NotZed@HelixCode.com>
* mail-ops.c (cleanup_load_folder): Set threaded view before
setting the folder (cleanup some flash ons tartup).
* message-list.c (message_list_init): Initialise a mempool for uid
string storage.
(new_id_from_uid): Added messagelist arg, allocate strings from
uid_pool.
(new_id_from_subject): Same. Fixed all callers.
(remove_node_diff): Dont free uid here.
(build_flat_diff): Nor here.
(clear_tree): Flush the mempool, rather than freeing the id's
directly.
(free_tree_ids): Removed, no longer required.
(free_tree_ids): Likewise.
(message_list_init): Dont connect to the table destroy signal
anymore to free the uid table.
(message_list_destroy): Free the uid pool here.
(*): Use accessors for messageid stuff.
(content_is_attachment): Removed, no longer required.
(ml_tree_value_at): Get the attachment flag directly from the
summary.
(ml_tree_value_at): For 'fake' nodes, try and do something better
than "?" for from, to, and size.
(subtree_size): New function, add up the total size of a subtree.
(subtree_earliest): Get the earliest date from a subtree.
(ml_tree_value_at): Return earliest date sent/received for fake
nodes.
(ml_tree_value_at): Return something to mark a fake subject line
as a fake subject, although i dont know, i guess this buggers up
sorting ...
(subtree_size): Check the info node is still there.
(subtree_earliest): Same here.
(subtree_unread): And here. The info node might vanish if the
folder has changed/is changing and we try and redraw stuff while
its doing it.
(message_list_drag_data_get): Use accessors.
2000-11-29 Jeffrey Stedfast <fejj@helixcode.com>
* message-list.c (message_list_drag_data_get): Implement.

View File

@ -1776,6 +1776,7 @@ cleanup_load_folder (gpointer in_data, gpointer op_data, CamelException *ex)
camel_folder_has_search_capability (input->
fb->
folder));
message_list_set_threaded(input->fb->message_list, mail_config_thread_list());
message_list_set_folder (input->fb->message_list, input->fb->folder);
}

View File

@ -18,6 +18,7 @@
#include <camel/camel-folder.h>
#include <e-util/ename/e-name-western.h>
#include <camel/camel-folder-thread.h>
#include <e-util/e-memory.h>
#include <string.h>
#include <ctype.h>
@ -95,7 +96,6 @@ static POA_GNOME_Evolution_MessageList__vepv evolution_message_list_vepv;
static void on_cursor_change_cmd (ETableScrolled *table, int row, gpointer user_data);
static gint on_click (ETableScrolled *table, gint row, gint col, GdkEvent *event, MessageList *list);
static char *filter_date (const void *data);
static void free_tree_ids (ETreeModel *etm);
static void save_tree_state(MessageList *ml);
@ -368,7 +368,7 @@ message_list_select (MessageList *message_list, int base_row,
info = get_message_info (message_list, mrow);
if (info && (info->flags & mask) == flags) {
e_table_scrolled_set_cursor_row (ets, vrow);
gtk_signal_emit(GTK_OBJECT (message_list), message_list_signals [MESSAGE_SELECTED], info->uid);
gtk_signal_emit(GTK_OBJECT (message_list), message_list_signals [MESSAGE_SELECTED], camel_message_info_uid(info));
return;
}
vrow += direction;
@ -397,7 +397,7 @@ message_list_drag_data_get (ETable *table,
case DND_TARGET_LIST_TYPE_URI:
/* drag & drop into nautilus */
mktemp (dirname);
filename = g_strdup_printf ("%s/%s.eml", dirname, minfo->subject);
filename = g_strdup_printf ("%s/%s.eml", dirname, camel_message_info_subject(minfo));
uids = g_ptr_array_new ();
g_ptr_array_add (uids, g_strdup (mlist->cursor_uid));
@ -611,8 +611,8 @@ subtree_unread(MessageList *ml, ETreePath *node)
uid = e_tree_model_node_get_data((ETreeModel *)ml->table_model, node);
if (uid == NULL) {
g_warning("I got a NULL uid at node %p", node);
} else if (id_is_uid(uid)) {
info = camel_folder_get_message_info(ml->folder, id_uid(uid));
} else if (id_is_uid(uid)
&& (info = camel_folder_get_message_info(ml->folder, id_uid(uid)))) {
if (!(info->flags & CAMEL_MESSAGE_SEEN))
return TRUE;
}
@ -624,33 +624,61 @@ subtree_unread(MessageList *ml, ETreePath *node)
return FALSE;
}
static gboolean
content_is_attachment(CamelMessageContentInfo *ci)
static int
subtree_size(MessageList *ml, ETreePath *node)
{
CamelMessageContentInfo *child;
const CamelMessageInfo *info;
char *uid;
int size = 0;
/* no info about content */
if (ci == NULL)
return FALSE;
while (node) {
ETreePath *child;
uid = e_tree_model_node_get_data((ETreeModel *)ml->table_model, node);
if (uid == NULL) {
g_warning("I got a NULL uid at node %p", node);
} else if (id_is_uid(uid)
&& (info = camel_folder_get_message_info(ml->folder, id_uid(uid)))) {
size += info->size;
}
if ((child = e_tree_model_node_get_first_child (E_TREE_MODEL (ml->table_model), node)))
size += subtree_size(ml, child);
/* we assume multipart/mixed is an attachment always
other multipart / * is only an attachment if it contains multipart/mixed's, or
non-text parts */
if (header_content_type_is(ci->type, "multipart", "*")) {
if (header_content_type_is(ci->type, "multipart", "mixed")) {
return TRUE;
}
child = ci->childs;
while (child) {
if (content_is_attachment(child)) {
return TRUE;
}
child = child->next;
}
return FALSE;
} else {
return !header_content_type_is(ci->type, "text", "*");
node = e_tree_model_node_get_next (E_TREE_MODEL (ml->table_model), node);
}
return size;
}
static time_t
subtree_earliest(MessageList *ml, ETreePath *node, int sent)
{
const CamelMessageInfo *info;
char *uid;
time_t earliest = 0, date;
while (node) {
ETreePath *child;
uid = e_tree_model_node_get_data((ETreeModel *)ml->table_model, node);
if (uid == NULL) {
g_warning("I got a NULL uid at node %p", node);
} else if (id_is_uid(uid)
&& (info = camel_folder_get_message_info(ml->folder, id_uid(uid)))) {
if (sent)
date = info->date_sent;
else
date = info->date_received;
if (earliest == 0 || date < earliest)
earliest = date;
}
if ((child = e_tree_model_node_get_first_child (E_TREE_MODEL (ml->table_model), node))) {
date = subtree_earliest(ml, child, sent);
if (earliest == 0 || (date != 0 && date < earliest))
earliest = date;
}
node = e_tree_model_node_get_next (E_TREE_MODEL (ml->table_model), node);
}
return earliest;
}
static void *
@ -660,6 +688,13 @@ ml_tree_value_at (ETreeModel *etm, ETreePath *path, int col, void *model_data)
const CamelMessageInfo *msg_info;
static char buffer [10];
char *uid;
static char *saved;
/* simlated(tm) static dynamic memory (sigh) */
if (saved) {
g_free(saved);
saved = 0;
}
/* retrieve the message information array */
uid = e_tree_model_node_get_data (etm, path);
@ -687,10 +722,7 @@ ml_tree_value_at (ETreeModel *etm, ETreePath *path, int col, void *model_data)
return GINT_TO_POINTER (0);
case COL_FLAGGED:
if (msg_info->flags & CAMEL_MESSAGE_FLAGGED)
return GINT_TO_POINTER (1);
else
return GINT_TO_POINTER (0);
return (void *)((msg_info->flags & CAMEL_MESSAGE_FLAGGED) != 0);
case COL_SCORE:
{
@ -705,22 +737,13 @@ ml_tree_value_at (ETreeModel *etm, ETreePath *path, int col, void *model_data)
}
case COL_ATTACHMENT:
if (content_is_attachment(msg_info->content))
return (void *)1;
else
return (void *)0;
return (void *)((msg_info->flags & CAMEL_MESSAGE_ATTACHMENTS) != 0);
case COL_FROM:
if (msg_info->from)
return msg_info->from;
else
return "";
return (char *)camel_message_info_from(msg_info);
case COL_SUBJECT:
if (msg_info->subject)
return msg_info->subject;
else
return "";
return (char *)camel_message_info_subject(msg_info);
case COL_SENT:
return GINT_TO_POINTER (msg_info->date_sent);
@ -729,20 +752,14 @@ ml_tree_value_at (ETreeModel *etm, ETreePath *path, int col, void *model_data)
return GINT_TO_POINTER (msg_info->date_received);
case COL_TO:
if (msg_info->to)
return msg_info->to;
else
return "";
return (char *)camel_message_info_to(msg_info);
case COL_SIZE:
sprintf (buffer, "%d", msg_info->size);
return buffer;
case COL_DELETED:
if (msg_info->flags & CAMEL_MESSAGE_DELETED)
return GINT_TO_POINTER (1);
else
return GINT_TO_POINTER (0);
return (void *)((msg_info->flags & CAMEL_MESSAGE_DELETED) != 0);
case COL_UNREAD:
return GINT_TO_POINTER (!(msg_info->flags & CAMEL_MESSAGE_SEEN));
@ -771,25 +788,59 @@ ml_tree_value_at (ETreeModel *etm, ETreePath *path, int col, void *model_data)
case COL_UNREAD:
/* this value should probably be cached, as it could take a bit
of processing to evaluate all the time */
return (void *)subtree_unread(message_list,
e_tree_model_node_get_first_child(etm, path));
return (void *)subtree_unread(message_list, e_tree_model_node_get_first_child(etm, path));
case COL_MESSAGE_STATUS:
case COL_FLAGGED:
case COL_SCORE:
case COL_ATTACHMENT:
case COL_DELETED:
case COL_COLOUR:
case COL_SENT:
case COL_RECEIVED:
return (void *) 0;
case COL_SENT:
return (void *)subtree_earliest(message_list, e_tree_model_node_get_first_child(etm, path), TRUE);
case COL_RECEIVED:
return (void *)subtree_earliest(message_list, e_tree_model_node_get_first_child(etm, path), FALSE);
case COL_SUBJECT:
return id_subject(uid);
saved = g_strdup_printf(_("[ %s ]"), id_subject(uid));
return saved;
case COL_FROM:
case COL_TO:
case COL_FROM: {
ETreePath *child;
/* the first child should always exist/etc */
if ( (child = e_tree_model_node_get_first_child(etm, path))
&& (uid = e_tree_model_node_get_data (etm, child))
&& id_is_uid(uid)
&& (msg_info = camel_folder_get_message_info (message_list->folder, id_uid(uid))) ) {
/* well, we could scan more children, build up a (more accurate) list, but this should do ok */
saved = g_strdup_printf(_("%s, et al."), camel_message_info_from(msg_info));
} else {
return _("<unknown>");
}
return saved;
}
case COL_TO: {
ETreePath *child;
/* the first child should always exist/etc */
if ( (child = e_tree_model_node_get_first_child(etm, path))
&& (uid = e_tree_model_node_get_data (etm, child))
&& id_is_uid(uid)
&& (msg_info = camel_folder_get_message_info (message_list->folder, id_uid(uid))) ) {
/* well, we could scan more children, build up a (more accurate) list, but this should do ok */
saved = g_strdup_printf(_("%s, et al."), camel_message_info_to(msg_info));
} else {
return _("<unknown>");
}
return saved;
}
case COL_SIZE:
return "?";
sprintf(buffer, "%d", subtree_size(message_list, e_tree_model_node_get_first_child(etm, path)));
return buffer;
}
g_assert_not_reached ();
@ -1008,8 +1059,6 @@ message_list_init (GtkObject *object)
ml_tree_is_cell_editable,
message_list);
e_tree_model_root_node_set_visible ((ETreeModel *)message_list->table_model, FALSE);
gtk_signal_connect (GTK_OBJECT (message_list->table_model), "destroy",
(GtkSignalFunc) free_tree_ids, NULL);
/*
* The etable
@ -1057,6 +1106,7 @@ message_list_init (GtkObject *object)
gtk_object_sink (GTK_OBJECT (message_list->etable));
message_list->uid_rowmap = g_hash_table_new (g_str_hash, g_str_equal);
message_list->uid_pool = e_mempool_new(1024, 512, E_MEMPOOL_ALIGN_BYTE);
}
static void
@ -1073,6 +1123,7 @@ message_list_destroy (GtkObject *object)
gtk_object_unref (GTK_OBJECT (message_list->etable));
g_hash_table_destroy (message_list->uid_rowmap);
e_mempool_destroy(message_list->uid_pool);
if (message_list->idle_id != 0)
g_source_remove(message_list->idle_id);
@ -1222,10 +1273,10 @@ clear_tree (MessageList *ml)
/* we also reset the uid_rowmap since it is no longer useful/valid anyway */
g_hash_table_destroy (ml->uid_rowmap);
ml->uid_rowmap = g_hash_table_new(g_str_hash, g_str_equal);
free_tree_ids(etm);
e_mempool_flush(ml->uid_pool, TRUE);
if (ml->tree_root) {
/* FIXME: Freeze here, buddy. */
/* we should be frozen already */
e_tree_model_node_remove (etm, ml->tree_root);
}
@ -1389,26 +1440,26 @@ build_tree (MessageList *ml, CamelFolderThread *thread, CamelFolderChangeInfo *c
}
static char *
new_id_from_uid(const char *uid)
new_id_from_uid(MessageList *ml, const char *uid)
{
char *res;
int len;
len = strlen(uid)+2;
res = g_malloc(len);
res = e_mempool_alloc(ml->uid_pool, len);
res[0] = 'u';
strcpy(res+1, uid);
return res;
}
static char *
new_id_from_subject(const char *subject)
new_id_from_subject(MessageList *ml, const char *subject)
{
char *res;
int len;
len = strlen(subject)+2;
res = g_malloc(len);
res = e_mempool_alloc(ml->uid_pool, len);
res[0] = 's';
strcpy(res+1, subject);
return res;
@ -1428,7 +1479,7 @@ build_subtree (MessageList *ml, ETreePath *parent, CamelFolderThreadNode *c, int
while (c) {
if (c->message) {
id = new_id_from_uid(c->message->uid);
id = new_id_from_uid(ml, camel_message_info_uid(c->message));
g_hash_table_insert(ml->uid_rowmap, id_uid(id), GINT_TO_POINTER ((*row)++));
if (c->child) {
if (c->message) {
@ -1439,7 +1490,7 @@ build_subtree (MessageList *ml, ETreePath *parent, CamelFolderThreadNode *c, int
expanded = TRUE;
}
} else {
id = new_id_from_subject(c->root_subject);
id = new_id_from_subject(ml, c->root_subject);
if (c->child) {
expanded = !g_hash_table_lookup(expanded_nodes, id) != 0;
}
@ -1465,7 +1516,7 @@ node_equal(ETreeModel *etm, ETreePath *ap, CamelFolderThreadNode *bp)
uid = e_tree_model_node_get_data(etm, ap);
if (id_is_uid(uid)) {
if (bp->message && strcmp(id_uid(uid), bp->message->uid)==0)
if (bp->message && strcmp(id_uid(uid), camel_message_info_uid(bp->message))==0)
return 1;
} else if (id_is_subject(uid)) {
if (bp->message == NULL && strcmp(id_subject(uid), bp->root_subject) == 0)
@ -1484,7 +1535,7 @@ add_node_diff(MessageList *ml, ETreePath *parent, ETreePath *path, CamelFolderTh
int expanded = FALSE;
if (c->message) {
id = new_id_from_uid(c->message->uid);
id = new_id_from_uid(ml, camel_message_info_uid(c->message));
/* need to remove the id first, as GHashTable' wont replace the key pointer for us */
g_hash_table_remove(ml->uid_rowmap, id_uid(id));
g_hash_table_insert(ml->uid_rowmap, id_uid(id), GINT_TO_POINTER (*row));
@ -1497,7 +1548,7 @@ add_node_diff(MessageList *ml, ETreePath *parent, ETreePath *path, CamelFolderTh
expanded = TRUE;
}
} else {
id = new_id_from_subject(c->root_subject);
id = new_id_from_subject(ml, c->root_subject);
if (c->child) {
expanded = !g_hash_table_lookup(expanded_nodes, id) != 0;
}
@ -1541,7 +1592,6 @@ remove_node_diff(MessageList *ml, ETreePath *node, int depth)
t(printf("removing rowid map entry: %s\n", id_uid(uid)));
g_hash_table_remove(ml->uid_rowmap, id_uid(uid));
}
g_free(uid);
e_tree_model_node_set_data(etm, node, NULL);
/* and only at the toplevel, remove the node (etree should optimise this remove somewhat) */
@ -1584,12 +1634,12 @@ build_subtree_diff(MessageList *ml, ETreePath *parent, ETreePath *path, CamelFol
int oldrow;
/* if this is a message row, check/update the row id map */
if (g_hash_table_lookup_extended(ml->uid_rowmap, bp->message->uid, (void *)&olduid, (void *)&oldrow)) {
if (g_hash_table_lookup_extended(ml->uid_rowmap, camel_message_info_uid(bp->message), (void *)&olduid, (void *)&oldrow)) {
if (oldrow != (*row)) {
g_hash_table_insert(ml->uid_rowmap, olduid, (void *)(*row));
}
} else {
g_warning("Cannot find uid %s in table?", bp->message->uid);
g_warning("Cannot find uid %s in table?", camel_message_info_uid(bp->message));
/*g_assert_not_reached();*/
}
}
@ -1661,22 +1711,6 @@ build_subtree_diff(MessageList *ml, ETreePath *parent, ETreePath *path, CamelFol
}
}
static gboolean
free_ids_cb (ETreeModel *model, ETreePath *node, gpointer data)
{
g_free (e_tree_model_node_get_data (model, node));
return FALSE;
}
static void
free_tree_ids (ETreeModel *etm)
{
ETreePath *root = e_tree_model_get_root (etm);
if (root)
e_tree_model_node_traverse(etm, root, free_ids_cb, NULL);
}
static void build_flat_diff(MessageList *ml, CamelFolderChangeInfo *changes);
static void
@ -1701,7 +1735,7 @@ build_flat (MessageList *ml, GPtrArray *uids, CamelFolderChangeInfo *changes)
e_tree_model_freeze(tree);
clear_tree (ml);
for (i = 0; i < uids->len; i++) {
uid = new_id_from_uid(uids->pdata[i]);
uid = new_id_from_uid(ml, uids->pdata[i]);
node = e_tree_model_node_insert (tree, ml->tree_root, -1, uid);
g_hash_table_insert (ml->uid_rowmap, id_uid(uid), GINT_TO_POINTER (i));
}
@ -1787,7 +1821,6 @@ build_flat_diff(MessageList *ml, CamelFolderChangeInfo *changes)
if (uid && id_is_uid(uid) && !strcmp(id_uid(uid), changes->uid_removed->pdata[i])) {
g_hash_table_remove(ml->uid_rowmap, olduid);
e_tree_model_node_remove((ETreeModel *)ml->table_model, node);
g_free(uid);
d(printf(" - removed\n"));
} else {
d(printf(" - is this the right uid, it doesn't match my map?\n"));
@ -1803,7 +1836,7 @@ build_flat_diff(MessageList *ml, CamelFolderChangeInfo *changes)
d(printf("Adding messages to view:\n"));
for (i=0;i<changes->uid_added->len;i++) {
d(printf(" %s\n", (char *)changes->uid_added->pdata[i]));
uid = new_id_from_uid(changes->uid_added->pdata[i]);
uid = new_id_from_uid(ml, changes->uid_added->pdata[i]);
node = e_tree_model_node_insert((ETreeModel *)ml->table_model, ml->tree_root, row, uid);
g_hash_table_insert(ml->uid_rowmap, id_uid(uid), GINT_TO_POINTER (row));
row++;
@ -1990,7 +2023,7 @@ on_click (ETableScrolled *table, gint row, gint col, GdkEvent *event, MessageLis
return FALSE;
}
camel_folder_set_message_flags(list->folder, info->uid, flag, ~info->flags);
camel_folder_set_message_flags(list->folder, camel_message_info_uid(info), flag, ~info->flags);
mail_tool_camel_lock_down();
@ -2043,7 +2076,6 @@ message_list_set_threaded(MessageList *ml, gboolean threaded)
if (ml->threaded ^ threaded) {
ml->threaded = threaded;
/*clear_tree(ml);*/
mail_do_regenerate_messagelist(ml, ml->search, NULL);
}
}
@ -2058,7 +2090,6 @@ message_list_set_search(MessageList *ml, const char *search)
if (search != NULL && ml->search !=NULL && strcmp(search, ml->search)==0)
return;
/*clear_tree(ml);*/
mail_do_regenerate_messagelist(ml, search, NULL);
}
@ -2183,7 +2214,7 @@ mail_do_regenerate_messagelist (MessageList *list, const gchar *search, CamelFol
{
regenerate_messagelist_input_t *input;
/* This gets called on empty folder-browsers by the bonobo ui
/* This may get called on empty folder-browsers by the bonobo ui
* callback for threaded view.
*/
if (!list->folder)

View File

@ -55,8 +55,9 @@ struct _MessageList {
CamelFolder *folder;
GHashTable *uid_rowmap; /* key is the uid, value is the row number.
Note: The key string is owned by table_model */
Note: The key string is owned by table_model (in uid_pool) */
struct _EMemPool *uid_pool; /* mempool to hold uid strings */
char *search; /* current search string */
gboolean threaded; /* are we displaying threaded view? */