diff options
-rw-r--r-- | mail/ChangeLog | 39 | ||||
-rw-r--r-- | mail/mail-ops.c | 1 | ||||
-rw-r--r-- | mail/message-list.c | 229 | ||||
-rw-r--r-- | mail/message-list.h | 5 |
4 files changed, 173 insertions, 101 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog index bba6b71818..90325a1c56 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -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. diff --git a/mail/mail-ops.c b/mail/mail-ops.c index 77c27f7ee6..ee269f91b9 100644 --- a/mail/mail-ops.c +++ b/mail/mail-ops.c @@ -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); } diff --git a/mail/message-list.c b/mail/message-list.c index 3202860703..41477fc8c9 100644 --- a/mail/message-list.c +++ b/mail/message-list.c @@ -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); + + 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; - /* 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; + 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; } - child = ci->childs; - while (child) { - if (content_is_attachment(child)) { - return TRUE; - } - child = child->next; + 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; } - 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 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: + 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 *) 0; - + 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) diff --git a/mail/message-list.h b/mail/message-list.h index 99776948b3..400da181c7 100644 --- a/mail/message-list.h +++ b/mail/message-list.h @@ -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? */ |