From a16344fff4780b6b1c5d8c2d6531963e1fe07d52 Mon Sep 17 00:00:00 2001 From: Not Zed Date: Wed, 3 Jan 2001 01:18:21 +0000 Subject: Fix for mail_get_message change, use queue thread. 2001-01-02 Not Zed * mail-callbacks.c (view_msg): Fix for mail_get_message change, use queue thread. * folder-browser.c (done_message_selected): Fix mail_Get_message calls, use new thread. (do_message_selected): " * mail-ops.c (mail_get_message): Add a thread argument so callers can specify which queue it executes on. * mail-mt.c (mail_msg_free): Fix a free order problem. (mail_msg_destroy): Call mail_msg_free to do the work. (mail_msgport_replied): " (mail_msgport_replied): Check/display errors if we get them. (mail_msgport_received): If we have a describe function, say what we're doing, also set busy/unbusy. (mail_msgport_replied): Clear busy when we get a reply. (mail_get_password): Unset busy. (mail_msg_received): Set busy as we go. (mail_msg_destroy): Unset busy when done. (mail_status): Blah blah, new status interface, the other wans't workable with the way the shell api works. 2000-12-29 Not Zed * folder-browser.c (do_message_selected): If we are reconfiguring, just keep polling till we are done (yeah kinda shitty, but easy). (folder_browser_set_uri): Clear reconfigure flag here. ick. (got_folder): And here too. (on_right_click): Remove locking. (hide_sender): and here too. (hide_subject): And here. (on_right_click): If we are in reconfigure, then the whole menu is disabled. * mail-mt.c (status_busy_timeout): Clear the status_busy_timeout_id. * mail-local.c (local_storage_new_folder_cb): Made getting folders completely synchronous. The shell expects it, and it was only synchronous before by a sideeffect. (do_reconfigure_folder): Remove locking stuff. (do_reconfigure_folder): Use our own much simpler copying routine than that stupid move_folder_contents thing. (update_progress): Use mail_status_message() instead. (do_reconfigure_folder): Set the reconfigure flag during reconfigure & set busy flag. (cleanup_reconfigure_folder): clear busy flag. * mail-tools.c (mail_tool_uri_to_folder): Remove the tool_lock stuff. (mail_tool_uri_to_folder_noex): Clear exception on exit. (mail_tool_move_folder_contents): Get rid of this really stupid function that is only used in one place. * component-factory.c (owner_set_cb): Use direct calls to get the folders, as this code must run synchronous. Remove the event wait stuff. * mail-callbacks.c (edit_msg): Call mail_get_messages, and create the composers ourself. (do_edit_messages): get_messages callback, create the composers and connect to signals we need. (view_msg): Dont call do_view_messages, just call mail_get_messge for each to get them in parallel. (do_view_message): view a single message. * mail-ops.c (mail_edit_messages): Just use mail_get_messages for this operation. Removed the other async operation stuff. Changed my mind, just removed entirely. (mail_do_view_messages): Removed. (mail_do_setup_folder): Removed. (mail_do_scan_subfolders): Make this run synchronously, as every caller expects it to (even if they didn't realise). 2000-12-28 Not Zed * mail-callbacks.c (send_queued_mail): Dont expunge the folder here, but in send_queue, otherwise it might execute out of order. (expunge_folder): Remove the talbe prechange stuff, and infact references to the message_list folder, as we have our own folder. Also, dont allow expunge if we're already expunging. (expunged_folder): Clkear the expunging flag if we're finished. * folder-browser-factory.c (control_deactivate): Likewise here. Hrm, i thought this function required a callback, silly me. * mail-tools.c (mail_tool_make_message_attachment): Remov e locking. * folder-browser.c (on_message_selected): Use a timeout handler so we dont select immediately. (folder_browser_set_uri): Changed to use mail_get_folder. (got_folder): New callback called when get_folder is finished. (folder_browser_destroy): Use new sync interface. * mail-ops.c (mail_get_message): New function to asynchrounously get a message. : #define out mail_tool_camel_lock stuff entirely. (mail_get_folder): New function to asynchrounously get a folder. (mail_do_load_folder): Removed, replaced by more generic function above. (mail_do_display_message): Removed, replaced by the more generic funciton get_message. (mail_get_messages): New function to get a list of messages asynchronously. (mail_sync_folder): New interface to sync a folder async. (mail_expunge_folder): New interface for expunging folder, with callback. (do_send_queue): Remove lock stuff, and expunge if (and only if) successful, also sync the sent folder while we're at it. * session.c (mail_session_request_dialog): Changed to use new mail_get_password call. * mail-mt.[ch]: New threading/interthread messaging framework. * main.c (main): Init the message/thread system. svn path=/trunk/; revision=7223 --- mail/ChangeLog | 119 +++++++ mail/Makefile.am | 2 + mail/component-factory.c | 20 +- mail/folder-browser-factory.c | 2 +- mail/folder-browser.c | 168 +++++++-- mail/folder-browser.h | 15 +- mail/mail-callbacks.c | 65 +++- mail/mail-local.c | 67 +++- mail/mail-mt.c | 517 +++++++++++++++++++++++++++ mail/mail-mt.h | 73 ++++ mail/mail-ops.c | 801 +++++++++++++----------------------------- mail/mail-ops.h | 30 +- mail/mail-tools.c | 8 +- mail/main.c | 3 + mail/session.c | 3 +- 15 files changed, 1254 insertions(+), 639 deletions(-) create mode 100644 mail/mail-mt.c create mode 100644 mail/mail-mt.h diff --git a/mail/ChangeLog b/mail/ChangeLog index 5146dc2595..d25aabe89e 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,122 @@ +2001-01-02 Not Zed + + * mail-callbacks.c (view_msg): Fix for mail_get_message change, + use queue thread. + + * folder-browser.c (done_message_selected): Fix mail_Get_message + calls, use new thread. + (do_message_selected): " + + * mail-ops.c (mail_get_message): Add a thread argument so callers + can specify which queue it executes on. + + * mail-mt.c (mail_msg_free): Fix a free order problem. + (mail_msg_destroy): Call mail_msg_free to do the work. + (mail_msgport_replied): " + (mail_msgport_replied): Check/display errors if we get them. + (mail_msgport_received): If we have a describe function, say what + we're doing, also set busy/unbusy. + (mail_msgport_replied): Clear busy when we get a reply. + (mail_get_password): Unset busy. + (mail_msg_received): Set busy as we go. + (mail_msg_destroy): Unset busy when done. + (mail_status): Blah blah, new status interface, the other wans't + workable with the way the shell api works. + +2000-12-29 Not Zed + + * folder-browser.c (do_message_selected): If we are reconfiguring, + just keep polling till we are done (yeah kinda shitty, but easy). + (folder_browser_set_uri): Clear reconfigure flag here. ick. + (got_folder): And here too. + (on_right_click): Remove locking. + (hide_sender): and here too. + (hide_subject): And here. + (on_right_click): If we are in reconfigure, then the whole menu is disabled. + + * mail-mt.c (status_busy_timeout): Clear the status_busy_timeout_id. + + * mail-local.c (local_storage_new_folder_cb): Made getting folders + completely synchronous. The shell expects it, and it was only + synchronous before by a sideeffect. + (do_reconfigure_folder): Remove locking stuff. + (do_reconfigure_folder): Use our own much simpler copying routine + than that stupid move_folder_contents thing. + (update_progress): Use mail_status_message() instead. + (do_reconfigure_folder): Set the reconfigure flag during + reconfigure & set busy flag. + (cleanup_reconfigure_folder): clear busy flag. + + * mail-tools.c (mail_tool_uri_to_folder): Remove the tool_lock + stuff. + (mail_tool_uri_to_folder_noex): Clear exception on exit. + (mail_tool_move_folder_contents): Get rid of this really stupid + function that is only used in one place. + + * component-factory.c (owner_set_cb): Use direct calls to get the + folders, as this code must run synchronous. Remove the event wait + stuff. + + * mail-callbacks.c (edit_msg): Call mail_get_messages, and create + the composers ourself. + (do_edit_messages): get_messages callback, create the composers + and connect to signals we need. + (view_msg): Dont call do_view_messages, just call + mail_get_messge for each to get them in parallel. + (do_view_message): view a single message. + + * mail-ops.c (mail_edit_messages): Just use mail_get_messages + for this operation. Removed the other async operation stuff. + Changed my mind, just removed entirely. + (mail_do_view_messages): Removed. + (mail_do_setup_folder): Removed. + (mail_do_scan_subfolders): Make this run synchronously, as every + caller expects it to (even if they didn't realise). + +2000-12-28 Not Zed + + * mail-callbacks.c (send_queued_mail): Dont expunge the folder + here, but in send_queue, otherwise it might execute out of order. + (expunge_folder): Remove the talbe prechange stuff, and infact + references to the message_list folder, as we have our own folder. + Also, dont allow expunge if we're already expunging. + (expunged_folder): Clkear the expunging flag if we're finished. + + * folder-browser-factory.c (control_deactivate): Likewise here. + Hrm, i thought this function required a callback, silly me. + + * mail-tools.c (mail_tool_make_message_attachment): Remov e + locking. + + * folder-browser.c (on_message_selected): Use a timeout handler so + we dont select immediately. + (folder_browser_set_uri): Changed to use mail_get_folder. + (got_folder): New callback called when get_folder is finished. + (folder_browser_destroy): Use new sync interface. + + * mail-ops.c (mail_get_message): New function to asynchrounously + get a message. + : #define out mail_tool_camel_lock stuff entirely. + (mail_get_folder): New function to asynchrounously get a folder. + (mail_do_load_folder): Removed, replaced by more generic function + above. + (mail_do_display_message): Removed, replaced by the more generic + funciton get_message. + (mail_get_messages): New function to get a list of messages + asynchronously. + (mail_sync_folder): New interface to sync a folder async. + (mail_expunge_folder): New interface for expunging folder, with + callback. + (do_send_queue): Remove lock stuff, and expunge if (and only if) + successful, also sync the sent folder while we're at it. + + * session.c (mail_session_request_dialog): Changed to use new + mail_get_password call. + + * mail-mt.[ch]: New threading/interthread messaging framework. + + * main.c (main): Init the message/thread system. + 2001-01-02 Dan Winship * mail-format.c (mail_part_is_inline): diff --git a/mail/Makefile.am b/mail/Makefile.am index ceb3e957ca..559f6fcae4 100644 --- a/mail/Makefile.am +++ b/mail/Makefile.am @@ -68,6 +68,8 @@ evolution_mail_SOURCES = \ mail-local.h \ mail-mlist-magic.c \ mail-mlist-magic.h \ + mail-mt.c \ + mail-mt.h \ mail-ops.c \ mail-ops.h \ mail-search-dialogue.c \ diff --git a/mail/component-factory.c b/mail/component-factory.c index c4abc1ca74..7e951261a2 100644 --- a/mail/component-factory.c +++ b/mail/component-factory.c @@ -118,6 +118,15 @@ create_folder (EvolutionShellComponent *shell_component, mail_do_create_folder (listener, physical_uri, type); } +static struct { + char *name; + CamelFolder **folder; +} standard_folders[] = { + { "Drafts", &drafts_folder }, + { "Outbox", &outbox_folder }, + { "Sent", &sent_folder }, +}; + static void owner_set_cb (EvolutionShellComponent *shell_component, EvolutionShellClient *shell_client, @@ -126,6 +135,7 @@ owner_set_cb (EvolutionShellComponent *shell_component, { GSList *sources; GNOME_Evolution_Shell corba_shell; + int i; g_print ("evolution-mail: Yeeeh! We have an owner!\n"); /* FIXME */ @@ -146,11 +156,11 @@ owner_set_cb (EvolutionShellComponent *shell_component, mail_local_storage_startup (shell_client, evolution_dir); - mail_do_setup_folder ("Drafts", &drafts_folder); - mail_do_setup_folder ("Outbox", &outbox_folder); - mail_do_setup_folder ("Sent", &sent_folder); - /* Don't proceed until those _folder variables are valid. */ - mail_operation_wait_for_finish (); + for (i=0;ifolder) - mail_do_sync_folder (fb->folder); + mail_sync_folder (fb->folder, NULL, NULL); } static void diff --git a/mail/folder-browser.c b/mail/folder-browser.c index 5a94c91ba9..d3ed8c7cfb 100644 --- a/mail/folder-browser.c +++ b/mail/folder-browser.c @@ -65,7 +65,7 @@ folder_browser_destroy (GtkObject *object) g_free (folder_browser->uri); if (folder_browser->folder) { - mail_do_sync_folder (folder_browser->folder); + mail_sync_folder (folder_browser->folder, NULL, NULL); camel_object_unref (CAMEL_OBJECT (folder_browser->folder)); } @@ -109,11 +109,53 @@ folder_browser_class_init (GtkObjectClass *object_class) #define EQUAL(a,b) (strcmp (a,b) == 0) +static void +got_folder(char *uri, CamelFolder *folder, void *data) +{ + FolderBrowser *fb = data; + + printf("got folder '%s' = %p\n", uri, folder); + + if (fb->folder == folder) + goto done; + + if (fb->folder) + camel_object_unref((CamelObject *)fb->folder); + g_free(fb->uri); + fb->uri = g_strdup(uri); + fb->folder = folder; + + if (folder == NULL) + goto done; + + camel_object_ref((CamelObject *)folder); + + gtk_widget_set_sensitive (GTK_WIDGET (fb->search->entry), + camel_folder_has_search_capability (folder)); + gtk_widget_set_sensitive (GTK_WIDGET (fb->search->option), + camel_folder_has_search_capability (folder)); + message_list_set_threaded(fb->message_list, mail_config_thread_list()); + message_list_set_folder(fb->message_list, folder); +done: + gtk_object_unref((GtkObject *)fb); + + /* Sigh, i dont like this (it can be set in reconfigure folder), + but its just easier right now to do it this way */ + fb->reconfigure = FALSE; +} + gboolean folder_browser_set_uri (FolderBrowser *folder_browser, const char *uri) { - if (*uri) - mail_do_load_folder (folder_browser, uri); + if (uri && *uri) { + gtk_object_ref((GtkObject *)folder_browser); + mail_get_folder(uri, got_folder, folder_browser); + } else { + /* Sigh, i dont like this (it can be set in reconfigure folder), + but its just easier right now to do it this way */ + folder_browser->reconfigure = FALSE; + } + return TRUE; } @@ -507,8 +549,6 @@ hide_subject(GtkWidget *w, FolderBrowser *fb) GString *expr; if (fb->mail_display->current_message) { - /* need to lock for full life of const data */ - mail_tool_camel_lock_up(); subject = camel_mime_message_get_subject(fb->mail_display->current_message); if (subject) { subject = strip_re(subject); @@ -522,7 +562,6 @@ hide_subject(GtkWidget *w, FolderBrowser *fb) return; } } - mail_tool_camel_lock_down(); } } @@ -534,8 +573,6 @@ hide_sender(GtkWidget *w, FolderBrowser *fb) GString *expr; if (fb->mail_display->current_message) { - /* need to lock for full life of const data */ - mail_tool_camel_lock_up(); from = camel_mime_message_get_from(fb->mail_display->current_message); if (camel_internet_address_get(from, 0, &real, &addr)) { expr = g_string_new("(match-all (header-contains \"from\" "); @@ -546,7 +583,6 @@ hide_sender(GtkWidget *w, FolderBrowser *fb) g_string_free(expr, TRUE); return; } - mail_tool_camel_lock_down(); } } @@ -559,7 +595,7 @@ on_right_click (ETable *table, gint row, gint col, GdkEvent *event, FolderBrowse GPtrArray *uids; int enable_mask = 0; int last_item, i; - char *mailing_list_name; + char *mailing_list_name = NULL; char *subject_match = NULL, *from_match = NULL; EPopupMenu filter_menu[] = { @@ -618,6 +654,11 @@ on_right_click (ETable *table, gint row, gint col, GdkEvent *event, FolderBrowse }; last_item = (sizeof (filter_menu) / sizeof (*filter_menu)) - 2; + + if (fb->reconfigure) { + enable_mask = 0; + goto display_menu; + } if (fb->folder != drafts_folder) enable_mask |= 1; @@ -629,7 +670,6 @@ on_right_click (ETable *table, gint row, gint col, GdkEvent *event, FolderBrowse const char *subject, *real, *addr; const CamelInternetAddress *from; - mail_tool_camel_lock_up(); mailing_list_name = mail_mlist_magic_detect_list (fb->mail_display->current_message, NULL, NULL); if ((subject = camel_mime_message_get_subject(fb->mail_display->current_message)) @@ -641,8 +681,6 @@ on_right_click (ETable *table, gint row, gint col, GdkEvent *event, FolderBrowse && camel_internet_address_get(from, 0, &real, &addr) && addr && addr[0]) from_match = g_strdup(addr); - - mail_tool_camel_lock_down(); } /* get a list of uids */ @@ -655,9 +693,11 @@ on_right_click (ETable *table, gint row, gint col, GdkEvent *event, FolderBrowse gboolean have_seen = FALSE; gboolean have_unseen = FALSE; - mail_tool_camel_lock_up(); for (i = 0; i < uids->len; i++) { info = camel_folder_get_message_info (fb->folder, uids->pdata[i]); + if (info == NULL) + continue; + if (info->flags & CAMEL_MESSAGE_SEEN) have_seen = TRUE; else @@ -673,7 +713,6 @@ on_right_click (ETable *table, gint row, gint col, GdkEvent *event, FolderBrowse if (have_seen && have_unseen && have_deleted && have_undeleted) break; } - mail_tool_camel_lock_down(); if (!have_unseen) enable_mask |= 4; @@ -685,6 +724,13 @@ on_right_click (ETable *table, gint row, gint col, GdkEvent *event, FolderBrowse if (!have_deleted) enable_mask |= 32; } + + /* free uids */ + for (i = 0; i < uids->len; i++) + g_free (uids->pdata[i]); + g_ptr_array_free (uids, TRUE); + +display_menu: /* generate the "Filter on Mailing List menu item name */ if (mailing_list_name == NULL) { @@ -712,11 +758,6 @@ on_right_click (ETable *table, gint row, gint col, GdkEvent *event, FolderBrowse if (fb->message_list->hidden == NULL) enable_mask |= 128; - /* free uids */ - for (i = 0; i < uids->len; i++) - g_free (uids->pdata[i]); - g_ptr_array_free (uids, TRUE); - e_popup_menu_run (menu, (GdkEventButton *)event, enable_mask, 0, fb); g_free(filter_menu[last_item].name); @@ -850,23 +891,94 @@ folder_browser_gui_init (FolderBrowser *fb) gtk_widget_show (GTK_WIDGET (fb)); } +/* mark the message seen if the current message still matches */ static gint -mark_msg_seen (gpointer data) +do_mark_seen (gpointer data) { - MessageList *ml = data; + FolderBrowser *fb = data; + + if (fb->new_uid && fb->loaded_uid + && strcmp(fb->new_uid, fb->loaded_uid) == 0) { + camel_folder_set_message_flags(fb->folder, fb->new_uid, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); + } - if (!ml->cursor_uid) - return FALSE; - - camel_folder_set_message_flags(ml->folder, ml->cursor_uid, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); return FALSE; } +/* callback when we have the message to display, after async loading it (see below) */ +/* if we have pending uid's, it means another was selected before we finished displaying + the last one - so we cycle through and start loading the pending one immediately now */ +static void done_message_selected(CamelFolder *folder, char *uid, CamelMimeMessage *msg, void *data) +{ + FolderBrowser *fb = data; + int timeout = mail_config_mark_as_seen_timeout (); + + if (folder != fb->folder) + return; + + mail_display_set_message(fb->mail_display, (CamelMedium *)msg); + + /* pain, if we have pending stuff, re-run */ + if (fb->pending_uid) { + g_free(fb->loading_uid); + fb->loading_uid = fb->pending_uid; + fb->pending_uid = NULL; + + mail_get_message(fb->folder, fb->loading_uid, done_message_selected, fb, mail_thread_new); + return; + } + + g_free(fb->loaded_uid); + fb->loaded_uid = fb->loading_uid; + fb->loading_uid = NULL; + + /* if we are still on the same message, do the 'idle read' thing */ + if (fb->seen_id) + gtk_timeout_remove(fb->seen_id); + + if (msg) { + if (timeout > 0) + fb->seen_id = gtk_timeout_add(timeout, do_mark_seen, fb); + else + do_mark_seen(fb); + } +} + +/* ok we waited enough, display it anyway (see below) */ +static gboolean +do_message_selected(FolderBrowser *fb) +{ + d(printf ("selecting uid %s (delayed)\n", fb->new_uid)); + + /* keep polling if we are busy */ + if (fb->reconfigure) + return TRUE; + + fb->loading_id = 0; + + /* if we are loading, then set a pending, but leave the loading, coudl cancel here (?) */ + if (fb->loading_uid) { + g_free(fb->pending_uid); + fb->pending_uid = g_strdup(fb->new_uid); + } else { + fb->loading_uid = g_strdup(fb->new_uid); + mail_get_message(fb->folder, fb->loading_uid, done_message_selected, fb, mail_thread_new); + } + + return FALSE; +} + +/* when a message is selected, wait a while before trying to display it */ static void on_message_selected (MessageList *ml, const char *uid, FolderBrowser *fb) { - d(printf ("selecting uid %s\n", uid)); - mail_do_display_message (ml, fb->mail_display, uid, mark_msg_seen); + d(printf ("selecting uid %s (direct)\n", uid)); + g_free(fb->new_uid); + fb->new_uid = g_strdup(uid); + if (fb->loading_id != 0) + gtk_timeout_remove(fb->loading_id); + + fb->loading_id = gtk_timeout_add(100, (GtkFunction)do_message_selected, fb); } static void diff --git a/mail/folder-browser.h b/mail/folder-browser.h index 054d64b8c7..41d282b7e5 100644 --- a/mail/folder-browser.h +++ b/mail/folder-browser.h @@ -35,7 +35,20 @@ struct _FolderBrowser { */ char *uri; CamelFolder *folder; - + + /* async loading stuff */ + char *loading_uid;/* what uid am i loading now */ + char *pending_uid; /* what uid should i load next */ + char *new_uid; /* place to save the next uid during idle timeout */ + char *loaded_uid; /* what we have loaded */ + guint loading_id, seen_id; + + /* a folder we are expunging, dont use other than to compare the pointer value */ + CamelFolder *expunging; + + /* set to true when we are reconfiguring stuff == can't do much else */ + int reconfigure; + MessageList *message_list; MailDisplay *mail_display; GtkWidget *vpaned; diff --git a/mail/mail-callbacks.c b/mail/mail-callbacks.c index 32104dba76..736bba530e 100644 --- a/mail/mail-callbacks.c +++ b/mail/mail-callbacks.c @@ -225,8 +225,6 @@ send_queued_mail (GtkWidget *widget, gpointer user_data) } mail_do_send_queue (outbox_folder, transport->url); - - mail_do_expunge_folder (outbox_folder); } void @@ -655,6 +653,26 @@ mark_as_unseen (BonoboUIComponent *uih, void *user_data, const char *path) { flag_messages(FOLDER_BROWSER(user_data), CAMEL_MESSAGE_SEEN, 0); } + +static void +do_edit_messages(CamelFolder *folder, GPtrArray *uids, GPtrArray *messages, void *data) +{ + /*FolderBrowser *fb = data;*/ + int i; + + for (i=0; ilen; i++) { + EMsgComposer *composer; + + composer = e_msg_composer_new_with_message(messages->pdata[i]); + if (composer) { + gtk_signal_connect (GTK_OBJECT (composer), "send", + composer_send_cb, NULL); + gtk_signal_connect (GTK_OBJECT (composer), "postpone", + composer_postpone_cb, NULL); + gtk_widget_show (GTK_WIDGET (composer)); + } + } +} void edit_msg (GtkWidget *widget, gpointer user_data) @@ -678,8 +696,7 @@ edit_msg (GtkWidget *widget, gpointer user_data) uids = g_ptr_array_new (); message_list_foreach (fb->message_list, enumerate_msg, uids); - /* FIXME: do we need to pass the postpone callback too? */ - mail_do_edit_messages (fb->folder, uids, (GtkSignalFunc) composer_send_cb); + mail_get_messages(fb->folder, uids, do_edit_messages, fb); } static void @@ -777,15 +794,24 @@ undelete_msg (GtkWidget *button, gpointer user_data) flag_messages(FOLDER_BROWSER(user_data), CAMEL_MESSAGE_DELETED, 0); } +static void expunged_folder(CamelFolder *f, void *data) +{ + FolderBrowser *fb = data; + + fb->expunging = NULL; +} + void expunge_folder (BonoboUIComponent *uih, void *user_data, const char *path) { FolderBrowser *fb = FOLDER_BROWSER(user_data); - - e_table_model_pre_change (fb->message_list->table_model); - - if (fb->message_list->folder) - mail_do_expunge_folder (fb->message_list->folder); + + if (fb->folder + && (fb->expunging == NULL + || fb->folder != fb->expunging)) { + fb->expunging = fb->folder; + mail_expunge_folder(fb->folder, expunged_folder, fb); + } } static void @@ -969,18 +995,35 @@ configure_folder (BonoboUIComponent *uih, void *user_data, const char *path) mail_local_reconfigure_folder(fb); } +static void +do_view_message(CamelFolder *folder, char *uid, CamelMimeMessage *message, void *data) +{ + /*FolderBrowser *fb = data;*/ + GtkWidget *view; + + if (message) { + view = mail_view_create(folder, uid, message); + gtk_widget_show(view); + } +} + void view_msg (GtkWidget *widget, gpointer user_data) { FolderBrowser *fb = user_data; GPtrArray *uids; - + int i; + if (!fb->folder) return; uids = g_ptr_array_new (); message_list_foreach (fb->message_list, enumerate_msg, uids); - mail_do_view_messages (fb->folder, uids, fb); + for (i=0;ilen;i++) { + mail_get_message(fb->folder, uids->pdata[i], do_view_message, fb, mail_thread_queued); + g_free(uids->pdata[i]); + } + g_ptr_array_free(uids, TRUE); } void diff --git a/mail/mail-local.c b/mail/mail-local.c index c86518e07a..bd322f505b 100644 --- a/mail/mail-local.c +++ b/mail/mail-local.c @@ -59,6 +59,7 @@ #include "mail-tools.h" #include "mail-threads.h" #include "folder-browser.h" +#include "mail-mt.h" #define d(x) @@ -179,7 +180,7 @@ static void update_progress(char *fmt, float percent) { if (fmt) - mail_op_set_message ("%s", fmt); + mail_status(fmt); /*mail_op_set_percentage (percent);*/ } @@ -237,7 +238,8 @@ do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) CamelStore *fromstore = NULL, *tostore = NULL; char *fromurl = NULL, *tourl = NULL; CamelFolder *fromfolder = NULL, *tofolder = NULL; - + GPtrArray *uids; + int i; char *metapath; char *tmpname; CamelURL *url = NULL; @@ -246,6 +248,11 @@ do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) d(printf("reconfiguring folder: %s to type %s\n", input->fb->uri, input->newtype)); + mail_status_start(_("Reconfiguring folder")); + + /* NOTE: This var is cleared by the folder_browser via the set_uri method */ + input->fb->reconfigure = TRUE; + /* get the actual location of the mailbox */ url = camel_url_new(input->fb->uri, ex); if (camel_exception_is_set(ex)) { @@ -261,9 +268,7 @@ do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) if (input->fb->folder != NULL) { update_progress(_("Closing current folder"), 0.0); - mail_tool_camel_lock_up (); camel_folder_sync(input->fb->folder, FALSE, ex); - mail_tool_camel_lock_down (); camel_object_unref (CAMEL_OBJECT (input->fb->folder)); input->fb->folder = NULL; } @@ -275,16 +280,12 @@ do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) d(printf("opening stores %s and %s\n", fromurl, tourl)); - mail_tool_camel_lock_up (); fromstore = camel_session_get_store(session, fromurl, ex); - mail_tool_camel_lock_down (); if (camel_exception_is_set(ex)) goto cleanup; - mail_tool_camel_lock_up (); tostore = camel_session_get_store(session, tourl, ex); - mail_tool_camel_lock_down (); if (camel_exception_is_set(ex)) goto cleanup; @@ -293,10 +294,8 @@ do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) d(printf("renaming %s to %s, and opening it\n", meta->name, tmpname)); update_progress(_("Renaming old folder and opening"), 0.0); - mail_tool_camel_lock_up (); camel_store_rename_folder(fromstore, meta->name, tmpname, ex); if (camel_exception_is_set(ex)) { - mail_tool_camel_lock_down (); goto cleanup; } @@ -306,7 +305,6 @@ do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) /* try and recover ... */ camel_exception_clear (ex); camel_store_rename_folder(fromstore, tmpname, meta->name, ex); - mail_tool_camel_lock_down (); goto cleanup; } @@ -323,16 +321,24 @@ do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) /* try and recover ... */ camel_exception_clear (ex); camel_store_rename_folder(fromstore, tmpname, meta->name, ex); - mail_tool_camel_lock_down (); goto cleanup; } update_progress(_("Copying messages"), 0.0); - mail_tool_move_folder_contents (fromfolder, tofolder, FALSE, ex); + uids = camel_folder_get_uids(fromfolder); + for (i=0;ilen;i++) { + mail_statusf("Copying message %d of %d", i, uids->len); + camel_folder_move_message_to(fromfolder, uids->pdata[i], tofolder, ex); + if (camel_exception_is_set(ex)) { + camel_folder_free_uids(fromfolder, uids); + goto cleanup; + } + } + camel_folder_free_uids(fromfolder, uids); + camel_folder_expunge(fromfolder, ex); d(printf("delete old mbox ...\n")); camel_store_delete_folder(fromstore, tmpname, ex); - mail_tool_camel_lock_down (); /* switch format */ g_free(meta->format); @@ -380,6 +386,8 @@ cleanup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException folder_browser_set_uri(input->fb, uri); g_free(uri); + mail_status_end(); + gtk_object_unref (GTK_OBJECT (input->fb)); g_free (input->newtype); } @@ -418,9 +426,6 @@ reconfigure_clicked(GnomeDialog *d, int button, reconfigure_folder_input_t *data gnome_dialog_close(d); } -/* kills a very annoying warning */ -void local_reconfigure_folder(FolderBrowser *fb); - void mail_local_reconfigure_folder(FolderBrowser *fb) { @@ -809,6 +814,7 @@ do_register_folder (gpointer in_data, gpointer op_data, CamelException *ex) if (meta->indexed) flags |= CAMEL_STORE_FOLDER_BODY_INDEX; local_folder->folder = camel_store_get_folder (store, meta->name, flags, ex); + printf("got folder exception %s\n", camel_exception_get_description(ex)); local_folder->last_unread = camel_folder_get_unread_message_count(local_folder->folder); camel_object_unref (CAMEL_OBJECT (store)); free_metainfo (meta); @@ -868,7 +874,32 @@ local_storage_new_folder_cb (EvolutionStorageListener *storage_listener, local_folder->path = g_strdup (path); local_folder->local_store = local_store; camel_object_ref((CamelObject *)local_store); - mail_operation_queue (&op_register_folder, local_folder, FALSE); + + /* Note: This needs to be synchronous, as that is what the shell + expects. Doesn't that suck. */ + /* This used to be made 'synchronous' by having us wait for + outstanding requests, which was BAD */ + + /*mail_operation_queue (&op_register_folder, local_folder, FALSE);*/ + { + CamelException *ex = camel_exception_new(); + + do_register_folder(local_folder, NULL, ex); + cleanup_register_folder(local_folder, NULL, ex); + +#if 0 + /* yay, so we can't do this, because we've probably got the bloody + splash screen up */ + if (camel_exception_is_set(ex)) { + char *msg = g_strdup_printf(_("Unable to register folder '%s':\n%s"), + path, camel_exception_get_description(ex)); + GnomeDialog *gd = (GnomeDialog *)gnome_error_dialog(msg); + gnome_dialog_run_and_close(gd); + g_free(msg); + } +#endif + camel_exception_free(ex); + } } static void diff --git a/mail/mail-mt.c b/mail/mail-mt.c new file mode 100644 index 0000000000..3441228ea4 --- /dev/null +++ b/mail/mail-mt.c @@ -0,0 +1,517 @@ + +#include +#include + +#include "e-util/e-msgport.h" +#include +#include + +#include "mail-mt.h" + +#include +#include +#include +#include +#include + +#include "folder-browser-factory.h" + +#define d(x) + +static void set_view_data(const char *current_message, int busy); + +static unsigned int mail_msg_seq; + +void *mail_msg_new(mail_msg_op_t *ops, EMsgPort *reply_port, size_t size) +{ + struct _mail_msg *msg; + + msg = g_malloc0(size); + msg->ops = ops; + msg->seq = mail_msg_seq++; + msg->msg.reply_port = reply_port; + camel_exception_init(&msg->ex); + + return msg; +} + +void mail_msg_free(void *msg) +{ + struct _mail_msg *m = msg; + + if (m->ops->destroy_msg) + m->ops->destroy_msg(m); + camel_exception_clear(&m->ex); + g_free(m); +} + +void mail_msg_check_error(void *msg) +{ + struct _mail_msg *m = msg; + char *what = NULL; + char *text; + GnomeDialog *gd; + + if (!camel_exception_is_set(&m->ex)) + return; + + if (m->ops->describe_msg) + what = m->ops->describe_msg(m, FALSE); + + if (what) + text = g_strdup_printf(_("Error while '%s':\n%s"), what, camel_exception_get_description(&m->ex)); + else + text = g_strdup_printf(_("Error while performing operation:\n%s"), camel_exception_get_description(&m->ex)); + + gd = (GnomeDialog *)gnome_error_dialog(text); + gnome_dialog_run_and_close(gd); + g_free(text); +} + +EMsgPort *mail_gui_port; +static GIOChannel *mail_gui_channel; +EMsgPort *mail_gui_reply_port; +static GIOChannel *mail_gui_reply_channel; + +/* a couple of global threads available */ +EThread *mail_thread_queued; /* for operations that can (or should) be queued */ +EThread *mail_thread_new; /* for operations that should run in a new thread each time */ + +static gboolean +mail_msgport_replied(GIOChannel *source, GIOCondition cond, void *d) +{ + EMsgPort *port = (EMsgPort *)d; + mail_msg_t *m; + + while (( m = (mail_msg_t *)e_msgport_get(port))) { + if (m->ops->reply_msg) + m->ops->reply_msg(m); + mail_msg_check_error(m); + if (m->ops->describe_msg) + mail_status_end(); + mail_msg_free(m); + } + + return TRUE; +} + +static gboolean +mail_msgport_received(GIOChannel *source, GIOCondition cond, void *d) +{ + EMsgPort *port = (EMsgPort *)d; + mail_msg_t *m; + + while (( m = (mail_msg_t *)e_msgport_get(port))) { + if (m->ops->describe_msg) { + char *text = m->ops->describe_msg(m, FALSE); + mail_status_start(text); + g_free(text); + } + if (m->ops->receive_msg) + m->ops->receive_msg(m); + if (m->msg.reply_port) + e_msgport_reply((EMsg *)m); + else { + if (m->ops->reply_msg) + m->ops->reply_msg(m); + if (m->ops->describe_msg) + mail_status_end(); + mail_msg_free(m); + } + } + + return TRUE; +} + +static void +mail_msg_destroy(EThread *e, EMsg *msg, void *data) +{ + mail_msg_t *m = (mail_msg_t *)msg; + + if (m->ops->describe_msg) + mail_status_end(); + mail_msg_free(m); +} + +static void +mail_msg_received(EThread *e, EMsg *msg, void *data) +{ + mail_msg_t *m = (mail_msg_t *)msg; + + if (m->ops->describe_msg) { + char *text = m->ops->describe_msg(m, FALSE); + printf("message received at thread\n"); + mail_status_start(text); + g_free(text); + } + + if (m->ops->receive_msg) + m->ops->receive_msg(m); +} + +void mail_msg_init(void) +{ + mail_gui_reply_port = e_msgport_new(); + mail_gui_reply_channel = g_io_channel_unix_new(e_msgport_fd(mail_gui_reply_port)); + g_io_add_watch(mail_gui_reply_channel, G_IO_IN, mail_msgport_replied, mail_gui_reply_port); + + mail_gui_port = e_msgport_new(); + mail_gui_channel = g_io_channel_unix_new(e_msgport_fd(mail_gui_port)); + g_io_add_watch(mail_gui_channel, G_IO_IN, mail_msgport_received, mail_gui_port); + + mail_thread_queued = e_thread_new(E_THREAD_QUEUE); + e_thread_set_msg_destroy(mail_thread_queued, mail_msg_destroy, 0); + e_thread_set_msg_received(mail_thread_queued, mail_msg_received, 0); + e_thread_set_reply_port(mail_thread_queued, mail_gui_reply_port); + + mail_thread_new = e_thread_new(E_THREAD_NEW); + e_thread_set_msg_destroy(mail_thread_new, mail_msg_destroy, 0); + e_thread_set_msg_received(mail_thread_new, mail_msg_received, 0); + e_thread_set_reply_port(mail_thread_new, mail_gui_reply_port); +} + +/* ********************************************************************** */ + +struct _set_msg { + struct _mail_msg msg; + char *text; +}; + +/* locks */ +static pthread_mutex_t status_lock = PTHREAD_MUTEX_INITIALIZER; +#define STATUS_BUSY_PENDING (2) + +#define MAIL_MT_LOCK(x) pthread_mutex_lock(&x) +#define MAIL_MT_UNLOCK(x) pthread_mutex_unlock(&x) + +/* blah blah */ + +#define STATUS_DELAY (5) + +static int status_depth; +static int status_showing; +static int status_shown; +static char *status_message_next; +static int status_message_clear; +static int status_timeout_id; +static int status_busy; + +struct _status_msg { + struct _mail_msg msg; + char *text; + int busy; +}; + +static gboolean +status_timeout(void *data) +{ + char *msg; + int busy = 0; + + d(printf("got status timeout\n")); + + MAIL_MT_LOCK(status_lock); + if (status_message_next) { + d(printf("setting message to '%s' busy %d\n", status_message_next, status_busy)); + msg = status_message_next; + status_message_next = NULL; + busy = status_depth > 0; + status_message_clear = 0; + MAIL_MT_UNLOCK(status_lock); + + /* copy msg so we can set it outside the lock */ + /* unset first is a hack to avoid the stack stuff that doesn't and can't work anyway */ + if (status_shown) + set_view_data(NULL, FALSE); + status_shown = TRUE; + set_view_data(msg, busy); + g_free(msg); + return TRUE; + } + + /* the delay-clear stuff doesn't work yet. Dont care ... */ + + status_showing = FALSE; + status_message_clear++; + if (status_message_clear >= STATUS_DELAY && status_depth==0) { + d(printf("clearing message, busy = %d\n", status_depth)); + } else { + d(printf("delaying clear\n")); + MAIL_MT_UNLOCK(status_lock); + return TRUE; + } + + status_timeout_id = 0; + + MAIL_MT_UNLOCK(status_lock); + + if (status_shown) + set_view_data(NULL, FALSE); + status_shown = FALSE; + + return FALSE; +} + +static void do_set_status(struct _mail_msg *mm) +{ + struct _status_msg *m = (struct _status_msg *)mm; + + MAIL_MT_LOCK(status_lock); + + if (status_timeout_id != 0) + gtk_timeout_remove(status_timeout_id); + + status_timeout_id = gtk_timeout_add(500, status_timeout, 0); + status_message_clear = 0; + + MAIL_MT_UNLOCK(status_lock); + + /* the 'clear' stuff doesn't really work yet, but oh well, + this stuff here needs a little changing for it to work */ + if (status_shown) + set_view_data(NULL, status_depth != 0); + status_shown = 0; + + if (m->text) { + status_shown = 1; + set_view_data(m->text, status_depth != 0); + } +} + +static void do_del_status(struct _mail_msg *mm) +{ + struct _status_msg *m = (struct _status_msg *)mm; + + g_free(m->text); +} + +struct _mail_msg_op set_status_op = { + NULL, + do_set_status, + NULL, + do_del_status, +}; + +/* start a new operation */ +void mail_status_start(const char *msg) +{ + struct _status_msg *m = NULL; + + MAIL_MT_LOCK(status_lock); + status_depth++; + MAIL_MT_UNLOCK(status_lock); + + if (msg == NULL || msg[0] == 0) + msg = _("Working"); + + m = mail_msg_new(&set_status_op, NULL, sizeof(*m)); + m->text = g_strdup(msg); + m->busy = TRUE; + + e_msgport_put(mail_gui_port, &m->msg.msg); +} + +/* end it */ +void mail_status_end(void) +{ + struct _status_msg *m = NULL; + + m = mail_msg_new(&set_status_op, NULL, sizeof(*m)); + m->text = NULL; + + MAIL_MT_LOCK(status_lock); + status_depth--; + m->busy = status_depth = 0; + MAIL_MT_UNLOCK(status_lock); + + e_msgport_put(mail_gui_port, &m->msg.msg); +} + +/* message during it */ +void mail_status(const char *msg) +{ + if (msg == NULL || msg[0] == 0) + msg = _("Working"); + + MAIL_MT_LOCK(status_lock); + + g_free(status_message_next); + status_message_next = g_strdup(msg); + + MAIL_MT_UNLOCK(status_lock); +} + +void mail_statusf(const char *fmt, ...) +{ + va_list ap; + char *text; + + va_start(ap, fmt); + text = g_strdup_vprintf(fmt, ap); + va_end(ap); + mail_status(text); + g_free(text); +} + +/* ********************************************************************** */ + +struct _pass_msg { + struct _mail_msg msg; + char *prompt; + int secret; + char *result; +}; + +/* libgnomeui's idea of an api/gui is very weird ... hence this dumb hack */ +static void focus_on_entry(GtkWidget *widget, void *user_data) +{ + if (GTK_IS_ENTRY(widget)) + gtk_widget_grab_focus(widget); +} + +static void pass_got(char *string, void *data) +{ + struct _pass_msg *m = data; + + if (string) + m->result = g_strdup (string); +} + +static void +do_get_pass(struct _mail_msg *mm) +{ + struct _pass_msg *m = (struct _pass_msg *)mm; + GtkWidget *dialogue; + + /* this api is just awful ... hence the hacks */ + dialogue = gnome_request_dialog(m->secret, m->prompt, NULL, + 0, pass_got, m, NULL); + e_container_foreach_leaf((GtkContainer *)dialogue, focus_on_entry, NULL); + + /* hrm, we can't run this async since the gui_port from which we're called + will reply to our message for us */ + gnome_dialog_run_and_close((GnomeDialog *)dialogue); + + /*gtk_widget_show(dialogue);*/ +} + +static void +do_free_pass(struct _mail_msg *mm) +{ + /*struct _pass_msg *m = (struct _pass_msg *)mm;*/ + + /* the string is passed out so we dont need to free it */ +} + +struct _mail_msg_op get_pass_op = { + NULL, + do_get_pass, + NULL, + do_free_pass, +}; + +/* returns the password, or NULL if cancelled */ +char * +mail_get_password(char *prompt, gboolean secret) +{ + char *ret; + struct _pass_msg *m, *r; + EMsgPort *pass_reply; + + pass_reply = e_msgport_new(); + + m = mail_msg_new(&get_pass_op, pass_reply, sizeof(*m)); + + m->prompt = prompt; + m->secret = secret; + + e_msgport_put(mail_gui_port, (EMsg *)m); + e_msgport_wait(pass_reply); + r = (struct _pass_msg *)e_msgport_get(pass_reply); + + g_assert(r == m); + + ret = m->result; + + mail_msg_free(m); + e_msgport_destroy(pass_reply); + + return ret; +} + + + +/* ******************** */ + +/* FIXME FIXME FIXME This is a totally evil hack. */ + +static GNOME_Evolution_ShellView +retrieve_shell_view_interface_from_control (BonoboControl *control) +{ + Bonobo_ControlFrame control_frame; + GNOME_Evolution_ShellView shell_view_interface; + CORBA_Environment ev; + + control_frame = bonobo_control_get_control_frame (control); + + if (control_frame == NULL) + return CORBA_OBJECT_NIL; + + CORBA_exception_init (&ev); + shell_view_interface = Bonobo_Unknown_queryInterface (control_frame, + "IDL:GNOME/Evolution/ShellView:1.0", + &ev); + CORBA_exception_free (&ev); + + if (shell_view_interface != CORBA_OBJECT_NIL) + gtk_object_set_data (GTK_OBJECT (control), + "mail_threads_shell_view_interface", + shell_view_interface); + else + g_warning ("Control frame doesn't have Evolution/ShellView."); + + return shell_view_interface; +} + +static void +set_view_data(const char *current_message, int busy) +{ + EList *controls; + EIterator *it; + + controls = folder_browser_factory_get_control_list (); + for (it = e_list_get_iterator (controls); e_iterator_is_valid (it); e_iterator_next (it)) { + BonoboControl *control; + GNOME_Evolution_ShellView shell_view_interface; + CORBA_Environment ev; + + control = BONOBO_CONTROL (e_iterator_get (it)); + + shell_view_interface = gtk_object_get_data (GTK_OBJECT (control), "mail_threads_shell_view_interface"); + + if (shell_view_interface == CORBA_OBJECT_NIL) + shell_view_interface = retrieve_shell_view_interface_from_control (control); + + CORBA_exception_init (&ev); + + if (shell_view_interface != CORBA_OBJECT_NIL) { + if ((current_message == NULL || current_message[0] == 0) && ! busy) { + printf("clearing msg\n"); + GNOME_Evolution_ShellView_unsetMessage (shell_view_interface, &ev); + } else { + printf("setting msg %s\n", current_message); + GNOME_Evolution_ShellView_setMessage (shell_view_interface, + current_message?current_message:"", + busy, + &ev); + } + } + + CORBA_exception_free (&ev); + + /* yeah we only set the first one. Why? Because it seems to leave + random ones lying around otherwise. Shrug. */ + break; + } + gtk_object_unref(GTK_OBJECT(it)); +} diff --git a/mail/mail-mt.h b/mail/mail-mt.h new file mode 100644 index 0000000000..c98785660c --- /dev/null +++ b/mail/mail-mt.h @@ -0,0 +1,73 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Authors: Michael Zucchi + * + * Copyright 2000, Helix Code, Inc. (http://www.helixcode.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _MAIL_MT +#define _MAIL_MT + +#include "camel/camel-exception.h" +#include "e-util/e-msgport.h" + +typedef struct _mail_msg { + EMsg msg; /* parent type */ + struct _mail_msg_op *ops; /* operation functions */ + unsigned int seq; /* seq number for synchronisation */ + CamelException ex; /* an initialised camel exception, upto the caller to use this */ +} mail_msg_t; + +/* callback functions for thread message */ +typedef struct _mail_msg_op { + char *(*describe_msg)(struct _mail_msg *msg, int complete); + + void (*receive_msg)(struct _mail_msg *msg); /* message received */ + void (*reply_msg)(struct _mail_msg *msg); /* message replied */ + void (*destroy_msg)(struct _mail_msg *msg); /* finalise message */ +} mail_msg_op_t; + +/* setup ports */ +void mail_msg_init(void); + +/* allocate a new message */ +void *mail_msg_new(mail_msg_op_t *ops, EMsgPort *reply_port, size_t size); +void mail_msg_free(void *msg); +void mail_msg_check_error(void *msg); + +/* set the status-bar message */ +/* start/end a new op */ +void mail_status_start(const char *msg); +void mail_status_end(void); +/* set a status during an op */ +void mail_statusf(const char *fmt, ...); +void mail_status(const char *msg); + +/* request a string/password */ +char *mail_get_password(char *prompt, gboolean secret); + +/* a message port that receives messages in the gui thread, used for sending port */ +extern EMsgPort *mail_gui_port; +/* a message port that receives messages in the gui thread, used for the reply port */ +extern EMsgPort *mail_gui_reply_port; + +/* some globally available threads */ +extern EThread *mail_thread_queued; /* for operations that can (or should) be queued */ +extern EThread *mail_thread_new; /* for operations that should run in a new thread each time */ + +#endif /* ! _MAIL_MT */ diff --git a/mail/mail-ops.c b/mail/mail-ops.c index 34ec1c6493..50464e1859 100644 --- a/mail/mail-ops.c +++ b/mail/mail-ops.c @@ -37,11 +37,15 @@ #include "folder-browser.h" #include "e-util/e-html-utils.h" +#include "mail-mt.h" + #define d(x) x -/* temporary 'hack' */ int mail_operation_run(const mail_operation_spec *op, void *in, int free); +#define mail_tool_camel_lock_down() +#define mail_tool_camel_lock_up() + /* ** FETCH MAIL ********************************************************** */ typedef struct fetch_mail_input_s @@ -123,7 +127,7 @@ mail_op_report_status (FilterDriver *driver, enum filter_status_t status, const /* FIXME: make it work */ switch (status) { case FILTER_STATUS_START: - mail_op_set_message_plain (desc); + mail_status(desc); break; case FILTER_STATUS_END: break; @@ -753,8 +757,6 @@ do_send_queue (gpointer in_data, gpointer op_data, CamelException *ex) for (i = 0; i < uids->len; i++) { CamelMimeMessage *message; - mail_tool_camel_lock_up (); - message = camel_folder_get_message (input->folder_queue, uids->pdata[i], ex); if (camel_exception_is_set (ex)) break; @@ -764,7 +766,6 @@ do_send_queue (gpointer in_data, gpointer op_data, CamelException *ex) camel_mime_message_set_date (message, CAMEL_MESSAGE_DATE_CURRENT, 0); xport = camel_session_get_transport (session, input->xport_uri, ex); - mail_tool_camel_lock_down (); if (camel_exception_is_set (ex)) break; @@ -774,26 +775,20 @@ do_send_queue (gpointer in_data, gpointer op_data, CamelException *ex) if (camel_exception_is_set (ex)) break; - mail_tool_camel_lock_up (); set = camel_folder_get_message_flags (input->folder_queue, uids->pdata[i]); camel_folder_set_message_flags (input->folder_queue, uids->pdata[i], CAMEL_MESSAGE_DELETED, ~set); - mail_tool_camel_lock_down (); - + /* now to save the message in Sent */ if (sent_folder) { CamelMessageInfo *info; - mail_tool_camel_lock_up (); - info = g_new0 (CamelMessageInfo, 1); info->flags = CAMEL_MESSAGE_SEEN; camel_folder_append_message (sent_folder, message, info, ex); g_free (info); - - mail_tool_camel_lock_down (); } } @@ -802,6 +797,12 @@ do_send_queue (gpointer in_data, gpointer op_data, CamelException *ex) for (i = 0; i < uids->len; i++) g_free (uids->pdata[i]); g_ptr_array_free (uids, TRUE); + + if (!camel_exception_is_set(ex)) + camel_folder_expunge(input->folder_queue, NULL); + + if (sent_folder) + camel_folder_sync(sent_folder, FALSE, NULL); } static void @@ -930,56 +931,6 @@ mail_do_append_mail (CamelFolder *folder, mail_operation_queue (&op_append_mail, input, TRUE); } -/* ** EXPUNGE FOLDER ****************************************************** */ - -static gchar * -describe_expunge_folder (gpointer in_data, gboolean gerund) -{ - CamelFolder *f = CAMEL_FOLDER (in_data); - - if (gerund) - return g_strdup_printf (_("Expunging \"%s\""), mail_tool_get_folder_name (f)); - else - return g_strdup_printf (_("Expunge \"%s\""), mail_tool_get_folder_name (f)); -} - -static void -setup_expunge_folder (gpointer in_data, gpointer op_data, CamelException *ex) -{ - camel_object_ref (CAMEL_OBJECT (in_data)); -} - -static void -do_expunge_folder (gpointer in_data, gpointer op_data, CamelException *ex) -{ - mail_tool_camel_lock_up (); - camel_folder_expunge (CAMEL_FOLDER (in_data), ex); - mail_tool_camel_lock_down (); -} - -static void -cleanup_expunge_folder (gpointer in_data, gpointer op_data, - CamelException *ex) -{ - camel_object_unref (CAMEL_OBJECT (in_data)); -} - -static const mail_operation_spec op_expunge_folder = { - describe_expunge_folder, - 0, - setup_expunge_folder, - do_expunge_folder, - cleanup_expunge_folder -}; - -void -mail_do_expunge_folder (CamelFolder *folder) -{ - g_return_if_fail (CAMEL_IS_FOLDER (folder)); - - mail_operation_queue (&op_expunge_folder, folder, FALSE); -} - /* ** TRANSFER MESSAGES **************************************************** */ typedef struct transfer_messages_input_s @@ -1286,6 +1237,8 @@ typedef struct scan_subfolders_op_s } scan_subfolders_op_t; +static int scan_subfolders_done; + static gchar * describe_scan_subfolders (gpointer in_data, gboolean gerund) { @@ -1382,6 +1335,8 @@ cleanup_scan_subfolders (gpointer in_data, gpointer op_data, gtk_object_unref (GTK_OBJECT (input->storage)); camel_object_unref (CAMEL_OBJECT (input->store)); + + scan_subfolders_done = TRUE; } static const mail_operation_spec op_scan_subfolders = { @@ -1400,15 +1355,25 @@ mail_do_scan_subfolders (CamelStore *store, EvolutionStorage *storage) g_return_if_fail (CAMEL_IS_STORE (store)); g_return_if_fail (EVOLUTION_IS_STORAGE (storage)); + scan_subfolders_done = FALSE; + input = g_new (scan_subfolders_input_t, 1); input->store = store; input->storage = storage; mail_operation_queue (&op_scan_subfolders, input, TRUE); + + /* Ok, so this must run synchrounously, sigh */ + while (!scan_subfolders_done) { + gtk_main_iteration(); + } } /* ** ATTACH MESSAGE ****************************************************** */ +#warning "mail_do_attach_message() isn't used anywhere? Remove after confirming" +#if 0 + typedef struct attach_message_input_s { EMsgComposer *composer; @@ -1512,6 +1477,8 @@ mail_do_attach_message (CamelFolder *folder, const char *uid, mail_operation_queue (&op_attach_message, input, TRUE); } +#endif + /* ** FORWARD MESSAGES **************************************************** */ typedef struct forward_messages_input_s { @@ -1734,100 +1701,66 @@ mail_do_forward_message (CamelMimeMessage *basis, /* ** LOAD FOLDER ********************************************************* */ -typedef struct load_folder_input_s -{ - FolderBrowser *fb; - gchar *url; -} -load_folder_input_t; +struct _get_folder_msg { + struct _mail_msg msg; -static gchar * -describe_load_folder (gpointer in_data, gboolean gerund) -{ - load_folder_input_t *input = (load_folder_input_t *) in_data; + char *uri; + CamelFolder *folder; + void (*done) (char *uri, CamelFolder *folder, void *data); + void *data; +}; - if (gerund) { - return g_strdup_printf (_("Loading \"%s\""), input->url); - } else { - return g_strdup_printf (_("Load \"%s\""), input->url); - } +static char *get_folder_desc(struct _mail_msg *mm, int done) +{ + struct _get_folder_msg *m = (struct _get_folder_msg *)mm; + + return g_strdup_printf(_("Opening folder %s"), m->uri); } -static void -setup_load_folder (gpointer in_data, gpointer op_data, CamelException *ex) +static void get_folder_get(struct _mail_msg *mm) { - load_folder_input_t *input = (load_folder_input_t *) in_data; - - gtk_object_ref (GTK_OBJECT (input->fb)); - - if (input->fb->uri) - g_free (input->fb->uri); + struct _get_folder_msg *m = (struct _get_folder_msg *)mm; - input->fb->uri = input->url; + m->folder = mail_tool_uri_to_folder(m->uri, &mm->ex); } -static void -do_load_folder (gpointer in_data, gpointer op_data, CamelException *ex) +static void get_folder_got(struct _mail_msg *mm) { - load_folder_input_t *input = (load_folder_input_t *) in_data; - - CamelFolder *folder; + struct _get_folder_msg *m = (struct _get_folder_msg *)mm; - folder = mail_tool_uri_to_folder (input->url, ex); - if (!folder) - return; - - if (input->fb->folder) { - mail_tool_camel_lock_up (); - camel_object_unref (CAMEL_OBJECT (input->fb->folder)); - mail_tool_camel_lock_down (); - } + /* FIXME: what to do when it fails? */ - input->fb->folder = folder; + if (m->done) + m->done(m->uri, m->folder, m->data); } -static void -cleanup_load_folder (gpointer in_data, gpointer op_data, CamelException *ex) -{ - load_folder_input_t *input = (load_folder_input_t *) in_data; - - if (input->fb->folder) { - gtk_widget_set_sensitive (GTK_WIDGET (input->fb->search->entry), - camel_folder_has_search_capability (input-> - fb-> - folder)); - gtk_widget_set_sensitive (GTK_WIDGET (input->fb->search->option), - 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); - } +static void get_folder_free(struct _mail_msg *mm) +{ + struct _get_folder_msg *m = (struct _get_folder_msg *)mm; - gtk_object_unref (GTK_OBJECT (input->fb)); + g_free(m->uri); + if (m->folder) + camel_object_unref((CamelObject *)m->folder); } -static const mail_operation_spec op_load_folder = { - describe_load_folder, - 0, - setup_load_folder, - do_load_folder, - cleanup_load_folder +static struct _mail_msg_op get_folder_op = { + get_folder_desc, + get_folder_get, + get_folder_got, + get_folder_free, }; void -mail_do_load_folder (FolderBrowser *fb, const char *url) +mail_get_folder(const char *uri, void (*done) (char *uri, CamelFolder *folder, void *data), void *data) { - load_folder_input_t *input; - - g_return_if_fail (IS_FOLDER_BROWSER (fb)); - g_return_if_fail (url != NULL); + struct _get_folder_msg *m; - input = g_new (load_folder_input_t, 1); - input->fb = fb; - input->url = g_strdup (url); + m = mail_msg_new(&get_folder_op, NULL, sizeof(*m)); + m->uri = g_strdup(uri); + m->data = data; + m->done = done; - mail_operation_queue (&op_load_folder, input, TRUE); + e_thread_put(mail_thread_new, (EMsg *)m); } /* ** CREATE FOLDER ******************************************************* */ @@ -1940,186 +1873,238 @@ mail_do_create_folder (const GNOME_Evolution_ShellComponentListener listener, mail_operation_queue (&op_create_folder, input, FALSE); } - /* ** SYNC FOLDER ********************************************************* */ -static gchar * -describe_sync_folder (gpointer in_data, gboolean gerund) +struct _sync_folder_msg { + struct _mail_msg msg; + + CamelFolder *folder; + void (*done) (CamelFolder *folder, void *data); + void *data; +}; + +static void sync_folder_sync(struct _mail_msg *mm) { - CamelFolder *f = CAMEL_FOLDER (in_data); + struct _sync_folder_msg *m = (struct _sync_folder_msg *)mm; - if (gerund) { - return g_strdup_printf (_("Synchronizing \"%s\""), mail_tool_get_folder_name (f)); - } else { - return g_strdup_printf (_("Synchronize \"%s\""), mail_tool_get_folder_name (f)); - } + camel_folder_sync(m->folder, FALSE, &mm->ex); } -static void -setup_sync_folder (gpointer in_data, gpointer op_data, CamelException *ex) { - camel_object_ref (CAMEL_OBJECT (in_data)); +static void sync_folder_synced(struct _mail_msg *mm) +{ + struct _sync_folder_msg *m = (struct _sync_folder_msg *)mm; + + if (m->done) + m->done(m->folder, m->data); } -static void -do_sync_folder (gpointer in_data, gpointer op_data, CamelException *ex) +static void sync_folder_free(struct _mail_msg *mm) { - mail_tool_camel_lock_up (); - camel_folder_sync (CAMEL_FOLDER (in_data), FALSE, ex); - mail_tool_camel_lock_down (); + struct _sync_folder_msg *m = (struct _sync_folder_msg *)mm; + + camel_object_unref((CamelObject *)m->folder); } -static void -cleanup_sync_folder (gpointer in_data, gpointer op_data, CamelException *ex) +static struct _mail_msg_op sync_folder_op = { + NULL, + sync_folder_sync, + sync_folder_synced, + sync_folder_free, +}; + +void +mail_sync_folder(CamelFolder *folder, void (*done) (CamelFolder *folder, void *data), void *data) { - camel_object_unref (CAMEL_OBJECT (in_data)); + struct _sync_folder_msg *m; + + m = mail_msg_new(&sync_folder_op, NULL, sizeof(*m)); + m->folder = folder; + camel_object_ref((CamelObject *)folder); + m->data = data; + m->done = done; + + e_thread_put(mail_thread_new, (EMsg *)m); } -static const mail_operation_spec op_sync_folder = { - describe_sync_folder, - 0, - setup_sync_folder, - do_sync_folder, - cleanup_sync_folder +/* ******************************************************************************** */ + +static void expunge_folder_expunge(struct _mail_msg *mm) +{ + struct _sync_folder_msg *m = (struct _sync_folder_msg *)mm; + + camel_folder_expunge(m->folder, &mm->ex); +} + +/* we just use the sync stuff where we can, since it would be the same */ +static struct _mail_msg_op expunge_folder_op = { + NULL, + expunge_folder_expunge, + sync_folder_synced, + sync_folder_free, }; void -mail_do_sync_folder (CamelFolder *folder) +mail_expunge_folder(CamelFolder *folder, void (*done) (CamelFolder *folder, void *data), void *data) { - g_return_if_fail (CAMEL_IS_FOLDER (folder)); + struct _sync_folder_msg *m; - /*mail_operation_queue (&op_sync_folder, folder, FALSE);*/ - mail_operation_run (&op_sync_folder, folder, FALSE); + m = mail_msg_new(&expunge_folder_op, NULL, sizeof(*m)); + m->folder = folder; + camel_object_ref((CamelObject *)folder); + m->data = data; + m->done = done; + + e_thread_put(mail_thread_new, (EMsg *)m); } -/* ** DISPLAY MESSAGE ***************************************************** */ +/* ** GET MESSAGE(s) ***************************************************** */ + +struct _get_message_msg { + struct _mail_msg msg; -typedef struct display_message_input_s + CamelFolder *folder; + char *uid; + void (*done) (CamelFolder *folder, char *uid, CamelMimeMessage *msg, void *data); + void *data; + CamelMimeMessage *message; +}; + +static char *get_message_desc(struct _mail_msg *mm, int done) { - MessageList *ml; - MailDisplay *md; - gchar *uid; - gint (*timeout) (gpointer); + struct _get_message_msg *m = (struct _get_message_msg *)mm; + + return g_strdup_printf(_("Retrieving message %s"), m->uid); } -display_message_input_t; -typedef struct display_message_data_s +static void get_message_get(struct _mail_msg *mm) { - CamelMimeMessage *msg; + struct _get_message_msg *m = (struct _get_message_msg *)mm; + + m->message = camel_folder_get_message(m->folder, m->uid, &mm->ex); } -display_message_data_t; -static gchar * -describe_display_message (gpointer in_data, gboolean gerund) +static void get_message_got(struct _mail_msg *mm) { - display_message_input_t *input = (display_message_input_t *) in_data; + struct _get_message_msg *m = (struct _get_message_msg *)mm; - if (gerund) { - if (input->uid) - return g_strdup_printf (_("Displaying message UID \"%s\""), - input->uid); - else - return g_strdup (_("Clearing message display")); - } else { - if (input->uid) - return g_strdup_printf (_("Display message UID \"%s\""), - input->uid); - else - return g_strdup (_("Clear message display")); - } + if (m->done) + m->done(m->folder, m->uid, m->message, m->data); } -static void -setup_display_message (gpointer in_data, gpointer op_data, - CamelException *ex) +static void get_message_free(struct _mail_msg *mm) { - display_message_input_t *input = (display_message_input_t *) in_data; - display_message_data_t *data = (display_message_data_t *) op_data; + struct _get_message_msg *m = (struct _get_message_msg *)mm; - data->msg = NULL; - gtk_object_ref (GTK_OBJECT (input->ml)); + g_free(m->uid); + camel_object_unref((CamelObject *)m->folder); } -static void -do_display_message (gpointer in_data, gpointer op_data, CamelException *ex) +static struct _mail_msg_op get_message_op = { + get_message_desc, + get_message_get, + get_message_got, + get_message_free, +}; + +void +mail_get_message(CamelFolder *folder, const char *uid, void (*done) (CamelFolder *folder, char *uid, CamelMimeMessage *msg, void *data), void *data, EThread *thread) { - display_message_input_t *input = (display_message_input_t *) in_data; - display_message_data_t *data = (display_message_data_t *) op_data; + struct _get_message_msg *m; - if (input->uid == NULL) { - data->msg = NULL; - return; - } + m = mail_msg_new(&get_message_op, NULL, sizeof(*m)); + m->folder = folder; + camel_object_ref((CamelObject *)folder); + m->uid = g_strdup(uid); + m->data = data; + m->done = done; - data->msg = camel_folder_get_message (input->ml->folder, input->uid, ex); + e_thread_put(thread, (EMsg *)m); } -static void -cleanup_display_message (gpointer in_data, gpointer op_data, - CamelException *ex) +/* ********************************************************************** */ + +struct _get_messages_msg { + struct _mail_msg msg; + + CamelFolder *folder; + GPtrArray *uids; + GPtrArray *messages; + + void (*done) (CamelFolder *folder, GPtrArray *uids, GPtrArray *msgs, void *data); + void *data; +}; + +static char * get_messages_desc(struct _mail_msg *mm, int done) { - display_message_input_t *input = (display_message_input_t *) in_data; - display_message_data_t *data = (display_message_data_t *) op_data; - MailDisplay *md = input->md; + return g_strdup_printf(_("Retrieving messages")); +} - if (data->msg == NULL) { - mail_display_set_message (md, NULL); - } else { - gint timeout = mail_config_mark_as_seen_timeout (); +static void get_messages_get(struct _mail_msg *mm) +{ + struct _get_messages_msg *m = (struct _get_messages_msg *)mm; + int i; + CamelMimeMessage *message; - if (input->ml->seen_id) - gtk_timeout_remove (input->ml->seen_id); + for (i=0; iuids->len; i++) { + mail_statusf(_("Retrieving message number %d of %d (uid \"%s\")"), + i+1, m->uids->len, (char *) m->uids->pdata[i]); - mail_display_set_message (md, CAMEL_MEDIUM (data->msg)); - camel_object_unref (CAMEL_OBJECT (data->msg)); + message = camel_folder_get_message(m->folder, m->uids->pdata[i], &mm->ex); + if (message == NULL) + break; - if (timeout > 0) { - input->ml->seen_id = gtk_timeout_add (timeout, - input->timeout, - input->ml); - } else { - input->ml->seen_id = 0; - input->timeout (input->ml); - } + g_ptr_array_add(m->messages, message); } +} + +static void get_messages_got(struct _mail_msg *mm) +{ + struct _get_messages_msg *m = (struct _get_messages_msg *)mm; - if (input->uid) - g_free (input->uid); - gtk_object_unref (GTK_OBJECT (input->ml)); + if (m->done) + m->done(m->folder, m->uids, m->messages, m->data); } -static const mail_operation_spec op_display_message = { - describe_display_message, - sizeof (display_message_data_t), - setup_display_message, - do_display_message, - cleanup_display_message +static void get_messages_free(struct _mail_msg *mm) +{ + struct _get_messages_msg *m = (struct _get_messages_msg *)mm; + int i; + + for (i=0;iuids->len;i++) + g_free(m->uids->pdata[i]); + g_ptr_array_free(m->uids, TRUE); + for (i=0;imessages->len;i++) { + if (m->messages->pdata[i]) + camel_object_unref((CamelObject *)m->messages->pdata[i]); + } + g_ptr_array_free(m->messages, TRUE); + camel_object_unref((CamelObject *)m->folder); +} + +static struct _mail_msg_op get_messages_op = { + get_messages_desc, + get_messages_get, + get_messages_got, + get_messages_free, }; void -mail_do_display_message (MessageList *ml, MailDisplay *md, const char *uid, - gint (*timeout) (gpointer)) +mail_get_messages(CamelFolder *folder, GPtrArray *uids, void (*done) (CamelFolder *folder, GPtrArray *uids, GPtrArray *msgs, void *data), void *data) { - display_message_input_t *input; - - g_return_if_fail (IS_MESSAGE_LIST (ml)); - g_return_if_fail (timeout != NULL); - - if (uid == NULL) { - mail_display_set_message (md, NULL); - return; - } + struct _get_messages_msg *m; - input = g_new (display_message_input_t, 1); - input->ml = ml; - input->md = md; - input->uid = g_strdup (uid); - input->timeout = timeout; + m = mail_msg_new(&get_messages_op, NULL, sizeof(*m)); + m->folder = folder; + camel_object_ref((CamelObject *)folder); + m->uids = uids; + m->messages = g_ptr_array_new(); + m->data = data; + m->done = done; - /* this is only temporary */ - /*mail_operation_queue (&op_display_message, input, TRUE);*/ - mail_operation_run (&op_display_message, input, TRUE); + e_thread_put(mail_thread_new, (EMsg *)m); } + /* dum de dum, below is an entirely async 'operation' thingy */ struct _op_data { void *out; @@ -2195,180 +2180,6 @@ mail_operation_run(const mail_operation_spec *op, void *in, int free) return TRUE; } - -/* ** EDIT MESSAGES ******************************************************* */ - -typedef struct edit_messages_input_s { - CamelFolder *folder; - GPtrArray *uids; - GtkSignalFunc signal; -} edit_messages_input_t; - -typedef struct edit_messages_data_s { - GPtrArray *messages; -} edit_messages_data_t; - -static gchar * -describe_edit_messages (gpointer in_data, gboolean gerund) -{ - edit_messages_input_t *input = (edit_messages_input_t *) in_data; - - if (gerund) - return g_strdup_printf - (_("Opening messages from folder \"%s\""), - mail_tool_get_folder_name (input->folder)); - else - return g_strdup_printf (_("Open messages from \"%s\""), - mail_tool_get_folder_name (input->folder)); -} - -static void -setup_edit_messages (gpointer in_data, gpointer op_data, CamelException *ex) -{ - edit_messages_input_t *input = (edit_messages_input_t *) in_data; - - camel_object_ref (CAMEL_OBJECT (input->folder)); -} - -static void -do_edit_messages (gpointer in_data, gpointer op_data, CamelException *ex) -{ - edit_messages_input_t *input = (edit_messages_input_t *) in_data; - edit_messages_data_t *data = (edit_messages_data_t *) op_data; - - int i; - - data->messages = g_ptr_array_new (); - - for (i = 0; i < input->uids->len; i++) { - CamelMimeMessage *message; - - mail_tool_camel_lock_up (); - message = camel_folder_get_message (input->folder, input->uids->pdata[i], ex); - mail_tool_camel_lock_down (); - - if (message) - g_ptr_array_add (data->messages, message); - - g_free (input->uids->pdata[i]); - } -} - -static void -cleanup_edit_messages (gpointer in_data, gpointer op_data, - CamelException *ex) -{ - edit_messages_input_t *input = (edit_messages_input_t *) in_data; - edit_messages_data_t *data = (edit_messages_data_t *) op_data; - - int i; - - for (i = 0; i < data->messages->len; i++) { - EMsgComposer *composer; - - composer = e_msg_composer_new_with_message (data->messages->pdata[i]); - camel_object_unref (CAMEL_OBJECT (data->messages->pdata[i])); - if (!composer) - continue; - - if (input->signal) - gtk_signal_connect (GTK_OBJECT (composer), "send", - input->signal, NULL); - - gtk_widget_show (GTK_WIDGET (composer)); - } - - g_ptr_array_free (input->uids, TRUE); - g_ptr_array_free (data->messages, TRUE); - camel_object_unref (CAMEL_OBJECT (input->folder)); - -} - -static const mail_operation_spec op_edit_messages = { - describe_edit_messages, - sizeof (edit_messages_data_t), - setup_edit_messages, - do_edit_messages, - cleanup_edit_messages -}; - -void -mail_do_edit_messages (CamelFolder *folder, GPtrArray *uids, - GtkSignalFunc signal) -{ - edit_messages_input_t *input; - - g_return_if_fail (CAMEL_IS_FOLDER (folder)); - g_return_if_fail (uids != NULL); - - input = g_new (edit_messages_input_t, 1); - input->folder = folder; - input->uids = uids; - input->signal = signal; - - mail_operation_queue (&op_edit_messages, input, TRUE); -} - -/* ** SETUP FOLDER ****************************************************** */ - -typedef struct setup_folder_input_s { - gchar *name; - CamelFolder **folder; -} setup_folder_input_t; - -static gchar * -describe_setup_folder (gpointer in_data, gboolean gerund) -{ - setup_folder_input_t *input = (setup_folder_input_t *) in_data; - - if (gerund) - return g_strdup_printf (_("Loading %s Folder"), input->name); - else - return g_strdup_printf (_("Load %s Folder"), input->name); -} - -static void -do_setup_folder (gpointer in_data, gpointer op_data, CamelException *ex) -{ - setup_folder_input_t *input = (setup_folder_input_t *) in_data; - gchar *url; - - url = g_strdup_printf ("file://%s/local/%s", evolution_dir, - input->name); - *(input->folder) = mail_tool_uri_to_folder (url, ex); - g_free (url); -} - -static void -cleanup_setup_folder (gpointer in_data, gpointer op_data, CamelException *ex) -{ - setup_folder_input_t *input = (setup_folder_input_t *) in_data; - - g_free (input->name); -} - -static const mail_operation_spec op_setup_folder = { - describe_setup_folder, - 0, - NULL, - do_setup_folder, - cleanup_setup_folder -}; - -void -mail_do_setup_folder (const char *name, CamelFolder **folder) -{ - setup_folder_input_t *input; - - g_return_if_fail (name != NULL); - g_return_if_fail (folder != NULL); - - input = g_new (setup_folder_input_t, 1); - input->name = g_strdup (name); - input->folder = folder; - mail_operation_queue (&op_setup_folder, input, TRUE); -} - /* ** SETUP TRASH VFOLDER ************************************************* */ typedef struct setup_trash_input_s { @@ -2537,136 +2348,6 @@ mail_do_setup_trash (const char *name, const char *store_uri, CamelFolder **fold mail_operation_queue (&op_setup_trash, input, TRUE); } - -/* ** VIEW MESSAGES ******************************************************* */ - -typedef struct view_messages_input_s { - CamelFolder *folder; - GPtrArray *uids; - FolderBrowser *fb; -} view_messages_input_t; - -typedef struct view_messages_data_s { - GPtrArray *messages; -} view_messages_data_t; - -static gchar * -describe_view_messages (gpointer in_data, gboolean gerund) -{ - view_messages_input_t *input = (view_messages_input_t *) in_data; - - if (gerund) - return g_strdup_printf - (_("Viewing messages from folder \"%s\""), - mail_tool_get_folder_name (input->folder)); - else - return g_strdup_printf (_("View messages from \"%s\""), - mail_tool_get_folder_name (input->folder)); -} - -static void -setup_view_messages (gpointer in_data, gpointer op_data, CamelException *ex) -{ - view_messages_input_t *input = (view_messages_input_t *) in_data; - - camel_object_ref (CAMEL_OBJECT (input->folder)); - gtk_object_ref (GTK_OBJECT (input->fb)); -} - -static void -do_view_messages (gpointer in_data, gpointer op_data, CamelException *ex) -{ - view_messages_input_t *input = (view_messages_input_t *) in_data; - view_messages_data_t *data = (view_messages_data_t *) op_data; - time_t last_update = 0; - int i; - - data->messages = g_ptr_array_new (); - - for (i = 0; i < input->uids->len; i++) { - CamelMimeMessage *message; - const gboolean last_message = (i+1 == input->uids->len); - time_t now; - - /* - * Update display every 2 seconds - */ - time (&now); - if (last_message || ((now - last_update) > 2)) { - mail_op_set_message (_("Retrieving message %d of %d (uid \"%s\")"), - i + 1, input->uids->len, (char *)input->uids->pdata[i]); - last_update = now; - } - - mail_tool_camel_lock_up (); - message = camel_folder_get_message (input->folder, input->uids->pdata[i], ex); - mail_tool_camel_lock_down (); - - g_ptr_array_add (data->messages, message); - } -} - -static void -cleanup_view_messages (gpointer in_data, gpointer op_data, - CamelException *ex) -{ - view_messages_input_t *input = (view_messages_input_t *) in_data; - view_messages_data_t *data = (view_messages_data_t *) op_data; - - int i; - - for (i = 0; i < data->messages->len; i++) { - CamelMimeMessage *msg; - gchar *uid; - GtkWidget *view; - - if (data->messages->pdata[i] == NULL) - continue; - - msg = data->messages->pdata[i]; - uid = input->uids->pdata[i]; - - view = mail_view_create (input->folder, uid, msg); - gtk_widget_show (view); - - /*Owned by the mail_display now*/ - camel_object_unref (CAMEL_OBJECT (data->messages->pdata[i])); - g_free (uid); - } - - g_ptr_array_free (input->uids, TRUE); - g_ptr_array_free (data->messages, TRUE); - camel_object_unref (CAMEL_OBJECT (input->folder)); - gtk_object_unref (GTK_OBJECT (input->fb)); -} - -static const mail_operation_spec op_view_messages = { - describe_view_messages, - sizeof (view_messages_data_t), - setup_view_messages, - do_view_messages, - cleanup_view_messages -}; - -void -mail_do_view_messages (CamelFolder *folder, GPtrArray *uids, - FolderBrowser *fb) -{ - view_messages_input_t *input; - - g_return_if_fail (CAMEL_IS_FOLDER (folder)); - g_return_if_fail (uids != NULL); - g_return_if_fail (IS_FOLDER_BROWSER (fb)); - - input = g_new (view_messages_input_t, 1); - input->folder = folder; - input->uids = uids; - input->fb = fb; - - mail_operation_queue (&op_view_messages, input, TRUE); -} - - /* ** SAVE MESSAGES ******************************************************* */ typedef struct save_messages_input_s { diff --git a/mail/mail-ops.h b/mail/mail-ops.h index 17ed16c9c5..bd51e1cc32 100644 --- a/mail/mail-ops.h +++ b/mail/mail-ops.h @@ -28,6 +28,7 @@ #include "evolution-storage.h" /*EvolutionStorage */ #include "composer/e-msg-composer.h" /*EMsgComposer */ #include "message-list.h" /*MessageList */ +#include "mail-mt.h" void mail_do_fetch_mail (const gchar *source_url, gboolean keep_on_server, CamelFolder *destination, @@ -45,7 +46,6 @@ void mail_do_send_queue (CamelFolder *folder_queue, void mail_do_append_mail (CamelFolder *folder, CamelMimeMessage *message, CamelMessageInfo *info); -void mail_do_expunge_folder (CamelFolder *folder); void mail_do_transfer_messages (CamelFolder *source, GPtrArray *uids, gboolean delete_from_source, gchar *dest_uri); @@ -60,16 +60,26 @@ void mail_do_attach_message (CamelFolder *folder, const char *uid, void mail_do_forward_message (CamelMimeMessage *basis, CamelFolder *source, GPtrArray *uids, /*array of allocated gchar *, will all be freed */ EMsgComposer *composer, gboolean attach); -void mail_do_load_folder (FolderBrowser *fb, const char *url); void mail_do_create_folder (const GNOME_Evolution_ShellComponentListener listener, const char *uri, const char *type); -void mail_do_sync_folder (CamelFolder *folder); -void mail_do_display_message (MessageList *ml, MailDisplay *md, const char *uid, - gint (*timeout) (gpointer)); -void mail_do_edit_messages (CamelFolder *folder, GPtrArray *uids, - GtkSignalFunc signal); -void mail_do_setup_folder (const char *name, CamelFolder **folder); void mail_do_setup_trash (const char *name, const char *store_uri, CamelFolder **folder); -void mail_do_view_messages (CamelFolder *folder, GPtrArray *uids, - FolderBrowser *fb); void mail_do_save_messages (CamelFolder *folder, GPtrArray *uids, gchar *path); + +/* get a single message, asynchronously */ +void mail_get_message(CamelFolder *folder, const char *uid, + void (*done) (CamelFolder *folder, char *uid, CamelMimeMessage *msg, void *data), void *data, + EThread *thread); + +/* get several messages */ +void mail_get_messages(CamelFolder *folder, GPtrArray *uids, + void (*done) (CamelFolder *folder, GPtrArray *uids, GPtrArray *msgs, void *data), void *data); + +/* same for a folder */ +void mail_get_folder(const char *uri, + void (*done) (char *uri, CamelFolder *folder, void *data), void *data); + +void mail_sync_folder(CamelFolder *folder, + void (*done) (CamelFolder *folder, void *data), void *data); +void mail_expunge_folder(CamelFolder *folder, + void (*done) (CamelFolder *folder, void *data), void *data); + diff --git a/mail/mail-tools.c b/mail/mail-tools.c index 0014d48553..5bfefa758b 100644 --- a/mail/mail-tools.c +++ b/mail/mail-tools.c @@ -221,6 +221,7 @@ mail_tool_do_movemail (const gchar *source_url, CamelException *ex) return dest_path; } +#if 0 void mail_tool_move_folder_contents (CamelFolder *source, CamelFolder *dest, gboolean use_cache, CamelException *ex) { @@ -352,6 +353,7 @@ mail_tool_move_folder_contents (CamelFolder *source, CamelFolder *dest, gboolean camel_object_unref (CAMEL_OBJECT (dest)); mail_tool_camel_lock_down(); } +#endif void mail_tool_set_uid_flags (CamelFolder *folder, const char *uid, guint32 mask, guint32 set) @@ -424,7 +426,6 @@ mail_tool_make_message_attachment (CamelMimeMessage *message) const char *subject; gchar *desc; - mail_tool_camel_lock_up(); /*camel_object_ref (CAMEL_OBJECT (message));*/ subject = camel_mime_message_get_subject (message); @@ -440,7 +441,6 @@ mail_tool_make_message_attachment (CamelMimeMessage *message) CAMEL_DATA_WRAPPER (message)); camel_mime_part_set_content_type (part, "message/rfc822"); /*camel_object_unref (CAMEL_OBJECT (message));*/ - mail_tool_camel_lock_down(); return part; } @@ -493,7 +493,6 @@ mail_tool_uri_to_folder (const char *uri, CamelException *ex) if (!strcmp (url->protocol, "vfolder")) { folder = vfolder_uri_to_folder (uri, ex); } else { - mail_tool_camel_lock_up (); store = camel_session_get_store (session, uri, ex); if (store) { char *name; @@ -505,7 +504,6 @@ mail_tool_uri_to_folder (const char *uri, CamelException *ex) folder = camel_store_get_folder ( store, name, CAMEL_STORE_FOLDER_CREATE, ex); } - mail_tool_camel_lock_down (); } if (camel_exception_is_set (ex)) { @@ -544,6 +542,8 @@ mail_tool_uri_to_folder_noex (const char *uri) gtk_widget_destroy (dialog); } + camel_exception_clear(&ex); + return result; } diff --git a/mail/main.c b/mail/main.c index 48ed4c1a7f..ce0b776b08 100644 --- a/mail/main.c +++ b/mail/main.c @@ -29,6 +29,7 @@ #include "component-factory.h" #include "composer/evolution-composer.h" #include "mail.h" +#include "mail-mt.h" #if 0 static int blowup(int status) @@ -80,6 +81,8 @@ main (int argc, char *argv []) e_cursors_init (); + mail_msg_init(); + component_factory_init (); evolution_composer_factory_init (composer_send_cb, composer_postpone_cb); diff --git a/mail/session.c b/mail/session.c index 508ea80ed3..6fd85712e4 100644 --- a/mail/session.c +++ b/mail/session.c @@ -11,6 +11,7 @@ #include "mail.h" #include "mail-session.h" #include "mail-threads.h" +#include "mail-mt.h" CamelSession *session; @@ -55,7 +56,7 @@ mail_session_request_dialog (const char *prompt, gboolean secret, const char *ke ans == NULL) return NULL; } else { - if (!mail_op_get_password ((char *) prompt, secret, &ans)) + if ((ans = mail_get_password ((char *) prompt, secret)) == NULL) return NULL; } -- cgit v1.2.3