From 9c21067261d2af663d762c7f655eea1a7573f1e9 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 16 Jun 2000 23:11:10 +0000 Subject: new function to do a uid to row mapping. (mark_msg_seen, select_msg, * message-list.c (get_message_row): new function to do a uid to row mapping. (mark_msg_seen, select_msg, message_changed, message_list_set_folder): Update for Camel flag changes. (on_cursor_change_cmd): Rename "row_to_select" to "selected_row", and keep a "selected_uid" as well. * mail-ops.c (composer_send_cb): Update for Camel flag changes, and fix some memory-handling bugs. (Free the post_send_data when the composer is destroyed, not when the user clicks "send", which could happen never, or more than once.) (delete_msg): Update for Camel flag changes, and fix the "holding down the delete key skips some messages" bug. svn path=/trunk/; revision=3600 --- mail/ChangeLog | 16 ++++++++ mail/mail-ops.c | 84 ++++++++++++++++++++++++----------------- mail/message-list.c | 105 +++++++++++++++++++++++++++++++++++++++------------- mail/message-list.h | 5 ++- 4 files changed, 150 insertions(+), 60 deletions(-) (limited to 'mail') diff --git a/mail/ChangeLog b/mail/ChangeLog index 27ea9425d3..fbd959274f 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,19 @@ +2000-06-16 Dan Winship + + * message-list.c (get_message_row): new function to do a uid to + row mapping. + (mark_msg_seen, select_msg, message_changed, + message_list_set_folder): Update for Camel flag changes. + (on_cursor_change_cmd): Rename "row_to_select" to "selected_row", + and keep a "selected_uid" as well. + + * mail-ops.c (composer_send_cb): Update for Camel flag changes, + and fix some memory-handling bugs. (Free the post_send_data when + the composer is destroyed, not when the user clicks "send", which + could happen never, or more than once.) + (delete_msg): Update for Camel flag changes, and fix the "holding + down the delete key skips some messages" bug. + 2000-06-15 Dan Winship * mail-ops.c (fetch_mail): diff --git a/mail/mail-ops.c b/mail/mail-ops.c index 81cb5ae139..c28c4a0de6 100644 --- a/mail/mail-ops.c +++ b/mail/mail-ops.c @@ -271,7 +271,8 @@ fetch_mail (GtkWidget *button, gpointer user_data) struct post_send_data { - CamelMimeMessage *message; + CamelFolder *folder; + const char *uid; guint32 flags; }; @@ -321,7 +322,7 @@ composer_send_cb (EMsgComposer *composer, gpointer data) mail_exception_dialog ("Could not load mail transport", ex, composer); camel_exception_free (ex); - goto free_psd; + return; } } @@ -340,26 +341,29 @@ composer_send_cb (EMsgComposer *composer, gpointer data) if (camel_exception_is_set (ex)) mail_exception_dialog ("Could not send message", ex, composer); else { - gtk_object_destroy (GTK_OBJECT (composer)); if (psd) { guint32 set; - set = camel_mime_message_get_flags (psd->message); - camel_mime_message_set_flags (psd->message, - psd->flags, ~set); + set = camel_folder_get_message_flags (psd->folder, + psd->uid, ex); + camel_folder_set_message_flags (psd->folder, psd->uid, + psd->flags, ~set, ex); } + gtk_object_destroy (GTK_OBJECT (composer)); } camel_exception_free (ex); gtk_object_unref (GTK_OBJECT (message)); - - free_psd: - if (psd) { - gtk_object_unref (GTK_OBJECT (psd->message)); - g_free (psd); - } } +static void +free_psd (GtkWidget *composer, gpointer user_data) +{ + struct post_send_data *psd = user_data; + + gtk_object_unref (GTK_OBJECT (psd->folder)); + g_free (psd); +} void send_msg (GtkWidget *widget, gpointer user_data) @@ -402,14 +406,18 @@ reply (FolderBrowser *fb, gboolean to_all) return; psd = g_new (struct post_send_data, 1); - psd->message = fb->mail_display->current_message; - gtk_object_ref (GTK_OBJECT (psd->message)); + psd->folder = fb->folder; + gtk_object_ref (GTK_OBJECT (psd->folder)); + psd->uid = fb->message_list->selected_uid; psd->flags = CAMEL_MESSAGE_ANSWERED; - composer = mail_generate_reply (psd->message, to_all); + composer = mail_generate_reply (fb->mail_display->current_message, + to_all); gtk_signal_connect (GTK_OBJECT (composer), "send", GTK_SIGNAL_FUNC (composer_send_cb), psd); + gtk_signal_connect (GTK_OBJECT (composer), "destroy", + GTK_SIGNAL_FUNC (free_psd), psd); gtk_widget_show (GTK_WIDGET (composer)); } @@ -450,25 +458,35 @@ void delete_msg (GtkWidget *button, gpointer user_data) { FolderBrowser *fb = user_data; - int row; - - if (fb->mail_display->current_message) { - guint32 flags; - - /* FIXME: table should watch the message with a signal and update display! */ - - flags = camel_mime_message_get_flags(fb->mail_display->current_message); - camel_mime_message_set_flags(fb->mail_display->current_message, CAMEL_MESSAGE_DELETED, ~flags); - printf("Message %s set to %s\n", fb->mail_display->current_message->message_uid, - flags&CAMEL_MESSAGE_DELETED ? "UNDELETED" : "DELETED"); - - - /* Move the cursor down a row... FIXME: should skip other - * deleted messages. - */ - row = e_table_get_selected_view_row (E_TABLE (fb->message_list->etable)); - e_table_select_row (E_TABLE (fb->message_list->etable), row + 1); + MessageList *ml = fb->message_list; + CamelException ex; + guint32 flags; + + if (!fb->mail_display->current_message) + return; + + camel_exception_init (&ex); + + flags = camel_folder_get_message_flags (fb->folder, ml->selected_uid, + &ex); + if (!camel_exception_is_set (&ex)) { + /* Toggle the deleted flag without touching other flags. */ + camel_folder_set_message_flags (fb->folder, ml->selected_uid, + CAMEL_MESSAGE_DELETED, + ~flags, &ex); } + + if (camel_exception_is_set (&ex)) { + mail_exception_dialog ("Could not toggle deleted flag", + &ex, fb); + camel_exception_clear (&ex); + return; + } + + /* Move the cursor down a row... FIXME: should skip other + * deleted messages. + */ + e_table_select_row (E_TABLE (ml->etable), ml->selected_row + 1); } void diff --git a/mail/message-list.c b/mail/message-list.c index 05db369fc7..5032e7c6af 100644 --- a/mail/message-list.c +++ b/mail/message-list.c @@ -61,7 +61,8 @@ select_row (ETable *table, gpointer user_data); -static CamelMessageInfo *get_message_info(MessageList *message_list, gint row) +static CamelMessageInfo * +get_message_info(MessageList *message_list, gint row) { CamelMessageInfo *info = NULL; @@ -84,27 +85,53 @@ static CamelMessageInfo *get_message_info(MessageList *message_list, gint row) return info; } -static void -message_changed (CamelMimeMessage *m, enum _MessageChangeType type, - MessageList *message_list) +static int +get_message_row (MessageList *message_list, const char *uid) { - guint row = GPOINTER_TO_UINT (gtk_object_get_data (GTK_OBJECT (m), - "row")); + CamelMessageInfo *info; + int row; + + if (message_list->search) { + GList *l; + + /* Yum. Linear search. See also "FIXME: This should use + * a better format" in message-list.h + */ + for (l = message_list->matches, row = 0; l; l = l->next, row++) { + if (!strcmp (uid, l->data)) + return row; + } + } else { + gpointer key, value; + + if (g_hash_table_lookup_extended (message_list->uid_rowmap, + uid, &key, &value)) + return GPOINTER_TO_INT (value); - e_table_model_row_changed (message_list->table_model, row); + row = g_hash_table_size (message_list->uid_rowmap); + for (; row < message_list->summary_table->len; row++) { + info = message_list->summary_table->pdata[row]; + g_hash_table_insert (message_list->uid_rowmap, + info->uid, GINT_TO_POINTER (row)); + if (!strcmp (uid, info->uid)) + return row; + } + } + + return -1; } static gint mark_msg_seen (gpointer data) { - CamelMimeMessage *msg = data; + MessageList *ml = data; guint32 flags; - g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (msg), FALSE); - - flags = camel_mime_message_get_flags (msg); - camel_mime_message_set_flags (msg, CAMEL_MESSAGE_SEEN, - CAMEL_MESSAGE_SEEN); + flags = camel_folder_get_message_flags (ml->folder, ml->selected_uid, + NULL); + camel_folder_set_message_flags (ml->folder, ml->selected_uid, + CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN, + NULL); return FALSE; } @@ -115,7 +142,6 @@ select_msg (MessageList *message_list, gint row) CamelException ex; CamelMimeMessage *message = NULL; CamelMessageInfo *msg_info; - static guint timeout; camel_exception_init (&ex); @@ -132,16 +158,16 @@ select_msg (MessageList *message_list, gint row) } if (message) { + static guint timeout; + if (timeout) gtk_timeout_remove (timeout); - gtk_object_set_data (GTK_OBJECT (message), "row", - GUINT_TO_POINTER (row)); - gtk_signal_connect(GTK_OBJECT (message), "message_changed", - message_changed, message_list); + mail_display_set_message (message_list->parent_folder_browser->mail_display, CAMEL_MEDIUM (message)); - timeout = gtk_timeout_add (1500, mark_msg_seen, message); gtk_object_unref (GTK_OBJECT (message)); + + timeout = gtk_timeout_add (1500, mark_msg_seen, message_list); } } @@ -684,6 +710,8 @@ message_list_destroy (GtkObject *object) g_ptr_array_free(message_list->summary_search_cache, TRUE); if (message_list->summary_table) camel_folder_free_summary(message_list->folder, message_list->summary_table); + if (message_list->uid_rowmap) + g_hash_table_destroy(message_list->uid_rowmap); for (i = 0; i < COL_LAST; i++) gtk_object_unref (GTK_OBJECT (message_list->table_cols [i])); @@ -837,13 +865,29 @@ message_list_set_search (MessageList *message_list, const char *search) static void folder_changed(CamelFolder *f, int type, MessageList *message_list) { + int row; + if (message_list->summary_table) camel_folder_free_summary(f, message_list->summary_table); message_list->summary_table = camel_folder_get_summary (f, NULL); + if (message_list->uid_rowmap) + g_hash_table_destroy(message_list->uid_rowmap); + message_list->uid_rowmap = g_hash_table_new (g_str_hash, g_str_equal); + message_list_set_search(message_list, message_list->search); } +static void +message_changed (CamelFolder *f, const char *uid, MessageList *message_list) +{ + int row; + + row = get_message_row (message_list, uid); + if (row != -1) + e_table_model_row_changed (message_list->table_model, row); +} + void message_list_set_folder (MessageList *message_list, CamelFolder *camel_folder) { @@ -863,7 +907,9 @@ message_list_set_folder (MessageList *message_list, CamelFolder *camel_folder) if (message_list->summary_table) camel_folder_free_summary(message_list->folder, message_list->summary_table); - + if (message_list->uid_rowmap) + g_hash_table_destroy(message_list->uid_rowmap); + camel_exception_init (&ex); if (message_list->folder) @@ -871,13 +917,14 @@ message_list_set_folder (MessageList *message_list, CamelFolder *camel_folder) message_list->folder = camel_folder; - gtk_signal_connect((GtkObject *)camel_folder, "folder_changed", folder_changed, message_list); + gtk_signal_connect(GTK_OBJECT (camel_folder), "folder_changed", + folder_changed, message_list); + gtk_signal_connect(GTK_OBJECT (camel_folder), "message_changed", + message_changed, message_list); gtk_object_ref (GTK_OBJECT (camel_folder)); - message_list->summary_table = camel_folder_get_summary (message_list->folder, NULL); - - message_list_set_search(message_list, message_list->search); + folder_changed (camel_folder, 0, message_list); select_msg (message_list, 0); } @@ -895,7 +942,7 @@ on_cursor_change_idle (gpointer data) { MessageList *message_list = data; - select_msg (message_list, message_list->row_to_select); + select_msg (message_list, message_list->selected_row); message_list->idle_id = 0; return FALSE; @@ -907,10 +954,16 @@ on_cursor_change_cmd (ETable *table, gpointer user_data) { MessageList *message_list; + CamelMessageInfo *info; message_list = MESSAGE_LIST (user_data); - message_list->row_to_select = row; + info = get_message_info (message_list, row); + if (!info) + return; + + message_list->selected_row = row; + message_list->selected_uid = info->uid; if (!message_list->idle_id) message_list->idle_id = g_idle_add_full (G_PRIORITY_LOW, on_cursor_change_idle, message_list, NULL); diff --git a/mail/message-list.h b/mail/message-list.h index 971aa6c37a..f40263407d 100644 --- a/mail/message-list.h +++ b/mail/message-list.h @@ -65,6 +65,7 @@ struct _MessageList { CamelFolder *folder; GPtrArray *summary_table; /* the summary of all messages */ + GHashTable *uid_rowmap; char *search; /* search string */ /* FIXME: This should use a better format ... */ @@ -72,8 +73,10 @@ struct _MessageList { int match_count; GPtrArray *summary_search_cache; /* summary info cache for searches */ + int selected_row; + const char *selected_uid; + /* used by the idle-call to select a row */ - int row_to_select; guint idle_id; } ; -- cgit v1.2.3