aboutsummaryrefslogtreecommitdiffstats
path: root/mail
diff options
context:
space:
mode:
authorPeter Williams <peterw@src.gnome.org>2000-08-11 01:30:50 +0800
committerPeter Williams <peterw@src.gnome.org>2000-08-11 01:30:50 +0800
commit8cb514d6dd9497893a35a089d07a132d51263ee7 (patch)
tree9f4e5d1f929da7e0be900919753d419fe4c9c61a /mail
parentbcbb63c59f80eb4e684036c5ef58ab141fb01b03 (diff)
downloadgsoc2013-evolution-8cb514d6dd9497893a35a089d07a132d51263ee7.tar
gsoc2013-evolution-8cb514d6dd9497893a35a089d07a132d51263ee7.tar.gz
gsoc2013-evolution-8cb514d6dd9497893a35a089d07a132d51263ee7.tar.bz2
gsoc2013-evolution-8cb514d6dd9497893a35a089d07a132d51263ee7.tar.lz
gsoc2013-evolution-8cb514d6dd9497893a35a089d07a132d51263ee7.tar.xz
gsoc2013-evolution-8cb514d6dd9497893a35a089d07a132d51263ee7.tar.zst
gsoc2013-evolution-8cb514d6dd9497893a35a089d07a132d51263ee7.zip
Merge with camel-async.
svn path=/trunk/; revision=4687
Diffstat (limited to 'mail')
-rw-r--r--mail/ChangeLog260
-rw-r--r--mail/Makefile.am12
-rw-r--r--mail/component-factory.c177
-rw-r--r--mail/folder-browser-factory.c2
-rw-r--r--mail/folder-browser.c153
-rw-r--r--mail/folder-browser.h4
-rw-r--r--mail/local-config.glade20
-rw-r--r--mail/mail-config-gui.c12
-rw-r--r--mail/mail-display.c29
-rw-r--r--mail/mail-display.h3
-rw-r--r--mail/mail-format.c66
-rw-r--r--mail/mail-identify.c2
-rw-r--r--mail/mail-local.c319
-rw-r--r--mail/mail-local.h27
-rw-r--r--mail/mail-ops.c2404
-rw-r--r--mail/mail-threads.c1016
-rw-r--r--mail/mail-threads.h48
-rw-r--r--mail/mail-vfolder.c29
-rw-r--r--mail/mail-vfolder.h2
-rw-r--r--mail/mail-view.c144
-rw-r--r--mail/mail.h12
-rw-r--r--mail/main.c6
-rw-r--r--mail/message-list.c387
-rw-r--r--mail/message-list.h1
-rw-r--r--mail/message-thread.c129
-rw-r--r--mail/message-thread.h12
-rw-r--r--mail/session.c92
-rw-r--r--mail/test-thread.c149
28 files changed, 3607 insertions, 1910 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index e734e79217..17591f38f1 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -9,13 +9,17 @@
assigned in the summary.
(message_list_init_renderers): Init colour column.
+2000-08-09 Peter Williams <peterw@helixcode.com>
+
+ * mail-display.c (part_for_url): Remove a gtk_object_get_data
+
2000-08-09 Cody Russell <bratsche@gnome.org>
* folder-browser-factory.c, mail-view.c: Make the toolbars
honor the user's gnomecc settings for detachable toolbars.
2000-08-09 Jeffrey Stedfast <fejj@helixcode.com>
-
+
* mail-ops.c (composer_send_cb): Get the from address set in the
composer, if that fails ONLY THEN get the default from mail config
@@ -42,7 +46,7 @@
separator between VFolder and Filter stuff.
* mail-ops.c (real_view_msg): Set the UID of the message that is
- being displayed
+ being displayed
2000-08-09 Ettore Perazzoli <ettore@helixcode.com>
@@ -50,6 +54,14 @@
`GNOME_STOCK_MENU_*' things instead of `GNOME_STOCK_PIXMAP_*'
things, that are too big and look bad.
+2000-08-09 Peter Williams <peterw@helixcode.com>
+
+ * mail-view.c (mail_view_create): Save the top window so that on_close
+ can find it [with set_data].
+ (on_close): Recover the top window.
+
+ * mail-threads.c (read_msg): Destroy the window instead of hiding it.
+
2000-08-09 Not Zed <NotZed@HelixCode.com>
* mail-autofilter.c (filter_gui_add_from_message): Helper function
@@ -144,6 +156,38 @@
* mail-view.c: Lets get rid of the last separator in the toolbar
until we add n/p
+2000-08-08 Ettore Perazzoli <ettore@helixcode.com>
+
+ * mail-threads.c (queue_window_delete_event_cb): Callback for
+ "delete_event", just doing nothing.
+ (create_queue_window): Connect it to the "delete_event" signal of
+ the progress dialog.
+
+2000-08-08 Peter Williams <peterw@helixcode.com>
+
+ * mail-threads.c (remove_next_pending): Sanity check for
+ job queue, which seems to have some issues.
+ (read_msg): Make sure that the next operation isn't started
+ before the last one is cleaned up.
+
+ * mail-callbacks.c (fetch_mail): Fix erroneous free.
+
+ * mail-config-gui.c (mail_config_druid): Wrap the gtk_main call.
+
+ * mail-ops.c (do_flag_messages): Allow specification of whether
+ to set the flags unconditionally or toggle their current state.
+
+ * message-list.c (ml_tree_set_value_at): Toggle the seen status;
+ don't set it unconditionally.
+
+ * mail-callbacks.c (delete_msg): Toggle the deletion status;
+ don't set it unconditionally.
+
+ * mail-tools.c (mail_tool_do_movemail): Fix for undeclared tmpfd.
+
+ * mail-local.c (local_reconfigure_folder): Big rewrite; make into
+ an asynchronous operation. Use some mail tools to make life easy.
+
2000-08-08 Dan Winship <danw@helixcode.com>
* main.c (main): Move mail_config_init after session_init, since
@@ -226,6 +270,18 @@
(create_imap_storage): Updated.
(create_news_storage): Updated.
+2000-08-07 Peter Williams <peterw@helixcode.com>
+
+ * mail-ops.c (cleanup_edit_messages): New operation: edit_messages
+ For continuing draft messages.
+ (attach_messages): Fix accidental 0 datasize.
+ (do_setup_draftbox): New operation: setup_draftbox. Soooo hacky.
+
+ * mail-callbacks.c: Move fejj's edit message to the async home.
+
+ * component-factory.c (owner_set_cb): Use mail_do_setup_draftbox.
+
+
2000-08-07 Jeffrey Stedfast <fejj@helixcode.com>
* mail-display.c:
@@ -299,9 +355,35 @@
* folder-browser-factory.c (control_activate): Remove bonobo 0.15
vs 0.15-and-a-half ifdef, since we require post-0.16 now.
+2000-08-04 Dan Winship <danw@helixcode.com>
+
+ * mail-threads.c (mail_operation_wait_for_finish): Don't use
+ "while (gtk_events_pending ()) gtk_main_iteration ();" inside
+ another tight loop, because it makes the thread spin rather than
+ blocking and waiting like it should.
+
2000-08-04 Peter Williams <peterw@helixcode.com>
- * mail-ops.c (move_msg): Fixed a pretty silly uninitialization bug.
+ * message-thread.c (do_thread_messages): Uninitialized variable
+ fix.
+
+ * mail-threads.c (read_msg): Small leak fix.
+
+ * component-factory.c (owner_unset_cb): Use mail_operations_
+ terminate() instead of wait_for_finish().
+
+ * mail-threads.c (mail_operation_queue): Centralize the clur
+ handling functions; fix a race condition where the dispatcher
+ would overwrite the closure before the main thread could
+ free the old one.
+ (mail_operations_terminate): New function, wait for ops to
+ finished and kill the other thread.
+ (dispatch): changes to die when terminate is called (abort
+ on NULL spec).
+
+ * mail-ops.c (cleanup_display_message): Fix improper handling
+ of displaying a NULL message (which means clear the message
+ display).
2000-08-04 Ettore Perazzoli <ettore@helixcode.com>
@@ -337,6 +419,20 @@
2000-08-03 Peter Williams <peterw@helixcode.com>
+ * mail-ops.c (op_forward_messages): Use the new dynamic
+ operation naming.
+
+ * message-thread.c (describe_thread_messages): Ditto.
+
+ * message-list.c (describe_regenerate_messagelist): Ditto.
+
+ * mail-threads.c (get_password_clicked): Dynamic generation
+ of descriptive text for mail operations. "Opening a folder" ->
+ "Opening INBOX". Supported only so far, will be implemented
+ quickly.
+ g_strdup() the old_message when changing the queue_window_label's
+ text.
+
* main.c (main): One more gconf reference to take out...
* mail-ops.c (composer_send_cb): Check for an identity before
@@ -366,6 +462,11 @@
* mail-config-druid.glade: Make the icon background dark blue
like the surrounding area.
+2000-08-02 Peter Williams <peterw@helixcode.com>
+
+ * component-factory.c (owner_unset_cb): Wait for async operations
+ to finish before exiting.
+
2000-08-02 Christopher James Lahey <clahey@helixcode.com>
* mail-ops.c, message-list.c: Emit "model_pre_change" where
@@ -375,6 +476,12 @@
* mail-config.h: #ifdef _MAIL_CONFIG_H protect the header.
+2000-08-01 Peter Williams <peterw@helixcode.com>
+
+ * mail-threads.c: Implement Solaris threads. Attempt
+ to join to the thread upon exit -- hopefully prevents
+ all those nasty zombie processes from popping up :-(
+
2000-08-01 Dan Winship <danw@helixcode.com>
* mail-crypto.c: New code to spawn off GPG/PGP to do stuff.
@@ -591,6 +698,33 @@
(main): More "guess the build mistake" fun, this time for the
failure to initialize Bonobo case.
+2000-07-24 Peter Williams <peterw@helixcode.com>
+
+ * mail-tools.c (mail_tool_set_uid_flags): Change
+ function to faithfully pass parameters to
+ camel_folder_set_message_flags; this function is
+ somewhat useless now. Other files synced with
+ API change.
+
+ * mail-ops.c (op_display_message): Change "display
+ a message" into "retrieve a messsage" in the
+ description of mail_op_display_message.
+
+ * mail-threads.c (display_timeout): New function.
+ Only display the progress dialog if the operation
+ takes more than a second to perform.
+ (hide_queue_window): New function. Hide the queue
+ window as an idle function... I'm thinking maybe
+ the problem with hiding it was due to us not
+ being in a GTK event sequence? Perhaps it's only
+ the timeout, which was not being cancelled, which
+ is now.
+
+ * message-list.c (get_message_uid): New function,
+ copy of get_message_info, except gets only the
+ UID, as that's all that most functions want, and
+ we avoid a Camel call.
+
2000-07-23 Ettore Perazzoli <ettore@helixcode.com>
* mail-ops.c (create_message_composer): New.
@@ -601,6 +735,94 @@
* folder-browser-factory.c (control_activate): Use `_()' instead
of `N_()'.
+2000-07-21 Peter Williams <peterw@helixcode.com>
+
+ * message-thread.c (setup_thread_messages): New
+ operation: thread_messages, simple wrapper around
+ thread_messages () and thread_messages_free();
+
+ * message-list.c (cleanup_regenerate_messagelist):
+ Use new thread_messages operation instead of just
+ calling ... thread_messages :-)
+
+ * folder-browser.c (folder_browser_destroy): Use new
+ sync_folder operation instead of calling camel_folder_sync
+ directly.
+
+ * component-factory.c (create_folder): Changed to use
+ new create_folder operation.
+
+ * mail-ops.c (mail_do_create_folder): New operation: create
+ folder. New operation: sync folder.
+
+ * mail-format.c (cmm_destroyed): Remove the url hashtable from
+ the larger hashtable when it gets destroyed.
+
+ * mail-callbacks.c (fetch_mail): Pass a hook function and data
+ down the chain to pick up the folder_changed and change the view.
+
+ * mail-ops.c: Rename from mail-ops-new.c now that it's a little more
+ solid.
+ (fetch_mail): Add new options to hook and unhook an event while the
+ filter driver runs. A hack, but all of the operations are to some
+ extent.
+ (cleanup_fetch_mail): Unref the destination folder if not NULL.
+ * mail-tools.c (mail_tool_filter_contents_into): Intermediate the
+ event hook/unhook hack here.
+
+2000-07-20 Peter Williams <peterw@helixcode.com>
+
+ * mail-ops-new.c (setup_send_mail): Fix silly forgetting-to-ref
+ problem on some sends (when not replying). Note the early exit
+ path with a big comment.
+
+ * message-list.c (message_list_set_folder): Don't call
+ folder_changed, call mail_do_regenerate_messagelist, as
+ the GDK_THREADS_ENTER in the former can deadlock us!
+
+ * folder-browser.c (folder_browser_set_uri): Ah, screw it.
+ Make 'load folder' asynchronous and pretend that it always
+ succeeds.
+
+ * mail-ops-new.c (mail_do_load_folder): New operation, loads
+ a folder into a FolderBrowser.
+
+ * mail-threads.c (read_msg): Check if the exception is
+ a user cancel; don't complain if it is.
+ (mail_operation_queue): Same.
+ (dispatch_func): Same.
+
+2000-07-20 Peter Williams <peterw@helixcode.com>
+
+ * mail-ops-new.c (cleanup_send_mail): Fix evil mistaken
+ unref.
+
+ * test-thread.c: Fit the new mail_operation_spec prototype.
+
+ * mail-callbacks.c (composer_send_cb): Hide the composer upon
+ start of send operation.
+
+ * folder-browser.c: #include "mail-ops-new.h"
+
+ * mail-threads.h: Change text fields of mail_operation_spec to
+ provide two forms of the name.
+
+ * mail-threads.c: Use appropriate new string fields.
+ (dispatch_func): Hide the progressbar by default.
+
+ * message-list.c (op_regenerate_messagelist): Fix the datasize from
+ 0 -> sizeof (regenerate_messagelist_data_t). Add the new gerund and
+ infinitive strings.
+ (do_regenerate_messagelist): Include some code that fell between the
+ cracks.
+
+ * mail-ops-new.c (op_scan_subfolders): Same datasize fix for
+ scan_subfolders.
+ (op_forward_message): Same.
+ (all): Add new gerund and inifinitive strings for mail_operation_spec.
+ (cleanup_send_mail): Destroy the composer on success; re-show it on
+ error. I'm so clever!
+
2000-07-20 Ettore Perazzoli <ettore@helixcode.com>
* component-factory.c (factory_fn): Updated for the new
@@ -610,6 +832,24 @@
* message-thread.c (thread_messages): What if message info is NULL?
+2000-07-17 Peter Williams <peterw@helixcode.com>
+
+ * component-factory.c (real_create_{imap,news}_storage): Instead of
+ directly calling evolution_storage_new_folder, queue up a list of
+ folders to register so that we don't do our CORBA in The Other Thread.
+ (create_{imap,news}_storage): Changes ancillary to the above.
+ (add_new_mailbox): New function to queue up a folder
+ (cleanup_create_info): New function to dequeue the folders and free mem.
+
+ * test-thread.c: s,ENABLE_BROKEN_THREADS,USE_BROKEN_THREADS -- oops
+
+ * mail-format.c: (mail_lookup_url_table): New function to get the url
+ table associated with a CamelMimeMessage because we can no longer
+ gtk_object_get_data on it.
+
+ * mail-display.c: replace 'gtk_object_get_data( message, "urls" )'
+ with 'mail_lookup_url_table( message )'
+
2000-07-16 Jeffrey Stedfast <fejj@helixcode.com>
* folder-browser.c, component-factory.c: Initial code to support
@@ -622,6 +862,16 @@
Preview]".
(real_send_mail): Call it.
+2000-07-14 Peter Williams <peterw@curious-george.helixcode.com>
+
+ * message-list.c (message_list_set_folder): Ported to CamelObject:
+ GTK_OBJECT->CAMEL_OBJECT; gtk_signal_connect->camel_object_hook_event;
+ GDK_THREADS_ENTER/LEAVE around "changed" event hooks.
+
+ * folder-browser.c (folder_browser_destroy): likewise.
+ (mail_uri_to_folder): likewise.
+ (folder_browser_load_folder): likewise.
+
2000-07-14 Ettore Perazzoli <ettore@helixcode.com>
* Makefile.am (evolution_mail_LDADD): Add `GCONF_LIBS'.
@@ -695,6 +945,10 @@
* mail-display.c (save_data): Change from evolution_dir to
g_get_home_dir() for default location of save file.
+2000-07-11 Dan Winship <danw@helixcode.com>
+
+ * Update for CamelFolder API changes
+
2000-07-11 Jeffrey Stedfast <fejj@helixcode.com>
* mail-ops.c (real_fetch_mail): Changed to use
diff --git a/mail/Makefile.am b/mail/Makefile.am
index 63c15e7e7e..f8f63885ce 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -44,6 +44,7 @@ evolution_mail_SOURCES = \
folder-browser-factory.c \
mail-autofilter.c \
mail-autofilter.h \
+ mail-callbacks.c \
mail-config.c \
mail-config.h \
mail-config-gui.c \
@@ -54,8 +55,11 @@ evolution_mail_SOURCES = \
mail-format.c \
mail-identify.c \
mail-ops.c \
+ mail-ops.h \
mail-threads.c \
mail-threads.h \
+ mail-tools.c \
+ mail-tools.h \
mail-types.h \
mail-vfolder.c \
mail-vfolder.h \
@@ -97,8 +101,12 @@ test_thread_SOURCES = \
mail-threads.h \
test-thread.c
-test_thread_LDADD = \
- $(BONOBO_HTML_GNOME_LIBS) \
+test_thread_LDADD = \
+ $(top_builddir)/camel/libcamel.la \
+ $(top_builddir)/e-util/libeutil.la \
+ $(top_builddir)/libibex/libibex.la \
+ $(BONOBO_HTML_GNOME_LIBS) \
+ $(UNICODE_LIBS) \
$(THREADS_LIBS)
test_thread_CFLAGS = -g $(THREADS_CFLAGS)
diff --git a/mail/component-factory.c b/mail/component-factory.c
index e565313901..2a96b11dfe 100644
--- a/mail/component-factory.c
+++ b/mail/component-factory.c
@@ -35,7 +35,8 @@
#include "evolution-shell-component.h"
#include "folder-browser.h"
#include "mail.h" /* YUCK FIXME */
-#include "mail-threads.h"
+#include "mail-tools.h"
+#include "mail-ops.h"
#include "e-util/e-gui-utils.h"
#include "e-util/e-setup.h"
@@ -45,7 +46,6 @@ CamelFolder *drafts_folder = NULL;
static void create_vfolder_storage (EvolutionShellComponent *shell_component);
static void create_imap_storage (EvolutionShellComponent *shell_component);
-static void real_create_generic_storage( gpointer user_data );
static void create_news_storage (EvolutionShellComponent *shell_component);
#define COMPONENT_FACTORY_ID "OAFIID:evolution-shell-component-factory:evolution-mail:0ea887d5-622b-4b8c-b525-18aa1cbe18a6"
@@ -97,41 +97,7 @@ create_folder (EvolutionShellComponent *shell_component,
const Evolution_ShellComponentListener listener,
void *closure)
{
- CORBA_Environment ev;
- CamelStore *store;
- CamelFolder *folder;
- CamelException ex;
- Evolution_ShellComponentListener_Result result;
-
- camel_exception_init (&ex);
- if (strcmp (type, "mail") != 0)
- result = Evolution_ShellComponentListener_UNSUPPORTED_TYPE;
- else {
- char *camel_url = g_strdup_printf ("mbox://%s", physical_uri);
-
- store = camel_session_get_store (session, camel_url, &ex);
- g_free (camel_url);
- if (!camel_exception_is_set (&ex)) {
- folder = camel_store_get_folder (store, "mbox",
- TRUE, &ex);
- gtk_object_unref (GTK_OBJECT (store));
- } else {
- folder = NULL;
- }
-
- if (!camel_exception_is_set (&ex)) {
- gtk_object_unref (GTK_OBJECT (folder));
- result = Evolution_ShellComponentListener_OK;
- } else {
- result = Evolution_ShellComponentListener_INVALID_URI;
- }
- }
-
- camel_exception_clear (&ex);
-
- CORBA_exception_init (&ev);
- Evolution_ShellComponentListener_report_result (listener, result, &ev);
- CORBA_exception_free (&ev);
+ mail_do_create_folder (listener, physical_uri, type);
}
static void
@@ -139,27 +105,12 @@ owner_set_cb (EvolutionShellComponent *shell_component,
EvolutionShellClient *shell_client,
gpointer user_data)
{
- CamelException *ex;
- CamelStore *store;
- char *url;
-
g_print ("evolution-mail: Yeeeh! We have an owner!\n"); /* FIXME */
/* GROSS HACK */
/*global_shell_client = shell_client;*/
- ex = camel_exception_new ();
- url = g_strdup_printf ("mbox://%s/local/Drafts", evolution_dir);
- store = camel_session_get_store (session, url, ex);
- g_free (url);
- if (!camel_exception_is_set (ex)) {
- drafts_folder = camel_store_get_folder (store, "mbox", TRUE, ex);
- gtk_object_unref (GTK_OBJECT (store));
- } else {
- drafts_folder = NULL;
- }
- camel_exception_free (ex);
-
+ mail_do_setup_draftbox ();
create_vfolder_storage (shell_component);
create_imap_storage (shell_component);
create_news_storage (shell_component);
@@ -168,6 +119,7 @@ owner_set_cb (EvolutionShellComponent *shell_component,
static void
owner_unset_cb (EvolutionShellComponent *shell_component, gpointer user_data)
{
+ mail_operations_terminate ();
gtk_main_quit ();
}
@@ -236,11 +188,6 @@ create_vfolder_storage (EvolutionShellComponent *shell_component)
vfolder_create_storage(shell_component);
}
-struct create_info_s {
- EvolutionStorage *storage;
- char *source;
-};
-
static void
create_imap_storage (EvolutionShellComponent *shell_component)
{
@@ -249,15 +196,14 @@ create_imap_storage (EvolutionShellComponent *shell_component)
Evolution_Shell corba_shell;
EvolutionStorage *storage;
char *source = NULL, *server, *p;
- struct create_info_s *ii;
-
+
config = mail_config_fetch ();
if (config->sources) {
const MailConfigService *s;
s = (MailConfigService *)config->sources->data;
source = s->url;
}
-
+
if (!source || g_strncasecmp (source, "imap://", 7))
return;
@@ -276,106 +222,19 @@ create_imap_storage (EvolutionShellComponent *shell_component)
server++;
for (p = server; *p && *p != '/'; p++);
-
+
server = g_strndup (server, (gint)(p - server));
storage = evolution_storage_new (server);
g_free (server);
-
+
if (evolution_storage_register_on_shell (storage, corba_shell) != EVOLUTION_STORAGE_OK) {
g_warning ("Cannot register storage");
g_free (source);
return;
}
-
- ii = g_new (struct create_info_s, 1);
- ii->storage = storage;
- ii->source = g_strdup (source);
-
-#ifdef USE_BROKEN_THREADS
- mail_operation_try ("Create IMAP Storage", real_create_generic_storage, g_free, ii);
-#else
- real_create_generic_storage (ii);
- g_free (ii);
-#endif
- /* Note the g_free as our cleanup function deleting the ii struct when we're done */
-}
-static void
-real_create_generic_storage (gpointer user_data)
-{
- CamelException *ex;
- EvolutionStorage *storage;
- char *source;
- CamelStore *store;
- CamelFolder *folder;
- GPtrArray *lsub;
- int i, max;
- struct create_info_s *ii;
-
- ii = (struct create_info_s *) user_data;
- storage = ii->storage;
- source = ii->source;
-
-#ifdef USE_BROKEN_THREADS
- mail_op_hide_progressbar ();
- mail_op_set_message ("Connecting to service...");
-#endif
- ex = camel_exception_new ();
-
- store = camel_session_get_store (session, source, ex);
- if (!store) {
- goto cleanup;
- }
-
- camel_service_connect (CAMEL_SERVICE (store), ex);
- if (camel_exception_get_id (ex) != CAMEL_EXCEPTION_NONE) {
- goto cleanup;
- }
-
-#ifdef USE_BROKEN_THREADS
- mail_op_set_message ("Connected. Examining folders...");
-#endif
-
- folder = camel_store_get_root_folder (store, ex);
- if (camel_exception_get_id (ex) != CAMEL_EXCEPTION_NONE) {
- goto cleanup;
- }
-
- lsub = camel_folder_get_subfolder_names (folder);
-
- max = lsub->len;
- for (i = 0; i < max; i++) {
- char *path, *buf, *dirname;
-
-#if 0
- if (strcmp (dir_sep, "/")) {
- dirname = e_strreplace ((char *)lsub->pdata[i], dir_sep, "/");
- } else {
- dirname = g_strdup ((char *)lsub->pdata[i]);
- }
-#endif
- dirname = g_strdup ((char *)lsub->pdata[i]);
-
- path = g_strdup_printf ("/%s", dirname);
- g_free (dirname);
- buf = g_strdup_printf ("%s/%s", source, path + 1);
- printf ("buf = %s\n", buf);
-
-#ifdef USE_BROKEN_THREADS
- mail_op_set_message ("Adding %s", path);
-#endif
-
- evolution_storage_new_folder (storage, path, "mail", buf, "description");
- }
-
- cleanup:
- g_free (ii->source);
-#ifdef USE_BROKEN_THREADS
- if (camel_exception_is_set (ex))
- mail_op_error ("%s", camel_exception_get_description (ex));
-#endif
- camel_exception_free (ex);
+ mail_do_scan_subfolders (source, TRUE, storage);
}
static void
@@ -386,7 +245,6 @@ create_news_storage (EvolutionShellComponent *shell_component)
Evolution_Shell corba_shell;
EvolutionStorage *storage;
char *source=NULL, *server, *p;
- struct create_info_s *ni;
config = mail_config_fetch ();
if (config->news) {
@@ -419,16 +277,7 @@ create_news_storage (EvolutionShellComponent *shell_component)
g_free (source);
return;
}
-
- ni = g_new( struct create_info_s, 1 );
- ni->storage = storage;
- ni->source = g_strdup( source );
-
-#ifdef USE_BROKEN_THREADS
- mail_operation_try( "Create News Storage", real_create_generic_storage, g_free, ni );
-#else
- real_create_generic_storage( ni );
- g_free( ni );
-#endif
- /* again note the g_free cleanup func */
+
+ mail_do_scan_subfolders (source, FALSE, storage);
}
+
diff --git a/mail/folder-browser-factory.c b/mail/folder-browser-factory.c
index ae170867d1..ba861969e3 100644
--- a/mail/folder-browser-factory.c
+++ b/mail/folder-browser-factory.c
@@ -117,7 +117,7 @@ control_activate (BonoboControl *control, BonoboUIHandler *uih,
NULL, -1,
BONOBO_UI_HANDLER_PIXMAP_NONE,
0,
- 0, 0, providers_config, NULL);
+ 0, 0, mail_config, NULL);
bonobo_ui_handler_menu_new_item (uih, "/Tools/Forget Passwords", _("Forget _Passwords"),
NULL, -1,
diff --git a/mail/folder-browser.c b/mail/folder-browser.c
index 4eb300214d..60feba556f 100644
--- a/mail/folder-browser.c
+++ b/mail/folder-browser.c
@@ -14,7 +14,10 @@
#include "e-util/e-sexp.h"
#include "folder-browser.h"
#include "mail.h"
+#include "mail-tools.h"
#include "message-list.h"
+#include "mail-threads.h"
+#include "mail-ops.h"
#include <widgets/e-paned/e-vpaned.h>
#include "mail-vfolder.h"
@@ -30,7 +33,6 @@
static GtkObjectClass *folder_browser_parent_class;
-
static void
folder_browser_destroy (GtkObject *object)
{
@@ -48,10 +50,10 @@ folder_browser_destroy (GtkObject *object)
g_free (folder_browser->uri);
if (folder_browser->folder) {
- camel_folder_sync (folder_browser->folder, FALSE, NULL);
- gtk_object_unref (GTK_OBJECT (folder_browser->folder));
+ mail_do_sync_folder (folder_browser->folder);
+ camel_object_unref (CAMEL_OBJECT (folder_browser->folder));
}
-
+
if (folder_browser->message_list)
bonobo_object_unref (BONOBO_OBJECT (folder_browser->message_list));
@@ -66,120 +68,31 @@ folder_browser_class_init (GtkObjectClass *object_class)
folder_browser_parent_class = gtk_type_class (PARENT_TYPE);
}
-CamelFolder *
-mail_uri_to_folder (const char *name)
-{
- char *msg;
- CamelStore *store = NULL;
- CamelFolder *folder = NULL;
- CamelException *ex;
-
- ex = camel_exception_new ();
-
- if (!strncmp (name, "vfolder:", 8)) {
- folder = vfolder_uri_to_folder(name);
- } else if (!strncmp (name, "imap:", 5)) {
- char *service, *ptr;
-
- service = g_strdup_printf ("%s/", name);
- for (ptr = service + 7; *ptr && *ptr != '/'; ptr++);
- ptr++;
- *ptr = '\0';
-
- store = camel_session_get_store (session, service, ex);
- g_free (service);
-
- if (store) {
- CamelURL *url = CAMEL_SERVICE (store)->url;
- char *folder_name;
-
- /*dir_sep = CAMEL_IMAP_STORE (store)->dir_sep;*/
-
- for (ptr = (char *)(name + 7); *ptr && *ptr != '/'; ptr++);
- if (*ptr == '/') {
- if (url && url->path) {
- ptr += strlen (url->path);
- if (*ptr == '/')
- ptr++;
- }
-
- if (*ptr == '/')
- ptr++;
- /*for ( ; *ptr && *ptr == '/'; ptr++);*/
-
- folder_name = g_strdup (ptr);
- /*tree_name = g_strdup (ptr);*/
- /*folder_name = e_strreplace (tree_name, "/", dir_sep);*/
-
- folder = camel_store_get_folder (store, folder_name, TRUE, ex);
- g_free (folder_name);
- }
- }
- } else if (!strncmp(name, "news:", 5)) {
- store = camel_session_get_store (session, name, ex);
- if (store) {
- const char *folder_name;
-
- folder_name = name + 5;
-
- folder = camel_store_get_folder (store, folder_name, FALSE, ex);
- }
- } else if (!strncmp (name, "file:", 5)) {
- folder = local_uri_to_folder(name, ex);
- } else {
- msg = g_strdup_printf ("Can't open URI %s", name);
- gnome_error_dialog (msg);
- g_free (msg);
- }
-
- if (camel_exception_get_id (ex)) {
- msg = g_strdup_printf ("Unable to get folder %s: %s\n", name,
- camel_exception_get_description (ex));
- gnome_error_dialog (msg);
- if (folder) {
- gtk_object_unref (GTK_OBJECT (folder));
- folder = NULL;
- }
- }
- camel_exception_free (ex);
-
- if (store)
- gtk_object_unref (GTK_OBJECT (store));
-
- return folder;
-}
-
-static gboolean
-folder_browser_load_folder (FolderBrowser *fb, const char *name)
-{
- CamelFolder *new_folder;
-
- new_folder = mail_uri_to_folder (name);
- if (!new_folder)
- return FALSE;
-
- if (fb->folder)
- gtk_object_unref (GTK_OBJECT (fb->folder));
- fb->folder = new_folder;
-
- gtk_widget_set_sensitive (GTK_WIDGET (fb->search_entry), camel_folder_has_search_capability (fb->folder));
- gtk_widget_set_sensitive (GTK_WIDGET (fb->search_menu), camel_folder_has_search_capability (fb->folder));
-
- message_list_set_folder (fb->message_list, new_folder);
-
- return TRUE;
-}
+/*
+ * static gboolean
+ * folder_browser_load_folder (FolderBrowser *fb, const char *name)
+ * {
+ * CamelFolder *new_folder;
+ *
+ * new_folder = mail_tool_uri_to_folder_noex (name);
+ *
+ * if (!new_folder)
+ * return FALSE;
+ *
+ * if (fb->folder)
+ * camel_object_unref (CAMEL_OBJECT (fb->folder));
+ * fb->folder = new_folder;
+ * message_list_set_folder (fb->message_list, new_folder);
+ * return TRUE;
+ * }
+ */
#define EQUAL(a,b) (strcmp (a,b) == 0)
-gboolean
-folder_browser_set_uri (FolderBrowser *folder_browser, const char *uri)
+gboolean folder_browser_set_uri (FolderBrowser *folder_browser, const char *uri)
{
- if (folder_browser->uri)
- g_free (folder_browser->uri);
-
- folder_browser->uri = g_strdup (uri);
- return folder_browser_load_folder (folder_browser, folder_browser->uri);
+ mail_do_load_folder (folder_browser, uri);
+ return TRUE;
}
void
@@ -223,7 +136,7 @@ search_set(FolderBrowser *fb)
text = gtk_entry_get_text((GtkEntry *)fb->search_entry);
if (text == NULL || text[0] == 0) {
- message_list_regenerate (fb->message_list, NULL);
+ mail_do_regenerate_messagelist (fb->message_list, NULL);
return;
}
@@ -243,7 +156,7 @@ search_set(FolderBrowser *fb)
str++;
}
}
- message_list_regenerate (fb->message_list, out->str);
+ mail_do_regenerate_messagelist (fb->message_list, out->str);
g_string_free(out, TRUE);
}
@@ -358,7 +271,7 @@ folder_browser_clear_search (FolderBrowser *fb)
{
gtk_entry_set_text (GTK_ENTRY (fb->search_entry), "");
gtk_option_menu_set_history (GTK_OPTION_MENU (fb->search_menu), 0);
- message_list_regenerate (fb->message_list, NULL);
+ mail_do_regenerate_messagelist (fb->message_list, NULL);
}
static int
@@ -481,7 +394,7 @@ my_folder_browser_init (GtkObject *object)
* Our instance data
*/
fb->message_list = MESSAGE_LIST (message_list_new (fb));
- fb->mail_display = MAIL_DISPLAY (mail_display_new (fb));
+ fb->mail_display = MAIL_DISPLAY (mail_display_new ());
gtk_signal_connect (GTK_OBJECT (fb->message_list->etable),
"key_press", GTK_SIGNAL_FUNC (etable_key), fb);
@@ -504,7 +417,3 @@ folder_browser_new (void)
E_MAKE_TYPE (folder_browser, "FolderBrowser", FolderBrowser, folder_browser_class_init, folder_browser_init, PARENT_TYPE);
-
-
-
-
diff --git a/mail/folder-browser.h b/mail/folder-browser.h
index 0bc3edf9c8..53bcb5b925 100644
--- a/mail/folder-browser.h
+++ b/mail/folder-browser.h
@@ -57,8 +57,8 @@ typedef struct {
GtkType folder_browser_get_type (void);
GtkWidget *folder_browser_new (void);
-gboolean folder_browser_set_uri (FolderBrowser *folder_browser,
- const char *uri);
+gboolean folder_browser_set_uri (FolderBrowser *folder_browser,
+ const char *uri);
void folder_browser_set_message_preview (FolderBrowser *folder_browser,
gboolean show_message_preview);
void folder_browser_clear_search (FolderBrowser *fb);
diff --git a/mail/local-config.glade b/mail/local-config.glade
index 3601433d78..3eaadbc833 100644
--- a/mail/local-config.glade
+++ b/mail/local-config.glade
@@ -214,26 +214,6 @@ recoverable. Please use this feature with care.</label>
<fill>False</fill>
</child>
</widget>
-
- <widget>
- <class>GtkProgressBar</class>
- <name>progress_format</name>
- <value>0</value>
- <lower>0</lower>
- <upper>100</upper>
- <bar_style>GTK_PROGRESS_CONTINUOUS</bar_style>
- <orientation>GTK_PROGRESS_LEFT_TO_RIGHT</orientation>
- <activity_mode>False</activity_mode>
- <show_text>False</show_text>
- <format>%P %%</format>
- <text_xalign>0.5</text_xalign>
- <text_yalign>0.5</text_yalign>
- <child>
- <padding>0</padding>
- <expand>False</expand>
- <fill>False</fill>
- </child>
- </widget>
</widget>
</widget>
diff --git a/mail/mail-config-gui.c b/mail/mail-config-gui.c
index 12d944e4e3..7ebcb09c6a 100644
--- a/mail/mail-config-gui.c
+++ b/mail/mail-config-gui.c
@@ -1259,7 +1259,9 @@ identity_dialog (const MailConfigIdentity *id, GtkWidget *parent)
GTK_SIGNAL_FUNC (iddialog_ok_clicked),
iddialog);
+ /*GDK_THREADS_ENTER ();*/
gnome_dialog_run_and_close (GNOME_DIALOG (iddialog->dialog));
+ /*GDK_THREADS_LEAVE ();*/
returnid = iddialog->id;
g_free (iddialog);
@@ -1356,7 +1358,9 @@ source_dialog (MailConfigService *source, GtkWidget *parent)
GTK_SIGNAL_FUNC (sdialog_ok_clicked),
sdialog);
+ /*GDK_THREADS_ENTER ();*/
gnome_dialog_run_and_close (GNOME_DIALOG (sdialog->dialog));
+ /*GDK_THREADS_LEAVE ();*/
returnsource = sdialog->source;
g_free (sdialog);
@@ -1452,7 +1456,9 @@ news_dialog (MailConfigService *source, GtkWidget *parent)
GTK_SIGNAL_FUNC (ndialog_ok_clicked),
ndialog);
+ /*GDK_THREADS_ENTER ();*/
gnome_dialog_run_and_close (GNOME_DIALOG (ndialog->dialog));
+ /*GDK_THREADS_LEAVE ();*/
returnsource = ndialog->source;
g_free (ndialog);
@@ -1679,8 +1685,10 @@ mail_config_druid (void)
gtk_signal_connect (GTK_OBJECT (fpage), "finish",
GTK_SIGNAL_FUNC (mail_druid_finish),
dialog);
-
+
+ GDK_THREADS_ENTER ();
gtk_main ();
+ GDK_THREADS_LEAVE ();
}
/* Main configuration dialog */
@@ -2131,7 +2139,9 @@ mail_config (void)
GTK_SIGNAL_FUNC (mail_config_apply_clicked),
dialog);
+ GDK_THREADS_ENTER ();
gnome_dialog_run (GNOME_DIALOG (dialog->dialog));
+ GDK_THREADS_LEAVE ();
/* Clean up */
gtk_object_unref (GTK_OBJECT (gui));
diff --git a/mail/mail-display.c b/mail/mail-display.c
index 9da2dcd4f0..f32887c3de 100644
--- a/mail/mail-display.c
+++ b/mail/mail-display.c
@@ -30,6 +30,8 @@
static GtkObjectClass *mail_display_parent_class;
+/* Sigh... gtk_object_set_data is nice to have... */
+extern GHashTable *mail_lookup_url_table (CamelMimeMessage *mime_message);
/*----------------------------------------------------------------------*
* Callbacks
@@ -61,7 +63,9 @@ write_data_to_file (CamelMimePart *part, const char *name, gboolean unique)
gnome_ok_cancel_dialog_modal (
"A file by that name already exists.\nOverwrite it?",
save_data_eexist_cb, &ok);
+ GDK_THREADS_ENTER();
gtk_main ();
+ GDK_THREADS_LEAVE();
if (!ok)
return FALSE;
fd = open (name, O_WRONLY | O_TRUNC);
@@ -86,11 +90,10 @@ write_data_to_file (CamelMimePart *part, const char *name, gboolean unique)
strerror (errno));
gnome_error_dialog (msg);
g_free (msg);
- gtk_object_unref (GTK_OBJECT (stream_fs));
+ camel_object_unref (CAMEL_OBJECT (stream_fs));
return FALSE;
}
- gtk_object_unref (GTK_OBJECT (stream_fs));
-
+ camel_object_unref (CAMEL_OBJECT (stream_fs));
return TRUE;
}
@@ -129,7 +132,7 @@ part_for_url (const char *url, CamelMimeMessage *message)
{
GHashTable *urls;
- urls = gtk_object_get_data (GTK_OBJECT (message), "urls");
+ urls = mail_lookup_url_table (message);
g_return_val_if_fail (urls != NULL, NULL);
return g_hash_table_lookup (urls, url);
}
@@ -252,7 +255,7 @@ on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data)
if (strncmp (eb->classid, "cid:", 4) != 0)
return FALSE;
message = gtk_object_get_data (GTK_OBJECT (html), "message");
- urls = gtk_object_get_data (GTK_OBJECT (message), "urls");
+ urls = mail_lookup_url_table (message);
medium = g_hash_table_lookup (urls, eb->classid);
g_return_val_if_fail (CAMEL_IS_MEDIUM (medium), FALSE);
wrapper = camel_medium_get_content_object (medium);
@@ -283,7 +286,7 @@ on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data)
/* ...convert the CamelStreamMem to a BonoboStreamMem... */
bstream = bonobo_stream_mem_create (ba->data, ba->len, TRUE, FALSE);
- gtk_object_unref (GTK_OBJECT (cstream));
+ camel_object_unref (CAMEL_OBJECT (cstream));
/* ...and hydrate the PersistStream from the BonoboStream. */
CORBA_exception_init (&ev);
@@ -316,7 +319,7 @@ on_url_requested (GtkHTML *html, const char *url, GtkHTMLStream *handle,
GHashTable *urls;
message = gtk_object_get_data (GTK_OBJECT (html), "message");
- urls = gtk_object_get_data (GTK_OBJECT (message), "urls");
+ urls = mail_lookup_url_table (message);
user_data = g_hash_table_lookup (urls, url);
if (user_data == NULL)
@@ -335,7 +338,7 @@ on_url_requested (GtkHTML *html, const char *url, GtkHTMLStream *handle,
stream_mem = camel_stream_mem_new_with_byte_array (ba);
camel_data_wrapper_write_to_stream (data, stream_mem);
gtk_html_write (html, handle, ba->data, ba->len);
- gtk_object_unref (GTK_OBJECT (stream_mem));
+ camel_object_unref (CAMEL_OBJECT (stream_mem));
} else if (strncmp (url, "x-evolution-data:", 17) == 0) {
GByteArray *ba = user_data;
@@ -426,7 +429,7 @@ mail_display_set_message (MailDisplay *mail_display,
/* Clean up from previous message. */
if (mail_display->current_message)
- gtk_object_unref (GTK_OBJECT (mail_display->current_message));
+ camel_object_unref (CAMEL_OBJECT (mail_display->current_message));
mail_display->current_message = (CamelMimeMessage*)medium;
@@ -435,7 +438,7 @@ mail_display_set_message (MailDisplay *mail_display,
"<BODY TEXT=\"#000000\" BGCOLOR=\"#FFFFFF\">\n");
if (medium) {
- gtk_object_ref (GTK_OBJECT (medium));
+ camel_object_ref (CAMEL_OBJECT (medium));
gtk_object_set_data (GTK_OBJECT (mail_display->html),
"message", medium);
mail_format_mime_message (CAMEL_MIME_MESSAGE (medium),
@@ -485,15 +488,11 @@ mail_display_class_init (GtkObjectClass *object_class)
}
GtkWidget *
-mail_display_new (FolderBrowser *parent_folder_browser)
+mail_display_new (void)
{
MailDisplay *mail_display = gtk_type_new (mail_display_get_type ());
GtkWidget *scroll, *html;
- g_assert (parent_folder_browser);
-
- mail_display->parent_folder_browser = parent_folder_browser;
-
gtk_box_set_homogeneous (GTK_BOX (mail_display), FALSE);
gtk_widget_show (GTK_WIDGET (mail_display));
diff --git a/mail/mail-display.h b/mail/mail-display.h
index d839978371..129b059612 100644
--- a/mail/mail-display.h
+++ b/mail/mail-display.h
@@ -25,7 +25,6 @@ struct _MailDisplay {
EScrollFrame *scroll;
GtkHTML *html;
- FolderBrowser *parent_folder_browser;
CamelMimeMessage *current_message;
};
@@ -34,7 +33,7 @@ typedef struct {
} MailDisplayClass;
GtkType mail_display_get_type (void);
-GtkWidget * mail_display_new (FolderBrowser *parent_folder_browser);
+GtkWidget * mail_display_new (void);
void mail_display_set_message (MailDisplay *mail_display,
CamelMedium *medium);
diff --git a/mail/mail-format.c b/mail/mail-format.c
index a96619631f..95d595fef9 100644
--- a/mail/mail-format.c
+++ b/mail/mail-format.c
@@ -104,8 +104,38 @@ static void write_headers (CamelMimeMessage *message,
static gboolean call_handler_function (CamelMimePart *part,
struct mail_format_data *mfd);
-static void free_urls (gpointer data);
+/* no gtk_object_set_data, sorry..... */
+
+static GHashTable *cmm_to_urls = NULL;
+
+static void
+free_url (gpointer key, gpointer value, gpointer data)
+{
+ g_free (key);
+}
+
+static void cmm_destroyed (CamelObject *cmm, gpointer event_data, gpointer user_data)
+{
+ GHashTable *ht;
+
+ g_return_if_fail (cmm);
+
+ ht = g_hash_table_lookup (cmm_to_urls, cmm);
+ g_hash_table_foreach (ht, free_url, NULL);
+ g_hash_table_destroy (ht);
+ g_hash_table_insert (cmm_to_urls, cmm, NULL);
+}
+
+GHashTable *mail_lookup_url_table (CamelMimeMessage *mime_message)
+{
+ if (!cmm_to_urls) {
+ cmm_to_urls = g_hash_table_new (g_direct_hash, g_direct_equal);
+ return NULL;
+ }
+
+ return g_hash_table_lookup (cmm_to_urls, mime_message);
+}
/**
* mail_format_mime_message:
@@ -128,32 +158,21 @@ mail_format_mime_message (CamelMimeMessage *mime_message,
mfd.html = html;
mfd.stream = stream;
mfd.root = root;
- mfd.urls = gtk_object_get_data (GTK_OBJECT (root), "urls");
+
+ if (!cmm_to_urls)
+ cmm_to_urls = g_hash_table_new (g_direct_hash, g_direct_equal);
+ mfd.urls = g_hash_table_lookup (cmm_to_urls, root);
+
if (!mfd.urls) {
mfd.urls = g_hash_table_new (g_str_hash, g_str_equal);
- gtk_object_set_data_full (GTK_OBJECT (root), "urls",
- mfd.urls, free_urls);
+ g_hash_table_insert (cmm_to_urls, root, mfd.urls);
+ camel_object_hook_event (CAMEL_OBJECT (root), "finalize", cmm_destroyed, NULL);
}
write_headers (mime_message, &mfd);
call_handler_function (CAMEL_MIME_PART (mime_message), &mfd);
}
-static void
-free_url (gpointer key, gpointer value, gpointer data)
-{
- g_free (key);
-}
-
-static void
-free_urls (gpointer data)
-{
- GHashTable *urls = data;
-
- g_hash_table_foreach (urls, free_url, NULL);
- g_hash_table_destroy (urls);
-}
-
static const char *
get_cid (CamelMimePart *part, struct mail_format_data *mfd)
{
@@ -500,7 +519,7 @@ get_data_wrapper_text (CamelDataWrapper *data)
} else
text = NULL;
- gtk_object_unref (GTK_OBJECT (memstream));
+ camel_object_unref (CAMEL_OBJECT (memstream));
return text;
}
@@ -662,7 +681,7 @@ fake_mime_part_from_data (const char *data, int len, const char *type)
return part;
}
-static void
+ static void
destroy_part (GtkObject *root, GtkObject *part)
{
gtk_object_unref (part);
@@ -787,7 +806,7 @@ try_inline_binhex (char *start, struct mail_format_data *mfd)
}
static void
-free_byte_array (GtkWidget *widget, gpointer user_data)
+free_byte_array (CamelObject *obj, gpointer event_data, gpointer user_data)
{
g_byte_array_free (user_data, TRUE);
}
@@ -946,8 +965,7 @@ handle_text_enriched (CamelMimePart *part, const char *mime_type,
xed = g_strdup_printf ("x-evolution-data:%p", part);
g_hash_table_insert (mfd->urls, xed, ba);
- gtk_signal_connect (GTK_OBJECT (mfd->root), "destroy",
- GTK_SIGNAL_FUNC (free_byte_array), ba);
+ camel_object_hook_event (CAMEL_OBJECT (mfd->root), "finalize", free_byte_array, ba);
mail_html_write (mfd->html, mfd->stream,
"<iframe src=\"%s\" frameborder=0 scrolling=no>"
"</iframe>", xed);
diff --git a/mail/mail-identify.c b/mail/mail-identify.c
index ba8a943f38..91c4efd5d7 100644
--- a/mail/mail-identify.c
+++ b/mail/mail-identify.c
@@ -101,7 +101,7 @@ mail_identify_mime_part (CamelMimePart *part)
gnome_vfs_mime_sniff_buffer_free (sniffer);
} else
type = NULL;
- gtk_object_unref (GTK_OBJECT (memstream));
+ camel_object_unref (CAMEL_OBJECT (memstream));
if (type)
return g_strdup (type);
diff --git a/mail/mail-local.c b/mail/mail-local.c
index 36ae9770a4..840df79f28 100644
--- a/mail/mail-local.c
+++ b/mail/mail-local.c
@@ -1,3 +1,29 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* mail-local.c: Local mailbox support. */
+
+/*
+ * Author:
+ * Michael Zucchi <NotZed@helixcode.com>
+ * Peter Williams <peterw@helixcode.com>
+ *
+ * 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 Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
/*
code for handling local mail boxes
@@ -24,6 +50,8 @@
#include "mail.h"
#include "mail-local.h"
+#include "mail-tools.h"
+#include "mail-threads.h"
#define d(x)
@@ -105,12 +133,11 @@ save_metainfo(struct _local_meta *meta)
}
CamelFolder *
-local_uri_to_folder(const char *uri, CamelException *ex)
+mail_tool_local_uri_to_folder(const char *uri, CamelException *ex)
{
CamelURL *url;
char *metapath;
char *storename;
- CamelStore *store;
CamelFolder *folder = NULL;
struct _local_meta *meta;
@@ -136,12 +163,7 @@ local_uri_to_folder(const char *uri, CamelException *ex)
printf("store name is %s\n", storename);
- store = camel_session_get_store(session, storename, ex);
- g_free(storename);
- if (store) {
- folder = camel_store_get_folder(store, meta->name, FALSE, ex);
- gtk_object_unref((GtkObject *)store);
- }
+ folder = mail_tool_get_folder_from_urlname (storename, meta->name, ex);
camel_url_free(url);
free_metainfo(meta);
@@ -167,36 +189,86 @@ local_uri_to_folder(const char *uri, CamelException *ex)
*/
-static void update_progress(GtkProgress *progress, char *fmt, float percent)
+static void update_progress(char *fmt, float percent)
{
if (fmt)
- gtk_progress_set_format_string(progress, fmt);
- gtk_progress_set_percentage(progress, percent);
- while( gtk_events_pending() )
- gtk_main_iteration();
+ mail_op_set_message ("%s", fmt);
+ mail_op_set_percentage (percent);
+}
+
+/* ******************** */
+
+typedef struct reconfigure_folder_input_s {
+ FolderBrowser *fb;
+ gchar *newtype;
+ GtkWidget *frame;
+ GtkWidget *apply;
+ GtkWidget *cancel;
+ GtkOptionMenu *optionlist;
+} reconfigure_folder_input_t;
+
+static gchar *describe_reconfigure_folder (gpointer in_data, gboolean gerund);
+static void setup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex);
+static void do_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex);
+static void cleanup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex);
+
+static gchar *
+describe_reconfigure_folder (gpointer in_data, gboolean gerund)
+{
+ reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data;
+
+ if (gerund)
+ return g_strdup_printf (_("Changing folder \"%s\" to \"%s\" format"),
+ input->fb->uri,
+ input->newtype);
+ else
+ return g_strdup_printf (_("Change folder \"%s\" to \"%s\" format"),
+ input->fb->uri,
+ input->newtype);
}
static void
-do_local_reconfigure_folder(FolderBrowser *fb, char *newtype, GtkProgress *progress, CamelException *ex)
+setup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex)
{
- CamelStore *fromstore, *tostore;
- char *fromurl, *tourl, *uri;
- CamelFolder *fromfolder, *tofolder;
- GPtrArray *uids;
- int i;
+ reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data;
+
+ if (!IS_FOLDER_BROWSER (input->fb)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "Input has a bad FolderBrowser in reconfigure_folder");
+ return;
+ }
+
+ if (!input->newtype) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No new folder type in reconfigure_folder");
+ return;
+ }
+
+ gtk_object_ref (GTK_OBJECT (input->fb));
+}
+
+static void
+do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex)
+{
+ reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data;
+
+ CamelStore *fromstore = NULL, *tostore = NULL;
+ char *fromurl = NULL, *tourl = NULL;
+ CamelFolder *fromfolder = NULL, *tofolder = NULL;
+
char *metapath;
char *tmpname;
- CamelURL *url;
+ char *uri;
+ CamelURL *url = NULL;
struct _local_meta *meta;
- printf("reconfiguring folder: %s to type %s\n", fb->uri, newtype);
+ printf("reconfiguring folder: %s to type %s\n", input->fb->uri, input->newtype);
/* get the actual location of the mailbox */
- url = camel_url_new(fb->uri, ex);
- if (url == NULL || camel_exception_is_set(ex)) {
- camel_exception_free(ex);
- g_warning("%s is not a workable url!", fb->uri);
- return;
+ url = camel_url_new(input->fb->uri, ex);
+ if (camel_exception_is_set(ex)) {
+ g_warning("%s is not a workable url!", input->fb->uri);
+ goto cleanup;
}
metapath = g_strdup_printf("%s/local-metadata.xml", url->path);
@@ -204,173 +276,158 @@ do_local_reconfigure_folder(FolderBrowser *fb, char *newtype, GtkProgress *progr
g_free(metapath);
/* first, 'close' the old folder */
- if (fb->folder != NULL) {
- update_progress(progress, "Closing current folder", 0.0);
- printf("Closing old folder ...\n");
- camel_folder_sync(fb->folder, FALSE, ex);
- gtk_object_unref (GTK_OBJECT (fb->folder));
- fb->folder = NULL;
+ 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;
}
camel_url_set_protocol(url, meta->format);
fromurl = camel_url_to_string(url, TRUE);
- camel_url_set_protocol(url, newtype);
+ camel_url_set_protocol(url, input->newtype);
tourl = camel_url_to_string(url, TRUE);
printf("opening stores %s and %s\n", fromurl, tourl);
+
+ mail_tool_camel_lock_up ();
fromstore = camel_session_get_store(session, fromurl, ex);
- if (camel_exception_is_set(ex)) {
- return;
- }
+ 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);
- if (camel_exception_is_set(ex)) {
- return;
- }
+ mail_tool_camel_lock_down ();
+ if (camel_exception_is_set(ex))
+ goto cleanup;
/* rename the old mbox and open it again */
tmpname = g_strdup_printf("%s_reconfig", meta->name);
- printf("renaming mbox to mboxtmp, and opening it\n");
- update_progress(progress, "Renaming old folder and opening", 0.0);
+ 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)) {
- return;
+ mail_tool_camel_lock_down ();
+ goto cleanup;
}
+
fromfolder = camel_store_get_folder(fromstore, tmpname, TRUE, ex);
if (fromfolder == NULL || camel_exception_is_set(ex)) {
/* try and recover ... */
+ camel_exception_clear (ex);
camel_store_rename_folder(fromstore, tmpname, meta->name, ex);
- return;
+ mail_tool_camel_lock_down ();
+ goto cleanup;
}
/* create a new mbox */
printf("Creating the destination mbox\n");
- update_progress(progress, "Creating new folder", 0.0);
+ update_progress("Creating new folder", 0.0);
+
tofolder = camel_store_get_folder(tostore, meta->name, TRUE, ex);
if (tofolder == NULL || camel_exception_is_set(ex)) {
printf("cannot open destination folder\n");
/* try and recover ... */
+ camel_exception_clear (ex);
camel_store_rename_folder(fromstore, tmpname, meta->name, ex);
- return;
+ mail_tool_camel_lock_down ();
+ goto cleanup;
}
- /* copy the messages across */
- uids = camel_folder_get_uids (fromfolder);
- printf("got %d messages in source\n", uids->len);
- update_progress(progress, "Copying messages", 0.0);
- for (i = 0; i < uids->len; i++) {
- CamelMimeMessage *msg;
- char *uid = uids->pdata[i];
- const CamelMessageInfo *info;
-
- update_progress(progress, NULL, i/uids->len);
-
- printf("copying message %s\n", uid);
- msg = camel_folder_get_message(fromfolder, uid, ex);
- if (camel_exception_is_set(ex)) {
- /* we're fucked a bit ... */
- /* need to: delete new folder
- rename old back again */
- g_warning("cannot get message");
- return;
- }
- info = camel_folder_get_message_info(fromfolder, uid);
- camel_folder_append_message(tofolder, msg, info, ex);
- if (camel_exception_is_set(ex)) {
- /* we're fucked a bit ... */
- /* need to: delete new folder
- rename old back again */
- g_warning("cannot append message");
- return;
- }
- gtk_object_unref((GtkObject *)msg);
- }
- update_progress(progress, "Synchronising", 0.0);
+ mail_tool_move_folder_contents (fromfolder, tofolder, FALSE, ex);
- /* sync while we're doing i/o, just to make sure */
- camel_folder_sync(tofolder, FALSE, ex);
- if (camel_exception_is_set(ex)) {
- /* same again */
- }
-
- /* delete everything in the old mailbox */
- printf("deleting old mbox contents\n");
- for (i = 0; i < uids->len; i++) {
- char *uid = uids->pdata[i];
- camel_folder_delete_message(fromfolder, uid);
- }
- camel_folder_sync(fromfolder, TRUE, ex);
- gtk_object_unref((GtkObject *)fromfolder);
- printf("and old mbox ...\n");
+ printf("delete old mbox ...\n");
camel_store_delete_folder(fromstore, tmpname, ex);
+ mail_tool_camel_lock_down ();
/* switch format */
g_free(meta->format);
- meta->format = g_strdup(newtype);
+ meta->format = g_strdup(input->newtype);
if (save_metainfo(meta) == -1) {
- g_warning("Cannot save folder metainfo, you'll probably find you can't\n"
- "open this folder anymore: %s", tourl);
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, "Cannot save folder metainfo; "
+ "you'll probably find you can't\n"
+ "open this folder anymore: %s", tourl);
}
free_metainfo(meta);
/* force a reload of the newly formatted folder */
printf("opening new source\n");
- uri = g_strdup(fb->uri);
- folder_browser_set_uri(fb, uri);
+ uri = g_strdup(input->fb->uri);
+ folder_browser_set_uri(input->fb, uri);
g_free(uri);
/* and unref our copy of the new folder ... */
- gtk_object_unref((GtkObject *)tofolder);
- g_free(fromurl);
- g_free(tourl);
+ cleanup:
+ if (tofolder)
+ camel_object_unref (CAMEL_OBJECT (tofolder));
+ if (fromfolder)
+ camel_object_unref (CAMEL_OBJECT (fromfolder));
+ if (fromstore)
+ camel_object_unref (CAMEL_OBJECT (fromstore));
+ if (tostore)
+ camel_object_unref (CAMEL_OBJECT (tostore));
+ if (fromurl)
+ g_free(fromurl);
+ if (tourl)
+ g_free(tourl);
+ if (url)
+ camel_url_free (url);
}
-struct _reconfig_data {
- FolderBrowser *fb;
- GtkProgress *progress;
- GtkWidget *frame;
- GtkWidget *apply;
- GtkWidget *cancel;
- GtkOptionMenu *optionlist;
+static void
+cleanup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex)
+{
+ reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data;
+
+ if (camel_exception_is_set(ex)) {
+ GtkWidget *win = gtk_widget_get_ancestor((GtkWidget *)input->frame, GTK_TYPE_WINDOW);
+ gnome_error_dialog_parented ("If you can no longer open this mailbox, then\n"
+ "you may need to repair it manually.", GTK_WINDOW (win));
+ }
+
+ gtk_object_unref (GTK_OBJECT (input->fb));
+ g_free (input->newtype);
+}
+
+static const mail_operation_spec op_reconfigure_folder =
+{
+ describe_reconfigure_folder,
+ 0,
+ setup_reconfigure_folder,
+ do_reconfigure_folder,
+ cleanup_reconfigure_folder
};
static void
-reconfigure_clicked(GnomeDialog *d, int button, struct _reconfig_data *data)
+reconfigure_clicked(GnomeDialog *d, int button, reconfigure_folder_input_t *data)
{
if (button == 0) {
GtkMenu *menu;
int type;
char *types[] = { "mh", "mbox" };
- CamelException *ex;
-
- ex = camel_exception_new();
menu = (GtkMenu *)gtk_option_menu_get_menu(data->optionlist);
type = g_list_index(GTK_MENU_SHELL(menu)->children, gtk_menu_get_active(menu));
if (type < 0 || type > 1)
type = 1;
- gtk_progress_set_percentage(data->progress, 0.0);
gtk_widget_set_sensitive(data->frame, FALSE);
gtk_widget_set_sensitive(data->apply, FALSE);
gtk_widget_set_sensitive(data->cancel, FALSE);
- do_local_reconfigure_folder(data->fb, types[type], data->progress, ex);
- if (camel_exception_is_set(ex)) {
- GtkWidget *win = gtk_widget_get_ancestor((GtkWidget *)d, GTK_TYPE_WINDOW);
- char *error;
-
- error = g_strdup_printf("A failure occured:\n %s\n\n"
- "If you can no longer open this mailbox, then\n"
- "you may need to repair it manually.",
- camel_exception_get_description(ex));
- gnome_error_dialog_parented(error, GTK_WINDOW (win));
- g_free(error);
- }
- camel_exception_free(ex);
+ data->newtype = g_strdup (types[type]);
+ mail_operation_queue (&op_reconfigure_folder, data, TRUE);
}
- if (button != -1) {
+
+ if (button != -1)
gnome_dialog_close(d);
- }
}
void
@@ -379,33 +436,31 @@ local_reconfigure_folder(FolderBrowser *fb)
CamelStore *store;
GladeXML *gui;
GnomeDialog *gd;
- struct _reconfig_data *data;
+ reconfigure_folder_input_t *data;
if (fb->folder == NULL) {
g_warning("Trying to reconfigure nonexistant folder");
return;
}
- data = g_malloc0(sizeof(*data));
+ data = g_new (reconfigure_folder_input_t, 1);
store = camel_folder_get_parent_store(fb->folder);
gui = glade_xml_new(EVOLUTION_GLADEDIR "/local-config.glade", "dialog_format");
gd = (GnomeDialog *)glade_xml_get_widget (gui, "dialog_format");
- data->progress = (GtkProgress *)glade_xml_get_widget (gui, "progress_format");
- gtk_progress_set_show_text(data->progress, TRUE);
data->frame = glade_xml_get_widget (gui, "frame_format");
data->apply = glade_xml_get_widget (gui, "apply_format");
data->cancel = glade_xml_get_widget (gui, "cancel_format");
data->optionlist = (GtkOptionMenu *)glade_xml_get_widget (gui, "option_format");
+ data->newtype = NULL;
data->fb = fb;
gtk_label_set_text((GtkLabel *)glade_xml_get_widget (gui, "label_format"),
((CamelService *)store)->url->protocol);
gtk_signal_connect((GtkObject *)gd, "clicked", reconfigure_clicked, data);
- gtk_object_set_data_full((GtkObject *)gd, "data", data, g_free);
gtk_widget_show((GtkWidget *)gd);
gtk_object_unref((GtkObject *)gui);
}
diff --git a/mail/mail-local.h b/mail/mail-local.h
index f24d3c7a2f..331832cfc8 100644
--- a/mail/mail-local.h
+++ b/mail/mail-local.h
@@ -1,3 +1,28 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* mail-local.h: Local mailbox support. */
+
+/*
+ * Author:
+ * Michael Zucchi <NotZed@helixcode.com>
+ *
+ * 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 Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
#ifndef _MAIL_LOCAL_H
#define _MAIL_LOCAL_H
@@ -5,7 +30,7 @@
#include "folder-browser.h"
/* mail-local.c */
-CamelFolder *local_uri_to_folder(const char *uri, CamelException *ex);
+CamelFolder *mail_tool_local_uri_to_folder(const char *uri, CamelException *ex);
void local_reconfigure_folder(FolderBrowser *fb);
#endif
diff --git a/mail/mail-ops.c b/mail/mail-ops.c
index 77045cb79d..d235c6b2d9 100644
--- a/mail/mail-ops.c
+++ b/mail/mail-ops.c
@@ -2,9 +2,9 @@
/* mail-ops.c: callbacks for the mail toolbar/menus */
/*
- * Authors: Dan Winship <danw@helixcode.com>
- * Jeffrey Stedfast <fejj@helixcode.com>
- * Peter Williams <peterw@helixcode.com>
+ * Author :
+ * Dan Winship <danw@helixcode.com>
+ * Peter Williams <peterw@helixcode.com>
*
* Copyright 2000 Helix Code, Inc. (http://www.helixcode.com)
*
@@ -25,1115 +25,1863 @@
*/
#include <config.h>
-#include <ctype.h>
-#include <errno.h>
#include <gnome.h>
-#include <libgnomeprint/gnome-print-master.h>
-#include <libgnomeprint/gnome-print-master-preview.h>
#include "mail.h"
#include "mail-threads.h"
-#include "folder-browser.h"
+#include "mail-tools.h"
+#include "mail-ops.h"
#include "e-util/e-setup.h"
-#include "filter/filter-editor.h"
-#include "filter/filter-driver.h"
-#include "widgets/e-table/e-table.h"
-#include "mail-local.h"
+#include "composer/e-msg-composer.h"
-/* FIXME: is there another way to do this? */
-#include "Evolution.h"
-#include "evolution-storage.h"
+/* ** FETCH MAIL ********************************************************** */
-#include "evolution-shell-client.h"
-
-#ifndef HAVE_MKSTEMP
-#include <fcntl.h>
-#include <sys/stat.h>
-#endif
+typedef struct fetch_mail_input_s
+{
+ gchar *source_url;
+ gboolean keep_on_server;
+ CamelFolder *destination;
+ gpointer hook_func;
+ gpointer hook_data;
+}
+fetch_mail_input_t;
+
+static gchar *describe_fetch_mail (gpointer in_data, gboolean gerund);
+static void setup_fetch_mail (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void do_fetch_mail (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void cleanup_fetch_mail (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+
+static gchar *
+describe_fetch_mail (gpointer in_data, gboolean gerund)
+{
+ fetch_mail_input_t *input = (fetch_mail_input_t *) in_data;
-struct post_send_data {
- CamelFolder *folder;
- const char *uid;
- guint32 flags;
-};
+ if (gerund)
+ return g_strdup_printf ("Fetching email from %s",
+ input->source_url);
+ else
+ return g_strdup_printf ("Fetch email from %s",
+ input->source_url);
+}
-typedef struct rfm_s {
- FolderBrowser *fb;
- MailConfigService *source;
-} rfm_t;
+static void
+setup_fetch_mail (gpointer in_data, gpointer op_data, CamelException * ex)
+{
+ fetch_mail_input_t *input = (fetch_mail_input_t *) in_data;
-typedef struct rsm_s {
- EMsgComposer *composer;
- CamelTransport *transport;
- CamelMimeMessage *message;
- const char *subject;
- char *from;
- struct post_send_data *psd;
- gboolean ok;
-} rsm_t;
+ if (!input->source_url) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "You have no remote mail source configured "
+ "to fetch mail from.");
+ return;
+ }
-static void
-real_fetch_mail( gpointer user_data );
+ if (input->destination == NULL)
+ return;
-static void
-real_send_mail( gpointer user_data );
+ if (!CAMEL_IS_FOLDER (input->destination)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "Bad folder passed to fetch_mail");
+ return;
+ }
-static void
-cleanup_send_mail( gpointer userdata );
+ camel_object_ref (CAMEL_OBJECT (input->destination));
+}
static void
-mail_exception_dialog (char *head, CamelException *ex, gpointer widget)
+do_fetch_mail (gpointer in_data, gpointer op_data, CamelException * ex)
{
- char *msg;
- GtkWindow *window =
- GTK_WINDOW (gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW));
+ fetch_mail_input_t *input;
+ CamelFolder *search_folder = NULL;
+
+ input = (fetch_mail_input_t *) in_data;
+
+ if (input->destination == NULL) {
+ input->destination = mail_tool_get_local_inbox (ex);
+
+ if (input->destination == NULL)
+ return;
+ }
- msg = g_strdup_printf ("%s:\n%s", head,
- camel_exception_get_description (ex));
- gnome_error_dialog_parented (msg, window);
- g_free (msg);
+ search_folder =
+ mail_tool_fetch_mail_into_searchable (input->source_url,
+ input->keep_on_server, ex);
+
+ if (search_folder == NULL) {
+ /* This happens with an IMAP source and on error */
+ camel_object_unref (CAMEL_OBJECT (input->destination));
+ input->destination = NULL;
+ return;
+ }
+
+ mail_tool_filter_contents_into (search_folder, input->destination,
+ input->hook_func, input->hook_data,
+ ex);
+ camel_object_unref (CAMEL_OBJECT (search_folder));
}
-#ifdef USE_BROKEN_THREADS
static void
-async_mail_exception_dialog (char *head, CamelException *ex, gpointer unused )
+cleanup_fetch_mail (gpointer in_data, gpointer op_data, CamelException * ex)
{
- mail_op_error( "%s: %s", head, camel_exception_get_description( ex ) );
+ fetch_mail_input_t *input = (fetch_mail_input_t *) in_data;
+
+ g_free (input->source_url);
+ if (input->destination)
+ camel_object_unref (CAMEL_OBJECT (input->destination));
}
-#else
-#define async_mail_exception_dialog mail_exception_dialog
-#endif
-static gboolean
-check_configured (void)
+static const mail_operation_spec op_fetch_mail = {
+ describe_fetch_mail,
+ 0,
+ setup_fetch_mail,
+ do_fetch_mail,
+ cleanup_fetch_mail
+};
+
+void
+mail_do_fetch_mail (const gchar * source_url, gboolean keep_on_server,
+ CamelFolder * destination,
+ gpointer hook_func, gpointer hook_data)
{
- if (mail_config_is_configured ())
- return TRUE;
-
- mail_config_druid ();
+ fetch_mail_input_t *input;
- return mail_config_is_configured ();
+ input = g_new (fetch_mail_input_t, 1);
+ input->source_url = g_strdup (source_url);
+ input->keep_on_server = keep_on_server;
+ input->destination = destination;
+ input->hook_func = hook_func;
+ input->hook_data = hook_data;
+
+ mail_operation_queue (&op_fetch_mail, input, TRUE);
}
-static void
-select_first_unread (CamelFolder *folder, int type, gpointer data)
+/* ** SEND MAIL *********************************************************** */
+
+typedef struct send_mail_input_s
{
- FolderBrowser *fb = data;
- ETable *table = E_TABLE_SCROLLED (fb->message_list->etable)->table;
- int mrow;
+ gchar *xport_uri;
+ CamelMimeMessage *message;
+ gchar *from;
+
+ /* If done_folder != NULL, will add done_flags to
+ * the flags of the message done_uid in done_folder. */
- mrow = e_table_view_to_model_row (table, 0);
- message_list_select (fb->message_list, mrow, MESSAGE_LIST_SELECT_NEXT,
- 0, CAMEL_MESSAGE_SEEN);
+ CamelFolder *done_folder;
+ char *done_uid;
+ guint32 done_flags;
+
+ GtkWidget *composer;
}
+send_mail_input_t;
+
+static gchar *describe_send_mail (gpointer in_data, gboolean gerund);
+static void setup_send_mail (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void do_send_mail (gpointer in_data, gpointer op_data,
+
+ CamelException * ex);
+static void cleanup_send_mail (gpointer in_data, gpointer op_data,
+ CamelException * ex);
-static CamelFolder *
-filter_get_folder(FilterDriver *fd, const char *uri, void *data)
+static gchar *
+describe_send_mail (gpointer in_data, gboolean gerund)
{
- return mail_uri_to_folder(uri);
+ send_mail_input_t *input = (send_mail_input_t *) in_data;
+
+ if (gerund) {
+ if (input->message->subject && input->message->subject[0])
+ return g_strdup_printf ("Sending \"%s\"",
+ input->message->subject);
+ else
+ return
+ g_strdup
+ ("Sending a message without a subject");
+ } else {
+ if (input->message->subject && input->message->subject[0])
+ return g_strdup_printf ("Send \"%s\"",
+ input->message->subject);
+ else
+ return g_strdup ("Send a message without a subject");
+ }
}
static void
-fetch_remote_mail (CamelFolder *source, CamelFolder *dest,
- gboolean keep_on_server, FolderBrowser *fb,
- CamelException *ex)
+setup_send_mail (gpointer in_data, gpointer op_data, CamelException * ex)
{
- CamelUIDCache *cache;
- GPtrArray *uids;
- int i;
+ send_mail_input_t *input = (send_mail_input_t *) in_data;
- uids = camel_folder_get_uids (source);
- if (keep_on_server) {
- GPtrArray *new_uids;
- char *url, *p, *filename;
-
- url = camel_url_to_string (
- CAMEL_SERVICE (source->parent_store)->url, FALSE);
- for (p = url; *p; p++) {
- if (!isascii ((unsigned char)*p) ||
- strchr (" /'\"`&();|<>${}!", *p))
- *p = '_';
- }
- filename = g_strdup_printf ("%s/config/cache-%s",
- evolution_dir, url);
- g_free (url);
-
- cache = camel_uid_cache_new (filename);
- g_free (filename);
- if (cache) {
- new_uids = camel_uid_cache_get_new_uids (cache, uids);
- camel_folder_free_uids (source, uids);
- uids = new_uids;
- } else {
- async_mail_exception_dialog ("Could not read UID "
- "cache file. You may "
- "receive duplicate "
- "messages.", NULL, fb);
- }
- } else
- cache = NULL;
+ if (!input->xport_uri) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No transport URI specified for send_mail operation.");
+ return;
+ }
- printf ("got %d new messages in source\n", uids->len);
- for (i = 0; i < uids->len; i++) {
- CamelMimeMessage *msg;
+ if (!CAMEL_IS_MIME_MESSAGE (input->message)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No message specified for send_mail operation.");
+ return;
+ }
- msg = camel_folder_get_message (source, uids->pdata[i], ex);
- if (camel_exception_is_set (ex)) {
- async_mail_exception_dialog ("Unable to get message",
- ex, fb);
- goto done;
- }
+ if (input->from == NULL) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No from address specified for send_mail operation.");
+ return;
+ }
- /* Append with flags = 0 since this is a new message */
- camel_folder_append_message (dest, msg, 0, ex);
- if (camel_exception_is_set (ex)) {
- async_mail_exception_dialog ("Unable to write message",
- ex, fb);
- gtk_object_unref (GTK_OBJECT (msg));
- goto done;
- }
+ /* NOTE THE EARLY EXIT!! */
- if (!cache)
- camel_folder_delete_message (source, uids->pdata[i]);
- gtk_object_unref (GTK_OBJECT (msg));
+ if (input->done_folder == NULL) {
+ camel_object_ref (CAMEL_OBJECT (input->message));
+ gtk_object_ref (GTK_OBJECT (input->composer));
+ gtk_widget_hide (GTK_WIDGET (input->composer));
+ return;
}
- camel_folder_sync (source, TRUE, ex);
+ if (!CAMEL_IS_FOLDER (input->done_folder)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "Bad done_folder specified for send_mail operation.");
+ return;
+ }
+
+ if (input->done_uid == NULL) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No done_uid specified for send_mail operation.");
+ return;
+ }
+
+ if (!GTK_IS_WIDGET (input->composer)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No composer specified for send_mail operation.");
+ return;
+ }
- done:
- if (cache) {
- camel_uid_cache_free_uids (uids);
- if (!camel_exception_is_set (ex))
- camel_uid_cache_save (cache);
- camel_uid_cache_destroy (cache);
- } else
- camel_folder_free_uids (source, uids);
+ camel_object_ref (CAMEL_OBJECT (input->message));
+ camel_object_ref (CAMEL_OBJECT (input->done_folder));
+ gtk_object_ref (GTK_OBJECT (input->composer));
+ gtk_widget_hide (GTK_WIDGET (input->composer));
}
-void
-real_fetch_mail (gpointer user_data)
-{
- rfm_t *info;
- FolderBrowser *fb = NULL;
- CamelException *ex;
- CamelStore *store = NULL, *dest_store = NULL;
- CamelFolder *folder = NULL, *dest_folder = NULL;
- char *url = NULL, *dest_url;
- FilterContext *fc = NULL;
- FilterDriver *driver = NULL;
- char *userrules, *systemrules;
- char *tmp_mbox = NULL, *source;
- guint handler_id = 0;
- struct stat st;
- gboolean keep;
-
- info = (rfm_t *) user_data;
- fb = info->fb;
- url = info->source->url;
- keep = info->source->keep_on_server;
-
- /* If using IMAP, don't do anything... */
- if (!strncmp (url, "imap:", 5))
+static void
+do_send_mail (gpointer in_data, gpointer op_data, CamelException * ex)
+{
+ send_mail_input_t *input = (send_mail_input_t *) in_data;
+ CamelTransport *xport;
+
+ mail_tool_camel_lock_up ();
+ camel_mime_message_set_from (input->message, input->from);
+
+ camel_medium_add_header (CAMEL_MEDIUM (input->message), "X-Mailer",
+ "Evolution (Developer Preview)");
+ camel_mime_message_set_date (input->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))
return;
- ex = camel_exception_new ();
+ mail_tool_send_via_transport (xport, CAMEL_MEDIUM (input->message),
+ ex);
- dest_url = g_strdup_printf ("mbox://%s/local/Inbox", evolution_dir);
- dest_store = camel_session_get_store (session, dest_url, ex);
- g_free (dest_url);
- if (!dest_store) {
- async_mail_exception_dialog ("Unable to get new mail", ex, fb);
- goto cleanup;
- }
-
- dest_folder = camel_store_get_folder (dest_store, "mbox", FALSE, ex);
- if (!dest_folder) {
- async_mail_exception_dialog ("Unable to get new mail", ex, fb);
- goto cleanup;
+ if (camel_exception_is_set (ex))
+ return;
+
+ if (input->done_folder) {
+ guint32 set;
+
+ mail_tool_camel_lock_up ();
+ set = camel_folder_get_message_flags (input->done_folder,
+ input->done_uid);
+ camel_folder_set_message_flags (input->done_folder,
+ input->done_uid,
+ input->done_flags, ~set);
+ mail_tool_camel_lock_down ();
}
+}
- tmp_mbox = g_strdup_printf ("%s/local/Inbox/movemail", evolution_dir);
+static void
+cleanup_send_mail (gpointer in_data, gpointer op_data, CamelException * ex)
+{
+ send_mail_input_t *input = (send_mail_input_t *) in_data;
- /* If fetching mail from an mbox store, safely copy it to a
- * temporary store first.
- */
- if (!strncmp (url, "mbox:", 5)) {
- int tmpfd;
+ camel_object_unref (CAMEL_OBJECT (input->message));
+ if (input->done_folder)
+ camel_object_unref (CAMEL_OBJECT (input->done_folder));
- tmpfd = open (tmp_mbox, O_RDWR | O_CREAT | O_APPEND, 0660);
+ g_free (input->from);
+ g_free (input->xport_uri);
+ g_free (input->done_uid);
- if (tmpfd == -1) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- "Couldn't create temporary "
- "mbox: %s", g_strerror (errno));
- async_mail_exception_dialog ("Unable to move mail", ex, fb );
- goto cleanup;
- }
- close (tmpfd);
-
- /* Skip over "mbox:" plus host part (if any) of url. */
- source = url + 5;
- if (!strncmp (source, "//", 2))
- source = strchr (source + 2, '/');
-
- camel_movemail (source, tmp_mbox, ex);
- if (camel_exception_is_set (ex)) {
- async_mail_exception_dialog ("Unable to move mail",
- ex, fb);
- goto cleanup;
- }
+ if (!camel_exception_is_set (ex))
+ gtk_widget_destroy (input->composer);
+ else
+ gtk_widget_show (input->composer);
+}
- if (stat (tmp_mbox, &st) == -1 || st.st_size == 0) {
- gnome_ok_dialog ("No new messages.");
- goto cleanup;
- }
+static const mail_operation_spec op_send_mail = {
+ describe_send_mail,
+ 0,
+ setup_send_mail,
+ do_send_mail,
+ cleanup_send_mail
+};
- folder = camel_store_get_folder (dest_store, "movemail",
- FALSE, ex);
- if (camel_exception_get_id (ex) != CAMEL_EXCEPTION_NONE) {
- async_mail_exception_dialog ("Unable to move mail", ex, fb);
- goto cleanup;
- }
- } else {
- CamelFolder *sourcefolder;
-
- store = camel_session_get_store(session, url, ex);
- if (!store) {
- async_mail_exception_dialog("Unable to get new mail", ex, fb);
- goto cleanup;
- }
-
- camel_service_connect(CAMEL_SERVICE (store), ex);
- if (camel_exception_get_id(ex) != CAMEL_EXCEPTION_NONE) {
- if (camel_exception_get_id(ex) != CAMEL_EXCEPTION_USER_CANCEL)
- async_mail_exception_dialog("Unable to get new mail", ex, fb);
- goto cleanup;
- }
+void
+mail_do_send_mail (const char *xport_uri,
+ CamelMimeMessage * message,
+ const char * from,
+ CamelFolder * done_folder,
+ const char *done_uid,
+ guint32 done_flags, GtkWidget * composer)
+{
+ send_mail_input_t *input;
+
+ input = g_new (send_mail_input_t, 1);
+ input->xport_uri = g_strdup (xport_uri);
+ input->message = message;
+ input->from = g_strdup (from);
+ input->done_folder = done_folder;
+ input->done_uid = g_strdup (done_uid);
+ input->done_flags = done_flags;
+ input->composer = composer;
+
+ mail_operation_queue (&op_send_mail, input, TRUE);
+}
- sourcefolder = camel_store_get_folder(store, "inbox", FALSE, ex);
- if (camel_exception_get_id(ex) != CAMEL_EXCEPTION_NONE) {
- async_mail_exception_dialog("Unable to get new mail", ex, fb);
- goto cleanup;
- }
+/* ** EXPUNGE FOLDER ****************************************************** */
- /* can we perform filtering on this source? */
- if (!(sourcefolder->has_summary_capability
- && sourcefolder->has_search_capability)) {
- folder = camel_store_get_folder (dest_store,
- "movemail", TRUE, ex);
- if (camel_exception_is_set (ex)) {
- async_mail_exception_dialog ("Unable to move mail", ex, fb);
- goto cleanup;
- }
-
- fetch_remote_mail (sourcefolder, folder, keep, fb, ex);
- gtk_object_unref (GTK_OBJECT (sourcefolder));
- if (camel_exception_is_set (ex))
- goto cleanup;
- } else {
- folder = sourcefolder;
- }
- }
+static gchar *describe_expunge_folder (gpointer in_data, gboolean gerund);
+static void setup_expunge_folder (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void do_expunge_folder (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void cleanup_expunge_folder (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+
+static gchar *
+describe_expunge_folder (gpointer in_data, gboolean gerund)
+{
+ CamelFolder *f = CAMEL_FOLDER (in_data);
- if (camel_folder_get_message_count (folder) == 0) {
- gnome_ok_dialog ("No new messages.");
- goto cleanup;
- } else if (camel_exception_is_set (ex)) {
- async_mail_exception_dialog ("Unable to get new mail", ex, fb);
- goto cleanup;
+ if (gerund)
+ return g_strdup_printf ("Expunging \"%s\"", f->full_name);
+ else
+ return g_strdup_printf ("Expunge \"%s\"", f->full_name);
+}
+
+static void
+setup_expunge_folder (gpointer in_data, gpointer op_data, CamelException * ex)
+{
+ if (!CAMEL_IS_FOLDER (in_data)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No folder is selected to be expunged");
+ return;
}
- folder_browser_clear_search (fb);
+ camel_object_ref (CAMEL_OBJECT (in_data));
+}
- /* apply filtering rules to this inbox */
- fc = filter_context_new();
- userrules = g_strdup_printf("%s/filters.xml", evolution_dir);
- systemrules = g_strdup_printf("%s/evolution/filtertypes.xml", EVOLUTION_DATADIR);
- rule_context_load((RuleContext *)fc, systemrules, userrules);
- g_free (userrules);
- g_free (systemrules);
+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 ();
+}
- driver = filter_driver_new(fc, filter_get_folder, 0);
+static void
+cleanup_expunge_folder (gpointer in_data, gpointer op_data,
+ CamelException * ex)
+{
+ camel_object_unref (CAMEL_OBJECT (in_data));
+}
- /* Attach a handler to the destination folder to select the first unread
- * message iff it changes and iff it's the folder being viewed.
- */
- if (dest_folder == fb->folder)
- handler_id = gtk_signal_connect (GTK_OBJECT (dest_folder), "folder_changed",
- GTK_SIGNAL_FUNC (select_first_unread), fb);
+static const mail_operation_spec op_expunge_folder = {
+ describe_expunge_folder,
+ 0,
+ setup_expunge_folder,
+ do_expunge_folder,
+ cleanup_expunge_folder
+};
- if (filter_driver_run(driver, folder, dest_folder) == -1) {
- async_mail_exception_dialog ("Unable to get new mail", ex, fb);
- goto cleanup;
- }
+void
+mail_do_expunge_folder (CamelFolder * folder)
+{
+ mail_operation_queue (&op_expunge_folder, folder, FALSE);
+}
+
+/* ** REFILE MESSAGES ***************************************************** */
- if (dest_folder == fb->folder)
- gtk_signal_disconnect (GTK_OBJECT (dest_folder), handler_id);
+typedef struct refile_messages_input_s
+{
+ CamelFolder *source;
+ GPtrArray *uids;
+ gchar *dest_uri;
+}
+refile_messages_input_t;
+
+static gchar *describe_refile_messages (gpointer in_data, gboolean gerund);
+static void setup_refile_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void do_refile_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void cleanup_refile_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+
+static gchar *
+describe_refile_messages (gpointer in_data, gboolean gerund)
+{
+ refile_messages_input_t *input = (refile_messages_input_t *) in_data;
- cleanup:
- if (stat (tmp_mbox, &st) == 0 && st.st_size == 0)
- unlink (tmp_mbox); /* FIXME: should use camel to do this */
- g_free (tmp_mbox);
+ if (gerund)
+ return
+ g_strdup_printf
+ ("Moving messages from \"%s\" into \"%s\"",
+ input->source->full_name, input->dest_uri);
+ else
+ return
+ g_strdup_printf
+ ("Move messages from \"%s\" into \"%s\"",
+ input->source->full_name, input->dest_uri);
+}
- if (driver)
- gtk_object_unref((GtkObject *)driver);
- if (fc)
- gtk_object_unref((GtkObject *)fc);
+static void
+setup_refile_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex)
+{
+ refile_messages_input_t *input = (refile_messages_input_t *) in_data;
- if (folder) {
- camel_folder_sync (folder, TRUE, ex);
- gtk_object_unref (GTK_OBJECT (folder));
+ if (!CAMEL_IS_FOLDER (input->source)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No source folder to refile messages from specified.");
+ return;
}
- if (dest_folder) {
- camel_folder_sync (dest_folder, TRUE, ex);
- gtk_object_unref (GTK_OBJECT (dest_folder));
+ if (input->uids == NULL) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No messages to refile have been specified.");
+ return;
}
- if (store) {
- camel_service_disconnect (CAMEL_SERVICE (store), ex);
- gtk_object_unref (GTK_OBJECT (store));
+ if (input->dest_uri == NULL) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No URI to refile to has been specified.");
+ return;
}
- if (dest_store && dest_store != fb->folder->parent_store) {
- camel_service_disconnect (CAMEL_SERVICE (dest_store), ex);
- gtk_object_unref (GTK_OBJECT (dest_store));
+ camel_object_ref (CAMEL_OBJECT (input->source));
+}
+
+static void
+do_refile_messages (gpointer in_data, gpointer op_data, CamelException * ex)
+{
+ refile_messages_input_t *input = (refile_messages_input_t *) in_data;
+ CamelFolder *dest;
+ gint i;
+
+ dest = mail_tool_uri_to_folder (input->dest_uri, ex);
+ if (camel_exception_is_set (ex))
+ return;
+
+ mail_tool_camel_lock_up ();
+ for (i = 0; i < input->uids->len; i++) {
+ camel_folder_move_message_to (input->source,
+ input->uids->pdata[i], dest,
+ ex);
+ g_free (input->uids->pdata[i]);
+ if (camel_exception_is_set (ex))
+ break;
}
- camel_exception_free (ex);
+
+ camel_object_unref (CAMEL_OBJECT (dest));
+ mail_tool_camel_lock_down ();
}
+static void
+cleanup_refile_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex)
+{
+ refile_messages_input_t *input = (refile_messages_input_t *) in_data;
+
+ camel_object_unref (CAMEL_OBJECT (input->source));
+ g_free (input->dest_uri);
+ g_ptr_array_free (input->uids, TRUE);
+}
+
+static const mail_operation_spec op_refile_messages = {
+ describe_refile_messages,
+ 0,
+ setup_refile_messages,
+ do_refile_messages,
+ cleanup_refile_messages
+};
+
void
-fetch_mail (GtkWidget *button, gpointer user_data)
+mail_do_refile_messages (CamelFolder * source, GPtrArray * uids,
+ gchar * dest_uri)
{
- MailConfigService *source;
- rfm_t *info;
+ refile_messages_input_t *input;
- if (!check_configured ())
- return;
+ input = g_new (refile_messages_input_t, 1);
+ input->source = source;
+ input->uids = uids;
+ input->dest_uri = g_strdup (dest_uri);
+
+ mail_operation_queue (&op_refile_messages, input, TRUE);
+}
+
+/* ** FLAG MESSAGES ******************************************************* */
- source = mail_config_get_default_source ();
- if (!source || !source->url) {
- GtkWidget *win = gtk_widget_get_ancestor (GTK_WIDGET (user_data),
- GTK_TYPE_WINDOW);
+typedef struct flag_messages_input_s
+{
+ CamelFolder *source;
+ GPtrArray *uids;
+ gboolean invert;
+ guint32 mask;
+ guint32 set;
+}
+flag_messages_input_t;
+
+static gchar *describe_flag_messages (gpointer in_data, gboolean gerund);
+static void setup_flag_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void do_flag_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void cleanup_flag_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+
+static gchar *
+describe_flag_messages (gpointer in_data, gboolean gerund)
+{
+ flag_messages_input_t *input = (flag_messages_input_t *) in_data;
+
+ /* FIXME: change based on flags being applied? */
- gnome_error_dialog_parented ("You have no remote mail source "
- "configured", GTK_WINDOW (win));
+ if (gerund)
+ return g_strdup_printf ("Marking messages in folder \"%s\"",
+ input->source->full_name);
+ else
+ return g_strdup_printf ("Mark messages in folder \"%s\"",
+ input->source->full_name);
+}
+
+static void
+setup_flag_messages (gpointer in_data, gpointer op_data, CamelException * ex)
+{
+ flag_messages_input_t *input = (flag_messages_input_t *) in_data;
+
+ if (!CAMEL_IS_FOLDER (input->source)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No source folder to flag messages from specified.");
return;
}
- /* This must be dynamically allocated so as not to be clobbered
- * when we return. Actually, making it static in the whole file
- * would probably work.
- */
+ if (input->uids == NULL) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No messages to flag have been specified.");
+ return;
+ }
- info = g_new (rfm_t, 1);
- info->fb = FOLDER_BROWSER (user_data);
- info->source = source;
+ camel_object_ref (CAMEL_OBJECT (input->source));
+}
-#ifdef USE_BROKEN_THREADS
- mail_operation_try (_("Fetching mail"), real_fetch_mail, NULL, info);
-#else
- real_fetch_mail (info);
-#endif
+static void
+do_flag_messages (gpointer in_data, gpointer op_data, CamelException * ex)
+{
+ flag_messages_input_t *input = (flag_messages_input_t *) in_data;
+ gint i;
+
+ for (i = 0; i < input->uids->len; i++) {
+ if (input->invert) {
+ const CamelMessageInfo *info;
+
+ mail_tool_camel_lock_up ();
+ info = camel_folder_get_message_info (input->source, input->uids->pdata[i]);
+ camel_folder_set_message_flags (input->source, input->uids->pdata[i],
+ input->mask, ~info->flags);
+ mail_tool_camel_lock_down ();
+ } else {
+ mail_tool_set_uid_flags (input->source, input->uids->pdata[i],
+ input->mask, input->set);
+ }
+
+ g_free (input->uids->pdata[i]);
+ }
}
-static gboolean
-ask_confirm_for_empty_subject (EMsgComposer *composer)
+static void
+cleanup_flag_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex)
{
- GtkWidget *message_box;
- int button;
+ flag_messages_input_t *input = (flag_messages_input_t *) in_data;
- message_box = gnome_message_box_new (_("This message has no subject.\nReally send?"),
- GNOME_MESSAGE_BOX_QUESTION,
- GNOME_STOCK_BUTTON_YES, GNOME_STOCK_BUTTON_NO,
- NULL);
+ camel_object_unref (CAMEL_OBJECT (input->source));
+ g_ptr_array_free (input->uids, TRUE);
+}
- button = gnome_dialog_run_and_close (GNOME_DIALOG (message_box));
+static const mail_operation_spec op_flag_messages = {
+ describe_flag_messages,
+ 0,
+ setup_flag_messages,
+ do_flag_messages,
+ cleanup_flag_messages
+};
+
+void
+mail_do_flag_messages (CamelFolder * source, GPtrArray * uids,
+ gboolean invert,
+ guint32 mask, guint32 set)
+{
+ flag_messages_input_t *input;
- if (button == 0)
- return TRUE;
+ input = g_new (flag_messages_input_t, 1);
+ input->source = source;
+ input->uids = uids;
+ input->invert = invert;
+ input->mask = mask;
+ input->set = set;
+
+ mail_operation_queue (&op_flag_messages, input, TRUE);
+}
+
+/* ** SCAN SUBFOLDERS ***************************************************** */
+
+typedef struct scan_subfolders_input_s
+{
+ gchar *source_uri;
+ gboolean add_INBOX;
+ EvolutionStorage *storage;
+}
+scan_subfolders_input_t;
+
+typedef struct scan_subfolders_folderinfo_s
+{
+ char *path;
+ char *uri;
+}
+scan_subfolders_folderinfo_t;
+
+typedef struct scan_subfolders_op_s
+{
+ GPtrArray *new_folders;
+}
+scan_subfolders_op_t;
+
+static gchar *describe_scan_subfolders (gpointer in_data, gboolean gerund);
+static void setup_scan_subfolders (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void do_scan_subfolders (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void cleanup_scan_subfolders (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+
+static gchar *
+describe_scan_subfolders (gpointer in_data, gboolean gerund)
+{
+ scan_subfolders_input_t *input = (scan_subfolders_input_t *) in_data;
+
+ if (gerund)
+ return g_strdup_printf ("Scanning folders in \"%s\"",
+ input->source_uri);
else
- return FALSE;
+ return g_strdup_printf ("Scan folders in \"%s\"",
+ input->source_uri);
}
static void
-set_x_mailer_header (CamelMedium *medium)
+setup_scan_subfolders (gpointer in_data, gpointer op_data,
+ CamelException * ex)
{
- char *mailer_string;
+ scan_subfolders_input_t *input = (scan_subfolders_input_t *) in_data;
+ scan_subfolders_op_t *data = (scan_subfolders_op_t *) op_data;
- mailer_string = g_strdup_printf ("Evolution %s (Developer Preview)", VERSION);
+ if (!input->source_uri) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No source uri to scan subfolders from was provided.");
+ return;
+ }
- camel_medium_add_header (medium, "X-Mailer", mailer_string);
+ if (!EVOLUTION_IS_STORAGE (input->storage)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No storage to scan subfolders into was provided.");
+ return;
+ }
- g_free (mailer_string);
+ gtk_object_ref (GTK_OBJECT (input->storage));
+ data->new_folders = g_ptr_array_new ();
}
static void
-real_send_mail (gpointer user_data)
+do_scan_subfolders (gpointer in_data, gpointer op_data, CamelException * ex)
{
- rsm_t *info = (rsm_t *) user_data;
- EMsgComposer *composer = NULL;
- CamelTransport *transport = NULL;
- CamelException *ex = NULL;
- CamelMimeMessage *message = NULL;
- const char *subject = NULL;
- char *from = NULL;
- struct post_send_data *psd = NULL;
+ scan_subfolders_input_t *input = (scan_subfolders_input_t *) in_data;
+ scan_subfolders_op_t *data = (scan_subfolders_op_t *) op_data;
-#ifdef USE_BROKEN_THREADS
- mail_op_hide_progressbar ();
- mail_op_set_message ("Connecting to transport...");
-#endif
+ scan_subfolders_folderinfo_t *info;
+ GPtrArray *lsub;
+ CamelFolder *folder;
+ int i;
+ char *splice;
- ex = camel_exception_new ();
- composer = info->composer;
- transport = info->transport;
- message = info->message;
- subject = info->subject;
- from = info->from;
- psd = info->psd;
+ if (input->source_uri[strlen (input->source_uri) - 1] == '/')
+ splice = "";
+ else
+ splice = "/";
- set_x_mailer_header (CAMEL_MEDIUM (message));
+ folder = mail_tool_get_root_of_store (input->source_uri, ex);
+ if (camel_exception_is_set (ex))
+ return;
- camel_mime_message_set_from (message, from);
- camel_mime_message_set_date (message, CAMEL_MESSAGE_DATE_CURRENT, 0);
+ mail_tool_camel_lock_up ();
- camel_service_connect (CAMEL_SERVICE (transport), ex);
+ /* we need a way to set the namespace */
+ lsub = camel_folder_get_subfolder_names (folder);
-#ifdef USE_BROKEN_THREADS
- mail_op_set_message ("Connected. Sending...");
-#endif
+ mail_tool_camel_lock_down ();
- if (!camel_exception_is_set (ex))
- camel_transport_send (transport, CAMEL_MEDIUM (message), ex);
+ if (input->add_INBOX) {
+ info = g_new (scan_subfolders_folderinfo_t, 1);
+ info->path = g_strdup ("/INBOX");
+ info->uri =
+ g_strdup_printf ("%s%sINBOX", input->source_uri,
+ splice);
+ g_ptr_array_add (data->new_folders, info);
+ }
- if (!camel_exception_is_set (ex)) {
-#ifdef USE_BROKEN_THREADS
- mail_op_set_message ("Sent. Disconnecting...");
-#endif
- camel_service_disconnect (CAMEL_SERVICE (transport), ex);
+ for (i = 0; i < lsub->len; i++) {
+ info = g_new (scan_subfolders_folderinfo_t, 1);
+ info->path = g_strdup_printf ("/%s", (char *) lsub->pdata[i]);
+ info->uri =
+ g_strdup_printf ("%s%s%s", input->source_uri, splice,
+ info->path);
+ g_ptr_array_add (data->new_folders, info);
}
- if (camel_exception_is_set (ex)) {
- async_mail_exception_dialog ("Could not send message", ex, composer);
- info->ok = FALSE;
- } else {
- if (psd) {
- camel_folder_set_message_flags (psd->folder, psd->uid,
- psd->flags, psd->flags);
- }
- info->ok = TRUE;
+ camel_folder_free_subfolder_names (folder, lsub);
+ camel_object_unref (CAMEL_OBJECT (folder));
+}
+
+static void
+cleanup_scan_subfolders (gpointer in_data, gpointer op_data,
+ CamelException * ex)
+{
+ scan_subfolders_input_t *input = (scan_subfolders_input_t *) in_data;
+ scan_subfolders_op_t *data = (scan_subfolders_op_t *) op_data;
+
+ int i;
+ for (i = 0; i < data->new_folders->len; i++) {
+ scan_subfolders_folderinfo_t *info;
+
+ info = data->new_folders->pdata[i];
+ evolution_storage_new_folder (input->storage,
+ info->path,
+ "mail",
+ info->uri, "(No description)");
+ g_free (info->path);
+ g_free (info->uri);
+ g_free (info);
}
- camel_exception_free (ex);
+ g_ptr_array_free (data->new_folders, TRUE);
+ gtk_object_unref (GTK_OBJECT (input->storage));
+ g_free (input->source_uri);
+}
+
+static const mail_operation_spec op_scan_subfolders = {
+ describe_scan_subfolders,
+ sizeof (scan_subfolders_op_t),
+ setup_scan_subfolders,
+ do_scan_subfolders,
+ cleanup_scan_subfolders
+};
+
+void
+mail_do_scan_subfolders (const gchar * source_uri, gboolean add_INBOX,
+ EvolutionStorage * storage)
+{
+ scan_subfolders_input_t *input;
+
+ input = g_new (scan_subfolders_input_t, 1);
+ input->source_uri = g_strdup (source_uri);
+ input->add_INBOX = add_INBOX;
+ input->storage = storage;
+
+ mail_operation_queue (&op_scan_subfolders, input, TRUE);
+}
+
+/* ** ATTACH MESSAGE ****************************************************** */
+
+typedef struct attach_message_input_s
+{
+ EMsgComposer *composer;
+ CamelFolder *folder;
+ gchar *uid;
+}
+attach_message_input_t;
+
+typedef struct attach_message_data_s
+{
+ CamelMimePart *part;
+}
+attach_message_data_t;
+
+static gchar *describe_attach_message (gpointer in_data, gboolean gerund);
+static void setup_attach_message (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void do_attach_message (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void cleanup_attach_message (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+
+static gchar *
+describe_attach_message (gpointer in_data, gboolean gerund)
+{
+ attach_message_input_t *input = (attach_message_input_t *) in_data;
+
+ if (gerund)
+ return
+ g_strdup_printf
+ ("Attaching messages from folder \"%s\"",
+ input->folder->full_name);
+ else
+ return g_strdup_printf ("Attach messages from \"%s\"",
+ input->folder->full_name);
}
static void
-cleanup_send_mail (gpointer userdata)
+setup_attach_message (gpointer in_data, gpointer op_data, CamelException * ex)
{
- rsm_t *info = (rsm_t *) userdata;
-
- if (info->ok) {
- gtk_object_destroy (GTK_OBJECT (info->composer));
+ attach_message_input_t *input = (attach_message_input_t *) in_data;
+
+ if (!input->uid) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No UID specified to attach.");
+ return;
}
- gtk_object_unref (GTK_OBJECT (info->message));
- g_free (info);
+ if (!CAMEL_IS_FOLDER (input->folder)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No folder to fetch the message from specified.");
+ return;
+ }
+
+ if (!E_IS_MSG_COMPOSER (input->composer)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No message composer from specified.");
+ return;
+ }
+
+ camel_object_ref (CAMEL_OBJECT (input->folder));
+ gtk_object_ref (GTK_OBJECT (input->composer));
}
static void
-composer_send_cb (EMsgComposer *composer, gpointer data)
-{
- const MailConfigIdentity *id = NULL;
- static CamelTransport *transport = NULL;
- struct post_send_data *psd = data;
- rsm_t *info;
- static char *from = NULL;
- const char *subject;
- CamelException *ex;
+do_attach_message (gpointer in_data, gpointer op_data, CamelException * ex)
+{
+ attach_message_input_t *input = (attach_message_input_t *) in_data;
+ attach_message_data_t *data = (attach_message_data_t *) op_data;
+
CamelMimeMessage *message;
- char *name, *addr;
-
- ex = camel_exception_new ();
-
- id = mail_config_get_default_identity ();
-
- if (!check_configured() || !id) {
- GtkWidget *message;
-
- message = gnome_warning_dialog_parented (_("You need to configure an identity\n"
- "before you can send mail."),
- GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (composer),
- GTK_TYPE_WINDOW)));
- gnome_dialog_run_and_close (GNOME_DIALOG (message));
+ CamelMimePart *part;
+
+ mail_tool_camel_lock_up ();
+ message = camel_folder_get_message (input->folder, input->uid, ex);
+ if (!message) {
+ mail_tool_camel_lock_down ();
+ return;
+ }
+
+ part = mail_tool_make_message_attachment (message);
+ camel_object_unref (CAMEL_OBJECT (message));
+ mail_tool_camel_lock_down ();
+ if (!part)
+ return;
+
+ data->part = part;
+}
+
+static void
+cleanup_attach_message (gpointer in_data, gpointer op_data,
+ CamelException * ex)
+{
+ attach_message_input_t *input = (attach_message_input_t *) in_data;
+ attach_message_data_t *data = (attach_message_data_t *) op_data;
+
+ e_msg_composer_attach (input->composer, data->part);
+ camel_object_unref (CAMEL_OBJECT (data->part));
+ camel_object_unref (CAMEL_OBJECT (input->folder));
+ gtk_object_unref (GTK_OBJECT (input->composer));
+ g_free (input->uid);
+}
+
+static const mail_operation_spec op_attach_message = {
+ describe_attach_message,
+ sizeof (attach_message_data_t),
+ setup_attach_message,
+ do_attach_message,
+ cleanup_attach_message
+};
+
+void
+mail_do_attach_message (CamelFolder * folder, const char *uid,
+ EMsgComposer * composer)
+{
+ attach_message_input_t *input;
+
+ input = g_new (attach_message_input_t, 1);
+ input->folder = folder;
+ input->uid = g_strdup (uid);
+ input->composer = composer;
+
+ mail_operation_queue (&op_attach_message, input, TRUE);
+}
+
+/* ** FORWARD MESSAGES **************************************************** */
+
+typedef struct forward_messages_input_s
+{
+ CamelMimeMessage *basis;
+ CamelFolder *source;
+ GPtrArray *uids;
+ EMsgComposer *composer;
+}
+forward_messages_input_t;
+
+typedef struct forward_messages_data_s
+{
+ gchar *subject;
+ GPtrArray *parts;
+}
+forward_messages_data_t;
+
+static gchar *describe_forward_messages (gpointer in_data, gboolean gerund);
+static void setup_forward_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void do_forward_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void cleanup_forward_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+
+static gchar *
+describe_forward_messages (gpointer in_data, gboolean gerund)
+{
+ forward_messages_input_t *input =
+
+ (forward_messages_input_t *) in_data;
+
+ if (gerund) {
+ if (input->basis->subject)
+ return g_strdup_printf ("Forwarding messages \"%s\"",
+ input->basis->subject);
+ else
+ return
+ g_strdup_printf
+ ("Forwarding a message without a subject");
+ } else {
+ if (input->basis->subject)
+ return g_strdup_printf ("Forward message \"%s\"",
+ input->basis->subject);
+ else
+ return
+ g_strdup_printf
+ ("Forward a message without a subject");
+ }
+}
+
+static void
+setup_forward_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex)
+{
+ forward_messages_input_t *input =
+
+ (forward_messages_input_t *) in_data;
+
+ if (!input->uids) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No UIDs specified to attach.");
+ return;
+ }
+
+ if (!CAMEL_IS_MIME_MESSAGE (input->basis)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No basic message to forward was specified.");
+ return;
+ }
+
+ if (!CAMEL_IS_FOLDER (input->source)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No folder to fetch the messages from specified.");
return;
}
-
- from = g_strdup (e_msg_composer_hdrs_get_from (E_MSG_COMPOSER_HDRS (composer->hdrs)));
- if (!from) {
- CamelInternetAddress *ciaddr;
-
- g_assert (id);
-
- name = id->name;
- g_assert (name);
-
- addr = id->address;
- g_assert (addr);
-
- ciaddr = camel_internet_address_new ();
- camel_internet_address_add (ciaddr, name, addr);
-
- from = camel_address_encode (CAMEL_ADDRESS (ciaddr));
+
+ if (!E_IS_MSG_COMPOSER (input->composer)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No message composer from specified.");
+ return;
}
-
- if (!transport) {
- MailConfigService *t;
- char *url;
-
- t = mail_config_get_transport ();
- url = t->url;
- g_assert (url);
-
- transport = camel_session_get_transport (session, url, ex);
- if (camel_exception_get_id (ex) != CAMEL_EXCEPTION_NONE) {
- mail_exception_dialog ("Could not load mail transport",
- ex, composer);
- camel_exception_free (ex);
+
+ camel_object_ref (CAMEL_OBJECT (input->basis));
+ camel_object_ref (CAMEL_OBJECT (input->source));
+ gtk_object_ref (GTK_OBJECT (input->composer));
+}
+
+static void
+do_forward_messages (gpointer in_data, gpointer op_data, CamelException * ex)
+{
+ forward_messages_input_t *input =
+
+ (forward_messages_input_t *) in_data;
+ forward_messages_data_t *data = (forward_messages_data_t *) op_data;
+
+ CamelMimeMessage *message;
+ CamelMimePart *part;
+ int i;
+
+ data->parts = g_ptr_array_new ();
+
+ mail_tool_camel_lock_up ();
+ for (i = 0; i < input->uids->len; i++) {
+ message =
+ camel_folder_get_message (input->source,
+ input->uids->pdata[i], ex);
+ g_free (input->uids->pdata[i]);
+ if (!message) {
+ mail_tool_camel_lock_down ();
return;
}
- }
-
- message = e_msg_composer_get_message (composer);
-
- subject = camel_mime_message_get_subject (message);
- if (!subject || !*subject) {
- if (!ask_confirm_for_empty_subject (composer)) {
- gtk_object_unref (GTK_OBJECT (message));
+ part = mail_tool_make_message_attachment (message);
+ if (!part) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
+ "Failed to generate mime part from "
+ "message while generating forwarded message.");
+ mail_tool_camel_lock_down ();
return;
}
+ camel_object_unref (CAMEL_OBJECT (message));
+ g_ptr_array_add (data->parts, part);
}
-
- info = g_new0 (rsm_t, 1);
- info->composer = composer;
- info->transport = transport;
- info->message = message;
- info->subject = subject;
- info->from = from;
- info->psd = psd;
-
-#ifdef USE_BROKEN_THREADS
- mail_operation_try ("Send Message", real_send_mail, cleanup_send_mail, info);
-#else
- real_send_mail (info);
- cleanup_send_mail (info);
-#endif
+
+ mail_tool_camel_lock_down ();
+
+ data->subject = mail_tool_generate_forward_subject (input->basis);
}
static void
-free_psd (GtkWidget *composer, gpointer user_data)
+cleanup_forward_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex)
{
- struct post_send_data *psd = user_data;
+ forward_messages_input_t *input =
- gtk_object_unref (GTK_OBJECT (psd->folder));
- g_free (psd);
-}
+ (forward_messages_input_t *) in_data;
+ forward_messages_data_t *data = (forward_messages_data_t *) op_data;
-static GtkWidget *
-create_msg_composer (const char *url)
-{
- MailConfigIdentity *id;
- gboolean send_html;
- gchar *sig_file = NULL;
- GtkWidget *composer_widget;
+ int i;
- id = mail_config_get_default_identity ();
- send_html = mail_config_send_html ();
-
- if (id) {
- sig_file = id->sig;
+ for (i = 0; i < data->parts->len; i++) {
+ e_msg_composer_attach (input->composer,
+ data->parts->pdata[i]);
+ camel_object_unref (CAMEL_OBJECT (data->parts->pdata[i]));
}
-
- if (url != NULL)
- composer_widget = e_msg_composer_new_from_url (url);
- else
- composer_widget = e_msg_composer_new_with_sig_file (sig_file);
+ camel_object_unref (CAMEL_OBJECT (input->source));
- e_msg_composer_set_send_html (E_MSG_COMPOSER (composer_widget),
- send_html);
+ e_msg_composer_set_headers (input->composer, NULL, NULL, NULL,
+ data->subject);
- return composer_widget;
+ gtk_object_unref (GTK_OBJECT (input->composer));
+ g_free (data->subject);
+ g_ptr_array_free (data->parts, TRUE);
+ g_ptr_array_free (input->uids, TRUE);
+ gtk_widget_show (GTK_WIDGET (input->composer));
}
+static const mail_operation_spec op_forward_messages = {
+ describe_forward_messages,
+ sizeof (forward_messages_data_t),
+ setup_forward_messages,
+ do_forward_messages,
+ cleanup_forward_messages
+};
+
void
-compose_msg (GtkWidget *widget, gpointer user_data)
+mail_do_forward_message (CamelMimeMessage * basis,
+ CamelFolder * source,
+ GPtrArray * uids, EMsgComposer * composer)
{
- GtkWidget *composer;
-
- if (!check_configured ())
- return;
-
- composer = create_msg_composer (NULL);
-
- gtk_signal_connect (GTK_OBJECT (composer), "send",
- GTK_SIGNAL_FUNC (composer_send_cb), NULL);
- gtk_widget_show (composer);
+ forward_messages_input_t *input;
+
+ input = g_new (forward_messages_input_t, 1);
+ input->basis = basis;
+ input->source = source;
+ input->uids = uids;
+ input->composer = composer;
+
+ mail_operation_queue (&op_forward_messages, input, TRUE);
}
-/* Send according to a mailto (RFC 2368) URL. */
-void
-send_to_url (const char *url)
+/* ** LOAD FOLDER ********************************************************* */
+
+typedef struct load_folder_input_s
{
- GtkWidget *composer;
+ FolderBrowser *fb;
+ gchar *url;
+}
+load_folder_input_t;
+
+static gchar *describe_load_folder (gpointer in_data, gboolean gerund);
+static void setup_load_folder (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void do_load_folder (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void cleanup_load_folder (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+
+static gchar *
+describe_load_folder (gpointer in_data, gboolean gerund)
+{
+ load_folder_input_t *input = (load_folder_input_t *) in_data;
- if (!check_configured ())
+ if (gerund) {
+ return g_strdup_printf ("Loading \"%s\"", input->url);
+ } else {
+ return g_strdup_printf ("Load \"%s\"", input->url);
+ }
+}
+
+static void
+setup_load_folder (gpointer in_data, gpointer op_data, CamelException * ex)
+{
+ load_folder_input_t *input = (load_folder_input_t *) in_data;
+
+ if (!IS_FOLDER_BROWSER (input->fb)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No folder browser specified to load into.");
return;
+ }
- composer = create_msg_composer (url);
+ if (!input->url) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No URL to load was specified.");
+ return;
+ }
+
+ gtk_object_ref (GTK_OBJECT (input->fb));
- gtk_signal_connect (GTK_OBJECT (composer), "send",
- GTK_SIGNAL_FUNC (composer_send_cb), NULL);
- gtk_widget_show (composer);
-}
+ if (input->fb->uri)
+ g_free (input->fb->uri);
+
+ input->fb->uri = input->url;
+}
static void
-reply (FolderBrowser *fb, gboolean to_all)
+do_load_folder (gpointer in_data, gpointer op_data, CamelException * ex)
{
- EMsgComposer *composer;
- struct post_send_data *psd;
+ load_folder_input_t *input = (load_folder_input_t *) in_data;
+
+ CamelFolder *folder;
- if (!check_configured () || !fb->message_list->cursor_uid ||
- !fb->mail_display->current_message)
+ folder = mail_tool_uri_to_folder (input->url, ex);
+ if (!folder)
return;
- psd = g_new (struct post_send_data, 1);
- psd->folder = fb->folder;
- gtk_object_ref (GTK_OBJECT (psd->folder));
- psd->uid = fb->message_list->cursor_uid;
- psd->flags = CAMEL_MESSAGE_ANSWERED;
+ if (input->fb->folder) {
+ mail_tool_camel_lock_up ();
+ camel_object_unref (CAMEL_OBJECT (input->fb->folder));
+ mail_tool_camel_lock_down ();
+ }
- composer = mail_generate_reply (fb->mail_display->current_message, to_all);
+ input->fb->folder = folder;
+}
+
+static void
+cleanup_load_folder (gpointer in_data, gpointer op_data, CamelException * ex)
+{
+ load_folder_input_t *input = (load_folder_input_t *) in_data;
+
+ 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_menu),
+ camel_folder_has_search_capability (input->
+ fb->
+ folder));
- 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);
+ message_list_set_folder (input->fb->message_list, input->fb->folder);
- gtk_widget_show (GTK_WIDGET (composer));
+ /*g_free (input->url); = fb->uri now */
}
+static const mail_operation_spec op_load_folder = {
+ describe_load_folder,
+ 0,
+ setup_load_folder,
+ do_load_folder,
+ cleanup_load_folder
+};
+
void
-reply_to_sender (GtkWidget *widget, gpointer user_data)
+mail_do_load_folder (FolderBrowser * fb, const char *url)
{
- reply (FOLDER_BROWSER (user_data), FALSE);
+ load_folder_input_t *input;
+
+ input = g_new (load_folder_input_t, 1);
+ input->fb = fb;
+ input->url = g_strdup (url);
+
+ mail_operation_queue (&op_load_folder, input, TRUE);
}
-void
-reply_to_all (GtkWidget *widget, gpointer user_data)
+/* ** CREATE FOLDER ******************************************************* */
+
+typedef struct create_folder_input_s
{
- reply (FOLDER_BROWSER (user_data), TRUE);
+ Evolution_ShellComponentListener listener;
+ char *uri;
+ char *type;
}
+create_folder_input_t;
-static void
-attach_msg (MessageList *ml, const char *uid, gpointer data)
+typedef struct create_folder_data_s
{
- EMsgComposer *composer = data;
- CamelMimeMessage *message;
- CamelMimePart *part;
- const char *subject;
- char *desc;
-
- message = camel_folder_get_message (ml->folder, uid, NULL);
- if (!message)
- return;
- subject = camel_mime_message_get_subject (message);
- if (subject)
- desc = g_strdup_printf ("Forwarded message - %s", subject);
- else
- desc = g_strdup ("Forwarded message");
-
- part = camel_mime_part_new ();
- camel_mime_part_set_disposition (part, "inline");
- camel_mime_part_set_description (part, desc);
- camel_medium_set_content_object (CAMEL_MEDIUM (part),
- CAMEL_DATA_WRAPPER (message));
- camel_mime_part_set_content_type (part, "message/rfc822");
-
- e_msg_composer_attach (composer, part);
-
- gtk_object_unref (GTK_OBJECT (part));
- gtk_object_unref (GTK_OBJECT (message));
- g_free (desc);
+ Evolution_ShellComponentListener_Result result;
+}
+create_folder_data_t;
+
+static gchar *describe_create_folder (gpointer in_data, gboolean gerund);
+static void setup_create_folder (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void do_create_folder (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void cleanup_create_folder (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+
+static gchar *
+describe_create_folder (gpointer in_data, gboolean gerund)
+{
+ create_folder_input_t *input = (create_folder_input_t *) in_data;
+
+ if (gerund) {
+ return g_strdup_printf ("Creating \"%s\"", input->uri);
+ } else {
+ return g_strdup_printf ("Create \"%s\"", input->uri);
+ }
}
-void
-forward_msg (GtkWidget *widget, gpointer user_data)
+static void
+setup_create_folder (gpointer in_data, gpointer op_data, CamelException * ex)
{
- FolderBrowser *fb = FOLDER_BROWSER (user_data);
- EMsgComposer *composer;
- CamelMimeMessage *cursor_msg;
- const char *from, *subject;
- char *fwd_subj;
-
- cursor_msg = fb->mail_display->current_message;
- if (!check_configured () || !cursor_msg)
+ create_folder_input_t *input = (create_folder_input_t *) in_data;
+
+ if (input->listener == CORBA_OBJECT_NIL) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "Invalid listener passed to create_folder");
return;
+ }
- composer = E_MSG_COMPOSER (create_msg_composer (NULL));
- message_list_foreach (fb->message_list, attach_msg, composer);
+ if (input->uri == NULL) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "Invalid url passed to create_folder");
+ return;
+ }
+
+ if (input->type == NULL) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No type passed to create_folder");
+ return;
+ }
+
+ /* FIXME: reference listener somehow? */
+}
- from = camel_mime_message_get_from (cursor_msg);
- subject = camel_mime_message_get_subject (cursor_msg);
- if (from) {
- if (subject && *subject) {
- fwd_subj = g_strdup_printf ("[%s] %s", from, subject);
+static void
+do_create_folder (gpointer in_data, gpointer op_data, CamelException * ex)
+{
+ create_folder_input_t *input = (create_folder_input_t *) in_data;
+ create_folder_data_t *data = (create_folder_data_t *) op_data;
+
+ CamelFolder *folder;
+ gchar *camel_url;
+
+ if (strcmp (input->type, "mail") != 0)
+ data->result =
+ Evolution_ShellComponentListener_UNSUPPORTED_TYPE;
+ else {
+ camel_url = g_strdup_printf ("mbox://%s", input->uri);
+ folder = mail_tool_get_folder_from_urlname (camel_url,
+ "mbox", ex);
+ g_free (camel_url);
+
+ if (!camel_exception_is_set (ex)) {
+ camel_object_unref (CAMEL_OBJECT (folder));
+ data->result = Evolution_ShellComponentListener_OK;
} else {
- fwd_subj = g_strdup_printf ("[%s] (forwarded message)",
- from);
+ data->result =
+ Evolution_ShellComponentListener_INVALID_URI;
}
- } else {
- fwd_subj = NULL;
}
+}
+
+static void
+cleanup_create_folder (gpointer in_data, gpointer op_data,
+ CamelException * ex)
+{
+ create_folder_input_t *input = (create_folder_input_t *) in_data;
+ create_folder_data_t *data = (create_folder_data_t *) op_data;
+
+ CORBA_Environment ev;
- e_msg_composer_set_headers (composer, NULL, NULL, NULL, fwd_subj);
- g_free (fwd_subj);
+ CORBA_exception_init (&ev);
+ Evolution_ShellComponentListener_report_result (input->listener,
+ data->result, &ev);
+ if (ev._major != CORBA_NO_EXCEPTION)
+ camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
+ "Exception while reporting result to shell "
+ "component listener.");
+ CORBA_exception_free (&ev);
- gtk_signal_connect (GTK_OBJECT (composer), "send",
- GTK_SIGNAL_FUNC (composer_send_cb), NULL);
+ /* FIXME: unref listener somehow? */
- gtk_widget_show (GTK_WIDGET (composer));
+ g_free (input->uri);
+ g_free (input->type);
}
-struct move_data {
- CamelFolder *source, *dest;
- CamelException *ex;
+static const mail_operation_spec op_create_folder = {
+ describe_create_folder,
+ sizeof (create_folder_data_t),
+ setup_create_folder,
+ do_create_folder,
+ cleanup_create_folder
};
-static void
-real_move_msg (MessageList *ml, const char *uid, gpointer user_data)
+void
+mail_do_create_folder (const Evolution_ShellComponentListener listener,
+ const char *uri, const char *type)
{
- struct move_data *rfd = user_data;
+ create_folder_input_t *input;
- if (camel_exception_is_set (rfd->ex))
- return;
+ input = g_new (create_folder_input_t, 1);
+ input->listener = listener;
+ input->uri = g_strdup (uri);
+ input->type = g_strdup (type);
- camel_folder_move_message_to (rfd->source, uid, rfd->dest, rfd->ex);
+ mail_operation_queue (&op_create_folder, input, FALSE);
}
-void
-move_msg (GtkWidget *widget, gpointer user_data)
-{
- FolderBrowser *fb = user_data;
- MessageList *ml = fb->message_list;
- char *uri, *physical, *path;
- struct move_data rfd;
- const char *allowed_types[] = { "mail", NULL };
- extern EvolutionShellClient *global_shell_client;
- static char *last = NULL;
-
- if (!last)
- last = g_strdup ("");
-
- evolution_shell_client_user_select_folder (global_shell_client,
- _("Move message(s) to"),
- last, allowed_types, &uri, &physical);
- if (!uri)
- return;
+/* ** SYNC FOLDER ********************************************************* */
+
+static gchar *describe_sync_folder (gpointer in_data, gboolean gerund);
+static void setup_sync_folder (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void do_sync_folder (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void cleanup_sync_folder (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+
+static gchar *
+describe_sync_folder (gpointer in_data, gboolean gerund)
+{
+ CamelFolder *f = CAMEL_FOLDER (in_data);
- path = strchr (uri, '/');
- if (path && strcmp (last, path) != 0) {
- g_free (last);
- last = g_strdup (path);
+ if (gerund) {
+ return g_strdup_printf ("Synchronizing \"%s\"", f->full_name);
+ } else {
+ return g_strdup_printf ("Synchronize \"%s\"", f->full_name);
}
- g_free (uri);
+}
- rfd.source = ml->folder;
- rfd.dest = mail_uri_to_folder (physical);
- g_free (physical);
- if (!rfd.dest)
+static void
+setup_sync_folder (gpointer in_data, gpointer op_data, CamelException * ex)
+{
+ if (!CAMEL_IS_FOLDER (in_data)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No folder is selected to be synced");
return;
- rfd.ex = camel_exception_new ();
-
- message_list_foreach (ml, real_move_msg, &rfd);
- gtk_object_unref (GTK_OBJECT (rfd.dest));
-
- if (camel_exception_is_set (rfd.ex))
- mail_exception_dialog ("Could not move message", rfd.ex, fb);
- camel_exception_free (rfd.ex);
+ }
+
+ camel_object_ref (CAMEL_OBJECT (in_data));
+}
+
+static void
+do_sync_folder (gpointer in_data, gpointer op_data, CamelException * ex)
+{
+ mail_tool_camel_lock_up ();
+ camel_folder_sync (CAMEL_FOLDER (in_data), FALSE, ex);
+ mail_tool_camel_lock_down ();
+}
+
+static void
+cleanup_sync_folder (gpointer in_data, gpointer op_data, CamelException * ex)
+{
+ camel_object_unref (CAMEL_OBJECT (in_data));
}
+static const mail_operation_spec op_sync_folder = {
+ describe_sync_folder,
+ 0,
+ setup_sync_folder,
+ do_sync_folder,
+ cleanup_sync_folder
+};
+
void
-mark_all_seen (BonoboUIHandler *uih, void *user_data, const char *path)
+mail_do_sync_folder (CamelFolder * folder)
{
- FolderBrowser *fb = FOLDER_BROWSER(user_data);
- MessageList *ml = fb->message_list;
- GPtrArray *uids;
- int i;
+ mail_operation_queue (&op_sync_folder, folder, FALSE);
+}
- uids = camel_folder_get_uids (ml->folder);
- for (i = 0; i < uids->len; i++) {
- camel_folder_set_message_flags (ml->folder, uids->pdata[i],
- CAMEL_MESSAGE_SEEN,
- CAMEL_MESSAGE_SEEN);
- }
+/* ** DISPLAY MESSAGE ***************************************************** */
+
+typedef struct display_message_input_s
+{
+ MessageList *ml;
+ gchar *uid;
+ gint (*timeout) (gpointer);
}
+display_message_input_t;
-static void
-real_edit_msg (MessageList *ml, const char *uid, gpointer user_data)
+typedef struct display_message_data_s
{
- CamelException *ex = user_data;
CamelMimeMessage *msg;
- GtkWidget *composer;
-
- if (camel_exception_is_set (ex))
- return;
-
- msg = camel_folder_get_message (ml->folder, uid, ex);
-
- composer = e_msg_composer_new_with_message (msg);
- gtk_signal_connect (GTK_OBJECT (composer), "send",
- GTK_SIGNAL_FUNC (composer_send_cb), NULL);
- gtk_widget_show (composer);
+}
+display_message_data_t;
+
+static gchar *describe_display_message (gpointer in_data, gboolean gerund);
+static void setup_display_message (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void do_display_message (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void cleanup_display_message (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+
+static gchar *
+describe_display_message (gpointer in_data, gboolean gerund)
+{
+ display_message_input_t *input = (display_message_input_t *) in_data;
+
+ 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 dispaly");
+ }
}
-void
-edit_msg (GtkWidget *widget, gpointer user_data)
+static void
+setup_display_message (gpointer in_data, gpointer op_data,
+ CamelException * ex)
{
- FolderBrowser *fb = FOLDER_BROWSER (user_data);
- MessageList *ml = fb->message_list;
- CamelException ex;
- extern CamelFolder *drafts_folder;
-
- camel_exception_init (&ex);
-
- if (fb->folder != drafts_folder) {
- camel_exception_setv (&ex, CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION,
- "FIXME: some error message about not being in the Drafts folder...");
- mail_exception_dialog ("Could not open message for editing", &ex, fb);
+ display_message_input_t *input = (display_message_input_t *) in_data;
+ display_message_data_t *data = (display_message_data_t *) op_data;
+
+ if (!IS_MESSAGE_LIST (input->ml)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "Invalid message list passed to display_message");
return;
}
-
- message_list_foreach (ml, real_edit_msg, &ex);
- if (camel_exception_is_set (&ex)) {
- mail_exception_dialog ("Could not open message for editing", &ex, fb);
- camel_exception_clear (&ex);
+
+ if (!input->timeout) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No timeout callback passed to display_message");
return;
}
-}
-void
-edit_message (BonoboUIHandler *uih, void *user_data, const char *path)
-{
- edit_msg (NULL, user_data);
+ data->msg = NULL;
+ gtk_object_ref (GTK_OBJECT (input->ml));
}
static void
-real_delete_msg (MessageList *ml, const char *uid, gpointer user_data)
+do_display_message (gpointer in_data, gpointer op_data, CamelException * ex)
{
- CamelException *ex = user_data;
- guint32 flags;
+ display_message_input_t *input = (display_message_input_t *) in_data;
+ display_message_data_t *data = (display_message_data_t *) op_data;
- if (camel_exception_is_set (ex))
+ if (input->uid == NULL) {
+ data->msg = NULL;
return;
+ }
- /* Toggle the deleted flag without touching other flags. */
- flags = camel_folder_get_message_flags (ml->folder, uid);
- camel_folder_set_message_flags (ml->folder, uid,
- CAMEL_MESSAGE_DELETED, ~flags);
+ data->msg = camel_folder_get_message (input->ml->folder,
+ input->uid, ex);
}
-void
-delete_msg (GtkWidget *button, gpointer user_data)
-{
- FolderBrowser *fb = user_data;
- MessageList *ml = fb->message_list;
- CamelException ex;
-
- camel_exception_init (&ex);
- message_list_foreach (ml, real_delete_msg, &ex);
- if (camel_exception_is_set (&ex)) {
- mail_exception_dialog ("Could not toggle deleted flag",
- &ex, fb);
- camel_exception_clear (&ex);
- return;
+static void
+cleanup_display_message (gpointer in_data, gpointer op_data,
+ CamelException * ex)
+{
+ 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->ml->parent_folder_browser->mail_display;
+
+ if (data->msg == NULL) {
+ mail_display_set_message (md, NULL);
+ } else {
+ if (input->ml->seen_id)
+ gtk_timeout_remove (input->ml->seen_id);
+
+ mail_display_set_message (md, CAMEL_MEDIUM (data->msg));
+ camel_object_unref (CAMEL_OBJECT (data->msg));
+
+ input->ml->seen_id =
+ gtk_timeout_add (1500, input->timeout, input->ml);
}
+
+ if (input->uid)
+ g_free (input->uid);
+ gtk_object_unref (GTK_OBJECT (input->ml));
}
-static void real_expunge_folder (gpointer user_data)
-{
- FolderBrowser *fb = FOLDER_BROWSER (user_data);
- CamelException ex;
+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
+};
- e_table_model_pre_change(fb->message_list->table_model);
+void
+mail_do_display_message (MessageList * ml, const char *uid,
+ gint (*timeout) (gpointer))
+{
+ display_message_input_t *input;
-#ifdef USE_BROKEN_THREADS
- mail_op_hide_progressbar ();
- mail_op_set_message ("Expunging %s...", fb->message_list->folder->full_name);
-#endif
+ input = g_new (display_message_input_t, 1);
+ input->ml = ml;
+ input->uid = g_strdup (uid);
+ input->timeout = timeout;
- camel_exception_init (&ex);
+ mail_operation_queue (&op_display_message, input, FALSE);
+}
- camel_folder_expunge (fb->message_list->folder, &ex);
+/* ** EDIT MESSAGES ******************************************************* */
- /* FIXME: is there a better way to force an update? */
- /* FIXME: Folder should raise a signal to say its contents has changed ... */
- e_table_model_changed (fb->message_list->table_model);
+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);
+static void setup_edit_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void do_edit_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void cleanup_edit_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+
+static gchar *
+describe_edit_messages (gpointer in_data, gboolean gerund)
+{
+ edit_messages_input_t *input = (edit_messages_input_t *) in_data;
- if (camel_exception_get_id (&ex) != CAMEL_EXCEPTION_NONE) {
- async_mail_exception_dialog ("Unable to expunge deleted messages", &ex, fb);
- }
+ if (gerund)
+ return g_strdup_printf
+ ("Opening messages from folder \"%s\"",
+ input->folder->full_name);
+ else
+ return g_strdup_printf ("Open messages from \"%s\"",
+ input->folder->full_name);
}
-void
-expunge_folder (BonoboUIHandler *uih, void *user_data, const char *path)
+static void
+setup_edit_messages (gpointer in_data, gpointer op_data, CamelException * ex)
{
- FolderBrowser *fb = FOLDER_BROWSER(user_data);
+ edit_messages_input_t *input = (edit_messages_input_t *) in_data;
- if (fb->message_list->folder) {
-#ifdef USE_BROKEN_THREADS
- mail_operation_try ("Expunge Folder", real_expunge_folder, NULL, fb);
-#else
- real_expunge_folder (fb);
-#endif
+ if (!input->uids) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No UIDs specified to edit.");
+ return;
+ }
+
+ if (!CAMEL_IS_FOLDER (input->folder)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No folder to fetch the messages from specified.");
+ return;
}
+
+ camel_object_ref (CAMEL_OBJECT (input->folder));
}
static void
-filter_druid_clicked(GtkWidget *w, int button, FolderBrowser *fb)
+do_edit_messages (gpointer in_data, gpointer op_data, CamelException * ex)
{
- FilterContext *fc;
+ edit_messages_input_t *input = (edit_messages_input_t *) in_data;
+ edit_messages_data_t *data = (edit_messages_data_t *) op_data;
+
+ int i;
- if (button == 0) {
- char *user;
+ data->messages = g_ptr_array_new ();
- fc = gtk_object_get_data((GtkObject *)w, "context");
- user = g_strdup_printf("%s/filters.xml", evolution_dir);
- rule_context_save((RuleContext *)fc, user);
- g_free(user);
- }
-
- if (button != -1) {
- gnome_dialog_close((GnomeDialog *)w);
+ 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]);
}
}
-void
-filter_edit (BonoboUIHandler *uih, void *user_data, const char *path)
+static void
+cleanup_edit_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex)
{
- FolderBrowser *fb = FOLDER_BROWSER (user_data);
- FilterContext *fc;
- char *user, *system;
- GtkWidget *w;
+ 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++) {
+ GtkWidget *composer;
+
+ composer = e_msg_composer_new_with_message (data->messages->pdata[i]);
+
+ if (input->signal)
+ gtk_signal_connect (GTK_OBJECT (composer), "send",
+ input->signal, NULL);
+
+ gtk_widget_show (composer);
+
+ camel_object_unref (CAMEL_OBJECT (data->messages->pdata[i]));
+ }
+
+ g_ptr_array_free (input->uids, TRUE);
+ g_ptr_array_free (data->messages, TRUE);
+ camel_object_unref (CAMEL_OBJECT (input->folder));
- fc = filter_context_new();
- user = g_strdup_printf("%s/filters.xml", evolution_dir);
- system = g_strdup_printf("%s/evolution/filtertypes.xml", EVOLUTION_DATADIR);
- rule_context_load((RuleContext *)fc, system, user);
- g_free(user);
- g_free(system);
- w = filter_editor_construct(fc);
- gtk_object_set_data_full((GtkObject *)w, "context", fc, (GtkDestroyNotify)gtk_object_unref);
- gtk_signal_connect((GtkObject *)w, "clicked", filter_druid_clicked, fb);
- gtk_widget_show(w);
}
+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
-vfolder_edit_vfolders (BonoboUIHandler *uih, void *user_data, const char *path)
+mail_do_edit_messages (CamelFolder * folder, GPtrArray *uids,
+ GtkSignalFunc signal)
{
- void vfolder_edit(void);
+ edit_messages_input_t *input;
+
+ input = g_new (edit_messages_input_t, 1);
+ input->folder = folder;
+ input->uids = uids;
+ input->signal = signal;
- vfolder_edit();
+ mail_operation_queue (&op_edit_messages, input, TRUE);
}
-void
-providers_config (BonoboUIHandler *uih, void *user_data, const char *path)
+/* ** SETUP DRAFTBOX ****************************************************** */
+
+static gchar *describe_setup_draftbox (gpointer in_data, gboolean gerund);
+static void noop_setup_draftbox (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void do_setup_draftbox (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+
+static gchar *
+describe_setup_draftbox (gpointer in_data, gboolean gerund)
{
- mail_config();
+ if (gerund)
+ return g_strdup_printf ("Loading Draftbox");
+ else
+ return g_strdup_printf ("Load Draftbox");
}
-void
-print_msg (GtkWidget *button, gpointer user_data)
+static void
+noop_setup_draftbox (gpointer in_data, gpointer op_data, CamelException * ex)
{
- FolderBrowser *fb = user_data;
- GnomePrintMaster *print_master;
- GnomePrintContext *print_context;
- GtkWidget *preview;
+}
- print_master = gnome_print_master_new ();
+static void
+do_setup_draftbox (gpointer in_data, gpointer op_data, CamelException * ex)
+{
+ extern CamelFolder *drafts_folder;
+ gchar *url;
- print_context = gnome_print_master_get_context (print_master);
- gtk_html_print (fb->mail_display->html, print_context);
+ url = g_strdup_printf ("mbox://%s/local/Drafts", evolution_dir);
+ drafts_folder = mail_tool_get_folder_from_urlname (url, "mbox", ex);
+ g_free (url);
+}
- preview = GTK_WIDGET (gnome_print_master_preview_new (
- print_master, "Mail Print Preview"));
- gtk_widget_show (preview);
+/*
+ *static void
+ *cleanup_setup_draftbox (gpointer in_data, gpointer op_data,
+ * CamelException * ex)
+ *{
+ *}
+ */
- gtk_object_unref (GTK_OBJECT (print_master));
-}
+static const mail_operation_spec op_setup_draftbox = {
+ describe_setup_draftbox,
+ 0,
+ noop_setup_draftbox,
+ do_setup_draftbox,
+ noop_setup_draftbox
+};
void
-configure_folder(BonoboUIHandler *uih, void *user_data, const char *path)
+mail_do_setup_draftbox (void)
{
- FolderBrowser *fb = FOLDER_BROWSER(user_data);
-
- local_reconfigure_folder(fb);
+ mail_operation_queue (&op_setup_draftbox, NULL, FALSE);
}
+/* ** VIEW MESSAGES ******************************************************* */
-struct view_msg_data {
+typedef struct view_messages_input_s {
+ CamelFolder *folder;
+ GPtrArray *uids;
FolderBrowser *fb;
- CamelException *ex;
-};
+} 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);
+static void setup_view_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void do_view_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+static void cleanup_view_messages (gpointer in_data, gpointer op_data,
+ CamelException * ex);
+
+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\"",
+ input->folder->full_name);
+ else
+ return g_strdup_printf ("View messages from \"%s\"",
+ input->folder->full_name);
+}
static void
-real_view_msg (MessageList *ml, const char *uid, gpointer user_data)
+setup_view_messages (gpointer in_data, gpointer op_data, CamelException * ex)
{
- struct view_msg_data *data = user_data;
- FolderBrowser *fb;
- CamelMimeMessage *msg;
- GtkWidget *view;
-
- if (camel_exception_is_set (data->ex))
+ view_messages_input_t *input = (view_messages_input_t *) in_data;
+
+ if (!input->uids) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No UIDs specified to view.");
return;
-
- msg = camel_folder_get_message (ml->folder, uid, data->ex);
-
- fb = FOLDER_BROWSER (folder_browser_new ());
- folder_browser_set_uri (fb, data->fb->uri);
-
- fb->message_list->cursor_uid = uid;
- fb->mail_display->current_message = msg;
-
- view = mail_view_create (fb);
-
- gtk_widget_show (view);
+ }
+
+ if (!CAMEL_IS_FOLDER (input->folder)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No folder to fetch the messages from specified.");
+ return;
+ }
+
+ if (!IS_FOLDER_BROWSER (input->fb)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No folder browser was specified.");
+ return;
+ }
+
+
+ camel_object_ref (CAMEL_OBJECT (input->folder));
+ gtk_object_ref (GTK_OBJECT (input->fb));
}
-void
-view_msg (GtkWidget *widget, gpointer user_data)
+static void
+do_view_messages (gpointer in_data, gpointer op_data, CamelException * ex)
{
- struct view_msg_data data;
- FolderBrowser *fb = user_data;
- FolderBrowser *folder_browser;
- CamelException ex;
- MessageList *ml;
-
- camel_exception_init (&ex);
-
- data.fb = fb;
- data.ex = &ex;
-
- ml = fb->message_list;
- message_list_foreach (ml, real_view_msg, &data);
- if (camel_exception_is_set (&ex)) {
- mail_exception_dialog ("Could not open message for viewing", &ex, fb);
- camel_exception_clear (&ex);
- return;
+ view_messages_input_t *input = (view_messages_input_t *) in_data;
+ view_messages_data_t *data = (view_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 ();
+
+ 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
-view_message (BonoboUIHandler *uih, void *user_data, const char *path)
+mail_do_view_messages (CamelFolder * folder, GPtrArray *uids,
+ FolderBrowser *fb)
{
- view_msg (NULL, user_data);
+ view_messages_input_t *input;
+
+ 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);
}
diff --git a/mail/mail-threads.c b/mail/mail-threads.c
index a5dbac2427..7f5e796a51 100644
--- a/mail/mail-threads.c
+++ b/mail/mail-threads.c
@@ -24,8 +24,6 @@
#include <config.h>
-#ifdef USE_BROKEN_THREADS
-
#include <string.h>
#include <glib.h>
#include "mail.h"
@@ -35,7 +33,7 @@
/* FIXME TODO: Do we need operations that don't get a progress window because
* they're quick, but we still want camel to be locked? We need some kind
- * of flag to mail_operation_try, but then we also need some kind of monitor
+ * of flag to mail_operation_queue, but then we also need some kind of monitor
* to open the window if it takes more than a second or something. That would
* probably entail another thread....
*/
@@ -44,37 +42,56 @@
* A function and its userdata
**/
-typedef struct closure_s {
- void (*callback)( gpointer );
- void (*cleanup)( gpointer );
- gpointer data;
-
- gchar *prettyname;
- /* gboolean gets_window; */
-} closure_t;
+typedef struct closure_s
+{
+ gpointer in_data;
+ gboolean free_in_data;
+ gpointer op_data;
+ const mail_operation_spec *spec;
+ CamelException *ex;
+ gchar *infinitive;
+ gchar *gerund;
+}
+closure_t;
/**
* A command issued through the compipe
**/
-typedef struct com_msg_s {
- enum com_msg_type_e { STARTING, PERCENTAGE, HIDE_PBAR, SHOW_PBAR, MESSAGE, PASSWORD, ERROR, FINISHED } type;
+typedef struct com_msg_s
+{
+ enum com_msg_type_e {
+ STARTING,
+ PERCENTAGE,
+ HIDE_PBAR,
+ SHOW_PBAR,
+ MESSAGE,
+ PASSWORD,
+ ERROR,
+ FINISHED
+ } type;
gfloat percentage;
gchar *message;
- void (*func)( gpointer );
- gpointer userdata;
+ closure_t *clur;
/* Password stuff */
gchar **reply;
gboolean secret;
gboolean *success;
-} com_msg_t;
+}
+com_msg_t;
+
+/**
+ * @dispatch_thread_started: gboolean that tells us whether
+ * the dispatch thread has been launched.
+ **/
+
+static gboolean dispatch_thread_started = FALSE;
/**
- * @mail_operation_in_progress: When true, there's
- * another thread executing a major ev-mail operation:
- * fetch_mail, etc.
+ * @queue_len : the number of operations pending
+ * and being executed.
*
* Because camel is not thread-safe we work
* with the restriction that more than one mailbox
@@ -82,7 +99,7 @@ typedef struct com_msg_s {
* concurrently check mail and move messages, etc.
**/
-static gboolean mail_operation_in_progress;
+static gint queue_len = 0;
/**
* @queue_window: The little window on the screen that
@@ -110,27 +127,22 @@ static GtkWidget *queue_window_progress = NULL;
static int progress_timeout_handle = -1;
/**
- * @op_queue: The list of operations the are scheduled
- * to proceed after the currently executing one. When
- * only one operation is going, this is NULL.
- **/
-
-static GSList *op_queue = NULL;
-
-/**
- * @compipe: The pipe through which the dispatcher communicates
+ * @main_compipe: The pipe through which the dispatcher communicates
* with the main thread for GTK+ calls
*
* @chan_reader: the GIOChannel that reads our pipe
*
- * @READER: the fd in our pipe that.... reads!
- * @WRITER: the fd in our pipe that.... writes!
+ * @MAIN_READER: the fd in our main pipe that.... reads!
+ * @MAIN_WRITER: the fd in our main pipe that.... writes!
*/
-#define READER compipe[0]
-#define WRITER compipe[1]
+#define MAIN_READER main_compipe[0]
+#define MAIN_WRITER main_compipe[1]
+#define DISPATCH_READER dispatch_compipe[0]
+#define DISPATCH_WRITER dispatch_compipe[1]
-static int compipe[2] = { -1, -1 };
+static int main_compipe[2] = { -1, -1 };
+static int dispatch_compipe[2] = { -1, -1 };
GIOChannel *chan_reader = NULL;
@@ -146,28 +158,50 @@ GIOChannel *chan_reader = NULL;
* the dispatch thread may proceed its operations.
*/
-G_LOCK_DEFINE_STATIC( modal_lock );
+G_LOCK_DEFINE_STATIC (modal_lock);
static GCond *modal_cond = NULL;
static gboolean modal_may_proceed = FALSE;
/**
+ * @ready_for_op: A lock that the main thread only releases
+ * when it is ready for the dispatch thread to do its thing
+ *
+ * @ready_cond: A condition for this ... condition
+ *
+ * @ready_may_proceed: a gboolean telling the dispatch thread
+ * when it may proceed.
+ **/
+
+G_LOCK_DEFINE_STATIC (ready_for_op);
+static GCond *ready_cond = NULL;
+static gboolean ready_may_proceed = FALSE;
+
+/**
* Static prototypes
**/
-static void create_queue_window( void );
-static void dispatch( closure_t *clur );
-static void *dispatch_func( void *data );
-static void check_compipe( void );
-static void check_cond( void );
-static gboolean read_msg( GIOChannel *source, GIOCondition condition, gpointer userdata );
-static void remove_next_pending( void );
-static void show_error( com_msg_t *msg );
-static void show_error_clicked( void );
-static void get_password( com_msg_t *msg );
-static void get_password_cb( gchar *string, gpointer data );
-static void get_password_clicked( GnomeDialog *dialog, gint button, gpointer user_data );
-static gboolean progress_timeout( gpointer data );
-static void timeout_toggle( gboolean active );
+static void create_queue_window (void);
+static void destroy_queue_window (void);
+static void *dispatch (void * data);
+static void check_dispatcher (void);
+static void check_compipes (void);
+static void check_cond (void);
+static gboolean read_msg (GIOChannel * source, GIOCondition condition,
+ gpointer userdata);
+static void remove_next_pending (void);
+static void show_error (com_msg_t * msg);
+static void show_error_clicked (GtkObject * obj);
+static void get_password (com_msg_t * msg);
+static void get_password_cb (gchar * string, gpointer data);
+static void get_password_clicked (GnomeDialog * dialog, gint button,
+
+ gpointer user_data);
+static gboolean progress_timeout (gpointer data);
+static void timeout_toggle (gboolean active);
+static gboolean display_timeout (gpointer data);
+static closure_t *new_closure (const mail_operation_spec * spec, gpointer input,
+ gboolean free_in_data);
+static void free_closure (closure_t *clur);
/* Pthread code */
/* FIXME: support other thread types!!!! */
@@ -190,17 +224,25 @@ static pthread_t dispatch_thread;
* enough.
*/
-#else /* defined USE_PTHREADS */
-choke on this: no thread type defined
+#elif defined( G_THREADS_IMPL_SOLARIS )
+
+#include <thread.h>
+
+static thread_t dispatch_thread;
+
+#else /* no supported thread impl */
+void
+f (void)
+{
+ Error_No_supported_thread_implementation_recognized ();
+ choke on this;
+}
#endif
/**
- * mail_operation_try:
- * @description: A user-friendly string describing the operation.
- * @callback: the function to call in another thread to start the operation
- * @cleanup: the function to call in the main thread when the callback is finished.
- * NULL is allowed.
- * @user_data: extra data passed to the callback
+ * mail_operation_queue:
+ * @spec: describes the operation to be performed
+ * @input: input data for the operation.
*
* Runs a mail operation asynchronously. If no other operation is running,
* we start another thread and call the callback in that thread. The function
@@ -215,66 +257,75 @@ choke on this: no thread type defined
**/
gboolean
-mail_operation_try( const gchar *description, void (*callback)( gpointer ),
- void (*cleanup)( gpointer ), gpointer user_data )
+mail_operation_queue (const mail_operation_spec * spec, gpointer input,
+ gboolean free_in_data)
{
closure_t *clur;
- g_assert( callback );
-
- clur = g_new( closure_t, 1 );
- clur->callback = callback;
- clur->cleanup = cleanup;
- clur->data = user_data;
- clur->prettyname = g_strdup( description );
-
- if( mail_operation_in_progress == FALSE ) {
- /* No operations are going on, none are pending. So
- * we check to see if we're initialized (create the
- * window and the pipes), and send off the operation
- * on its merry way.
- */
- mail_operation_in_progress = TRUE;
+ g_assert (spec);
+
+ clur = new_closure (spec, input, free_in_data);
+
+ if (spec->setup)
+ (spec->setup) (clur->in_data, clur->op_data, clur->ex);
+
+ if (camel_exception_is_set (clur->ex)) {
+ if (clur->ex->id != CAMEL_EXCEPTION_USER_CANCEL) {
+ GtkWidget *err_dialog;
+ gchar *msg;
+
+ msg =
+ g_strdup_printf
+ ("Error while preparing to %s:\n" "%s",
+ clur->infinitive,
+ camel_exception_get_description (clur->ex));
+ err_dialog = gnome_error_dialog (msg);
+ g_free (msg);
+ gnome_dialog_set_close (GNOME_DIALOG (err_dialog),
+ TRUE);
+ /*gnome_dialog_run_and_close (GNOME_DIALOG (err_dialog)); */
+ /*gtk_widget_destroy (err_dialog); */
+ gtk_widget_show (GTK_WIDGET (err_dialog));
+
+ g_warning ("Setup failed for `%s': %s",
+ clur->infinitive,
+ camel_exception_get_description (clur->
+ ex));
+ }
- check_compipe();
- create_queue_window();
- gtk_widget_show_all( queue_window );
- gnome_win_hints_set_layer( queue_window,
- WIN_LAYER_ONTOP );
- gnome_win_hints_set_state( queue_window,
- WIN_STATE_ARRANGE_IGNORE );
- gnome_win_hints_set_hints( queue_window,
- WIN_HINTS_SKIP_FOCUS |
- WIN_HINTS_SKIP_WINLIST |
- WIN_HINTS_SKIP_TASKBAR );
- gtk_widget_hide( queue_window_pending );
+ free_closure (clur);
+ return FALSE;
+ }
- dispatch( clur );
+ if (queue_len == 0) {
+ check_cond ();
+ check_compipes ();
+ check_dispatcher ();
+ create_queue_window ();
+ /*gtk_widget_show_all (queue_window); */
+ gtk_timeout_add (1000, display_timeout, NULL);
} else {
GtkWidget *label;
- /* Zut. We already have an operation running. Well,
- * queue ourselves up.
- *
- * Yes, g_slist_prepend is faster down here.. But we pop
- * operations off the beginning of the list later and
- * that's a lot faster.
+ /* We already have an operation running. Well,
+ * queue ourselves up. (visually)
*/
- op_queue = g_slist_append( op_queue, clur );
-
/* Show us in the pending window. */
- label = gtk_label_new( description );
- gtk_misc_set_alignment( GTK_MISC( label ), 1.0, 0.5 );
- gtk_box_pack_start( GTK_BOX( queue_window_pending ), label,
- FALSE, TRUE, 2 );
+ label = gtk_label_new (clur->infinitive);
+ gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (queue_window_pending), label,
+ FALSE, TRUE, 2);
+ gtk_widget_show (label);
/* If we want the next op to be on the bottom, uncomment this */
/* 1 = first on list always (0-based) */
/* gtk_box_reorder_child( GTK_BOX( queue_window_pending ), label, 1 ); */
- gtk_widget_show_all( queue_window_pending );
+ gtk_widget_show (queue_window_pending);
}
+ write (DISPATCH_WRITER, clur, sizeof (closure_t));
+ queue_len++;
return TRUE;
}
@@ -286,13 +337,14 @@ mail_operation_try( const gchar *description, void (*callback)( gpointer ),
* Threadsafe for, nay, intended to be called by, the dispatching thread.
**/
-void mail_op_set_percentage( gfloat percentage )
+void
+mail_op_set_percentage (gfloat percentage)
{
com_msg_t msg;
msg.type = PERCENTAGE;
msg.percentage = percentage;
- write( WRITER, &msg, sizeof( msg ) );
+ write (MAIN_WRITER, &msg, sizeof (msg));
}
/**
@@ -307,12 +359,13 @@ void mail_op_set_percentage( gfloat percentage )
* that, right?
*/
-void mail_op_hide_progressbar( void )
+void
+mail_op_hide_progressbar (void)
{
com_msg_t msg;
msg.type = HIDE_PBAR;
- write( WRITER, &msg, sizeof( msg ) );
+ write (MAIN_WRITER, &msg, sizeof (msg));
}
/**
@@ -322,12 +375,13 @@ void mail_op_hide_progressbar( void )
* Threadsafe for, nay, intended to be called by, the dispatching thread.
**/
-void mail_op_show_progressbar( void )
+void
+mail_op_show_progressbar (void)
{
com_msg_t msg;
msg.type = SHOW_PBAR;
- write( WRITER, &msg, sizeof( msg ) );
+ write (MAIN_WRITER, &msg, sizeof (msg));
}
/**
@@ -340,17 +394,18 @@ void mail_op_show_progressbar( void )
* Threadsafe for, nay, intended to be called by, the dispatching thread.
**/
-void mail_op_set_message( gchar *fmt, ... )
+void
+mail_op_set_message (gchar * fmt, ...)
{
com_msg_t msg;
va_list val;
- va_start( val, fmt );
+ va_start (val, fmt);
msg.type = MESSAGE;
- msg.message = g_strdup_vprintf( fmt, val );
- va_end( val );
+ msg.message = g_strdup_vprintf (fmt, val);
+ va_end (val);
- write( WRITER, &msg, sizeof( msg ) );
+ write (MAIN_WRITER, &msg, sizeof (msg));
}
/**
@@ -365,30 +420,31 @@ void mail_op_set_message( gchar *fmt, ... )
* message.
**/
-gboolean mail_op_get_password( gchar *prompt, gboolean secret, gchar **dest )
+gboolean
+mail_op_get_password (gchar * prompt, gboolean secret, gchar ** dest)
{
com_msg_t msg;
gboolean result;
- check_cond();
-
msg.type = PASSWORD;
msg.secret = secret;
msg.message = prompt;
msg.reply = dest;
msg.success = &result;
-
+
(*dest) = NULL;
- G_LOCK( modal_lock );
+ G_LOCK (modal_lock);
- write( WRITER, &msg, sizeof( msg ) );
+ write (MAIN_WRITER, &msg, sizeof (msg));
modal_may_proceed = FALSE;
- while( modal_may_proceed == FALSE )
- g_cond_wait( modal_cond, g_static_mutex_get_mutex( &G_LOCK_NAME( modal_lock ) ) );
+ while (modal_may_proceed == FALSE)
+ g_cond_wait (modal_cond,
+ g_static_mutex_get_mutex (&G_LOCK_NAME
+ (modal_lock)));
- G_UNLOCK( modal_lock );
+ G_UNLOCK (modal_lock);
return result;
}
@@ -402,27 +458,28 @@ gboolean mail_op_get_password( gchar *prompt, gboolean secret, gchar **dest )
* Threadsafe for, nay, intended to be called by, the dispatching thread.
**/
-void mail_op_error( gchar *fmt, ... )
+void
+mail_op_error (gchar * fmt, ...)
{
com_msg_t msg;
va_list val;
- check_cond();
-
- va_start( val, fmt );
+ va_start (val, fmt);
msg.type = ERROR;
- msg.message = g_strdup_vprintf( fmt, val );
- va_end( val );
+ msg.message = g_strdup_vprintf (fmt, val);
+ va_end (val);
- G_LOCK( modal_lock );
+ G_LOCK (modal_lock);
modal_may_proceed = FALSE;
- write( WRITER, &msg, sizeof( msg ) );
+ write (MAIN_WRITER, &msg, sizeof (msg));
- while( modal_may_proceed == FALSE )
- g_cond_wait( modal_cond, g_static_mutex_get_mutex( &G_LOCK_NAME( modal_lock ) ) );
+ while (modal_may_proceed == FALSE)
+ g_cond_wait (modal_cond,
+ g_static_mutex_get_mutex (&G_LOCK_NAME
+ (modal_lock)));
- G_UNLOCK( modal_lock );
+ G_UNLOCK (modal_lock);
}
/**
@@ -432,12 +489,13 @@ void mail_op_error( gchar *fmt, ... )
* to finish executing
*/
-void mail_operation_wait_for_finish( void )
+void
+mail_operation_wait_for_finish (void)
{
- while( mail_operation_in_progress ) {
- while( gtk_events_pending() )
- gtk_main_iteration();
- }
+ while (queue_len)
+ gtk_main_iteration ();
+ /* Sigh. Otherwise we deadlock upon exit. */
+ GDK_THREADS_LEAVE ();
}
/**
@@ -445,15 +503,82 @@ void mail_operation_wait_for_finish( void )
*
* Returns TRUE if operations are being executed asynchronously
* when called, FALSE if not.
- */
+ **/
+
+gboolean
+mail_operations_are_executing (void)
+{
+ return (queue_len > 0);
+}
+
+/**
+ * mail_operations_terminate:
+ *
+ * Let the operations finish then terminate the dispatch thread
+ **/
-gboolean mail_operations_are_executing( void )
+void
+mail_operations_terminate (void)
{
- return mail_operation_in_progress;
+ closure_t clur;
+
+ mail_operation_wait_for_finish();
+
+ memset (&clur, 0, sizeof (closure_t));
+ clur.spec = NULL;
+
+ write (DISPATCH_WRITER, &clur, sizeof (closure_t));
}
/* ** Static functions **************************************************** */
+static void check_dispatcher (void)
+{
+ int res;
+
+ if (dispatch_thread_started)
+ return;
+
+#if defined( G_THREADS_IMPL_POSIX )
+ res = pthread_create (&dispatch_thread, NULL,
+ (void *) &dispatch, NULL);
+#elif defined( G_THREADS_IMPL_SOLARIS )
+ res = thr_create (NULL, 0, (void *) &dispatch, NULL, 0, &dispatch_thread);
+#else /* no known impl */
+ Error_No_thread_create_implementation ();
+ choke on this;
+#endif
+ if (res != 0) {
+ g_warning ("Error launching dispatch thread!");
+ /* FIXME: more error handling */
+ } else
+ dispatch_thread_started = TRUE;
+}
+
+static void
+print_hide (GtkWidget * wid)
+{
+ g_message ("$$$ hide signal emitted");
+}
+
+static void
+print_unmap (GtkWidget * wid)
+{
+ g_message ("$$$ unmap signal emitted");
+}
+
+static void
+print_map (GtkWidget * wid)
+{
+ g_message ("$$$ map signal emitted");
+}
+
+static void
+print_show (GtkWidget * wid)
+{
+ g_message ("$$$ show signal emitted");
+}
+
/**
* create_queue_window:
*
@@ -462,72 +587,115 @@ gboolean mail_operations_are_executing( void )
*/
static void
-create_queue_window( void )
+queue_window_delete_event_cb (GtkWindow *window,
+ void *data)
+{
+ /* Do nothing. Just prevent GTK+ from destroying the window. */
+}
+
+static void
+create_queue_window (void)
{
GtkWidget *vbox;
GtkWidget *pending_vb, *pending_lb;
GtkWidget *progress_lb, *progress_bar;
/* Check to see if we've only hidden it */
- if( queue_window != NULL )
+ if (queue_window != NULL)
return;
- queue_window = gtk_window_new( GTK_WINDOW_DIALOG );
- gtk_container_set_border_width( GTK_CONTAINER( queue_window ), 8 );
+ queue_window = gtk_window_new (GTK_WINDOW_DIALOG);
+ gtk_container_set_border_width (GTK_CONTAINER (queue_window), 8);
- vbox = gtk_vbox_new( FALSE, 4 );
+ gtk_signal_connect (GTK_OBJECT (queue_window), "delete_event",
+ GTK_SIGNAL_FUNC (queue_window_delete_event_cb), NULL);
- pending_vb = gtk_vbox_new( FALSE, 2 );
+ vbox = gtk_vbox_new (FALSE, 4);
+
+ pending_vb = gtk_vbox_new (FALSE, 2);
queue_window_pending = pending_vb;
- pending_lb = gtk_label_new( _("Currently pending operations:") );
- gtk_misc_set_alignment( GTK_MISC( pending_lb ), 0.0, 0.0 );
- gtk_box_pack_start( GTK_BOX( pending_vb ), pending_lb,
- FALSE, TRUE, 0 );
+ pending_lb = gtk_label_new (_("Currently pending operations:"));
+ gtk_misc_set_alignment (GTK_MISC (pending_lb), 0.0, 0.0);
+ gtk_box_pack_start (GTK_BOX (pending_vb), pending_lb, FALSE, TRUE, 0);
- gtk_box_pack_start( GTK_BOX( vbox ), pending_vb,
- TRUE, TRUE, 4 );
+ gtk_box_pack_start (GTK_BOX (vbox), pending_vb, TRUE, TRUE, 4);
/* FIXME: 'operation' is not the warmest cuddliest word. */
- progress_lb = gtk_label_new( "" );
+ progress_lb = gtk_label_new ("");
queue_window_message = progress_lb;
- gtk_box_pack_start( GTK_BOX( vbox ), progress_lb,
- FALSE, TRUE, 4 );
+ gtk_box_pack_start (GTK_BOX (vbox), progress_lb, FALSE, TRUE, 4);
- progress_bar = gtk_progress_bar_new();
+ progress_bar = gtk_progress_bar_new ();
queue_window_progress = progress_bar;
/* FIXME: is this fit for l10n? */
- gtk_progress_bar_set_orientation( GTK_PROGRESS_BAR( progress_bar ),
- GTK_PROGRESS_LEFT_TO_RIGHT );
- gtk_progress_bar_set_bar_style( GTK_PROGRESS_BAR( progress_bar ),
- GTK_PROGRESS_CONTINUOUS );
- gtk_box_pack_start( GTK_BOX( vbox ), progress_bar,
- FALSE, TRUE, 4 );
+ gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (progress_bar),
+ GTK_PROGRESS_LEFT_TO_RIGHT);
+ gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (progress_bar),
+ GTK_PROGRESS_CONTINUOUS);
+ gtk_box_pack_start (GTK_BOX (vbox), progress_bar, FALSE, TRUE, 4);
+
+ gtk_container_add (GTK_CONTAINER (queue_window), vbox);
+
+ gtk_widget_show (GTK_WIDGET (progress_bar));
+ gtk_widget_show (GTK_WIDGET (progress_lb));
+ gtk_widget_show (GTK_WIDGET (pending_lb));
+ gtk_widget_show (GTK_WIDGET (pending_vb));
+ gtk_widget_show (GTK_WIDGET (vbox));
+
+ gtk_signal_connect (GTK_OBJECT (queue_window), "hide", print_hide,
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (queue_window), "unmap", print_unmap,
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (queue_window), "show", print_show,
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (queue_window), "map", print_map,
+ NULL);
+}
- gtk_container_add( GTK_CONTAINER( queue_window ), vbox );
+static void destroy_queue_window (void)
+{
+ g_return_if_fail (queue_window);
+
+ timeout_toggle (FALSE);
+ gtk_widget_destroy (queue_window);
+
+ queue_window = NULL;
+ queue_window_progress = NULL;
+ queue_window_pending = NULL;
+ queue_window_message = NULL;
}
/**
- * check_compipe:
+ * check_compipes:
*
* Check and see if our pipe has been opened and open
* it if necessary.
**/
-static void check_compipe( void )
+static void
+check_compipes (void)
{
- if( READER > 0 )
- return;
+ if (MAIN_READER < 0) {
+ if (pipe (main_compipe) < 0) {
+ g_warning ("Call to pipe(2) failed!");
- if( pipe( compipe ) < 0 ) {
- g_warning( "Call to pipe(2) failed!" );
+ /* FIXME: better error handling. How do we react? */
+ return;
+ }
- /* FIXME: better error handling. How do we react? */
- return;
+ chan_reader = g_io_channel_unix_new (MAIN_READER);
+ g_io_add_watch (chan_reader, G_IO_IN, read_msg, NULL);
}
- chan_reader = g_io_channel_unix_new( READER );
- g_io_add_watch( chan_reader, G_IO_IN, read_msg, NULL );
+ if (DISPATCH_READER < 0) {
+ if (pipe (dispatch_compipe) < 0) {
+ g_warning ("Call to pipe(2) failed!");
+
+ /* FIXME: better error handling. How do we react? */
+ return;
+ }
+ }
}
/**
@@ -536,62 +704,94 @@ static void check_compipe( void )
* See if our condition is initialized and do so if necessary
**/
-static void check_cond( void )
+static void
+check_cond (void)
{
- if( modal_cond == NULL )
- modal_cond = g_cond_new();
+ if (modal_cond == NULL)
+ modal_cond = g_cond_new ();
+
+ if (ready_cond == NULL)
+ ready_cond = g_cond_new ();
}
/**
* dispatch:
- * @clur: The function to execute and its userdata
+ * @clur: The operation to execute and its parameters
*
* Start a thread that executes the closure and exit
* it when done.
*/
-static void dispatch( closure_t *clur )
+static void *
+dispatch (void *unused)
{
- int res;
+ size_t len;
+ closure_t *clur;
+ com_msg_t msg;
- res = pthread_create( &dispatch_thread, NULL, (void *) &dispatch_func, clur );
+ /* Let the compipes be created */
+ sleep (1);
- if( res != 0 ) {
- g_warning( "Error launching dispatch thread!" );
- /* FIXME: more error handling */
- }
-}
+ while (1) {
+ clur = g_new (closure_t, 1);
+ len = read (DISPATCH_READER, clur, sizeof (closure_t));
-/**
- * dispatch_func:
- * @data: the closure to run
- *
- * Runs the closure and exits the thread.
- */
+ if (len <= 0)
+ break;
-static void *dispatch_func( void *data )
-{
- com_msg_t msg;
- closure_t *clur = (closure_t *) data;
+ if (len != sizeof (closure_t)) {
+ g_warning ("dispatcher: Didn't read full message!");
+ continue;
+ }
+
+ if (clur->spec == NULL)
+ break;
- msg.type = STARTING;
- msg.message = clur->prettyname;
- write( WRITER, &msg, sizeof( msg ) );
+ msg.type = STARTING;
+ msg.message = g_strdup (clur->gerund);
+ write (MAIN_WRITER, &msg, sizeof (msg));
- /*GDK_THREADS_ENTER ();*/
- (clur->callback)( clur->data );
- /*GDK_THREADS_LEAVE ();*/
+ mail_op_hide_progressbar ();
+
+ (clur->spec->callback) (clur->in_data, clur->op_data, clur->ex);
+
+ if (camel_exception_is_set (clur->ex)) {
+ if (clur->ex->id != CAMEL_EXCEPTION_USER_CANCEL) {
+ g_warning ("Callback failed for `%s': %s",
+ clur->infinitive,
+ camel_exception_get_description (clur->
+ ex));
+ mail_op_error ("Error while `%s':\n" "%s",
+ clur->gerund,
+ camel_exception_get_description (clur->
+ ex));
+ }
+ }
- msg.type = FINISHED;
- msg.func = clur->cleanup; /* NULL is ok */
- msg.userdata = clur->data;
- write( WRITER, &msg, sizeof( msg ) );
+ msg.type = FINISHED;
+ msg.clur = clur;
- g_free( clur->prettyname );
- g_free( data );
+ G_LOCK (ready_for_op);
+ write (MAIN_WRITER, &msg, sizeof (msg));
- pthread_exit( 0 );
- return NULL; /*NOTREACHED*/
+ ready_may_proceed = FALSE;
+ while (ready_may_proceed == FALSE)
+ g_cond_wait (ready_cond,
+ g_static_mutex_get_mutex (&G_LOCK_NAME
+ (ready_for_op)));
+ G_UNLOCK (ready_for_op);
+ }
+
+#ifdef G_THREADS_IMPL_POSIX
+ pthread_exit (0);
+#elif defined( G_THREADS_IMPL_SOLARIS )
+ thr_exit (NULL);
+#else /* no known impl */
+ Error_No_thread_exit_implemented ();
+ choke on this;
+#endif
+ return NULL;
+ /*NOTREACHED*/
}
/**
@@ -604,75 +804,82 @@ static void *dispatch_func( void *data )
* action.
**/
-static gboolean read_msg( GIOChannel *source, GIOCondition condition, gpointer userdata )
+static gboolean
+read_msg (GIOChannel * source, GIOCondition condition, gpointer userdata)
{
com_msg_t *msg;
- closure_t *clur;
- GSList *temp;
guint size;
- msg = g_new0( com_msg_t, 1 );
+ msg = g_new0 (com_msg_t, 1);
- g_io_channel_read( source, (gchar *) msg,
- sizeof( com_msg_t ) / sizeof( gchar ),
- &size );
+ g_io_channel_read (source, (gchar *) msg,
+ sizeof (com_msg_t) / sizeof (gchar), &size);
- if( size != sizeof( com_msg_t ) ) {
- g_warning( _("Incomplete message written on pipe!") );
+ if (size != sizeof (com_msg_t)) {
+ g_warning (_("Incomplete message written on pipe!"));
msg->type = ERROR;
- msg->message = g_strdup( _("Error reading commands from dispatching thread.") );
+ msg->message =
+ g_strdup (_
+ ("Error reading commands from dispatching thread."));
}
/* This is very important, though I'm not quite sure why
* it is as we are in the main thread right now.
*/
- GDK_THREADS_ENTER();
+ GDK_THREADS_ENTER ();
- switch( msg->type ) {
+ switch (msg->type) {
case STARTING:
- DEBUG (("*** Message -- STARTING\n"));
- gtk_label_set_text( GTK_LABEL( queue_window_message ), msg->message );
- gtk_progress_bar_update( GTK_PROGRESS_BAR( queue_window_progress ), 0.0 );
- g_free( msg );
+ DEBUG (("*** Message -- STARTING %s\n", msg->message));
+ gtk_label_set_text (GTK_LABEL (queue_window_message),
+ msg->message);
+ gtk_progress_bar_update (GTK_PROGRESS_BAR
+ (queue_window_progress), 0.0);
+ g_free (msg->message);
+ g_free (msg);
break;
case PERCENTAGE:
DEBUG (("*** Message -- PERCENTAGE\n"));
- gtk_progress_bar_update( GTK_PROGRESS_BAR( queue_window_progress ), msg->percentage );
- g_free( msg );
+ gtk_progress_bar_update (GTK_PROGRESS_BAR
+ (queue_window_progress),
+ msg->percentage);
+ g_free (msg);
break;
case HIDE_PBAR:
DEBUG (("*** Message -- HIDE_PBAR\n"));
- gtk_progress_set_activity_mode( GTK_PROGRESS( queue_window_progress ), TRUE );
- timeout_toggle( TRUE );
-
- g_free( msg );
+ gtk_progress_set_activity_mode (GTK_PROGRESS
+ (queue_window_progress),
+ TRUE);
+ timeout_toggle (TRUE);
+ g_free (msg);
break;
case SHOW_PBAR:
DEBUG (("*** Message -- SHOW_PBAR\n"));
- timeout_toggle( FALSE );
- gtk_progress_set_activity_mode( GTK_PROGRESS( queue_window_progress ), FALSE );
-
- g_free( msg );
+ timeout_toggle (FALSE);
+ gtk_progress_set_activity_mode (GTK_PROGRESS
+ (queue_window_progress),
+ FALSE);
+ g_free (msg);
break;
case MESSAGE:
DEBUG (("*** Message -- MESSAGE\n"));
- gtk_label_set_text( GTK_LABEL( queue_window_message ),
- msg->message );
- g_free( msg->message );
- g_free( msg );
+ gtk_label_set_text (GTK_LABEL (queue_window_message),
+ msg->message);
+ g_free (msg->message);
+ g_free (msg);
break;
case PASSWORD:
DEBUG (("*** Message -- PASSWORD\n"));
- g_assert( msg->reply );
- g_assert( msg->success );
- get_password( msg );
+ g_assert (msg->reply);
+ g_assert (msg->success);
+ get_password (msg);
/* don't free msg! done later */
break;
case ERROR:
DEBUG (("*** Message -- ERROR\n"));
- show_error( msg );
- g_free( msg );
+ show_error (msg);
+ g_free (msg);
break;
/* Don't fall through; dispatch_func does the FINISHED
@@ -680,40 +887,58 @@ static gboolean read_msg( GIOChannel *source, GIOCondition condition, gpointer u
*/
case FINISHED:
- DEBUG (("*** Message -- FINISH\n"));
- if( msg->func )
- (msg->func)( msg->userdata );
+ DEBUG (
+ ("*** Message -- FINISH %s\n",
+ msg->clur->gerund));
+
+ if (msg->clur->spec->cleanup)
+ (msg->clur->spec->cleanup) (msg->clur->in_data,
+ msg->clur->op_data,
+ msg->clur->ex);
+
+ G_LOCK (ready_for_op);
+ ready_may_proceed = TRUE;
+ g_cond_signal (ready_cond);
+ G_UNLOCK (ready_for_op);
+
+ if (camel_exception_is_set (msg->clur->ex) &&
+ msg->clur->ex->id != CAMEL_EXCEPTION_USER_CANCEL) {
+ g_warning ("Error on cleanup of `%s': %s",
+ msg->clur->infinitive,
+ camel_exception_get_description (msg->
+ clur->
+ ex));
+ }
- if( op_queue == NULL ) {
- g_print("\tNo more ops -- hide %p.\n", queue_window);
+ free_closure (msg->clur);
+ queue_len--;
+
+ if (queue_len == 0) {
+ g_print ("\tNo more ops -- hide %p.\n", queue_window);
/* All done! */
- gtk_widget_hide( queue_window );
- mail_operation_in_progress = FALSE;
+ /* gtk_widget_hide seems to have problems sometimes
+ * here... perhaps because we're in a gsource handler,
+ * not a GTK event handler? Anyway, we defer the hiding
+ * til an idle. */
+ /*gtk_idle_add (hide_queue_window, NULL);*/
+ /*gtk_widget_hide (queue_window); */
+ destroy_queue_window ();
} else {
- g_print("\tOperation left.\n");
-
- /* There's another operation left */
-
- /* Pop it off the front */
- clur = op_queue->data;
- temp = g_slist_next( op_queue );
- g_slist_free_1( op_queue );
- op_queue = temp;
+ g_print ("\tOperation(s) left.\n");
- /* Clear it out of the 'pending' vbox */
- remove_next_pending();
-
- /* Run run run little process */
- dispatch( clur );
+ /* There's another operation left :
+ * Clear it out of the 'pending' vbox
+ */
+ remove_next_pending ();
}
- g_free( msg );
+ g_free (msg);
break;
default:
- g_warning( _("Corrupted message from dispatching thread?") );
+ g_warning (_("Corrupted message from dispatching thread?"));
break;
}
- GDK_THREADS_LEAVE();
+ GDK_THREADS_LEAVE ();
return TRUE;
}
@@ -725,23 +950,30 @@ static gboolean read_msg( GIOChannel *source, GIOCondition condition, gpointer u
* 'pending' message.
**/
-static void remove_next_pending( void )
+static void
+remove_next_pending (void)
{
GList *children;
- children = gtk_container_children( GTK_CONTAINER( queue_window_pending ) );
+ children =
+ gtk_container_children (GTK_CONTAINER (queue_window_pending));
/* Skip past the header label */
- children = g_list_first( children );
- children = g_list_next( children );
+ children = g_list_first (children);
+ children = g_list_next (children);
+
+ if (!children) {
+ g_warning ("Mistake in queue window!");
+ return;
+ }
/* Nuke the one on top */
- gtk_container_remove( GTK_CONTAINER( queue_window_pending ),
- GTK_WIDGET( children->data ) );
+ gtk_container_remove (GTK_CONTAINER (queue_window_pending),
+ GTK_WIDGET (children->data));
/* Hide it? */
- if( g_list_next( children ) == NULL )
- gtk_widget_hide( queue_window_pending );
+ if (g_list_next (children) == NULL)
+ gtk_widget_hide (queue_window_pending);
}
/**
@@ -750,28 +982,36 @@ static void remove_next_pending( void )
* Show the error dialog and wait for user OK
**/
-static void show_error( com_msg_t *msg )
+static void
+show_error (com_msg_t * msg)
{
GtkWidget *err_dialog;
+ gchar *old_message;
+
+ err_dialog = gnome_error_dialog (msg->message);
+ gnome_dialog_set_close (GNOME_DIALOG (err_dialog), TRUE);
+ gtk_signal_connect (GTK_OBJECT (err_dialog), "clicked",
+ (GtkSignalFunc) show_error_clicked, NULL);
+ g_free (msg->message);
- err_dialog = gnome_error_dialog( msg->message );
- gnome_dialog_set_close( GNOME_DIALOG(err_dialog), TRUE );
- gtk_signal_connect( GTK_OBJECT( err_dialog ), "clicked", (GtkSignalFunc) show_error_clicked, NULL );
- g_free( msg->message );
+ /* Save the old message, but display a new one right now */
+ gtk_label_get (GTK_LABEL (queue_window_message), &old_message);
+ gtk_object_set_data (GTK_OBJECT (err_dialog), "old_message",
+ g_strdup (old_message));
+ gtk_label_set_text (GTK_LABEL (queue_window_message),
+ _("Waiting for user to close error dialog"));
- G_LOCK( modal_lock );
+ G_LOCK (modal_lock);
- timeout_toggle( FALSE );
+ timeout_toggle (FALSE);
modal_may_proceed = FALSE;
- gtk_widget_show( GTK_WIDGET( err_dialog ) );
- gnome_win_hints_set_layer( err_dialog,
- WIN_LAYER_ONTOP );
- gnome_win_hints_set_state( err_dialog,
- WIN_STATE_ARRANGE_IGNORE );
- gnome_win_hints_set_hints( err_dialog,
+ gtk_widget_show_all (GTK_WIDGET (err_dialog));
+ gnome_win_hints_set_layer (err_dialog, WIN_LAYER_ONTOP);
+ gnome_win_hints_set_state (err_dialog, WIN_STATE_ARRANGE_IGNORE);
+ gnome_win_hints_set_hints (err_dialog,
WIN_HINTS_SKIP_FOCUS |
WIN_HINTS_SKIP_WINLIST |
- WIN_HINTS_SKIP_TASKBAR );
+ WIN_HINTS_SKIP_TASKBAR);
}
/**
@@ -781,12 +1021,21 @@ static void show_error( com_msg_t *msg )
* the dispatch thread is allowed to continue.
**/
-static void show_error_clicked( void )
+static void
+show_error_clicked (GtkObject * obj)
{
+ gchar *old_message;
+
+ /* Restore the old message */
+ old_message = gtk_object_get_data (obj, "old_message");
+ gtk_label_set_text (GTK_LABEL (queue_window_message),
+ old_message);
+ g_free (old_message);
+
modal_may_proceed = TRUE;
- timeout_toggle( TRUE );
- g_cond_signal( modal_cond );
- G_UNLOCK( modal_lock );
+ timeout_toggle (TRUE);
+ g_cond_signal (modal_cond);
+ G_UNLOCK (modal_lock);
}
/**
@@ -795,66 +1044,81 @@ static void show_error_clicked( void )
* Ask for a password and put the answer in *(msg->reply)
**/
-static void get_password( com_msg_t *msg )
+static void
+get_password (com_msg_t * msg)
{
GtkWidget *dialog;
+ gchar *old_message;
+
+ dialog = gnome_request_dialog (msg->secret, msg->message, NULL,
+ 0, get_password_cb, msg, NULL);
+ gnome_dialog_set_close (GNOME_DIALOG (dialog), TRUE);
+ gtk_signal_connect (GTK_OBJECT (dialog), "clicked",
+ get_password_clicked, msg);
- dialog = gnome_request_dialog( msg->secret, msg->message, NULL,
- 0, get_password_cb, msg,
- NULL );
- gnome_dialog_set_close( GNOME_DIALOG(dialog), TRUE );
- gtk_signal_connect( GTK_OBJECT( dialog ), "clicked", get_password_clicked, msg );
+ /* Save the old message, but display a new one right now */
+ gtk_label_get (GTK_LABEL (queue_window_message), &old_message);
+ gtk_object_set_data (GTK_OBJECT (dialog), "old_message", g_strdup(old_message));
+ gtk_label_set_text (GTK_LABEL (queue_window_message),
+ _("Waiting for user to enter data"));
- G_LOCK( modal_lock );
+ G_LOCK (modal_lock);
modal_may_proceed = FALSE;
- if( dialog == NULL ) {
+ if (dialog == NULL) {
*(msg->success) = FALSE;
- *(msg->reply) = g_strdup( _("Could not create dialog box.") );
+ *(msg->reply) = g_strdup (_("Could not create dialog box."));
modal_may_proceed = TRUE;
- g_cond_signal( modal_cond );
- G_UNLOCK( modal_lock );
+ g_cond_signal (modal_cond);
+ G_UNLOCK (modal_lock);
} else {
*(msg->reply) = NULL;
- timeout_toggle( FALSE );
- gtk_widget_show( GTK_WIDGET( dialog ) );
- gnome_win_hints_set_layer( dialog,
- WIN_LAYER_ONTOP );
- gnome_win_hints_set_state( dialog,
- WIN_STATE_ARRANGE_IGNORE );
- gnome_win_hints_set_hints( dialog,
+ timeout_toggle (FALSE);
+ gtk_widget_show_all (GTK_WIDGET (dialog));
+ gnome_win_hints_set_layer (dialog, WIN_LAYER_ONTOP);
+ gnome_win_hints_set_state (dialog, WIN_STATE_ARRANGE_IGNORE);
+ gnome_win_hints_set_hints (dialog,
WIN_HINTS_SKIP_FOCUS |
WIN_HINTS_SKIP_WINLIST |
- WIN_HINTS_SKIP_TASKBAR );
+ WIN_HINTS_SKIP_TASKBAR);
}
}
-static void get_password_cb( gchar *string, gpointer data )
+static void
+get_password_cb (gchar * string, gpointer data)
{
com_msg_t *msg = (com_msg_t *) data;
- if (string)
- *(msg->reply) = g_strdup( string );
- else
- *(msg->reply) = NULL;
+ if (string)
+ *(msg->reply) = g_strdup (string);
+ else
+ *(msg->reply) = NULL;
}
-static void get_password_clicked( GnomeDialog *dialog, gint button, gpointer user_data )
+static void
+get_password_clicked (GnomeDialog * dialog, gint button, gpointer user_data)
{
com_msg_t *msg = (com_msg_t *) user_data;
+ gchar *old_message;
+
+ /* Restore the old message */
+ old_message = gtk_object_get_data (GTK_OBJECT (dialog), "old_message");
+ gtk_label_set_text (GTK_LABEL (queue_window_message),
+ old_message);
+ g_free (old_message);
- if( button == 1 || *(msg->reply) == NULL ) {
+ if (button == 1 || *(msg->reply) == NULL) {
*(msg->success) = FALSE;
- *(msg->reply) = g_strdup( _("User cancelled query.") );
+ *(msg->reply) = g_strdup (_("User cancelled query."));
} else
*(msg->success) = TRUE;
- g_free( msg );
+ g_free (msg);
modal_may_proceed = TRUE;
- timeout_toggle( TRUE );
- g_cond_signal( modal_cond );
- G_UNLOCK( modal_lock );
+ timeout_toggle (TRUE);
+ g_cond_signal (modal_cond);
+ G_UNLOCK (modal_lock);
}
/* NOT totally copied from gtk+/gtk/testgtk.c, really! */
@@ -865,8 +1129,14 @@ progress_timeout (gpointer data)
gfloat new_val;
GtkAdjustment *adj;
+ if (queue_window == NULL) {
+ gtk_timeout_remove (progress_timeout_handle);
+ progress_timeout_handle = -1;
+ return FALSE;
+ }
+
adj = GTK_PROGRESS (data)->adjustment;
-
+
new_val = adj->value + 1;
if (new_val > adj->upper)
new_val = adj->lower;
@@ -885,20 +1155,100 @@ progress_timeout (gpointer data)
**/
static void
-timeout_toggle( gboolean active )
+timeout_toggle (gboolean active)
{
- if( (GTK_PROGRESS( queue_window_progress ))->activity_mode == 0 )
+ if (!queue_window)
+ return;
+
+ if ((GTK_PROGRESS (queue_window_progress))->activity_mode == 0)
return;
- if( active ) {
- if( progress_timeout_handle < 0 )
- progress_timeout_handle = gtk_timeout_add( 80, progress_timeout, queue_window_progress );
+ if (active) {
+ /* We do this in case queue_window_progress gets reset */
+ if (progress_timeout_handle < 0) {
+ progress_timeout_handle =
+ gtk_timeout_add (80, progress_timeout,
+ queue_window_progress);
+ } else {
+ gtk_timeout_remove (progress_timeout_handle);
+ progress_timeout_handle =
+ gtk_timeout_add (80, progress_timeout,
+ queue_window_progress);
+ }
} else {
- if( progress_timeout_handle >= 0 ) {
- gtk_timeout_remove( progress_timeout_handle );
+ if (progress_timeout_handle >= 0) {
+ gtk_timeout_remove (progress_timeout_handle);
progress_timeout_handle = -1;
}
}
}
-#endif
+/* This can theoretically run into problems where if a short operation starts
+ * and finishes, then another short operation starts and finishes a second
+ * later, we will see the window prematurely. My response: oh noooooo!
+ *
+ * Solution: keep the timeout's handle and remove the timeout upon reception
+ * of FINISH, and zero out the handle in this function. Whatever.
+ */
+static gboolean
+display_timeout (gpointer data)
+{
+ if (queue_len > 0 && queue_window) {
+ gtk_widget_show (queue_window);
+ gnome_win_hints_set_layer (queue_window, WIN_LAYER_ONTOP);
+ gnome_win_hints_set_state (queue_window,
+ WIN_STATE_ARRANGE_IGNORE);
+ gnome_win_hints_set_hints (queue_window,
+ WIN_HINTS_SKIP_FOCUS |
+ WIN_HINTS_SKIP_WINLIST |
+ WIN_HINTS_SKIP_TASKBAR);
+
+ if (queue_len == 1)
+ gtk_widget_hide (queue_window_pending);
+ }
+
+ return FALSE;
+}
+
+static closure_t *
+new_closure (const mail_operation_spec * spec, gpointer input,
+ gboolean free_in_data)
+{
+ closure_t *clur;
+
+ clur = g_new0 (closure_t, 1);
+ clur->spec = spec;
+ clur->in_data = input;
+ clur->free_in_data = free_in_data;
+ clur->ex = camel_exception_new ();
+
+ clur->op_data = g_malloc (spec->datasize);
+
+ camel_exception_init (clur->ex);
+
+ clur->infinitive = (spec->describe) (input, FALSE);
+ clur->gerund = (spec->describe) (input, TRUE);
+
+ return clur;
+}
+
+static void
+free_closure (closure_t *clur)
+{
+ clur->spec = NULL;
+
+ if (clur->free_in_data)
+ g_free (clur->in_data);
+ clur->in_data = NULL;
+
+ g_free (clur->op_data);
+ clur->op_data = NULL;
+
+ camel_exception_free (clur->ex);
+ clur->ex = NULL;
+
+ g_free (clur->infinitive);
+ g_free (clur->gerund);
+
+ g_free (clur);
+}
diff --git a/mail/mail-threads.h b/mail/mail-threads.h
index e26acdbb14..1aeb486935 100644
--- a/mail/mail-threads.h
+++ b/mail/mail-threads.h
@@ -25,28 +25,44 @@
#ifndef _MAIL_THREADS_H_
#define _MAIL_THREADS_H_
-#ifdef USE_BROKEN_THREADS
+#include <camel/camel-exception.h>
+#include <stdlib.h> /*size_t */
+
+/* Returns a g_strdup'ed string that describes what's going to happen,
+ * tersely but specifically.
+ */
+typedef gchar *(*mail_op_describe_func) (gpointer /*input_data*/, gboolean /*gerund*/);
+typedef void (*mail_op_func) (gpointer, gpointer, CamelException *);
+
+typedef struct _mail_operation_spec
+{
+ mail_op_describe_func describe;
+ size_t datasize;
+ mail_op_func setup;
+ mail_op_func callback;
+ mail_op_func cleanup;
+}
+mail_operation_spec;
+
/* Schedule to operation to happen eventually */
-gboolean mail_operation_try( const gchar *description,
- void (*callback)( gpointer ),
- void (*cleanup)( gpointer ),
- gpointer user_data );
+gboolean mail_operation_queue (const mail_operation_spec * spec,
+ gpointer input, gboolean free_in_data);
/* User interface hooks for the other thread */
-void mail_op_set_percentage( gfloat percentage );
-void mail_op_hide_progressbar( void );
-void mail_op_show_progressbar( void );
-void mail_op_set_message( gchar *fmt, ... ) G_GNUC_PRINTF( 1, 2 );
-void mail_op_error( gchar *fmt, ... ) G_GNUC_PRINTF( 1, 2 );
-gboolean mail_op_get_password( gchar *prompt, gboolean secret, gchar **dest );
+void mail_op_set_percentage (gfloat percentage);
+void mail_op_hide_progressbar (void);
+void mail_op_show_progressbar (void);
+void
+mail_op_set_message (gchar * fmt, ...) G_GNUC_PRINTF (1, 2);
+void mail_op_error (gchar * fmt, ...) G_GNUC_PRINTF (1, 2);
+gboolean mail_op_get_password (gchar * prompt, gboolean secret,
+ gchar ** dest);
/* Wait for the async operations to finish */
-void mail_operation_wait_for_finish( void );
-
-gboolean mail_operations_are_executing( void );
-
-#endif /* defined USE_BROKEN_THREADS */
+void mail_operation_wait_for_finish (void);
+gboolean mail_operations_are_executing (void);
+void mail_operations_terminate (void);
#endif /* defined _MAIL_THREADS_H_ */
diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c
index fab59ef991..1fc5b8b2e3 100644
--- a/mail/mail-vfolder.c
+++ b/mail/mail-vfolder.c
@@ -19,12 +19,12 @@
#include "evolution-shell-component.h"
#include "folder-browser.h"
#include "mail-vfolder.h"
+#include "mail-tools.h"
#include "mail-autofilter.h"
#include "camel/camel.h"
#include "filter/vfolder-context.h"
-#include "filter/vfolder-rule.h"
#include "filter/vfolder-editor.h"
#define d(x) x
@@ -171,19 +171,17 @@ vfolder_create_storage(EvolutionShellComponent *shell_component)
vfolder_refresh();
}
+/* THIS IS ANALOGOUS TO mail_tool_uri_to_folder. IT IS NOT ASYNCHRONOUS */
/* maps the shell's uri to the real vfolder uri and open the folder */
CamelFolder *
-vfolder_uri_to_folder(const char *uri)
+vfolder_uri_to_folder(const char *uri, CamelException *ex)
{
- CamelFolder *mail_uri_to_folder(const char *);
void camel_vee_folder_add_folder(CamelFolder *, CamelFolder *);
struct _vfolder_info *info;
char *storeuri, *foldername;
VfolderRule *rule;
- CamelStore *store = NULL;
CamelFolder *folder = NULL, *sourcefolder;
- CamelException *ex;
const char *sourceuri;
int sources;
@@ -202,23 +200,19 @@ vfolder_uri_to_folder(const char *uri)
storeuri = g_strdup_printf("vfolder:%s/vfolder/%s", evolution_dir, info->name);
foldername = g_strdup_printf("mbox?%s", info->query);
- ex = camel_exception_new ();
- store = camel_session_get_store (session, storeuri, ex);
- if (store == NULL)
- goto cleanup;
- folder = camel_store_get_folder (store, foldername, TRUE, ex);
- if (folder == NULL)
- goto cleanup;
+ folder = mail_tool_get_folder_from_urlname (storeuri, foldername, ex);
sourceuri = NULL;
sources = 0;
while ( (sourceuri = vfolder_rule_next_source(rule, sourceuri)) ) {
d(printf("adding vfolder source: %s\n", sourceuri));
- sourcefolder = mail_uri_to_folder(sourceuri);
+ sourcefolder = mail_tool_uri_to_folder (sourceuri, ex);
if (sourcefolder) {
sources++;
+ mail_tool_camel_lock_up ();
camel_vee_folder_add_folder(folder, sourcefolder);
+ mail_tool_camel_lock_down ();
}
}
/* if we didn't have any sources, just use Inbox as the default */
@@ -227,12 +221,15 @@ vfolder_uri_to_folder(const char *uri)
defaulturi = g_strdup_printf("file://%s/local/Inbox", evolution_dir);
d(printf("No sources configured/found, using default: %s\n", defaulturi));
- sourcefolder = mail_uri_to_folder(defaulturi);
+ sourcefolder = mail_tool_uri_to_folder (defaulturi, ex);
g_free(defaulturi);
- if (sourcefolder)
+ if (sourcefolder) {
+ mail_tool_camel_lock_up ();
camel_vee_folder_add_folder(folder, sourcefolder);
+ mail_tool_camel_lock_down ();
+ }
}
-cleanup:
+
g_free(foldername);
g_free(storeuri);
diff --git a/mail/mail-vfolder.h b/mail/mail-vfolder.h
index 4e87276322..2ff19cc3ea 100644
--- a/mail/mail-vfolder.h
+++ b/mail/mail-vfolder.h
@@ -15,7 +15,7 @@
void vfolder_create_storage(EvolutionShellComponent *shell_component);
-CamelFolder *vfolder_uri_to_folder(const char *uri);
+CamelFolder *vfolder_uri_to_folder(const char *uri, CamelException *ex);
void vfolder_edit(void);
FilterPart *vfolder_create_part(const char *name);
void vfolder_gui_add_rule(VfolderRule *rule);
diff --git a/mail/mail-view.c b/mail/mail-view.c
index a98cc4d5ca..6c336a47f8 100644
--- a/mail/mail-view.c
+++ b/mail/mail-view.c
@@ -20,17 +20,111 @@
*
*/
-#include <mail.h>
-#include <camel.h>
+#include <config.h>
+#include "mail.h"
+#include "mail-ops.h"
+#include "camel/camel.h"
+
+typedef struct mail_view_data_s {
+ CamelFolder *source;
+ gchar *uid;
+ CamelMimeMessage *msg;
+ MailDisplay *md;
+} mail_view_data;
+
+static void
+mail_view_data_free (gpointer mvd)
+{
+ mail_view_data *data = (mail_view_data *) mvd;
+
+ if (data->uid)
+ g_free (data->uid);
+ if (data->msg)
+ camel_object_unref (CAMEL_OBJECT (data->msg));
+ if (data->source)
+ camel_object_unref (CAMEL_OBJECT (data->source));
+
+ g_free (data);
+}
+
+static mail_view_data *
+mail_view_data_new (CamelFolder *source, const gchar *uid, CamelMimeMessage *msg)
+{
+ mail_view_data *data;
+
+ data = g_new (mail_view_data, 1);
+ data->source = source;
+ camel_object_ref (CAMEL_OBJECT (data->source));
+ data->msg = msg;
+ camel_object_ref (CAMEL_OBJECT (data->msg));
+ data->uid = g_strdup (uid);
+
+ return data;
+}
static void
on_close (GtkWidget *menuitem, gpointer user_data)
{
- GtkWidget *view;
-
- view = gtk_widget_get_toplevel (menuitem);
-
- gtk_widget_destroy (view);
+ GtkWidget *view_window;
+
+ view_window = gtk_object_get_data (GTK_OBJECT (menuitem), "view-window");
+ g_return_if_fail (view_window);
+ gtk_widget_destroy (GTK_WIDGET (view_window));
+}
+
+static void
+view_reply_to_sender (GtkWidget *widget, gpointer user_data)
+{
+ mail_view_data *data = (mail_view_data *) user_data;
+
+ mail_reply (data->source, data->msg, data->uid, FALSE);
+}
+
+static void
+view_reply_to_all (GtkWidget *widget, gpointer user_data)
+{
+ mail_view_data *data = (mail_view_data *) user_data;
+
+ mail_reply (data->source, data->msg, data->uid, TRUE);
+}
+
+static void
+view_forward_msg (GtkWidget *widget, gpointer user_data)
+{
+ mail_view_data *data = (mail_view_data *) user_data;
+
+ GPtrArray *uids;
+ EMsgComposer *composer;
+
+ uids = g_ptr_array_new();
+ g_ptr_array_add (uids, g_strdup (data->uid));
+
+ composer = E_MSG_COMPOSER (e_msg_composer_new ());
+ gtk_signal_connect (GTK_OBJECT (composer), "send",
+ GTK_SIGNAL_FUNC (composer_send_cb), NULL);
+
+ mail_do_forward_message (data->msg, data->source, uids, composer);
+}
+
+static void
+view_print_msg (GtkWidget *widget, gpointer user_data)
+{
+ mail_view_data *data = (mail_view_data *) user_data;
+
+ mail_print_msg (data->md);
+}
+
+static void
+view_delete_msg (GtkWidget *button, gpointer user_data)
+{
+ mail_view_data *data = (mail_view_data *) user_data;
+
+ GPtrArray *uids;
+
+ uids = g_ptr_array_new();
+ g_ptr_array_add (uids, g_strdup (data->uid));
+ mail_do_flag_messages (data->source, uids, TRUE,
+ CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_DELETED);
}
static GnomeUIInfo mail_view_toolbar [] = {
@@ -39,18 +133,18 @@ static GnomeUIInfo mail_view_toolbar [] = {
save_msg, GNOME_STOCK_PIXMAP_SAVE),*/
GNOMEUIINFO_ITEM_STOCK (N_("Reply"), N_("Reply to the sender of this message"),
- reply_to_sender, GNOME_STOCK_PIXMAP_MAIL_RPL),
+ view_reply_to_sender, GNOME_STOCK_PIXMAP_MAIL_RPL),
GNOMEUIINFO_ITEM_STOCK (N_("Reply to All"), N_("Reply to all recipients of this message"),
- reply_to_all, GNOME_STOCK_PIXMAP_MAIL_RPL),
+ view_reply_to_all, GNOME_STOCK_PIXMAP_MAIL_RPL),
- GNOMEUIINFO_ITEM_STOCK (N_("Forward"), N_("Forward this message"), forward_msg, GNOME_STOCK_PIXMAP_MAIL_FWD),
+ GNOMEUIINFO_ITEM_STOCK (N_("Forward"), N_("Forward this message"), view_forward_msg, GNOME_STOCK_PIXMAP_MAIL_FWD),
GNOMEUIINFO_SEPARATOR,
- GNOMEUIINFO_ITEM_STOCK (N_("Print"), N_("Print the selected message"), print_msg, GNOME_STOCK_PIXMAP_PRINT),
+ GNOMEUIINFO_ITEM_STOCK (N_("Print"), N_("Print the selected message"), view_print_msg, GNOME_STOCK_PIXMAP_PRINT),
- GNOMEUIINFO_ITEM_STOCK (N_("Delete"), N_("Delete this message"), delete_msg, GNOME_STOCK_PIXMAP_TRASH),
+ GNOMEUIINFO_ITEM_STOCK (N_("Delete"), N_("Delete this message"), view_delete_msg, GNOME_STOCK_PIXMAP_TRASH),
/*GNOMEUIINFO_SEPARATOR,*/
@@ -82,16 +176,17 @@ static GnomeUIInfo mail_view_menubar[] =
};
GtkWidget *
-mail_view_create (FolderBrowser *folder_browser)
+mail_view_create (CamelFolder *source, const char *uid, CamelMimeMessage *msg)
{
- CamelMimeMessage *msg;
GtkWidget *window;
GtkWidget *toolbar;
GtkWidget *mail_display;
- char *subject;
GnomeDockItemBehavior behavior;
+ char *subject;
+ mail_view_data *data;
+
+ data = mail_view_data_new (source, uid, msg);
- msg = folder_browser->mail_display->current_message;
subject = (char *) camel_mime_message_get_subject (msg);
if (!subject)
subject = "";
@@ -102,26 +197,30 @@ mail_view_create (FolderBrowser *folder_browser)
gnome_app_fill_toolbar_with_data (GTK_TOOLBAR (toolbar),
mail_view_toolbar,
- NULL, folder_browser);
+ NULL, data);
behavior = GNOME_DOCK_ITEM_BEH_NORMAL;
if (!gnome_preferences_get_toolbar_detachable ())
behavior |= GNOME_DOCK_ITEM_BEH_LOCKED;
- gnome_app_add_toolbar (GNOME_APP (window),
+ gnome_app_add_toolbar (GNOME_APP (window),
GTK_TOOLBAR (toolbar),
GNOME_APP_TOOLBAR_NAME,
behavior,
GNOME_DOCK_TOP, 1, 0, 0);
gnome_app_create_menus (GNOME_APP (window), mail_view_menubar);
-
+
+ gtk_object_set_data_full (GTK_OBJECT (window), "mvd", data,
+ mail_view_data_free);
+
gtk_widget_ref (mail_view_menubar[0].widget);
gtk_object_set_data_full (GTK_OBJECT (window), "file",
mail_view_menubar[0].widget,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_ref (file_menu[0].widget);
+ gtk_object_set_data (GTK_OBJECT (file_menu[0].widget), "view-window", window);
gtk_object_set_data_full (GTK_OBJECT (window), "close",
file_menu[0].widget,
(GtkDestroyNotify) gtk_widget_unref);
@@ -131,11 +230,14 @@ mail_view_create (FolderBrowser *folder_browser)
mail_view_menubar[1].widget,
(GtkDestroyNotify) gtk_widget_unref);
- mail_display = mail_display_new (folder_browser);
+ mail_display = mail_display_new ();
mail_display_set_message (MAIL_DISPLAY (mail_display), CAMEL_MEDIUM (msg));
gtk_widget_set_usize (mail_display, 600, 600);
-
+ data->md = MAIL_DISPLAY (mail_display);
gnome_app_set_contents (GNOME_APP (window), mail_display);
return window;
}
+
+
+
diff --git a/mail/mail.h b/mail/mail.h
index 3ff7422370..2bc829dc36 100644
--- a/mail/mail.h
+++ b/mail/mail.h
@@ -31,8 +31,8 @@
void folder_browser_factory_init (void);
BonoboControl *folder_browser_factory_new_control (const char *uri);
-/* folder-browser */
-CamelFolder *mail_uri_to_folder (const char *uri);
+/* mail-config */
+void mail_config_druid (void);
/* mail-crypto */
char *mail_crypto_openpgp_decrypt (const char *ciphertext,
@@ -60,7 +60,7 @@ char *mail_get_message_body (CamelDataWrapper *data, gboolean want_plain,
/* mail-identify */
char *mail_identify_mime_part (CamelMimePart *part);
-/* mail-ops */
+/* mail-callbacks */
void fetch_mail (GtkWidget *widget, gpointer user_data);
void compose_msg (GtkWidget *widget, gpointer user_data);
void send_to_url (const char *url);
@@ -83,8 +83,12 @@ void providers_config (BonoboUIHandler *uih, void *user_data, const char *path);
void configure_folder(BonoboUIHandler *uih, void *user_data, const char *path);
+void mail_reply (CamelFolder *folder, CamelMimeMessage *msg, const char *uid, gboolean to_all);
+void composer_send_cb (EMsgComposer *composer, gpointer data);
+void mail_print_msg (MailDisplay *md);
+
/* mail view */
-GtkWidget *mail_view_create (FolderBrowser *folder_browser);
+GtkWidget *mail_view_create (CamelFolder *source, const char *uid, CamelMimeMessage *msg);
/* session */
void session_init (void);
diff --git a/mail/main.c b/mail/main.c
index 8ad567da21..372abf8b8a 100644
--- a/mail/main.c
+++ b/mail/main.c
@@ -30,9 +30,7 @@ main (int argc, char *argv [])
bindtextdomain (PACKAGE, EVOLUTION_LOCALEDIR);
textdomain (PACKAGE);
-#ifdef USE_BROKEN_THREADS
g_thread_init( NULL );
-#endif
od_assert_using_oaf ();
gnome_init_with_popt_table ("evolution-mail-component", VERSION,
@@ -59,13 +57,9 @@ main (int argc, char *argv [])
mail_config_init ();
component_factory_init ();
-#ifdef USE_BROKEN_THREADS
GDK_THREADS_ENTER ();
-#endif
bonobo_main ();
-#ifdef USE_BROKEN_THREADS
GDK_THREADS_LEAVE ();
-#endif
mail_config_write_on_exit ();
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);
}
diff --git a/mail/message-list.h b/mail/message-list.h
index 443d92d7f4..4f9719f30b 100644
--- a/mail/message-list.h
+++ b/mail/message-list.h
@@ -99,7 +99,6 @@ GtkType message_list_get_type (void);
BonoboObject *message_list_new (FolderBrowser *parent_folder_browser);
void message_list_set_folder (MessageList *message_list,
CamelFolder *camel_folder);
-void message_list_regenerate (MessageList *message_list, const char *search);
GtkWidget *message_list_get_widget (MessageList *message_list);
void message_list_foreach (MessageList *message_list,
diff --git a/mail/message-thread.c b/mail/message-thread.c
index f199c27341..fa362f04ee 100644
--- a/mail/message-thread.c
+++ b/mail/message-thread.c
@@ -31,9 +31,15 @@
#include <ctype.h>
#include "message-thread.h"
+#include "mail-tools.h"
+#include "mail-threads.h"
#define d(x)
+static struct _container *thread_messages(CamelFolder *folder, GPtrArray *uids);
+static void thread_messages_free(struct _container *);
+
+/* for debug only */
int dump_tree(struct _container *c, int depth);
static void
@@ -331,7 +337,7 @@ dump_tree(struct _container *c, int depth)
return count;
}
-void thread_messages_free(struct _container *c)
+static void thread_messages_free(struct _container *c)
{
struct _container *n;
@@ -407,7 +413,7 @@ sort_thread(struct _container **cp)
*cp = head;
}
-struct _container *
+static struct _container *
thread_messages(CamelFolder *folder, GPtrArray *uids)
{
GHashTable *id_table, *no_id_table;
@@ -419,13 +425,20 @@ thread_messages(CamelFolder *folder, GPtrArray *uids)
no_id_table = g_hash_table_new(NULL, NULL);
for (i=0;i<uids->len;i++) {
const CamelMessageInfo *mi;
+ mail_tool_camel_lock_up ();
mi = camel_folder_get_message_info (folder, uids->pdata[i]);
+ mail_tool_camel_lock_down ();
if (mi == NULL) {
g_warning("Folder doesn't contain uid %s", (char *)uids->pdata[i]);
continue;
}
+ if (mi == NULL) {
+ g_warning("Folder doesn't contain uid %s", uids->pdata[i]);
+ continue;
+ }
+
if (mi->message_id) {
d(printf("doing : %s\n", mi->message_id));
c = g_hash_table_lookup(id_table, mi->message_id);
@@ -495,6 +508,116 @@ thread_messages(CamelFolder *folder, GPtrArray *uids)
return head;
}
+/* ** THREAD MESSAGES ***************************************************** */
+
+typedef struct thread_messages_input_s {
+ MessageList *ml;
+ GPtrArray *uids;
+ gboolean use_camel_uidfree;
+ void (*build) (MessageList *, ETreePath *,
+ struct _container *, int *);
+} thread_messages_input_t;
+
+typedef struct thread_messages_data_s {
+ struct _container *container;
+ int row;
+} thread_messages_data_t;
+
+static gchar *describe_thread_messages (gpointer in_data, gboolean gerund);
+static void setup_thread_messages (gpointer in_data, gpointer op_data, CamelException *ex);
+static void do_thread_messages (gpointer in_data, gpointer op_data, CamelException *ex);
+static void cleanup_thread_messages (gpointer in_data, gpointer op_data, CamelException *ex);
+
+static gchar *describe_thread_messages (gpointer in_data, gboolean gerund)
+{
+ if (gerund)
+ return g_strdup ("Threading message list");
+ else
+ return g_strdup ("Thread message list");
+}
+
+static void setup_thread_messages (gpointer in_data, gpointer op_data, CamelException *ex)
+{
+ thread_messages_input_t *input = (thread_messages_input_t *) in_data;
+
+ if (!IS_MESSAGE_LIST (input->ml)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No messagelist to thread was provided to thread_messages");
+ return;
+ }
+
+ if (!input->uids) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No uids were provided to thread_messages");
+ return;
+ }
+
+ if (!input->build) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
+ "No build callback provided to thread_messages");
+ return;
+ }
+
+ gtk_object_ref (GTK_OBJECT (input->ml));
+}
+
+static void do_thread_messages (gpointer in_data, gpointer op_data, CamelException *ex)
+{
+ thread_messages_input_t *input = (thread_messages_input_t *) in_data;
+ thread_messages_data_t *data = (thread_messages_data_t *) op_data;
+
+ data->container = thread_messages (input->ml->folder, input->uids);
+ data->row = 0;
+}
+
+static void cleanup_thread_messages (gpointer in_data, gpointer op_data, CamelException *ex)
+{
+ thread_messages_input_t *input = (thread_messages_input_t *) in_data;
+ thread_messages_data_t *data = (thread_messages_data_t *) op_data;
+
+ (input->build) (input->ml, input->ml->tree_root,
+ data->container, &(data->row));
+ thread_messages_free (data->container);
+
+ if (input->use_camel_uidfree) {
+ mail_tool_camel_lock_up ();
+ camel_folder_free_uids (input->ml->folder, input->uids);
+ mail_tool_camel_lock_down ();
+ } else {
+ g_strfreev ((char **)input->uids->pdata);
+ g_ptr_array_free (input->uids, FALSE);
+ }
+
+ gtk_object_unref (GTK_OBJECT (input->ml));
+}
+
+static const mail_operation_spec op_thread_messages =
+{
+ describe_thread_messages,
+ sizeof (thread_messages_data_t),
+ setup_thread_messages,
+ do_thread_messages,
+ cleanup_thread_messages
+};
+
+void mail_do_thread_messages (MessageList *ml, GPtrArray *uids,
+ gboolean use_camel_uidfree,
+ void (*build) (MessageList *, ETreePath *,
+ struct _container *, int *))
+{
+ thread_messages_input_t *input;
+
+ input = g_new (thread_messages_input_t, 1);
+ input->ml = ml;
+ input->uids = uids;
+ input->use_camel_uidfree = use_camel_uidfree;
+ input->build = build;
+
+ mail_operation_queue (&op_thread_messages, input, TRUE);
+}
+
+/* ************************************************************************ */
+
#ifdef STANDALONE
static char *
@@ -546,7 +669,7 @@ main (int argc, char**argv)
}
#endif
- summary = camel_folder_get_summary(folder, ex);
+ summary = camel_folder_get_summary(folder);
thread_messages((CamelMessageInfo **)summary->pdata, summary->len);
return 0;
diff --git a/mail/message-thread.h b/mail/message-thread.h
index d66baacbdd..46a7a36b03 100644
--- a/mail/message-thread.h
+++ b/mail/message-thread.h
@@ -1,6 +1,9 @@
#ifndef _MESSAGE_THREAD_H
#define _MESSAGE_THREAD_H
+#include <gnome.h>
+#include "message-list.h"
+
struct _container {
struct _container *next,
*parent,
@@ -11,11 +14,10 @@ struct _container {
int order; /* the order of this message in the folder */
};
-struct _container *thread_messages(CamelFolder *folder, GPtrArray *uids);
-void thread_messages_free(struct _container *);
-
-/* for debug only */
-int dump_tree(struct _container *c, int depth);
+void mail_do_thread_messages (MessageList *ml, GPtrArray *uids,
+ gboolean use_camel_uidfree,
+ void (*build) (MessageList *, ETreePath *,
+ struct _container *, int *));
#endif /* !_MESSAGE_THREAD_H */
diff --git a/mail/session.c b/mail/session.c
index 7eaefd390c..3c5d52abb0 100644
--- a/mail/session.c
+++ b/mail/session.c
@@ -20,9 +20,7 @@ GHashTable *passwords;
* we deadlock....
*/
-#ifdef USE_BROKEN_THREADS
#define ASYNC_AUTH_CALLBACK
-#endif
#ifndef ASYNC_AUTH_CALLBACK
static void
@@ -63,7 +61,7 @@ mail_request_dialog (const char *prompt, gboolean secret, const char *key)
ans == NULL)
return NULL;
#else
- if (!mail_op_get_password (data, secret, &ans))
+ if (!mail_op_get_password (prompt, secret, &ans))
return NULL;
#endif
@@ -115,13 +113,99 @@ auth_callback (CamelAuthCallbackMode mode, char *data, gboolean secret,
return ans;
}
+/* ******************** */
+
+typedef struct _timeout_data_s {
+ CamelTimeoutCallback cb;
+ gpointer camel_data;
+ gboolean result;
+} timeout_data_t;
+
+static gchar *
+describe_camel_timeout (gpointer in_data, gboolean gerund)
+{
+ /* FIXME this is so wrong */
+
+ if (gerund)
+ return g_strdup ("Keeping connection alive");
+ else
+ return g_strdup ("Keep connection alive");
+}
+
+static void
+noop_camel_timeout (gpointer in_data, gpointer op_data, CamelException *ex)
+{
+}
+
+static void
+do_camel_timeout (gpointer in_data, gpointer op_data, CamelException *ex)
+{
+ timeout_data_t *td = (timeout_data_t *) in_data;
+
+ td->result = (td->cb) (td->camel_data);
+}
+
+static const mail_operation_spec spec_camel_timeout =
+{
+ describe_camel_timeout,
+ 0,
+ noop_camel_timeout,
+ do_camel_timeout,
+ noop_camel_timeout
+};
+
+static gboolean
+camel_timeout (gpointer data)
+{
+ timeout_data_t *td = (timeout_data_t *) data;
+
+ if (td->result == FALSE) {
+ g_free (td);
+ return FALSE;
+ }
+
+ mail_operation_queue (&spec_camel_timeout, td, FALSE);
+ return TRUE;
+}
+
+static guint
+register_callback (guint32 interval, CamelTimeoutCallback cb, gpointer camel_data)
+{
+ timeout_data_t *td;
+
+ /* We do this because otherwise the timeout can get called
+ * more often than the dispatch thread can get rid of it,
+ * leading to timeout calls piling up, and we don't have a
+ * good way to watch the return values. It's not cool.
+ */
+ g_return_val_if_fail (interval > 1000, 0);
+
+ td = g_new (timeout_data_t, 1);
+ td->result = TRUE;
+ td->cb = cb;
+ td->camel_data = camel_data;
+
+ return gtk_timeout_add_full (interval, camel_timeout, NULL,
+ td, g_free);
+}
+
+static gboolean
+remove_callback (guint handle)
+{
+ gtk_timeout_remove (handle);
+ return TRUE;
+}
+
+/* ******************** */
+
void
session_init (void)
{
e_setup_base_dir ();
camel_init ();
- session = camel_session_new (auth_callback);
+ session = camel_session_new (auth_callback, register_callback,
+ remove_callback);
}
static gboolean
diff --git a/mail/test-thread.c b/mail/test-thread.c
index b9fb5bb0b2..7a389605ec 100644
--- a/mail/test-thread.c
+++ b/mail/test-thread.c
@@ -8,30 +8,44 @@
#include <stdio.h>
#include "mail-threads.h"
-#ifdef ENABLE_BROKEN_THREADS
-
-static void op_1( gpointer userdata );
-static void op_2( gpointer userdata );
-static void op_3( gpointer userdata );
-static void op_4( gpointer userdata );
-static void op_5( gpointer userdata );
-static void done( gpointer userdata );
+static gchar *desc_1 (gpointer in, gboolean gerund);
+static void op_1( gpointer in, gpointer op, CamelException *ex );
+static gchar *desc_2 (gpointer in, gboolean gerund);
+static void op_2( gpointer in, gpointer op, CamelException *ex );
+static gchar *desc_3 (gpointer in, gboolean gerund);
+static void op_3( gpointer in, gpointer op, CamelException *ex );
+static gchar *desc_4 (gpointer in, gboolean gerund);
+static void op_4( gpointer in, gpointer op, CamelException *ex );
+static gchar *desc_5 (gpointer in, gboolean gerund);
+static void op_5( gpointer in, gpointer op, CamelException *ex );
+static gchar *desc_6 (gpointer in, gboolean gerund);
+static gchar *desc_7 (gpointer in, gboolean gerund);
+static gchar *desc_8 (gpointer in, gboolean gerund);
+static void done( gpointer in, gpointer op, CamelException *ex );
+static void exception( gpointer in, gpointer op, CamelException *ex );
static gboolean queue_ops( void );
+const mail_operation_spec spec1 = { desc_1, 0, NULL, op_1, done };
+const mail_operation_spec spec2 = { desc_2, 0, NULL, op_2, done };
+const mail_operation_spec spec3 = { desc_3, 0, NULL, op_3, done };
+const mail_operation_spec spec4 = { desc_4, 0, NULL, op_4, NULL };
+const mail_operation_spec spec5 = { desc_5, 0, NULL, op_5, done };
+const mail_operation_spec spec6 = { desc_6, 0, exception, op_4, NULL };
+const mail_operation_spec spec7 = { desc_7, 0, NULL, exception, NULL };
+const mail_operation_spec spec8 = { desc_8, 0, NULL, op_4, exception };
+
static gboolean queue_ops( void )
{
int i;
- gchar buf[32];
g_message( "Top of queue_ops" );
- mail_operation_try( "The Crawling Progress Bar of Doom", op_1, done, "op1 finished" );
- mail_operation_try( "The Mysterious Message Setter", op_2, done, "op2 finished" );
- mail_operation_try( "The Error Dialog of No Return", op_3, done, "op3 finished" );
+ mail_operation_queue( &spec1, "op1 finished", FALSE );
+ mail_operation_queue( &spec2, "op2 finished", FALSE );
+ mail_operation_queue( &spec3, "op3 finished", FALSE );
for( i = 0; i < 3; i++ ) {
- sprintf( buf, "Queue Filler %d", i );
- mail_operation_try( buf, op_4, NULL, GINT_TO_POINTER( i ) );
+ mail_operation_queue( &spec4, GINT_TO_POINTER( i ), FALSE );
}
g_message( "Waiting for finish..." );
@@ -39,20 +53,23 @@ static gboolean queue_ops( void )
g_message( "Ops done -- queue some more!" );
- mail_operation_try( "Progress Bar Redux", op_1, NULL, NULL );
+ mail_operation_queue( &spec1, "done a second time", FALSE );
g_message( "Waiting for finish again..." );
mail_operation_wait_for_finish();
g_message( "Ops done -- more, more!" );
- mail_operation_try( "Dastardly Password Stealer", op_5, NULL, NULL );
+ mail_operation_queue( &spec5, "passwords stolen", FALSE );
for( i = 0; i < 3; i++ ) {
- sprintf( buf, "Queue Filler %d", i );
- mail_operation_try( buf, op_4, NULL, GINT_TO_POINTER( i ) );
+ mail_operation_queue( &spec4, GINT_TO_POINTER( i ), FALSE );
}
+ mail_operation_queue( &spec6, NULL, FALSE );
+ mail_operation_queue( &spec7, NULL, FALSE );
+ mail_operation_queue( &spec8, NULL, FALSE );
+
g_message( "Waiting for finish AGAIN..." );
mail_operation_wait_for_finish();
g_message( "Ops done again. Exiting 0" );
@@ -60,7 +77,12 @@ static gboolean queue_ops( void )
return FALSE;
}
-static void op_1( gpointer userdata )
+static void exception( gpointer in, gpointer op, CamelException *ex )
+{
+ camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, "I don't feel like it.");
+}
+
+static void op_1( gpointer in, gpointer op, CamelException *ex )
{
gfloat pct;
@@ -73,7 +95,7 @@ static void op_1( gpointer userdata )
}
}
-static void op_2( gpointer userdata )
+static void op_2( gpointer in, gpointer op, CamelException *ex )
{
int i;
@@ -87,7 +109,7 @@ static void op_2( gpointer userdata )
sleep( 1 );
}
-static void op_3( gpointer userdata )
+static void op_3( gpointer in, gpointer op, CamelException *ex )
{
gfloat pct;
@@ -103,14 +125,14 @@ static void op_3( gpointer userdata )
sleep( 1 );
}
-static void op_4( gpointer userdata )
+static void op_4( gpointer in, gpointer op, CamelException *ex )
{
mail_op_hide_progressbar();
- mail_op_set_message( "Filler # %d", GPOINTER_TO_INT( userdata ) );
+ mail_op_set_message( "Filler # %d", GPOINTER_TO_INT( in ) );
sleep( 1 );
}
-static void op_5( gpointer userdata )
+static void op_5( gpointer in, gpointer op, CamelException *ex )
{
gchar *pass;
gboolean ret;
@@ -128,26 +150,81 @@ static void op_5( gpointer userdata )
sleep( 1 );
}
-static void done( gpointer userdata )
+static void done( gpointer in, gpointer op, CamelException *ex )
{
- g_message( "Operation done: %s", (gchar *) userdata );
+ g_message( "Operation done: %s", (gchar *) in );
}
-int main( int argc, char **argv )
+static gchar *desc_1 (gpointer in, gboolean gerund)
{
- g_thread_init( NULL );
- gnome_init( "test-thread", "0.0", argc, argv );
- gtk_idle_add( (GtkFunction) queue_ops, NULL );
- gtk_main();
- return 0;
+ if (gerund)
+ return g_strdup ("Showing the Crawling Progress Bar of Doom");
+ else
+ return g_strdup ("Progress Bar");
+}
+
+static gchar *desc_2 (gpointer in, gboolean gerund)
+{
+ if (gerund)
+ return g_strdup ("Exploring the Mysterious Message Setter");
+ else
+ return g_strdup ("Explore");
+}
+
+static gchar *desc_3 (gpointer in, gboolean gerund)
+{
+ if (gerund)
+ return g_strdup ("Dare the Error Dialog of No Return");
+ else
+ return g_strdup ("Dare");
+}
+
+static gchar *desc_4 (gpointer in, gboolean gerund)
+{
+ if (gerund)
+ return g_strdup_printf ("Filling Queue Space -- %d", GPOINTER_TO_INT (in));
+ else
+ return g_strdup_printf ("Filler -- %d", GPOINTER_TO_INT (in));
+}
+
+static gchar *desc_5 (gpointer in, gboolean gerund)
+{
+ if (gerund)
+ return g_strdup ("Stealing your Password");
+ else
+ return g_strdup ("The Dastardly Password Stealer");
+}
+
+static gchar *desc_6 (gpointer in, gboolean gerund)
+{
+ if (gerund)
+ return g_strdup ("Setting exception on setup");
+ else
+ return g_strdup ("Exception on setup");
+}
+
+static gchar *desc_7 (gpointer in, gboolean gerund)
+{
+ if (gerund)
+ return g_strdup ("Setting exception in process");
+ else
+ return g_strdup ("Exception coming soon");
+}
+
+static gchar *desc_8 (gpointer in, gboolean gerund)
+{
+ if (gerund)
+ return g_strdup ("Setting exception in cleanup");
+ else
+ return g_strdup ("Exception in cleanup");
}
-#else
int main( int argc, char **argv )
{
- g_message( "Threads aren't enabled, so they cannot be tested." );
+ g_thread_init( NULL );
+ gnome_init( "test-thread", "0.0", argc, argv );
+ gtk_idle_add( (GtkFunction) queue_ops, NULL );
+ gtk_main();
return 0;
}
-
-#endif