diff options
Diffstat (limited to 'mail/message-list.c')
-rw-r--r-- | mail/message-list.c | 387 |
1 files changed, 241 insertions, 146 deletions
diff --git a/mail/message-list.c b/mail/message-list.c index cdec9b2339..51ca345953 100644 --- a/mail/message-list.c +++ b/mail/message-list.c @@ -9,6 +9,7 @@ * * (C) 2000 Helix Code, Inc. */ + #include <config.h> #include <gnome.h> #include <bonobo/bonobo-main.h> @@ -19,15 +20,17 @@ #include <camel/camel-folder.h> #include "message-list.h" #include "message-thread.h" +#include "mail-threads.h" +#include "mail-tools.h" +#include "mail-ops.h" #include "mail-config.h" +#include "mail-vfolder.h" +#include "mail-autofilter.h" #include "mail.h" #include "Mail.h" #include "widgets/e-table/e-table-header-item.h" #include "widgets/e-table/e-table-item.h" -#include "mail-vfolder.h" -#include "mail-autofilter.h" - #include "art/mail-new.xpm" #include "art/mail-read.xpm" #include "art/mail-replied.xpm" @@ -107,6 +110,44 @@ get_message_info (MessageList *message_list, int row) return camel_folder_get_message_info (message_list->folder, uid); } +/* Gets the uid of the message displayed at a given view row */ +static const char * +get_message_uid (MessageList *message_list, int row) +{ + ETreeModel *model = (ETreeModel *)message_list->table_model; + ETreePath *node; + const char *uid; + + if (row >= e_table_model_row_count (message_list->table_model)) + return NULL; + + node = e_tree_model_node_at_row (model, row); + g_return_val_if_fail (node != NULL, NULL); + uid = e_tree_model_node_get_data (model, node); + + if (strncmp (uid, "uid:", 4) != 0) + return NULL; + uid += 4; + + return uid; +} + +static gint +mark_msg_seen (gpointer data) +{ + MessageList *ml = data; + GPtrArray *uids; + + if (!ml->cursor_uid) + return FALSE; + + uids = g_ptr_array_new (); + g_ptr_array_add (uids, g_strdup (ml->cursor_uid)); + mail_do_flag_messages (ml->folder, uids, FALSE, + CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); + return FALSE; +} + /** * message_list_select: * @message_list: a MessageList @@ -138,66 +179,30 @@ message_list_select (MessageList *message_list, int base_row, last = e_table_model_row_count (message_list->table_model); vrow = e_table_model_to_view_row (ets->table, base_row); + + /* We don't know whether to use < or > due to "direction" */ while (vrow != last) { - vrow += direction; mrow = e_table_view_to_model_row (ets->table, vrow); info = get_message_info (message_list, mrow); if (info && (info->flags & mask) == flags) { e_table_scrolled_set_cursor_row (ets, mrow); + mail_do_display_message (message_list, info->uid, mark_msg_seen); return; } + vrow += direction; } mail_display_set_message (message_list->parent_folder_browser->mail_display, NULL); } -static gint -mark_msg_seen (gpointer data) -{ - MessageList *ml = data; - guint32 flags; - - if (!ml->cursor_uid) - return FALSE; - - flags = camel_folder_get_message_flags (ml->folder, ml->cursor_uid); - camel_folder_set_message_flags (ml->folder, ml->cursor_uid, - CAMEL_MESSAGE_SEEN, - CAMEL_MESSAGE_SEEN); - return FALSE; -} - /* select a message and display it */ static void select_msg (MessageList *message_list, gint row) { - CamelException ex; - CamelMimeMessage *message; - const CamelMessageInfo *msg_info; - MailDisplay *md = message_list->parent_folder_browser->mail_display; - - camel_exception_init (&ex); - - msg_info = get_message_info (message_list, row); - if (msg_info) { - message = camel_folder_get_message (message_list->folder, - msg_info->uid, &ex); - if (camel_exception_get_id (&ex)) { - printf ("Unable to get message: %s\n", - ex.desc?ex.desc:"unknown_reason"); - return; - } - - if (message_list->seen_id) - gtk_timeout_remove (message_list->seen_id); + const char *uid; - mail_display_set_message (md, CAMEL_MEDIUM (message)); - gtk_object_unref (GTK_OBJECT (message)); - - message_list->seen_id = - gtk_timeout_add (1500, mark_msg_seen, message_list); - } else - mail_display_set_message (md, NULL); + uid = get_message_uid (message_list, row); + mail_do_display_message (message_list, uid, mark_msg_seen); } @@ -317,6 +322,7 @@ ml_tree_set_value_at (ETreeModel *etm, ETreePath *path, int col, MessageList *message_list = model_data; const CamelMessageInfo *msg_info; char *uid; + GPtrArray *uids; if (col != COL_MESSAGE_STATUS) return; @@ -330,8 +336,11 @@ ml_tree_set_value_at (ETreeModel *etm, ETreePath *path, int col, if (!msg_info) return; - camel_folder_set_message_flags (message_list->folder, msg_info->uid, - CAMEL_MESSAGE_SEEN, ~msg_info->flags); + uids = g_ptr_array_new (); + g_ptr_array_add (uids, g_strdup (uid)); + mail_do_flag_messages (message_list->folder, uids, TRUE, + CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); + if (message_list->seen_id) { gtk_timeout_remove (message_list->seen_id); message_list->seen_id = 0; @@ -571,38 +580,40 @@ message_list_init (GtkObject *object) { MessageList *message_list = MESSAGE_LIST (object); char *spec; - + message_list->table_model = (ETableModel *) e_tree_simple_new (ml_tree_icon_at, ml_tree_value_at, ml_tree_set_value_at, ml_tree_is_cell_editable, message_list); e_tree_model_root_node_set_visible ((ETreeModel *)message_list->table_model, FALSE); - + message_list_init_renderers (message_list); message_list_init_header (message_list); - + /* * The etable */ - + spec = message_list_get_layout (message_list); message_list->etable = e_table_scrolled_new ( message_list->header_model, message_list->table_model, spec); g_free (spec); - + gtk_object_set(GTK_OBJECT(message_list->etable), "cursor_mode", E_TABLE_CURSOR_LINE, "drawfocus", FALSE, "drawgrid", FALSE, NULL); - - gtk_signal_connect (GTK_OBJECT (message_list->etable), "realize", - GTK_SIGNAL_FUNC (select_row), message_list); - + + /* + *gtk_signal_connect (GTK_OBJECT (message_list->etable), "realize", + * GTK_SIGNAL_FUNC (select_row), message_list); + */ + gtk_signal_connect (GTK_OBJECT (message_list->etable), "cursor_change", - GTK_SIGNAL_FUNC (on_cursor_change_cmd), message_list); - + GTK_SIGNAL_FUNC (on_cursor_change_cmd), message_list); + gtk_signal_connect (GTK_OBJECT (message_list->etable), "right_click", GTK_SIGNAL_FUNC (on_right_click), message_list); @@ -662,7 +673,7 @@ message_list_destroy (GtkObject *object) g_source_remove(message_list->idle_id); if (message_list->folder) - gtk_object_unref (GTK_OBJECT (message_list->folder)); + camel_object_unref (CAMEL_OBJECT (message_list->folder)); GTK_OBJECT_CLASS (message_list_parent_class)->destroy (object); } @@ -820,86 +831,29 @@ build_flat (MessageList *ml, ETreePath *parent, GPtrArray *uids) } } -void -message_list_regenerate (MessageList *message_list, const char *search) -{ - ETreeModel *etm = E_TREE_MODEL (message_list->table_model); - GPtrArray *uids; - int row = 0; - - e_table_model_pre_change(message_list->table_model); - - if (message_list->search) { - g_free (message_list->search); - message_list->search = NULL; - } - - if (message_list->uid_rowmap) { - g_hash_table_foreach (message_list->uid_rowmap, - free_key, NULL); - g_hash_table_destroy (message_list->uid_rowmap); - } - message_list->uid_rowmap = g_hash_table_new (g_str_hash, g_str_equal); - - if (search && camel_folder_has_search_capability (message_list->folder)) { - CamelException ex; - - camel_exception_init (&ex); - uids = camel_folder_search_by_expression (message_list->folder, - search, &ex); - if (camel_exception_is_set (&ex)) { - e_notice (NULL, GNOME_MESSAGE_BOX_ERROR, - "Search failed: %s", - camel_exception_get_description (&ex)); - camel_exception_clear (&ex); - } else - message_list->search = g_strdup (search); - } else - uids = camel_folder_get_uids (message_list->folder); - - /* FIXME: free the old tree data */ - - /* Clear the old contents, build the new */ - if (message_list->tree_root) - e_tree_model_node_remove(etm, message_list->tree_root); - message_list->tree_root = - e_tree_model_node_insert(etm, NULL, 0, message_list); - e_tree_model_node_set_expanded (etm, message_list->tree_root, TRUE); - - if (mail_config_thread_list()) { - struct _container *head; - - head = thread_messages (message_list->folder, uids); - build_tree (message_list, message_list->tree_root, head, &row); - thread_messages_free (head); - } else - build_flat (message_list, message_list->tree_root, uids); - - if (search) { - camel_folder_search_free(message_list->folder, uids); - } else { - camel_folder_free_uids (message_list->folder, uids); - } - - e_table_model_changed (message_list->table_model); - select_msg (message_list, 0); -} - static void -folder_changed (CamelFolder *f, int type, MessageList *message_list) +folder_changed (CamelObject *o, gpointer event_data, gpointer user_data) { - message_list_regenerate (message_list, message_list->search); + MessageList *message_list = MESSAGE_LIST (user_data); + GDK_THREADS_ENTER(); /* Very important!!!! */ + mail_do_regenerate_messagelist (message_list, message_list->search); + GDK_THREADS_LEAVE(); /* Very important!!!! */ } static void -message_changed (CamelFolder *f, const char *uid, MessageList *message_list) +message_changed (CamelObject *o, gpointer uid, gpointer user_data) { + MessageList *message_list = MESSAGE_LIST (user_data); int row; + GDK_THREADS_ENTER(); /* Very important!!!! */ + row = GPOINTER_TO_INT (g_hash_table_lookup (message_list->uid_rowmap, uid)); if (row != -1) e_table_model_row_changed (message_list->table_model, row); + + GDK_THREADS_LEAVE(); /* Very important!!!! */ } void @@ -916,18 +870,20 @@ message_list_set_folder (MessageList *message_list, CamelFolder *camel_folder) camel_exception_init (&ex); if (message_list->folder) - gtk_object_unref (GTK_OBJECT (message_list->folder)); + camel_object_unref (CAMEL_OBJECT (message_list->folder)); message_list->folder = camel_folder; - gtk_signal_connect(GTK_OBJECT (camel_folder), "folder_changed", + camel_object_hook_event(CAMEL_OBJECT (camel_folder), "folder_changed", folder_changed, message_list); - gtk_signal_connect(GTK_OBJECT (camel_folder), "message_changed", + camel_object_hook_event(CAMEL_OBJECT (camel_folder), "message_changed", message_changed, message_list); - gtk_object_ref (GTK_OBJECT (camel_folder)); + camel_object_ref (CAMEL_OBJECT (camel_folder)); - folder_changed (camel_folder, 0, message_list); + /*gtk_idle_add (regen_message_list, message_list);*/ + /*folder_changed (CAMEL_OBJECT (camel_folder), 0, message_list);*/ + mail_do_regenerate_messagelist (message_list, message_list->search); } GtkWidget * @@ -953,13 +909,13 @@ static void on_cursor_change_cmd (ETableScrolled *table, int row, gpointer user_data) { MessageList *message_list; - const CamelMessageInfo *info; + const char *uid; message_list = MESSAGE_LIST (user_data); message_list->cursor_row = row; - info = get_message_info (message_list, row); - message_list->cursor_uid = info ? info->uid : NULL; + uid = get_message_uid (message_list, row); + message_list->cursor_uid = uid; /*NULL ok*/ if (!message_list->idle_id) { message_list->idle_id = @@ -972,10 +928,13 @@ on_cursor_change_cmd (ETableScrolled *table, int row, gpointer user_data) static gint idle_select_row (gpointer user_data) { - ETableScrolled *ets = user_data; - int mrow = e_table_view_to_model_row (ets->table, 0); + MessageList *ml = MESSAGE_LIST (user_data); + ETableScrolled *ets = E_TABLE_SCROLLED (ml->etable); + int mrow; - e_table_scrolled_set_cursor_row (ets, mrow); + mrow = e_table_view_to_model_row (ets->table, 0); + message_list_select (ml, mrow, MESSAGE_LIST_SELECT_NEXT, + 0, CAMEL_MESSAGE_SEEN); return FALSE; } @@ -984,7 +943,7 @@ select_row (ETableScrolled *table, gpointer user_data) { MessageList *message_list = user_data; - gtk_idle_add (idle_select_row, message_list->etable); + gtk_idle_add (idle_select_row, message_list); } static void @@ -1082,12 +1041,12 @@ static void mlfe_callback (int row, gpointer user_data) { struct message_list_foreach_data *mlfe_data = user_data; - const CamelMessageInfo *info; + const char *uid; - info = get_message_info (mlfe_data->message_list, row); - if (info) { + uid = get_message_uid (mlfe_data->message_list, row); + if (uid) { mlfe_data->callback (mlfe_data->message_list, - info->uid, + uid, mlfe_data->user_data); } } @@ -1111,6 +1070,142 @@ message_list_toggle_threads (BonoboUIHandler *uih, void *user_data, const char *path) { MessageList *ml = user_data; - mail_config_set_thread_list(bonobo_ui_handler_menu_get_toggle_state (uih, path)); - message_list_regenerate (ml, ml->search); + + mail_config_set_thread_list (bonobo_ui_handler_menu_get_toggle_state (uih, path)); + mail_do_regenerate_messagelist (ml, ml->search); +} + +/* ** REGENERATE MESSAGELIST ********************************************** */ + +typedef struct regenerate_messagelist_input_s { + MessageList *ml; + char *search; +} regenerate_messagelist_input_t; + +typedef struct regenerate_messagelist_data_s { + GPtrArray *uids; +} regenerate_messagelist_data_t; + +static gchar *describe_regenerate_messagelist (gpointer in_data, gboolean gerund); +static void setup_regenerate_messagelist (gpointer in_data, gpointer op_data, CamelException *ex); +static void do_regenerate_messagelist (gpointer in_data, gpointer op_data, CamelException *ex); +static void cleanup_regenerate_messagelist (gpointer in_data, gpointer op_data, CamelException *ex); + +static gchar *describe_regenerate_messagelist (gpointer in_data, gboolean gerund) +{ + if (gerund) + return g_strdup ("Rebuilding message view"); + else + return g_strdup ("Rebuild message view"); +} + +static void setup_regenerate_messagelist (gpointer in_data, gpointer op_data, CamelException *ex) +{ + regenerate_messagelist_input_t *input = (regenerate_messagelist_input_t *) in_data; + + if (!IS_MESSAGE_LIST (input->ml)) { + camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM, + "No messagelist specified to regenerate"); + return; + } + + gtk_object_ref (GTK_OBJECT (input->ml)); + e_table_model_pre_change (input->ml->table_model); +} + +static void do_regenerate_messagelist (gpointer in_data, gpointer op_data, CamelException *ex) +{ + regenerate_messagelist_input_t *input = (regenerate_messagelist_input_t *) in_data; + regenerate_messagelist_data_t *data = (regenerate_messagelist_data_t *) op_data; + + if (input->ml->search) { + g_free (input->ml->search); + input->ml->search = NULL; + } + + if (input->ml->uid_rowmap) { + g_hash_table_foreach (input->ml->uid_rowmap, + free_key, NULL); + g_hash_table_destroy (input->ml->uid_rowmap); + } + input->ml->uid_rowmap = g_hash_table_new (g_str_hash, g_str_equal); + + mail_tool_camel_lock_up(); + + if (input->search) { + data->uids = camel_folder_search_by_expression (input->ml->folder, + input->search, ex); + if (camel_exception_is_set (ex)) { + mail_tool_camel_lock_down(); + return; + } + + input->ml->search = g_strdup (input->search); + } else + data->uids = camel_folder_get_uids (input->ml->folder); + + mail_tool_camel_lock_down(); +} + +static void cleanup_regenerate_messagelist (gpointer in_data, gpointer op_data, CamelException *ex) +{ + regenerate_messagelist_input_t *input = (regenerate_messagelist_input_t *) in_data; + regenerate_messagelist_data_t *data = (regenerate_messagelist_data_t *) op_data; + + ETreeModel *etm; + + etm = E_TREE_MODEL (input->ml->table_model); + + /* FIXME: free the old tree data */ + + if (data->uids == NULL) { /*exception*/ + gtk_object_unref (GTK_OBJECT (input->ml)); + return; + } + + /* Clear the old contents, build the new */ + if (input->ml->tree_root) + e_tree_model_node_remove(etm, input->ml->tree_root); + input->ml->tree_root = + e_tree_model_node_insert(etm, NULL, 0, input->ml); + e_tree_model_node_set_expanded (etm, input->ml->tree_root, TRUE); + + if (mail_config_thread_list()) { + mail_do_thread_messages (input->ml, data->uids, + (gboolean) !(input->search), + build_tree); + } else { + build_flat (input->ml, input->ml->tree_root, data->uids); + + if (input->search) { + camel_folder_search_free (input->ml->folder, data->uids); + } else { + camel_folder_free_uids (input->ml->folder, data->uids); + } + } + + e_table_model_changed (input->ml->table_model); + select_row (NULL, input->ml); + g_free (input->search); + gtk_object_unref (GTK_OBJECT (input->ml)); +} + +static const mail_operation_spec op_regenerate_messagelist = +{ + describe_regenerate_messagelist, + sizeof (regenerate_messagelist_data_t), + setup_regenerate_messagelist, + do_regenerate_messagelist, + cleanup_regenerate_messagelist +}; + +void mail_do_regenerate_messagelist (MessageList *list, const gchar *search) +{ + regenerate_messagelist_input_t *input; + + input = g_new (regenerate_messagelist_input_t, 1); + input->ml = list; + input->search = g_strdup (search); + + mail_operation_queue (&op_regenerate_messagelist, input, TRUE); } |