From 351903ad90942abecccf363f97a6639c74ef2e58 Mon Sep 17 00:00:00 2001 From: Not Zed Date: Thu, 22 Feb 2001 22:27:40 +0000 Subject: Make op cancellable/report internals. (get_folder_get): 2001-02-23 Not Zed * mail-ops.c (create_folder_get): Make op cancellable/report internals. (get_folder_get): (sync_folder_sync): (get_folderinfo_get): Make op cancellable/report internals. * mail-vtrash.c (get_trash_get): Setup the operation registration, and create a pseudo "start/stop" operation. * component-factory.c (owner_set_cb): Make trash creation async. * mail-local.c (register_folder_desc): A description of what we're doing. * mail-mt.c (mail_msg_new): Set status callback to operation_new. (mail_operation_status): Operation status function, proxy messages to main thread, and attempt to present a meaningful ui experience for operations. svn path=/trunk/; revision=8351 --- mail/ChangeLog | 21 +++++ mail/component-factory.c | 2 +- mail/mail-local.c | 21 +++-- mail/mail-mt.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++- mail/mail-mt.h | 1 + mail/mail-ops.c | 10 +++ mail/mail-vtrash.c | 40 ++++++---- 7 files changed, 267 insertions(+), 31 deletions(-) (limited to 'mail') diff --git a/mail/ChangeLog b/mail/ChangeLog index f38dbdf3a7..69bddff9d7 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,24 @@ +2001-02-23 Not Zed + + * mail-ops.c (create_folder_get): Make op cancellable/report + internals. + (get_folder_get): + (sync_folder_sync): + (get_folderinfo_get): Make op cancellable/report internals. + + * mail-vtrash.c (get_trash_get): Setup the operation registration, + and create a pseudo "start/stop" operation. + + * component-factory.c (owner_set_cb): Make trash creation async. + + * mail-local.c (register_folder_desc): A description of what we're + doing. + + * mail-mt.c (mail_msg_new): Set status callback to operation_new. + (mail_operation_status): Operation status function, proxy messages + to main thread, and attempt to present a meaningful ui experience + for operations. + 2001-02-22 Jeffrey Stedfast * openpgp-utils.c (openpgp_verify): Fixed memory corruption bug. diff --git a/mail/component-factory.c b/mail/component-factory.c index 762ec0764b..34a0e64d4a 100644 --- a/mail/component-factory.c +++ b/mail/component-factory.c @@ -215,7 +215,7 @@ owner_set_cb (EvolutionShellComponent *shell_component, g_free (uri); } - mail_msg_wait (vtrash_create ("file:/", NULL, NULL)); + vtrash_create ("file:/", NULL, NULL); mail_session_enable_interaction (TRUE); diff --git a/mail/mail-local.c b/mail/mail-local.c index eba6f36992..f27778aaac 100644 --- a/mail/mail-local.c +++ b/mail/mail-local.c @@ -445,6 +445,14 @@ struct _register_msg { MailLocalFolder *local_folder; }; +static char *register_folder_desc(struct _mail_msg *mm, int done) +{ + struct _register_msg *m = (struct _register_msg *)mm; + + printf("returning description for %s\n", m->local_folder->uri); + + return g_strdup_printf(_("Opening '%s'"), m->local_folder->uri); +} static void register_folder_register(struct _mail_msg *mm) @@ -488,7 +496,7 @@ register_folder_register(struct _mail_msg *mm) camel_object_unref (CAMEL_OBJECT (store)); free_metainfo (meta); - camel_operation_register(mm->cancel); + camel_operation_unregister(mm->cancel); } static void @@ -518,17 +526,12 @@ register_folder_free(struct _mail_msg *mm) } static struct _mail_msg_op register_folder_op = { - NULL, + register_folder_desc, register_folder_register, register_folder_registered, register_folder_free, }; -static void new_status(struct _CamelOperation *op, const char *what, int pc, void *data) -{ - printf("oepration %s %d %% complete\n", what, pc); -} - static void local_storage_new_folder_cb (EvolutionStorageListener *storage_listener, const char *path, @@ -557,10 +560,6 @@ local_storage_new_folder_cb (EvolutionStorageListener *storage_listener, m->local_folder = local_folder; - /* HACK: so we reuse the cancel pointer */ - camel_operation_unref(m->msg.cancel); - m->msg.cancel = camel_operation_new(new_status, m); - /* run synchronous, the shell expects it (I think) */ id = m->msg.seq; e_thread_put(mail_thread_queued, (EMsg *)m); diff --git a/mail/mail-mt.c b/mail/mail-mt.c index 72af0f750d..991d1cf33e 100644 --- a/mail/mail-mt.c +++ b/mail/mail-mt.c @@ -17,17 +17,35 @@ #include "folder-browser-factory.h" +#include +#include + #define d(x) static void set_view_data(const char *current_message, int busy); static void set_stop(int sensitive); - 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); #define MAIL_MT_LOCK(x) pthread_mutex_lock(&x) #define MAIL_MT_UNLOCK(x) pthread_mutex_unlock(&x) +/* background operation status stuff */ +struct _mail_msg_priv { + GtkProgressBar *bar; + GtkLabel *label; + + /* for pending requests, before timeout_id is activated (then bar will be ! NULL) */ + char *what; + int pc; + int timeout_id; +}; + +static GtkWindow *progress_dialogue; +static int progress_row; + +/* mail_msg stuff */ 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 pthread_mutex_t mail_msg_lock = PTHREAD_MUTEX_INITIALIZER; @@ -45,8 +63,9 @@ void *mail_msg_new(mail_msg_op_t *ops, EMsgPort *reply_port, size_t size) msg->ops = ops; msg->seq = mail_msg_seq++; msg->msg.reply_port = reply_port; - msg->cancel = camel_operation_new(NULL, NULL); /* FIXME: report status somehow? */ + msg->cancel = camel_operation_new(mail_operation_status, (void *)msg->seq); camel_exception_init(&msg->ex); + msg->priv = g_malloc0(sizeof(*msg->priv)); g_hash_table_insert(mail_msg_active, (void *)msg->seq, msg); @@ -55,6 +74,15 @@ void *mail_msg_new(mail_msg_op_t *ops, EMsgPort *reply_port, size_t size) return msg; } +/* either destroy the progress (in event_data), or the whole dialogue (in data) */ +static void destroy_widgets(CamelObject *o, void *event_data, void *data) +{ + if (data) + gtk_widget_destroy((GtkWidget *)data); + if (event_data) + gtk_widget_destroy((GtkWidget *)event_data); +} + void mail_msg_free(void *msg) { struct _mail_msg *m = msg; @@ -67,10 +95,27 @@ void mail_msg_free(void *msg) g_hash_table_remove(mail_msg_active, (void *)m->seq); pthread_cond_broadcast(&mail_msg_cond); + /* this closes the bar, and/or the whole progress dialogue, once we're out of things to do */ + if (g_hash_table_size(mail_msg_active) == 0) { + if (progress_dialogue != NULL) { + void *data = progress_dialogue; + progress_dialogue = NULL; + progress_row = 0; + mail_proxy_event(destroy_widgets, NULL, data, NULL); + } + } else if (m->priv->bar) { + mail_proxy_event(destroy_widgets, NULL, m->priv->bar, m->priv->label); + } + + if (m->priv->timeout_id > 0) + gtk_timeout_remove(m->priv->timeout_id); + MAIL_MT_UNLOCK(mail_msg_lock); camel_operation_unref(m->cancel); camel_exception_clear(&m->ex); + g_free(m->priv->what); + g_free(m->priv); g_free(m); } @@ -628,6 +673,160 @@ static void mail_disable_stop(void) MAIL_MT_UNLOCK(status_lock); } +/* ******************************************************************************** */ + +struct _op_status_msg { + struct _mail_msg msg; + + struct _CamelOperation *op; + char *what; + int pc; + void *data; +}; + +GtkTable *progress_table; + +static int op_status_timeout(void *d) +{ + int id = (int)d; + struct _mail_msg *msg; + struct _mail_msg_priv *data; + + MAIL_MT_LOCK(mail_msg_lock); + + msg = g_hash_table_lookup(mail_msg_active, (void *)id); + if (msg == NULL) { + MAIL_MT_UNLOCK(mail_msg_lock); + return FALSE; + } + + data = msg->priv; + + if (progress_dialogue == NULL) { + progress_dialogue = (GtkWindow *)gtk_window_new(GTK_WINDOW_DIALOG); + gtk_window_set_title(progress_dialogue, _("Evolution progress")); + gtk_window_set_policy(progress_dialogue, 0, 0, 1); + gtk_window_set_position(progress_dialogue, GTK_WIN_POS_CENTER); + progress_table = (GtkTable *)gtk_table_new(1, 2, FALSE); + gtk_container_add((GtkContainer *)progress_dialogue, (GtkWidget *)progress_table); + } + + data->bar = (GtkProgressBar *)gtk_progress_bar_new(); + gtk_progress_set_show_text((GtkProgress *)data->bar, TRUE); + + gtk_progress_set_percentage((GtkProgress *)data->bar, (gfloat)(data->pc/100.0)); + gtk_progress_set_format_string((GtkProgress *)data->bar, data->what); + + if (msg->ops->describe_msg) { + char *desc = msg->ops->describe_msg(msg, FALSE); + data->label = (GtkLabel *)gtk_label_new(desc); + g_free(desc); + } else { + data->label = (GtkLabel *)gtk_label_new(_("Working")); + } + + gtk_table_attach(progress_table, (GtkWidget *)data->label, 0, 1, progress_row, progress_row+1, GTK_EXPAND|GTK_FILL, 0, 3, 1); + gtk_table_attach(progress_table, (GtkWidget *)data->bar, 1, 2, progress_row, progress_row+1, GTK_EXPAND|GTK_FILL, 0, 3, 1); + progress_row++; + + gtk_widget_show_all((GtkWidget *)progress_table); + gtk_widget_show((GtkWidget *)progress_dialogue); + + data->timeout_id = -1; + + MAIL_MT_UNLOCK(mail_msg_lock); + + return FALSE; +} + +static void do_op_status(struct _mail_msg *mm) +{ + struct _op_status_msg *m = (struct _op_status_msg *)mm; + struct _mail_msg *msg; + struct _mail_msg_priv *data; + char *out, *p, *o, c; + + g_assert(mail_gui_thread == pthread_self()); + + MAIL_MT_LOCK(mail_msg_lock); + + msg = g_hash_table_lookup(mail_msg_active, m->data); + if (msg == NULL) { + MAIL_MT_UNLOCK(mail_msg_lock); + return; + } + + data = msg->priv; + + out = alloca(strlen(m->what)*2+1); + o = out; + p = m->what; + while ((c = *p++)) { + if (c=='%') + *o++ = '%'; + *o++ = c; + } + *o = 0; + + if (data->timeout_id == 0) { + data->what = g_strdup(out); + data->pc = m->pc; + data->timeout_id = gtk_timeout_add(2000, op_status_timeout, m->data); + MAIL_MT_UNLOCK(mail_msg_lock); + return; + } + + if (data->bar == NULL) { + g_free(data->what); + data->what = g_strdup(out); + data->pc = m->pc; + MAIL_MT_UNLOCK(mail_msg_lock); + return; + } + + gtk_progress_set_percentage((GtkProgress *)data->bar, (gfloat)(m->pc/100.0)); + gtk_progress_set_format_string((GtkProgress *)data->bar, out); + + MAIL_MT_UNLOCK(mail_msg_lock); +} + +static void do_op_status_free(struct _mail_msg *mm) +{ + struct _op_status_msg *m = (struct _op_status_msg *)mm; + + g_free(m->what); +} + +struct _mail_msg_op op_status_op = { + NULL, + do_op_status, + NULL, + do_op_status_free, +}; + +static void +mail_operation_status(struct _CamelOperation *op, const char *what, int pc, void *data) +{ + struct _op_status_msg *m; + + printf("got operation statys: %s %d%%\n", what, pc); + + m = mail_msg_new(&op_status_op, NULL, sizeof(*m)); + m->op = op; + m->what = g_strdup(what); + switch (pc) { + case CAMEL_OPERATION_START: + pc = 0; + break; + case CAMEL_OPERATION_END: + pc = 100; + break; + } + m->pc = pc; + m->data = data; + e_msgport_put(mail_gui_port, (EMsg *)m); +} + /* ******************** */ /* FIXME FIXME FIXME This is a totally evil hack. */ diff --git a/mail/mail-mt.h b/mail/mail-mt.h index 935b4b15b8..cc9f1be756 100644 --- a/mail/mail-mt.h +++ b/mail/mail-mt.h @@ -35,6 +35,7 @@ typedef struct _mail_msg { unsigned int seq; /* seq number for synchronisation */ CamelOperation *cancel; /* a cancellation/status handle */ CamelException ex; /* an initialised camel exception, upto the caller to use this */ + struct _mail_msg_priv *priv; /* private for internal use */ } mail_msg_t; /* callback functions for thread message */ diff --git a/mail/mail-ops.c b/mail/mail-ops.c index f512c11e14..d0d8c930dc 100644 --- a/mail/mail-ops.c +++ b/mail/mail-ops.c @@ -928,7 +928,9 @@ static void get_folderinfo_get(struct _mail_msg *mm) { struct _get_folderinfo_msg *m = (struct _get_folderinfo_msg *)mm; + camel_operation_register(mm->cancel); m->info = camel_store_get_folder_info(m->store, NULL, FALSE, TRUE, TRUE, &mm->ex); + camel_operation_unregister(mm->cancel); } static void get_folderinfo_got(struct _mail_msg *mm) @@ -1079,7 +1081,9 @@ static void get_folder_get(struct _mail_msg *mm) { struct _get_folder_msg *m = (struct _get_folder_msg *)mm; + camel_operation_register(mm->cancel); m->folder = mail_tool_uri_to_folder(m->uri, &mm->ex); + camel_operation_unregister(mm->cancel); } static void get_folder_got(struct _mail_msg *mm) @@ -1144,7 +1148,9 @@ static void get_store_get(struct _mail_msg *mm) { struct _get_store_msg *m = (struct _get_store_msg *)mm; + camel_operation_register(mm->cancel); m->store = camel_session_get_store(session, m->uri, &mm->ex); + camel_operation_unregister(mm->cancel); } static void get_store_got(struct _mail_msg *mm) @@ -1214,9 +1220,11 @@ static void create_folder_get(struct _mail_msg *mm) struct _create_folder_msg *m = (struct _create_folder_msg *)mm; /* FIXME: supply a way to make indexes optional */ + camel_operation_register(mm->cancel); m->folder = mail_tool_get_folder_from_urlname(m->uri, "mbox", CAMEL_STORE_FOLDER_CREATE|CAMEL_STORE_FOLDER_BODY_INDEX, &mm->ex); + camel_operation_unregister(mm->cancel); } static void create_folder_got(struct _mail_msg *mm) @@ -1275,7 +1283,9 @@ static void sync_folder_sync(struct _mail_msg *mm) { struct _sync_folder_msg *m = (struct _sync_folder_msg *)mm; + camel_operation_register(mm->cancel); camel_folder_sync(m->folder, FALSE, &mm->ex); + camel_operation_unregister(mm->cancel); } static void sync_folder_synced(struct _mail_msg *mm) diff --git a/mail/mail-vtrash.c b/mail/mail-vtrash.c index ff76756e73..207e72ef06 100644 --- a/mail/mail-vtrash.c +++ b/mail/mail-vtrash.c @@ -55,22 +55,22 @@ extern CamelSession *session; CamelFolder * vtrash_uri_to_folder (const char *uri, CamelException *ex) { - CamelFolder *folder = NULL; - - g_return_val_if_fail (uri != NULL, NULL); - - if (strncmp (uri, "vtrash:", 7)) - return NULL; - - VTRASH_LOCK (vtrash_hash_lock); - if (vtrash_hash) { - folder = g_hash_table_lookup (vtrash_hash, uri); - - camel_object_ref (CAMEL_OBJECT (folder)); - } - VTRASH_UNLOCK (vtrash_hash_lock); - - return folder; + CamelFolder *folder = NULL; + + g_return_val_if_fail (uri != NULL, NULL); + + if (strncmp (uri, "vtrash:", 7)) + return NULL; + + VTRASH_LOCK (vtrash_hash_lock); + if (vtrash_hash) { + folder = g_hash_table_lookup (vtrash_hash, uri); + + camel_object_ref (CAMEL_OBJECT (folder)); + } + VTRASH_UNLOCK (vtrash_hash_lock); + + return folder; } static void @@ -207,7 +207,10 @@ get_trash_get (struct _mail_msg *mm) struct _get_trash_msg *m = (struct _get_trash_msg *)mm; CamelStore *store; GPtrArray *urls; - + + camel_operation_register(mm->cancel); + camel_operation_start(mm->cancel, _("Getting matches")); + urls = g_ptr_array_new (); /* we don't want to connect */ @@ -239,6 +242,9 @@ get_trash_get (struct _mail_msg *mm) vtrash_add (store, m->folder, m->store_uri, _("vTrash")); } } + + camel_operation_end(mm->cancel); + camel_operation_unregister(mm->cancel); } static void -- cgit v1.2.3