From 3a8716453e0fa5b1c4a1e0ee28f6d7f4cc3d44df Mon Sep 17 00:00:00 2001 From: Pierre Pronchery Date: Mon, 18 Sep 2006 23:21:37 +0000 Subject: [PATCH] Sending mails progressively --- src/callbacks.c | 51 +++++++++++++++++++++++++++++++++++++++ src/callbacks.h | 6 +++++ src/compose.c | 63 ++++++++++++++++++++++++++++++------------------- src/compose.h | 10 ++++++++ 4 files changed, 106 insertions(+), 24 deletions(-) diff --git a/src/callbacks.c b/src/callbacks.c index 71a66d1..127daaa 100644 --- a/src/callbacks.c +++ b/src/callbacks.c @@ -2,7 +2,10 @@ +#include #include +#include +#include #include "compose.h" #include "mailer.h" #include "callbacks.h" @@ -153,3 +156,51 @@ void on_compose_help_about(GtkWidget * widget, gpointer data) on_help_about(widget, c->mailer); } + + +/* send mail */ +gboolean on_send_closex(GtkWidget * widget, GdkEvent * event, gpointer data) +{ + Compose * c = data; + + on_send_cancel(widget, c); + return FALSE; +} + + +void on_send_cancel(GtkWidget * widget, gpointer data) +{ + Compose * c = data; + + g_io_channel_shutdown(c->channel, TRUE, NULL); + gtk_widget_destroy(c->snd_window); + free(c->buf); +} + + +gboolean on_send_write(GIOChannel * source, GIOCondition condition, + gpointer data) +{ + Compose * c = data; + gsize i; + + if((i = (c->buf_len - c->buf_pos) % 512) == 0) + i = 512; + if(g_io_channel_write_chars(source, &c->buf[c->buf_pos], i, &i, NULL) + != G_IO_STATUS_NORMAL) + { + mailer_error(c->mailer, strerror(errno), FALSE); + on_send_cancel(c->snd_window, c); + return FALSE; + } + c->buf_pos+=i; + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(c->snd_progress), + c->buf_pos / c->buf_len); + if(c->buf_pos >= c->buf_len) + { + on_send_cancel(c->snd_window, c); + compose_delete(c); + return FALSE; + } + return TRUE; +} diff --git a/src/callbacks.h b/src/callbacks.h index 09aa155..a9216ab 100644 --- a/src/callbacks.h +++ b/src/callbacks.h @@ -37,4 +37,10 @@ void on_compose_view_bcc(GtkWidget * widget, gpointer data); /* help menu */ void on_compose_help_about(GtkWidget * widget, gpointer data); +/* send mail */ +gboolean on_send_closex(GtkWidget * widget, GdkEvent * event, gpointer data); +void on_send_cancel(GtkWidget * widget, gpointer data); +gboolean on_send_write(GIOChannel * source, GIOCondition condition, + gpointer data); + #endif /* !MAILER_CALLBACKS_H */ diff --git a/src/compose.c b/src/compose.c index 19c4d71..5b6d5cf 100644 --- a/src/compose.c +++ b/src/compose.c @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -221,40 +222,54 @@ void compose_send(Compose * compose) _send_mail(compose, msg, msg_len); } g_free(body); - free(msg); } -static int _mail_child(int fdin[2]); +static int _mail_child(int fd[2]); static int _send_mail(Compose * compose, char * msg, size_t msg_len) { - int fdin[2]; - pid_t pid; - int status; - int ret = 0; + int fd[2]; + GtkWidget * hbox; + GtkWidget * widget; - if(pipe(fdin) != 0 || (pid = fork()) == -1) + if(pipe(fd) != 0 || (compose->pid = fork()) == -1) return mailer_error(compose->mailer, strerror(errno), 1); - if(pid == 0) - return _mail_child(fdin); - if(close(fdin[0]) != 0) + if(compose->pid == 0) + return _mail_child(fd); + if(close(fd[0]) != 0 || fcntl(fd[1], F_SETFL, O_NONBLOCK) == -1) mailer_error(compose->mailer, strerror(errno), 0); - /* FIXME send mail progressively */ - write(1, msg, msg_len); - if(write(fdin[1], msg, msg_len) != msg_len) - ret = mailer_error(compose->mailer, strerror(errno), 1); - if(close(fdin[1]) != 0) - mailer_error(compose->mailer, strerror(errno), 0); - if(waitpid(pid, &status, 0) != pid) - ret = mailer_error(compose->mailer, strerror(errno), 1); - else if(WIFEXITED(status)) - fprintf(stderr, "%s%s%d\n", "mailer: sendmail: ", - "Exited with error ", WEXITSTATUS(status)); - return ret; + compose->snd_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_transient_for(GTK_WINDOW(compose->snd_window), + GTK_WINDOW(compose->window)); + gtk_window_set_title(GTK_WINDOW(compose->snd_window), + "Sending mail..."); + g_signal_connect(G_OBJECT(compose->snd_window), "delete_event", + G_CALLBACK(on_send_closex), compose); + hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new("Progression: "), + FALSE, FALSE, 0); + compose->snd_progress = gtk_progress_bar_new(); + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(compose->snd_progress), + 0.0); + gtk_box_pack_start(GTK_BOX(hbox), compose->snd_progress, TRUE, TRUE, 0); + widget = gtk_button_new_from_stock(GTK_STOCK_CANCEL); + g_signal_connect(G_OBJECT(widget), "clicked", G_CALLBACK( + on_send_cancel), compose); + gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER(compose->snd_window), 4); + gtk_container_add(GTK_CONTAINER(compose->snd_window), hbox); + gtk_widget_show_all(compose->snd_window); + compose->fd = fd[1]; + compose->buf = msg; + compose->buf_len = msg_len; + compose->buf_pos = 0; + compose->channel = g_io_channel_unix_new(fd[1]); + g_io_add_watch(compose->channel, G_IO_OUT, on_send_write, compose); + return 0; } -static int _mail_child(int fdin[2]) +static int _mail_child(int fd[2]) { - if(close(fdin[1]) != 0 || close(0) != 0 || dup2(fdin[0], 0) == -1) + if(close(fd[1]) != 0 || close(0) != 0 || dup2(fd[0], 0) == -1) perror("mailer"); else { diff --git a/src/compose.h b/src/compose.h index d4c36ca..b40d2b1 100644 --- a/src/compose.h +++ b/src/compose.h @@ -13,6 +13,16 @@ typedef struct _Compose { Mailer * mailer; + /* sending mail */ + pid_t pid; + int fd; + char * buf; + size_t buf_len; + size_t buf_pos; + GIOChannel * channel; + GtkWidget * snd_window; + GtkWidget * snd_progress; + /* widgets */ GtkWidget * window; GtkWidget * from;