aboutsummaryrefslogtreecommitdiffstats
path: root/mail
diff options
context:
space:
mode:
author3 <NotZed@Ximian.com>2001-10-23 14:28:27 +0800
committerMichael Zucci <zucchi@src.gnome.org>2001-10-23 14:28:27 +0800
commit343f36cffe95db2943ba897b83bbb88a6c25c366 (patch)
tree251f60b25f8a089c66e18bfee088efe0aefa104e /mail
parent51d6b1c4eaf133c0aec1dd7413353e2ec1fac994 (diff)
downloadgsoc2013-evolution-343f36cffe95db2943ba897b83bbb88a6c25c366.tar.gz
gsoc2013-evolution-343f36cffe95db2943ba897b83bbb88a6c25c366.tar.zst
gsoc2013-evolution-343f36cffe95db2943ba897b83bbb88a6c25c366.zip
Completely re-done. We now hae a completely async dialogue when requested
2001-10-23 <NotZed@Ximian.com> * mail-session.c (get_password): Completely re-done. We now hae a completely async dialogue when requested from antoehr thread, and dont use gtk_main() if we can avoid it (which is normally the case). This stuff is only partially finished, and will mena the removal of the same from mail-mt.c, and the mail_user_message() code will be moved here and changed to work in a similar way. * mail-callbacks.c (empty_trash): Dont try and connect to remote stores just to get the trash. Also, always run empty trash async, and make sure we unref the trash. (empty_trash): Hmm, dont unref the trash, causes a problem on exit, i suspect something else is doing funky unrefs on it. * mail-tools.c (mail_tool_get_trash): Pass a 'connect' arg, tell it whether it should tryand connect or not to the parent service, if it isn't already connected. * component-factory.c (owner_unset_cb): Dont try wait_all here, could potentially deadlock. (idle_quit): Keep returning TRUE if we have outstanding processing. Note that this may busy-wait during exit processign with busy tasks :( (idle_quit): Keep calling ourselves till we no longer get called (i.e. gtk_main really quits). * mail-mt.c (mail_msg_active): New function, returns TRUE if events are still active/outstanding. (do_op_status): @$@$#@@!#@!! didn't unlock the mail_msg_lock if data->activity was NULL and we had no global_shell_client anymore! Also shortcut processing if this is going to be the case. (mail_msg_init): Setup a temporary other gui_port for redoing with new semantics password, user message and progress reporting. (mail_get_password): #ifdef'd out all this code temporarily, till it gets fully moved to mail-session.c 2001-10-22 <NotZed@Ximian.com> * component-factory.c (owner_set_cb): Dont call enable_interaction here. (interactive_cb): But here instead, let the shell tell us when its ok to go interactive. svn path=/trunk/; revision=13933
Diffstat (limited to 'mail')
-rw-r--r--mail/ChangeLog44
-rw-r--r--mail/component-factory.c46
-rw-r--r--mail/mail-callbacks.c18
-rw-r--r--mail/mail-mt.c192
-rw-r--r--mail/mail-mt.h1
-rw-r--r--mail/mail-session.c284
-rw-r--r--mail/mail-tools.c16
-rw-r--r--mail/mail-tools.h2
8 files changed, 487 insertions, 116 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index 1bef9ae40d..f4745073ea 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,3 +1,47 @@
+2001-10-23 <NotZed@Ximian.com>
+
+ * mail-session.c (get_password): Completely re-done. We now hae a
+ completely async dialogue when requested from antoehr thread, and
+ dont use gtk_main() if we can avoid it (which is normally the
+ case). This stuff is only partially finished, and will mena the
+ removal of the same from mail-mt.c, and the mail_user_message()
+ code will be moved here and changed to work in a similar way.
+
+ * mail-callbacks.c (empty_trash): Dont try and connect to remote
+ stores just to get the trash. Also, always run empty trash async,
+ and make sure we unref the trash.
+ (empty_trash): Hmm, dont unref the trash, causes a problem on
+ exit, i suspect something else is doing funky unrefs on it.
+
+ * mail-tools.c (mail_tool_get_trash): Pass a 'connect' arg, tell
+ it whether it should tryand connect or not to the parent service,
+ if it isn't already connected.
+
+ * component-factory.c (owner_unset_cb): Dont try wait_all here,
+ could potentially deadlock.
+ (idle_quit): Keep returning TRUE if we have outstanding
+ processing. Note that this may busy-wait during exit processign
+ with busy tasks :(
+ (idle_quit): Keep calling ourselves till we no longer get called
+ (i.e. gtk_main really quits).
+
+ * mail-mt.c (mail_msg_active): New function, returns TRUE if
+ events are still active/outstanding.
+ (do_op_status): @$@$#@@!#@!! didn't unlock the mail_msg_lock if
+ data->activity was NULL and we had no global_shell_client anymore!
+ Also shortcut processing if this is going to be the case.
+ (mail_msg_init): Setup a temporary other gui_port for redoing with
+ new semantics password, user message and progress reporting.
+ (mail_get_password): #ifdef'd out all this code temporarily, till
+ it gets fully moved to mail-session.c
+
+2001-10-22 <NotZed@Ximian.com>
+
+ * component-factory.c (owner_set_cb): Dont call enable_interaction
+ here.
+ (interactive_cb): But here instead, let the shell tell us when its
+ ok to go interactive.
+
2001-10-22 Jeffrey Stedfast <fejj@ximian.com>
* mail-format.c (write_one_text_plain_chunk): Oops, revert my
diff --git a/mail/component-factory.c b/mail/component-factory.c
index d6603cb9cc..c4be75f94d 100644
--- a/mail/component-factory.c
+++ b/mail/component-factory.c
@@ -718,8 +718,6 @@ owner_set_cb (EvolutionShellComponent *shell_component,
got_folder, standard_folders[i].folder, mail_thread_new));
}
- mail_session_enable_interaction (TRUE);
-
mail_autoreceive_setup ();
if (mail_config_is_corrupt ()) {
@@ -754,6 +752,12 @@ debug_cb (EvolutionShellComponent *shell_component, gpointer user_data)
}
static void
+interactive_cb (EvolutionShellComponent *shell_component, gboolean on, gpointer user_data)
+{
+ mail_session_enable_interaction(on);
+}
+
+static void
handle_external_uri_cb (EvolutionShellComponent *shell_component,
const char *uri,
void *data)
@@ -788,19 +792,32 @@ user_create_new_item_cb (EvolutionShellComponent *shell_component,
static gboolean
idle_quit (gpointer user_data)
{
- mail_msg_wait_all();
-
- if (e_list_length (folder_browser_factory_get_control_list ()))
- return TRUE;
-
- g_hash_table_foreach (storages_hash, free_storage, NULL);
- g_hash_table_destroy (storages_hash);
-
- mail_vfolder_shutdown ();
+ static int shutdown_vfolder = FALSE;
+ static int shutdown_shutdown = FALSE;
+ if (!shutdown_shutdown) {
+ if (e_list_length (folder_browser_factory_get_control_list ()))
+ return TRUE;
+
+ if (mail_msg_active(-1)) {
+ /* short sleep? */
+ return TRUE;
+ }
+
+ if (!shutdown_vfolder) {
+ shutdown_vfolder = TRUE;
+ mail_vfolder_shutdown();
+ return TRUE;
+ }
+
+ shutdown_shutdown = TRUE;
+ g_hash_table_foreach (storages_hash, free_storage, NULL);
+ g_hash_table_destroy (storages_hash);
+ }
+
gtk_main_quit ();
- return FALSE;
+ return TRUE;
}
static void owner_unset_cb (EvolutionShellComponent *shell_component, gpointer user_data);
@@ -814,6 +831,7 @@ static struct {
{ "owner_set", owner_set_cb, },
{ "owner_unset", owner_unset_cb, },
{ "debug", debug_cb, },
+ { "interactive", interactive_cb },
{ "destroy", owner_unset_cb, },
{ "handle_external_uri", handle_external_uri_cb, },
{ "user_create_new_item", user_create_new_item_cb }
@@ -830,14 +848,12 @@ owner_unset_cb (EvolutionShellComponent *shell_component, gpointer user_data)
if (mail_config_get_empty_trash_on_exit ())
empty_trash (NULL, NULL, NULL);
- mail_msg_wait_all();
-
unref_standard_folders ();
mail_importer_uninit ();
global_shell_client = NULL;
-
mail_session_enable_interaction (FALSE);
+
g_idle_add_full (G_PRIORITY_LOW, idle_quit, NULL, NULL);
}
diff --git a/mail/mail-callbacks.c b/mail/mail-callbacks.c
index 2b7176aef3..f2e9db08fe 100644
--- a/mail/mail-callbacks.c
+++ b/mail/mail-callbacks.c
@@ -2391,13 +2391,9 @@ empty_trash (BonoboUIComponent *uih, void *user_data, const char *path)
CamelFolder *vtrash;
FolderBrowser *fb;
CamelException ex;
- gboolean async;
fb = user_data ? FOLDER_BROWSER (user_data) : NULL;
- /* the only time all three args are NULL is for empty-on-exit */
- async = !(uih == NULL && fb == NULL && path == NULL);
-
if (fb && !confirm_expunge (fb))
return;
@@ -2415,13 +2411,10 @@ empty_trash (BonoboUIComponent *uih, void *user_data, const char *path)
/* make sure this store is a remote store */
if (provider->flags & CAMEL_PROVIDER_IS_STORAGE &&
provider->flags & CAMEL_PROVIDER_IS_REMOTE) {
- vtrash = mail_tool_get_trash (account->source->url, &ex);
+ vtrash = mail_tool_get_trash (account->source->url, FALSE, &ex);
if (vtrash) {
- if (async)
- mail_expunge_folder (vtrash, empty_trash_expunged_cb, NULL);
- else
- camel_folder_sync (vtrash, TRUE, NULL);
+ mail_expunge_folder (vtrash, empty_trash_expunged_cb, NULL);
}
}
}
@@ -2433,12 +2426,9 @@ empty_trash (BonoboUIComponent *uih, void *user_data, const char *path)
}
/* Now empty the local trash folder */
- vtrash = mail_tool_get_trash ("file:/", &ex);
+ vtrash = mail_tool_get_trash ("file:/", TRUE, &ex);
if (vtrash) {
- if (async)
- mail_expunge_folder (vtrash, empty_trash_expunged_cb, NULL);
- else
- camel_folder_sync (vtrash, TRUE, NULL);
+ mail_expunge_folder (vtrash, empty_trash_expunged_cb, NULL);
}
camel_exception_clear (&ex);
diff --git a/mail/mail-mt.c b/mail/mail-mt.c
index 2dd4109047..ab240d595f 100644
--- a/mail/mail-mt.c
+++ b/mail/mail-mt.c
@@ -35,6 +35,7 @@
/*#define MALLOC_CHECK*/
#define LOG_OPS
+#define LOG_LOCKS
#define d(x)
static void set_stop(int sensitive);
@@ -42,9 +43,13 @@ static void mail_enable_stop(void);
static void mail_disable_stop(void);
static void mail_operation_status(struct _CamelOperation *op, const char *what, int pc, void *data);
+#ifdef LOG_LOCKS
+#define MAIL_MT_LOCK(x) (log_locks?fprintf(log, "%ld: lock " # x "\n", pthread_self()):0, pthread_mutex_lock(&x))
+#define MAIL_MT_UNLOCK(x) (log_locks?fprintf(log, "%ld: unlock " # x "\n", pthread_self()): 0, pthread_mutex_unlock(&x))
+#else
#define MAIL_MT_LOCK(x) pthread_mutex_lock(&x)
#define MAIL_MT_UNLOCK(x) pthread_mutex_unlock(&x)
-
+#endif
extern EvolutionShellClient *global_shell_client;
/* background operation status stuff */
@@ -62,10 +67,11 @@ static GdkPixbuf *progress_icon[2] = { NULL, NULL };
/* mail_msg stuff */
#ifdef LOG_OPS
static FILE *log;
+static int log_ops, log_locks, log_init;
#endif
static unsigned int mail_msg_seq; /* sequence number of each message */
-static GHashTable *mail_msg_active; /* table of active messages, must hold mail_msg_lock to access */
+static GHashTable *mail_msg_active_table; /* table of active messages, must hold mail_msg_lock to access */
static pthread_mutex_t mail_msg_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t mail_msg_cond = PTHREAD_COND_INITIALIZER;
@@ -81,13 +87,26 @@ void *mail_msg_new(mail_msg_op_t *ops, EMsgPort *reply_port, size_t size)
MAIL_MT_LOCK(mail_msg_lock);
-#ifdef LOG_OPS
- if (log == NULL && getenv("EVOLUTION_MAIL_LOG_OPS") != NULL) {
+#if defined(LOG_OPS) || defined(LOG_LOCKS)
+ if (!log_init) {
time_t now = time(0);
+ log_init = TRUE;
+ log_ops = getenv("EVOLUTION_MAIL_LOG_OPS") != NULL;
+ log_locks = getenv("EVOLUTION_MAIL_LOG_LOCKS") != NULL;
log = fopen("evolution-mail-ops.log", "w+");
setvbuf(log, NULL, _IOLBF, 0);
fprintf(log, "Started evolution-mail: %s\n", ctime(&now));
+#ifdef LOG_OPS
+ if (log_ops)
+ fprintf(log, "Logging async operations\n");
+#endif
+#ifdef LOG_LOCKS
+ if (log_locks) {
+ fprintf(log, "Logging lock operations, mail_gui_thread = %ld\n\n", mail_gui_thread);
+ fprintf(log, "%ld: lock mail_msg_lock\n", pthread_self());
+ }
+#endif
g_warning("Logging mail operations to evolution-mail-ops.log");
}
#endif
@@ -99,12 +118,12 @@ void *mail_msg_new(mail_msg_op_t *ops, EMsgPort *reply_port, size_t size)
camel_exception_init(&msg->ex);
msg->priv = g_malloc0(sizeof(*msg->priv));
- g_hash_table_insert(mail_msg_active, (void *)msg->seq, msg);
+ g_hash_table_insert(mail_msg_active_table, (void *)msg->seq, msg);
d(printf("New message %p\n", msg));
#ifdef LOG_OPS
- if (log)
+ if (log_ops)
fprintf(log, "%p: New\n", msg);
#endif
MAIL_MT_UNLOCK(mail_msg_lock);
@@ -161,10 +180,10 @@ void mail_msg_free(void *msg)
MAIL_MT_LOCK(mail_msg_lock);
#ifdef LOG_OPS
- if (log)
+ if (log_ops)
fprintf(log, "%p: Free\n", msg);
#endif
- g_hash_table_remove(mail_msg_active, (void *)m->seq);
+ g_hash_table_remove(mail_msg_active_table, (void *)m->seq);
pthread_cond_broadcast(&mail_msg_cond);
/* We need to make sure we dont lose a reference here YUCK YUCK */
@@ -250,7 +269,7 @@ void mail_msg_cancel(unsigned int msgid)
struct _mail_msg *m;
MAIL_MT_LOCK(mail_msg_lock);
- m = g_hash_table_lookup(mail_msg_active, (void *)msgid);
+ m = g_hash_table_lookup(mail_msg_active_table, (void *)msgid);
if (m)
camel_operation_cancel(m->cancel);
@@ -268,32 +287,46 @@ void mail_msg_wait(unsigned int msgid)
if (ismain) {
MAIL_MT_LOCK(mail_msg_lock);
- m = g_hash_table_lookup(mail_msg_active, (void *)msgid);
+ m = g_hash_table_lookup(mail_msg_active_table, (void *)msgid);
while (m) {
MAIL_MT_UNLOCK(mail_msg_lock);
gtk_main_iteration();
MAIL_MT_LOCK(mail_msg_lock);
- m = g_hash_table_lookup(mail_msg_active, (void *)msgid);
+ m = g_hash_table_lookup(mail_msg_active_table, (void *)msgid);
}
MAIL_MT_UNLOCK(mail_msg_lock);
} else {
MAIL_MT_LOCK(mail_msg_lock);
- m = g_hash_table_lookup(mail_msg_active, (void *)msgid);
+ m = g_hash_table_lookup(mail_msg_active_table, (void *)msgid);
while (m) {
pthread_cond_wait(&mail_msg_cond, &mail_msg_lock);
- m = g_hash_table_lookup(mail_msg_active, (void *)msgid);
+ m = g_hash_table_lookup(mail_msg_active_table, (void *)msgid);
}
MAIL_MT_UNLOCK(mail_msg_lock);
}
}
+int mail_msg_active(unsigned int msgid)
+{
+ int active;
+
+ MAIL_MT_LOCK(mail_msg_lock);
+ if (msgid == (unsigned int)-1)
+ active = g_hash_table_size(mail_msg_active_table) > 0;
+ else
+ active = g_hash_table_lookup(mail_msg_active_table, (void *)msgid) != NULL;
+ MAIL_MT_UNLOCK(mail_msg_lock);
+
+ return active;
+}
+
void mail_msg_wait_all(void)
{
int ismain = pthread_self() == mail_gui_thread;
if (ismain) {
MAIL_MT_LOCK(mail_msg_lock);
- while (g_hash_table_size(mail_msg_active) > 0) {
+ while (g_hash_table_size(mail_msg_active_table) > 0) {
MAIL_MT_UNLOCK(mail_msg_lock);
gtk_main_iteration();
MAIL_MT_LOCK(mail_msg_lock);
@@ -301,7 +334,7 @@ void mail_msg_wait_all(void)
MAIL_MT_UNLOCK(mail_msg_lock);
} else {
MAIL_MT_LOCK(mail_msg_lock);
- while (g_hash_table_size(mail_msg_active) > 0) {
+ while (g_hash_table_size(mail_msg_active_table) > 0) {
pthread_cond_wait(&mail_msg_cond, &mail_msg_lock);
}
MAIL_MT_UNLOCK(mail_msg_lock);
@@ -310,6 +343,12 @@ void mail_msg_wait_all(void)
EMsgPort *mail_gui_port;
static GIOChannel *mail_gui_channel;
+static guint mail_gui_watch;
+
+EMsgPort *mail_gui_port2;
+static GIOChannel *mail_gui_channel2;
+static guint mail_gui_watch2;
+
EMsgPort *mail_gui_reply_port;
static GIOChannel *mail_gui_reply_channel;
@@ -333,7 +372,7 @@ mail_msgport_replied(GIOChannel *source, GIOCondition cond, void *d)
#endif
#ifdef LOG_OPS
- if (log)
+ if (log_ops)
fprintf(log, "%p: Replied to GUI thread\n", m);
#endif
@@ -360,7 +399,7 @@ mail_msgport_received(GIOChannel *source, GIOCondition cond, void *d)
#endif
#ifdef LOG_OPS
- if (log)
+ if (log_ops)
fprintf(log, "%p: Received at GUI thread\n", m);
#endif
@@ -378,6 +417,29 @@ mail_msgport_received(GIOChannel *source, GIOCondition cond, void *d)
return TRUE;
}
+/* Test code, lighterwight, more configurable calls */
+static gboolean
+mail_msgport_received2(GIOChannel *source, GIOCondition cond, void *d)
+{
+ EMsgPort *port = (EMsgPort *)d;
+ mail_msg_t *m;
+
+ while (( m = (mail_msg_t *)e_msgport_get(port))) {
+#ifdef LOG_OPS
+ if (log_ops)
+ fprintf(log, "%p: Received at GUI2 thread\n", m);
+#endif
+
+ if (m->ops->receive_msg)
+ m->ops->receive_msg(m);
+ else
+ mail_msg_free(m);
+ }
+
+ return TRUE;
+}
+
+
static void
mail_msg_destroy(EThread *e, EMsg *msg, void *data)
{
@@ -407,7 +469,7 @@ mail_msg_received(EThread *e, EMsg *msg, void *data)
char *text = m->ops->describe_msg(m, FALSE);
#ifdef LOG_OPS
- if (log)
+ if (log_ops)
fprintf(log, "%p: Received at thread %ld: '%s'\n", m, pthread_self(), text);
#endif
@@ -418,7 +480,7 @@ mail_msg_received(EThread *e, EMsg *msg, void *data)
}
#ifdef LOG_OPS
else
- if (log)
+ if (log_ops)
fprintf(log, "%p: Received at thread %ld\n", m, pthread_self());
#endif
@@ -457,7 +519,13 @@ void mail_msg_init(void)
mail_gui_port = e_msgport_new();
mail_gui_channel = g_io_channel_unix_new(e_msgport_fd(mail_gui_port));
- g_io_add_watch(mail_gui_channel, G_IO_IN, mail_msgport_received, mail_gui_port);
+ mail_gui_watch = g_io_add_watch(mail_gui_channel, G_IO_IN, mail_msgport_received, mail_gui_port);
+
+ /* experimental temporary */
+ mail_gui_port2 = e_msgport_new();
+ mail_gui_channel2 = g_io_channel_unix_new(e_msgport_fd(mail_gui_port2));
+ mail_gui_watch2 = g_io_add_watch(mail_gui_channel2, G_IO_IN, mail_msgport_received2, mail_gui_port2);
+
mail_thread_queued = e_thread_new(E_THREAD_QUEUE);
e_thread_set_msg_destroy(mail_thread_queued, mail_msg_destroy, 0);
@@ -475,7 +543,7 @@ void mail_msg_init(void)
e_thread_set_reply_port(mail_thread_new, mail_gui_reply_port);
e_thread_set_queue_limit(mail_thread_new, 10);
- mail_msg_active = g_hash_table_new(NULL, NULL);
+ mail_msg_active_table = g_hash_table_new(NULL, NULL);
mail_gui_thread = pthread_self();
mail_async_event = mail_async_event_new();
@@ -488,6 +556,13 @@ static pthread_mutex_t status_lock = PTHREAD_MUTEX_INITIALIZER;
/* ********************************************************************** */
+#if 0
+static GnomeDialog *password_dialogue = NULL;
+static EDList password_list = E_DLIST_INITIALISER(password_list);
+static struct _pass_msg *password_current = NULL;
+
+static void do_get_pass (struct _mail_msg *mm);
+
struct _pass_msg {
struct _mail_msg msg;
const char *prompt;
@@ -496,12 +571,15 @@ struct _pass_msg {
char *result;
char *service_url;
GtkWidget *check;
+ int inmain;
};
static void
pass_got (char *string, void *data)
{
struct _pass_msg *m = data;
+
+ printf("password got! string = '%s'\n", string?string:"<nil>");
if (string) {
MailConfigService *service = NULL;
@@ -533,6 +611,18 @@ pass_got (char *string, void *data)
if (m->cache)
*(m->cache) = remember;
+
+ }
+
+ if (!m->inmain)
+ e_msgport_reply((EMsg *)m);
+
+ password_dialogue = NULL;
+
+ m = e_dlist_remhead(&password_list);
+ if (m) {
+ printf("Have queued password request, showing now the other is finished\n");
+ do_get_pass(m);
}
}
@@ -546,10 +636,17 @@ do_get_pass (struct _mail_msg *mm)
GList *children, *iter;
gboolean show;
char *title;
-
+
+ /* If we already have a password_dialogue up, save this request till later */
+ if (!m->inmain && password_dialogue) {
+ e_dlist_addtail(&password_list, (EDListNode *)mm);
+ return;
+ }
+
+ password_current = m;
+
/* this api is just awful ... hence the hacks */
- dialogue = gnome_request_dialog (m->secret, m->prompt, NULL,
- 0, pass_got, m, NULL);
+ dialogue = gnome_request_dialog (m->secret, m->prompt, NULL, 0, pass_got, m, NULL);
/* Remember the password? */
check = gtk_check_button_new_with_label (m->service_url ? _("Remember this password") :
@@ -577,14 +674,12 @@ do_get_pass (struct _mail_msg *mm)
/* do some dirty stuff to put the checkbutton after the entry */
entry = NULL;
children = gtk_container_children (GTK_CONTAINER (GNOME_DIALOG (dialogue)->vbox));
-
for (iter = children; iter; iter = iter->next) {
if (GTK_IS_ENTRY (iter->data)) {
entry = GTK_WIDGET (iter->data);
break;
}
}
-
g_list_free (children);
if (entry) {
@@ -592,8 +687,7 @@ do_get_pass (struct _mail_msg *mm)
gtk_container_remove (GTK_CONTAINER (GNOME_DIALOG (dialogue)->vbox), entry);
}
- gtk_box_pack_end (GTK_BOX (GNOME_DIALOG (dialogue)->vbox),
- check, TRUE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (GNOME_DIALOG (dialogue)->vbox), check, TRUE, FALSE, 0);
if (entry) {
gtk_box_pack_end (GTK_BOX (GNOME_DIALOG (dialogue)->vbox), entry, TRUE, FALSE, 0);
@@ -617,10 +711,16 @@ do_get_pass (struct _mail_msg *mm)
gtk_window_set_title (GTK_WINDOW (dialogue), title);
g_free (title);
-
- gnome_dialog_run_and_close ((GnomeDialog *)dialogue);
-
- /*gtk_widget_show(dialogue);*/
+
+ if (m->inmain) {
+ printf("showing dialogue in main\n");
+ password_current = NULL;
+ gnome_dialog_run_and_close ((GnomeDialog *)dialogue);
+ e_msgport_reply((EMsg *)m);
+ } else {
+ printf("showing dialogue async\n");
+ gtk_widget_show(dialogue);
+ }
}
static void
@@ -653,23 +753,19 @@ mail_get_password (CamelService *service, const char *prompt, gboolean secret, g
m->prompt = prompt;
m->secret = secret;
m->cache = cache;
+ m->inmain = pthread_self() == mail_gui_thread;
if (service) {
m->service_url = camel_url_to_string (service->url, CAMEL_URL_HIDE_ALL);
} else
m->service_url = NULL;
- if (pthread_self () == mail_gui_thread) {
+ if (m->inmain) {
do_get_pass ((struct _mail_msg *)m);
r = m;
} else {
- static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
-
- /* we want this single-threaded, this is the easiest way to do it without blocking ? */
- pthread_mutex_lock (&lock);
- e_msgport_put (mail_gui_port, (EMsg *)m);
+ e_msgport_put (mail_gui_port2, (EMsg *)m);
e_msgport_wait (pass_reply);
r = (struct _pass_msg *)e_msgport_get (pass_reply);
- pthread_mutex_unlock (&lock);
}
g_assert (r == m);
@@ -682,6 +778,7 @@ mail_get_password (CamelService *service, const char *prompt, gboolean secret, g
return ret;
}
+#endif
/* ******************** */
@@ -948,7 +1045,6 @@ void *mail_call_main(mail_call_t type, MailMainFunc func, ...)
return ret;
}
-
/* ********************************************************************** */
/* locked via status_lock */
static int busy_state;
@@ -1015,8 +1111,10 @@ static void do_op_status(struct _mail_msg *mm)
MAIL_MT_LOCK (mail_msg_lock);
- msg = g_hash_table_lookup (mail_msg_active, m->data);
- if (msg == NULL) {
+ msg = g_hash_table_lookup (mail_msg_active_table, m->data);
+
+ /* shortcut processing, i.e. if we have no global_shell_client and no activity, we can't create one */
+ if (msg == NULL || (msg->priv->activity == NULL && global_shell_client == NULL)) {
MAIL_MT_UNLOCK (mail_msg_lock);
return;
}
@@ -1092,15 +1190,15 @@ static void do_op_status(struct _mail_msg *mm)
}
return;
}
- }
-
- activity = data->activity;
- if (activity) {
+ } else if (data->activity) {
+ activity = data->activity;
gtk_object_ref (GTK_OBJECT (activity));
MAIL_MT_UNLOCK (mail_msg_lock);
-
+
evolution_activity_client_update (activity, out, (double)(pc/100.0));
gtk_object_unref (GTK_OBJECT (activity));
+ } else {
+ MAIL_MT_UNLOCK (mail_msg_lock);
}
}
diff --git a/mail/mail-mt.h b/mail/mail-mt.h
index e3aebab7c5..96561d70ee 100644
--- a/mail/mail-mt.h
+++ b/mail/mail-mt.h
@@ -58,6 +58,7 @@ void mail_msg_check_error(void *msg);
void mail_msg_cancel(unsigned int msgid);
void mail_msg_wait(unsigned int msgid);
void mail_msg_wait_all(void);
+int mail_msg_active(unsigned int msgid);
/* request a string/password */
char *mail_get_password (CamelService *service, const char *prompt,
diff --git a/mail/mail-session.c b/mail/mail-session.c
index 0101845f74..36dcb1e3be 100644
--- a/mail/mail-session.c
+++ b/mail/mail-session.c
@@ -39,6 +39,8 @@
#include "mail-mt.h"
#include "e-util/e-passwords.h"
+#define d(x)
+
CamelSession *session;
@@ -130,55 +132,267 @@ make_key (CamelService *service, const char *item)
return key;
}
-static char *
-main_get_password (CamelSession *session, const char *prompt, gboolean secret,
- CamelService *service, const char *item, CamelException *ex)
+/* ********************************************************************** */
+
+static GnomeDialog *password_dialogue = NULL;
+static EDList password_list = E_DLIST_INITIALISER(password_list);
+static struct _pass_msg *password_current = NULL;
+static int password_destroy_id;
+
+struct _pass_msg {
+ struct _mail_msg msg;
+
+ CamelSession *session;
+ const char *prompt;
+ gboolean secret;
+ CamelService *service;
+ const char *item;
+ CamelException *ex;
+
+ char *service_url;
+ char *key;
+
+ GtkWidget *check;
+ char *result;
+ int ismain;
+};
+
+static void do_get_pass(struct _mail_msg *mm);
+
+static void
+pass_got (char *string, void *data)
{
- MailSession *mail_session = MAIL_SESSION (session);
- gboolean cache = TRUE;
- char *key, *ans;
-
- if (!strcmp (item, "popb4smtp_uri")) {
- char *url = camel_url_to_string(service->url, 0);
- const MailConfigAccount *account = mail_config_get_account_by_transport_url(url);
+ struct _pass_msg *m = data;
+
+ if (string) {
+ MailConfigService *service = NULL;
+ const MailConfigAccount *mca;
+ gboolean remember;
- g_free(url);
- if (account == NULL)
- return NULL;
+ m->result = g_strdup (string);
+ remember = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (m->check));
+ if (m->service_url) {
+ mca = mail_config_get_account_by_source_url (m->service_url);
+ if (mca) {
+ service = mca->source;
+ } else {
+ mca = mail_config_get_account_by_transport_url (m->service_url);
+ if (mca)
+ service = mca->transport;
+ }
+
+ if (service) {
+ mail_config_service_set_save_passwd (service, remember);
+
+ /* set `remember' to TRUE because people don't want to have to
+ re-enter their passwords for this session even if they told
+ us not to cache their passwords in the dialog...*sigh* */
+ remember = TRUE;
+ }
+ }
- return g_strdup(account->source->url);
+ if (remember)
+ e_passwords_add_password(m->key, m->result);
+ } else {
+ camel_exception_set(m->ex, CAMEL_EXCEPTION_USER_CANCEL, _("User canceled operation."));
}
-
- key = make_key (service, item);
- if (!key)
- return NULL;
- ans = e_passwords_get_password (key);
- if (ans) {
- g_free (key);
- return ans;
+ if (password_destroy_id) {
+ gtk_signal_disconnect((GtkObject *)password_dialogue, password_destroy_id);
+ password_destroy_id = 0;
}
+
+ password_dialogue = NULL;
+ e_msgport_reply((EMsg *)m);
+
+ if ((m = (struct _pass_msg *)e_dlist_remhead(&password_list)))
+ do_get_pass((struct _mail_msg *)m);
+}
+
+static void
+request_password_deleted(GtkWidget *w, struct _pass_msg *m)
+{
+ password_destroy_id = 0;
+ pass_got(NULL, m);
+}
+
+static void
+request_password(struct _pass_msg *m)
+{
+ const MailConfigAccount *mca = NULL;
+ GtkWidget *dialogue;
+ GtkWidget *check, *entry;
+ GList *children, *iter;
+ gboolean show;
+ char *title;
+
+ /* If we already have a password_dialogue up, save this request till later */
+ if (!m->ismain && password_dialogue) {
+ e_dlist_addtail(&password_list, (EDListNode *)m);
+ return;
+ }
+
+ password_current = m;
+
+ /* FIXME: Remove this total snot */
+
+ /* this api is just awful ... hence the major hacks */
+ password_dialogue = dialogue = gnome_request_dialog (m->secret, m->prompt, NULL, 0, pass_got, m, NULL);
+
+ /* cant bleieve how @!@#!@# 5this api is, it doesn't handle this for you, BLAH! */
+ password_destroy_id = gtk_signal_connect((GtkObject *)dialogue, "destroy", request_password_deleted, m);
+
+ /* Remember the password? */
+ check = gtk_check_button_new_with_label (m->service_url ? _("Remember this password") :
+ _("Remember this password for the remainder of this session"));
+ show = TRUE;
- if (!mail_session->interaction_enabled ||
- !(ans = mail_get_password (service, prompt, secret, &cache))) {
- g_free (key);
- camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
- _("User canceled operation."));
- return NULL;
+ if (m->service_url) {
+ mca = mail_config_get_account_by_source_url(m->service_url);
+ if (mca)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), mca->source->save_passwd);
+ else {
+ mca = mail_config_get_account_by_transport_url (m->service_url);
+ if (mca)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), mca->transport->save_passwd);
+ else {
+ d(printf ("Cannot figure out which account owns URL \"%s\"\n", m->service_url));
+ show = FALSE;
+ }
+ }
}
- if (cache)
- e_passwords_add_password (key, ans);
+ if (show)
+ gtk_widget_show (check);
+
+ /* do some dirty stuff to put the checkbutton after the entry */
+ entry = NULL;
+ children = gtk_container_children (GTK_CONTAINER (GNOME_DIALOG (dialogue)->vbox));
+ for (iter = children; iter; iter = iter->next) {
+ if (GTK_IS_ENTRY (iter->data)) {
+ entry = GTK_WIDGET (iter->data);
+ break;
+ }
+ }
+ g_list_free (children);
+
+ if (entry) {
+ gtk_object_ref (GTK_OBJECT (entry));
+ gtk_container_remove (GTK_CONTAINER (GNOME_DIALOG (dialogue)->vbox), entry);
+ }
+
+ gtk_box_pack_end (GTK_BOX (GNOME_DIALOG (dialogue)->vbox), check, TRUE, FALSE, 0);
+
+ if (entry) {
+ gtk_box_pack_end (GTK_BOX (GNOME_DIALOG (dialogue)->vbox), entry, TRUE, FALSE, 0);
+ gtk_widget_grab_focus (entry);
+ gtk_object_unref (GTK_OBJECT (entry));
+ }
+
+ m->check = check;
+
+ if (mca) {
+ char *name;
+
+ name = e_utf8_to_gtk_string (GTK_WIDGET (dialogue), mca->name);
+ title = g_strdup_printf (_("Enter Password for %s"), name);
+ g_free (name);
+ } else
+ title = g_strdup (_("Enter Password"));
+
+ gtk_window_set_title (GTK_WINDOW (dialogue), title);
+ g_free (title);
+
+ if (m->ismain) {
+ password_current = NULL;
+ gnome_dialog_run_and_close ((GnomeDialog *)dialogue);
+ } else {
+ gtk_widget_show(dialogue);
+ }
+}
+
+static void
+do_get_pass(struct _mail_msg *mm)
+{
+ struct _pass_msg *m = (struct _pass_msg *)mm;
+ MailSession *mail_session = MAIL_SESSION (m->session);
+
+ if (!strcmp (m->item, "popb4smtp_uri")) {
+ char *url = camel_url_to_string(m->service->url, 0);
+ const MailConfigAccount *account = mail_config_get_account_by_transport_url(url);
+
+ g_free(url);
+ if (account)
+ m->result = g_strdup(account->source->url);
+ } else if (m->key) {
+ m->result = e_passwords_get_password(m->key);
+ if (m->result == NULL) {
+ if (mail_session->interaction_enabled) {
+ request_password(m);
+ return;
+ }
+ }
+ }
+
+ e_msgport_reply((EMsg *)mm);
+}
- return ans;
+static void
+do_free_pass(struct _mail_msg *mm)
+{
+ struct _pass_msg *m = (struct _pass_msg *)mm;
+
+ g_free(m->service_url);
+ g_free(m->key);
}
+static struct _mail_msg_op get_pass_op = {
+ NULL,
+ do_get_pass,
+ NULL,
+ do_free_pass,
+};
+
static char *
-get_password (CamelSession *session, const char *prompt, gboolean secret,
- CamelService *service, const char *item, CamelException *ex)
+get_password (CamelSession *session, const char *prompt, gboolean secret, CamelService *service, const char *item, CamelException *ex)
{
- return (char *)mail_call_main(MAIL_CALL_p_ppippp, (MailMainFunc)main_get_password,
- session, prompt, secret, service, item, ex);
+ struct _pass_msg *m, *r;
+ EMsgPort *pass_reply;
+ char *ret;
+
+ /* We setup an async request and send it off, and wait for it to return */
+ /* If we're really in main, we dont of course ...
+ ... but this shouldn't be allowed because of locking issues */
+ pass_reply = e_msgport_new ();
+ m = mail_msg_new(&get_pass_op, pass_reply, sizeof(struct _pass_msg));
+ m->ismain = pthread_self() == mail_gui_thread;
+ m->session = session;
+ m->prompt = prompt;
+ m->secret = secret;
+ m->service = service;
+ m->item = item;
+ m->ex = ex;
+ if (service)
+ m->service_url = camel_url_to_string (service->url, CAMEL_URL_HIDE_ALL);
+ m->key = make_key(service, item);
+
+ if (m->ismain)
+ do_get_pass(m);
+ else {
+ extern EMsgPort *mail_gui_port2;
+
+ e_msgport_put(mail_gui_port2, (EMsg *)m);
+ }
+
+ e_msgport_wait(pass_reply);
+ r = (struct _pass_msg *)e_msgport_get(pass_reply);
+ g_assert(m == r);
+
+ ret = m->result;
+ mail_msg_free(m);
+ e_msgport_destroy(pass_reply);
+
+ return ret;
}
static void
diff --git a/mail/mail-tools.c b/mail/mail-tools.c
index 96ef278567..383060d2b8 100644
--- a/mail/mail-tools.c
+++ b/mail/mail-tools.c
@@ -93,16 +93,24 @@ mail_tool_get_inbox (const gchar *url, CamelException *ex)
}
CamelFolder *
-mail_tool_get_trash (const gchar *url, CamelException *ex)
+mail_tool_get_trash (const gchar *url, int connect, CamelException *ex)
{
CamelStore *store;
CamelFolder *trash;
-
- store = camel_session_get_store (session, url, ex);
+
+ if (connect)
+ store = camel_session_get_store (session, url, ex);
+ else
+ store = (CamelStore *)camel_session_get_service(session, url, CAMEL_PROVIDER_STORE, ex);
+
if (!store)
return NULL;
- trash = camel_store_get_trash (store, ex);
+ if (connect || ((CamelService *)store)->status == CAMEL_SERVICE_CONNECTED)
+ trash = camel_store_get_trash (store, ex);
+ else
+ trash = NULL;
+
camel_object_unref (CAMEL_OBJECT (store));
return trash;
diff --git a/mail/mail-tools.h b/mail/mail-tools.h
index d19d6553ca..37afb8666c 100644
--- a/mail/mail-tools.h
+++ b/mail/mail-tools.h
@@ -47,7 +47,7 @@ CamelFolder *mail_tool_get_local_inbox (CamelException *ex);
CamelFolder *mail_tool_get_inbox (const gchar *url, CamelException *ex);
/* Get the "trash" for a url (uses global session) */
-CamelFolder *mail_tool_get_trash (const gchar *url, CamelException *ex);
+CamelFolder *mail_tool_get_trash (const gchar *url, int connect, CamelException *ex);
/* Does a camel_movemail into the local movemail folder
* and returns the path to the new movemail folder that was created. which shoudl be freed later */