aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNot Zed <NotZed@Ximian.com>2001-02-23 06:27:40 +0800
committerMichael Zucci <zucchi@src.gnome.org>2001-02-23 06:27:40 +0800
commit351903ad90942abecccf363f97a6639c74ef2e58 (patch)
tree9ab0be988df48a43aac83f2a789a9918e24d2517
parent7698a3941bb5ad9faf3b5b4831e0400f81cc9b64 (diff)
downloadgsoc2013-evolution-351903ad90942abecccf363f97a6639c74ef2e58.tar.gz
gsoc2013-evolution-351903ad90942abecccf363f97a6639c74ef2e58.tar.zst
gsoc2013-evolution-351903ad90942abecccf363f97a6639c74ef2e58.zip
Make op cancellable/report internals. (get_folder_get):
2001-02-23 Not Zed <NotZed@Ximian.com> * 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
-rw-r--r--mail/ChangeLog21
-rw-r--r--mail/component-factory.c2
-rw-r--r--mail/mail-local.c21
-rw-r--r--mail/mail-mt.c203
-rw-r--r--mail/mail-mt.h1
-rw-r--r--mail/mail-ops.c10
-rw-r--r--mail/mail-vtrash.c40
7 files changed, 267 insertions, 31 deletions
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 <NotZed@Ximian.com>
+
+ * 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 <fejj@ximian.com>
* 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 <libgnomeui/gnome-dialog.h>
+#include <gtk/gtkprogress.h>
+
#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