[balsa] Enable multi-threaded POP3 retrieval
- From: Peter Bloomfield <peterb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [balsa] Enable multi-threaded POP3 retrieval
- Date: Fri, 5 Jan 2018 22:26:19 +0000 (UTC)
commit ba206693c53ab3b6b3103f2271adea2de4801032
Author: Albrecht Dreß <albrecht dress arcor de>
Date: Fri Jan 5 17:24:15 2018 -0500
Enable multi-threaded POP3 retrieval
* libbalsa/libbalsa-marshal.list, libbalsa/mailbox.[ch]:
new simplified signature for the mailbox 'progress-notify' signal
and the related helper libbalsa_mailbox_progress_notify()
* libbalsa/libbalsa-progress.[ch]: heavy re-factoring of the progress dialogue,
including a fully thread-safe interface, simplified access functions,
and a new activity mode
* libbalsa/mailbox_pop3.c, libbalsa/send.[ch]:
use new progress dialogue interface,
pass option to disable send progress dialogue
* src/balsa-app.[ch]: define and initialise enable progress dialogue settings,
use changed send function signature
* src/balsa-message.c, src/balsa-mime-widget-message.c,
src/balsa-mime-widget-vcalendar.c, src/sendmsg-window.c:
use changed send function signature
* src/main-window.[ch]: implement multi-threaded POP3 retrieval,
remove old progress implementation, use changed send function signature,
replace two-state enum by bool
* src/main.c: remove old progress implementation stuff
* src/pref-manager.c: replace progress dialogue settings
by two new bool values and related check boxes
* src/save-restore.c: save/restore new progress dialogue bool values
* src/threads.h: completely remove the file
Signed-off-by: Peter Bloomfield <PeterBloomfield bellsouth net>
ChangeLog | 27 +++
libbalsa/libbalsa-marshal.list | 3 +-
libbalsa/libbalsa-progress.c | 400 +++++++++++++++++++++++++------------
libbalsa/libbalsa-progress.h | 60 ++++---
libbalsa/mailbox.c | 28 ++-
libbalsa/mailbox.h | 21 +-
libbalsa/mailbox_pop3.c | 34 ++--
libbalsa/send.c | 69 +++----
libbalsa/send.h | 23 +-
src/balsa-app.c | 7 +-
src/balsa-app.h | 3 +-
src/balsa-message.c | 2 +
src/balsa-mime-widget-message.c | 1 +
src/balsa-mime-widget-vcalendar.c | 1 +
src/main-window.c | 394 ++++++++++++-------------------------
src/main-window.h | 8 +-
src/main.c | 39 +----
src/pref-manager.c | 41 +---
src/save-restore.c | 34 +---
src/sendmsg-window.c | 2 +-
src/threads.h | 60 ------
21 files changed, 578 insertions(+), 679 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index f82dffc..3e4466f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2018-01-05 Albrecht Dreß <albrecht dress arcor de>
+
+ Enable multi-threaded POP3 retrieval
+
+ * libbalsa/libbalsa-marshal.list, libbalsa/mailbox.[ch]:
+ new simplified signature for the mailbox '' signal
+ and the related helper libbalsa_mailbox_progress_notify()
+ * libbalsa/libbalsa-progress.[ch]: heavy re-factoring of the progress dialogue,
+ including a fully thread-safe interface, simplified access functions,
+ and a new activity mode
+ * libbalsa/mailbox_pop3.c, libbalsa/send.[ch]:
+ use new progress dialogue interface,
+ pass option to disable send progress dialogue
+ * src/balsa-app.[ch]: define and initialise enable progress dialogue settings,
+ use changed send function signature
+ * src/balsa-message.c, src/balsa-mime-widget-message.c,
+ src/balsa-mime-widget-vcalendar.c, src/sendmsg-window.c:
+ use changed send function signature
+ * src/main-window.[ch]: implement multi-threaded POP3 retrieval,
+ remove old progress implementation, use changed send function signature,
+ replace two-state enum by bool
+ * src/main.c: remove old progress implementation stuff
+ * src/pref-manager.c: replace progress dialogue settings
+ by two new bool values and related check boxes
+ * src/save-restore.c: save/restore new progress dialogue bool values
+ * src/threads.h: completely remove the file
+
2018-01-04 Peter Bloomfield <pbloomfield bellsouth net>
Fix a use-after-free bug
diff --git a/libbalsa/libbalsa-marshal.list b/libbalsa/libbalsa-marshal.list
index b670324..a382dfb 100644
--- a/libbalsa/libbalsa-marshal.list
+++ b/libbalsa/libbalsa-marshal.list
@@ -12,6 +12,7 @@ POINTER:OBJECT
POINTER:POINTER,POINTER
POINTER:VOID
VOID:INT,INT,INT
-VOID:INT,INT,INT,STRING
+VOID:INT,DOUBLE,STRING
+# VOID:INT,INT,INT,STRING
VOID:OBJECT,BOOLEAN
VOID:POINTER,INT
diff --git a/libbalsa/libbalsa-progress.c b/libbalsa/libbalsa-progress.c
index a7034e7..2192114 100644
--- a/libbalsa/libbalsa-progress.c
+++ b/libbalsa/libbalsa-progress.c
@@ -25,130 +25,202 @@
/* note: this value is forced as minimum and maximum width of the dialogue, which may be wrong for /very/
high-resolution screens */
#define PROGRESS_DIALOG_WIDTH 320
+#define FADER_DURATION 500U
+#define ACTIVITY_DURATION 100U
+typedef struct {
+ ProgressDialog *dialog;
+ const gchar *title;
+ GtkWindow *parent;
+ const gchar *id;
+ gboolean done;
+ GCond cond;
+} create_progress_dlg_t;
+
+
+typedef struct {
+ ProgressDialog *dialog;
+ gchar *id;
+ gboolean finished;
+ gchar *message;
+ gdouble fraction;
+} update_progress_data_t;
+
+
+typedef struct {
+ GtkWidget *revealer;
+ GtkWidget *progress;
+ GtkWidget *label;
+ guint activity_id;
+ guint fadeout_id;
+} progress_widget_data_t;
+
+
+static void libbalsa_progress_dialog_ensure_real(ProgressDialog *progress_dialog,
+ const gchar
*dialog_title,
+ GtkWindow
*parent,
+ const gchar
*progress_id);
+static gboolean libbalsa_progress_dialog_create_cb(create_progress_dlg_t *dlg_data);
+
static void progress_dialog_response_cb(GtkWidget *dialog,
gint response);
static void progress_dialog_destroy_cb(GtkWidget G_GNUC_UNUSED *widget,
- gpointer
user_data);
-static GtkWidget *find_widget_by_name(GtkContainer *container,
- const gchar *id);
-static GtkWidget *create_progress_widget(const gchar *progress_id,
- const gchar *title);
-static gboolean remove_progress_widget(gpointer user_data);
-static void send_progress_data_free(LibbalsaProgressData *progress_data);
+ ProgressDialog
*progress_dialog);
+static progress_widget_data_t *find_progress_data_by_name(GtkContainer *container,
+
const gchar *id);
+static GtkWidget *create_progress_widget(const gchar *progress_id)
+ G_GNUC_WARN_UNUSED_RESULT;
+static gboolean remove_progress_widget(progress_widget_data_t *progress_data);
+static void libbalsa_progress_dialog_update_real(ProgressDialog *progress_dialog,
+ const gchar
*progress_id,
+ gboolean
finished,
+ gdouble
fraction,
+ const gchar
*message);
+static gboolean libbalsa_progress_dialog_update_cb(update_progress_data_t *upd_data);
+static gboolean progress_activity(GtkProgressBar *progress);
+
+
+void
+libbalsa_progress_dialog_ensure(ProgressDialog *progress_dialog,
+ const gchar *dialog_title,
+ GtkWindow *parent,
+ const gchar *progress_id)
+{
+ g_return_if_fail((progress_dialog != NULL) && (dialog_title != NULL) && (progress_id != NULL));
+
+ g_mutex_lock(&progress_dialog->mutex);
+ if (libbalsa_am_i_subthread()) {
+ create_progress_dlg_t dlgdata;
+
+ /* shift the work to an idle callback, and return only after it has been run */
+ dlgdata.dialog = progress_dialog;
+ dlgdata.title = dialog_title;
+ dlgdata.parent = parent;
+ dlgdata.id = progress_id;
+ dlgdata.done = FALSE;
+ g_cond_init(&dlgdata.cond);
+ gdk_threads_add_idle((GSourceFunc) libbalsa_progress_dialog_create_cb, &dlgdata);
+
+ while (!dlgdata.done) {
+ g_cond_wait(&dlgdata.cond, &progress_dialog->mutex);
+ }
+ g_cond_clear(&dlgdata.cond);
+ } else {
+ libbalsa_progress_dialog_ensure_real(progress_dialog, dialog_title, parent, progress_id);
+ }
-/* While libbalsa_progress_dialog_update() will always be called from the main context (typically from an
idle callback),
- * libbalsa_progress_dialog_ensure /may/ also be called from a thread, so we must ensure the integrity of
the progress dialogue
- * widget. As both functions should be really fast, one big common progress dialogue mutex is sufficient. */
-static GMutex progress_mutex;
+ g_mutex_unlock(&progress_dialog->mutex);
+}
void
-libbalsa_progress_dialog_ensure(GtkWidget **progress_dialog,
- const gchar *dialog_title,
- GtkWindow *parent,
- const gchar *progress_id)
+libbalsa_progress_dialog_update(ProgressDialog *progress_dialog,
+ const gchar *progress_id,
+ gboolean finished,
+ gdouble fraction,
+ const gchar *message,
+ ...)
{
- GtkWidget *progress_widget;
- GtkWidget *content_box;
+ g_return_if_fail((progress_dialog != NULL) && (progress_id != NULL));
- g_return_if_fail((progress_dialog != NULL) && (dialog_title != NULL) && (progress_id != NULL));
+ g_mutex_lock(&progress_dialog->mutex);
+
+ /* nothing to do if the progress dialogue has been closed */
+ if (progress_dialog->dialog != NULL) {
+ gchar *real_msg;
- g_mutex_lock(&progress_mutex);
+ if (message != NULL) {
+ va_list args;
- if (*progress_dialog == NULL) {
+ va_start(args, message);
+ real_msg = g_strdup_vprintf(message, args);
+ va_end(args);
+ } else {
+ real_msg = NULL;
+ }
+
+ if (libbalsa_am_i_subthread()) {
+ update_progress_data_t *update_data;
+
+ update_data = g_malloc(sizeof(update_progress_data_t));
+ update_data->dialog = progress_dialog;
+ update_data->id = g_strdup(progress_id);
+ update_data->finished = finished;
+ update_data->fraction = fraction;
+ update_data->message = real_msg;
+ gdk_threads_add_idle((GSourceFunc) libbalsa_progress_dialog_update_cb, update_data);
+ } else {
+ libbalsa_progress_dialog_update_real(progress_dialog, progress_id, finished,
fraction, real_msg);
+ g_free(real_msg);
+ }
+ }
+
+ g_mutex_unlock(&progress_dialog->mutex);
+}
+
+
+/* --- local functions --- */
+
+/* note: the mutex ProgressDialog::mutex is always locked when this function is called */
+static void
+libbalsa_progress_dialog_ensure_real(ProgressDialog *progress_dialog,
+ const gchar *dialog_title,
+ GtkWindow *parent,
+ const gchar *progress_id)
+{
+ GtkWidget *content_box;
+ const progress_widget_data_t *progress_data;
+
+ if (progress_dialog->dialog == NULL) {
GdkGeometry hints;
- *progress_dialog = gtk_dialog_new_with_buttons(dialog_title, parent,
+ progress_dialog->dialog = gtk_dialog_new_with_buttons(dialog_title, parent,
GTK_DIALOG_DESTROY_WITH_PARENT | libbalsa_dialog_flags(), _("_Hide"), GTK_RESPONSE_CLOSE,
NULL);
- gtk_window_set_role(GTK_WINDOW(*progress_dialog), "progress_dialog");
+ gtk_window_set_role(GTK_WINDOW(progress_dialog->dialog), "progress_dialog");
hints.min_width = PROGRESS_DIALOG_WIDTH;
hints.min_height = 1;
hints.max_width = PROGRESS_DIALOG_WIDTH;
hints.max_height = -1;
- gtk_window_set_geometry_hints(GTK_WINDOW(*progress_dialog), NULL, &hints, GDK_HINT_MIN_SIZE +
GDK_HINT_MAX_SIZE);
- gtk_window_set_resizable(GTK_WINDOW(*progress_dialog), FALSE);
- g_signal_connect(G_OBJECT(*progress_dialog), "response", G_CALLBACK(progress_dialog_response_cb),
NULL);
- g_signal_connect(G_OBJECT(*progress_dialog), "destroy", G_CALLBACK(progress_dialog_destroy_cb),
progress_dialog);
+ gtk_window_set_geometry_hints(GTK_WINDOW(progress_dialog->dialog), NULL, &hints, GDK_HINT_MIN_SIZE +
GDK_HINT_MAX_SIZE);
+ gtk_window_set_resizable(GTK_WINDOW(progress_dialog->dialog), FALSE);
+ g_signal_connect(G_OBJECT(progress_dialog->dialog), "response",
G_CALLBACK(progress_dialog_response_cb), NULL);
+ g_signal_connect(G_OBJECT(progress_dialog->dialog), "destroy",
G_CALLBACK(progress_dialog_destroy_cb), progress_dialog);
- content_box = gtk_dialog_get_content_area(GTK_DIALOG(*progress_dialog));
+ content_box = gtk_dialog_get_content_area(GTK_DIALOG(progress_dialog->dialog));
gtk_box_set_spacing(GTK_BOX(content_box), 6);
- gtk_widget_show_all(*progress_dialog);
+ gtk_widget_show_all(progress_dialog->dialog);
} else {
- content_box = gtk_dialog_get_content_area(GTK_DIALOG(*progress_dialog));
+ content_box = gtk_dialog_get_content_area(GTK_DIALOG(progress_dialog->dialog));
}
- progress_widget = find_widget_by_name(GTK_CONTAINER(content_box), progress_id);
- if (progress_widget != NULL) {
- if (!gtk_revealer_get_child_revealed(GTK_REVEALER(progress_widget))) {
- gtk_revealer_set_reveal_child(GTK_REVEALER(progress_widget), TRUE);
+ progress_data = find_progress_data_by_name(GTK_CONTAINER(content_box), progress_id);
+ if (progress_data != NULL) {
+ if (!gtk_revealer_get_child_revealed(GTK_REVEALER(progress_data->revealer))) {
+ gtk_revealer_set_reveal_child(GTK_REVEALER(progress_data->revealer), TRUE);
}
} else {
- progress_widget = create_progress_widget(progress_id, progress_id);
+ GtkWidget *progress_widget;
+
+ progress_widget = create_progress_widget(progress_id);
gtk_revealer_set_reveal_child(GTK_REVEALER(progress_widget), TRUE);
gtk_box_pack_start(GTK_BOX(content_box), progress_widget, FALSE, FALSE, 0);
gtk_widget_show_all(progress_widget);
}
-
- g_mutex_unlock(&progress_mutex);
}
-static void
-revealer_destroy_notify(gpointer timer_id)
-{
- g_source_remove(GPOINTER_TO_UINT(timer_id));
-}
-gboolean
-libbalsa_progress_dialog_update(gpointer user_data)
+/* note: the mutex ProgressDialog::mutex is never locked when this function is called */
+static gboolean
+libbalsa_progress_dialog_create_cb(create_progress_dlg_t *dlg_data)
{
- LibbalsaProgressData *ctrl_data = (LibbalsaProgressData *) user_data;
-
- g_return_val_if_fail(ctrl_data != NULL, FALSE);
-
- g_mutex_lock(&progress_mutex);
-
- if (ctrl_data->progress_dialog == NULL) {
- if (ctrl_data->finished) {
- libbalsa_information(LIBBALSA_INFORMATION_MESSAGE, "%s:\n%s", ctrl_data->progress_id,
ctrl_data->message);
- }
- } else {
- GtkWidget *progress_widget;
- GtkWidget *content_box;
-
- content_box = gtk_dialog_get_content_area(GTK_DIALOG(ctrl_data->progress_dialog));
- progress_widget = find_widget_by_name(GTK_CONTAINER(content_box), ctrl_data->progress_id);
- if (progress_widget != NULL) {
- if (ctrl_data->message != NULL) {
- GtkLabel *label;
-
- label = GTK_LABEL(g_object_get_data(G_OBJECT(progress_widget), "label"));
- gtk_label_set_text(label, ctrl_data->message);
- }
- if (isnan(ctrl_data->fraction) != 1) {
- GtkProgressBar *progress;
-
- progress = GTK_PROGRESS_BAR(g_object_get_data(G_OBJECT(progress_widget),
"progress"));
- gtk_progress_bar_set_fraction(progress, ctrl_data->fraction);
- }
- if (ctrl_data->finished) {
- guint timer_id;
-
- gtk_revealer_set_reveal_child(GTK_REVEALER(progress_widget), FALSE);
-
- /* set a timer and remember it's id so we can remove it properly if the user
destroys the whole dialogue */
- timer_id = g_timeout_add(500, remove_progress_widget, progress_widget);
- g_object_set_data_full(G_OBJECT(progress_widget), "timer",
GUINT_TO_POINTER(timer_id),
- revealer_destroy_notify);
- }
- }
- }
-
- g_mutex_unlock(&progress_mutex);
- send_progress_data_free(ctrl_data);
+ g_mutex_lock(&dlg_data->dialog->mutex);
+ libbalsa_progress_dialog_ensure_real(dlg_data->dialog, dlg_data->title, dlg_data->parent,
dlg_data->id);
+ dlg_data->done = TRUE;
+ g_cond_signal(&dlg_data->cond);
+ g_mutex_unlock(&dlg_data->dialog->mutex);
return FALSE;
}
@@ -166,69 +238,83 @@ progress_dialog_response_cb(GtkWidget *dialog,
static void
progress_dialog_destroy_cb(GtkWidget G_GNUC_UNUSED *widget,
- gpointer user_data)
+ ProgressDialog *progress_dialog)
{
- g_mutex_lock(&progress_mutex);
- *((gpointer *) user_data) = NULL;
- g_mutex_unlock(&progress_mutex);
+ g_mutex_lock(&progress_dialog->mutex);
+ progress_dialog->dialog = NULL;
+ g_mutex_unlock(&progress_dialog->mutex);
}
-static GtkWidget *
-find_widget_by_name(GtkContainer *container,
- const gchar *id)
+static void
+progress_data_destroy_cb(GtkWidget G_GNUC_UNUSED *widget,
+ progress_widget_data_t *progress_data)
+{
+ if (progress_data->activity_id != 0U) {
+ g_source_remove(progress_data->activity_id);
+ progress_data->activity_id = 0U;
+ }
+ if (progress_data->fadeout_id != 0U) {
+ g_source_remove(progress_data->fadeout_id);
+ progress_data->fadeout_id = 0U;
+ }
+}
+
+
+static progress_widget_data_t *
+find_progress_data_by_name(GtkContainer *container,
+ const gchar *id)
{
GList *children;
GList *this_child;
- GtkWidget *widget;
+ progress_widget_data_t *data;
children = gtk_container_get_children(container);
- widget = NULL;
+ data = NULL;
this_child = children;
- while ((widget == NULL) && (this_child != NULL)) {
+ while ((data == NULL) && (this_child != NULL)) {
if (strcmp(gtk_widget_get_name(GTK_WIDGET(this_child->data)), id) == 0) {
- widget = GTK_WIDGET(this_child->data);
+ data = g_object_get_data(G_OBJECT(this_child->data), "data");
} else {
this_child = this_child->next;
}
}
g_list_free(children);
- return widget;
+ return data;
}
static GtkWidget *
-create_progress_widget(const gchar *progress_id,
- const gchar *title)
+create_progress_widget(const gchar *progress_id)
{
- GtkWidget *result;
GtkWidget *box;
GtkWidget *label;
- GtkWidget *progress;
+ progress_widget_data_t *widget_data;
- result = gtk_revealer_new();
- gtk_revealer_set_transition_type(GTK_REVEALER(result), GTK_REVEALER_TRANSITION_TYPE_CROSSFADE);
- gtk_revealer_set_transition_duration(GTK_REVEALER(result), 500);
- gtk_revealer_set_reveal_child(GTK_REVEALER(result), FALSE);
- gtk_widget_set_name(result, progress_id);
+ widget_data = g_malloc0(sizeof(progress_widget_data_t));
+ widget_data->revealer = gtk_revealer_new();
+ gtk_revealer_set_transition_type(GTK_REVEALER(widget_data->revealer),
GTK_REVEALER_TRANSITION_TYPE_CROSSFADE);
+ gtk_revealer_set_transition_duration(GTK_REVEALER(widget_data->revealer), FADER_DURATION);
+ gtk_revealer_set_reveal_child(GTK_REVEALER(widget_data->revealer), FALSE);
+ gtk_widget_set_name(widget_data->revealer, progress_id);
+ g_object_set_data_full(G_OBJECT(widget_data->revealer), "data", widget_data, g_free);
+ g_signal_connect(G_OBJECT(widget_data->revealer), "destroy", G_CALLBACK(progress_data_destroy_cb),
widget_data);
box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
- gtk_container_add(GTK_CONTAINER(result), box);
+ gtk_container_add(GTK_CONTAINER(widget_data->revealer), box);
- label = gtk_label_new(title);
+ label = gtk_label_new(progress_id);
gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
- label = gtk_label_new(" ");
- gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
- g_object_set_data(G_OBJECT(result), "label", label);
- gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
+ widget_data->label = gtk_label_new(" ");
+ gtk_label_set_line_wrap(GTK_LABEL(widget_data->label), TRUE);
+ gtk_box_pack_start(GTK_BOX(box), widget_data->label, FALSE, FALSE, 0);
- progress = gtk_progress_bar_new();
- g_object_set_data(G_OBJECT(result), "progress", progress);
- gtk_box_pack_start(GTK_BOX(box), progress, FALSE, FALSE, 0);
+ widget_data->progress = gtk_progress_bar_new();
+ gtk_box_pack_start(GTK_BOX(box), widget_data->progress, FALSE, FALSE, 0);
- return result;
+ return widget_data->revealer;
}
@@ -245,17 +331,15 @@ count_revealers(GtkWidget *widget,
static gboolean
-remove_progress_widget(gpointer user_data)
+remove_progress_widget(progress_widget_data_t *progress_data)
{
- GtkWidget *progress = GTK_WIDGET(user_data);
GtkWidget *parent_dialog;
GtkWidget *content_box;
guint rev_children = 0U;
- (void) g_object_steal_data(G_OBJECT(progress), "timer");
-
- parent_dialog = gtk_widget_get_toplevel(progress);
- gtk_widget_destroy(progress);
+ progress_data->fadeout_id = 0U;
+ parent_dialog = gtk_widget_get_toplevel(progress_data->revealer);
+ gtk_widget_destroy(progress_data->revealer);
/* count the GtkRevealer children left, so we can just destroy the dialogue if there is none */
content_box = gtk_dialog_get_content_area(GTK_DIALOG(parent_dialog));
@@ -269,10 +353,70 @@ remove_progress_widget(gpointer user_data)
}
+/* note: the mutex ProgressDialog::mutex is never locked when this function is called */
+static gboolean
+libbalsa_progress_dialog_update_cb(update_progress_data_t *upd_data)
+{
+ g_mutex_lock(&upd_data->dialog->mutex);
+ libbalsa_progress_dialog_update_real(upd_data->dialog, upd_data->id, upd_data->finished,
upd_data->fraction, upd_data->message);
+ g_mutex_unlock(&upd_data->dialog->mutex);
+ g_free(upd_data->id);
+ g_free(upd_data->message);
+ g_free(upd_data);
+ return FALSE;
+}
+
+
+/* note: the mutex ProgressDialog::mutex is always locked when this function is called */
static void
-send_progress_data_free(LibbalsaProgressData *progress_data)
+libbalsa_progress_dialog_update_real(ProgressDialog *progress_dialog,
+ const gchar *progress_id,
+ gboolean finished,
+ gdouble fraction,
+ const gchar *message)
+{
+ if (progress_dialog->dialog == NULL) {
+ if (finished) {
+ libbalsa_information(LIBBALSA_INFORMATION_MESSAGE, "%s:\n%s", progress_id, message);
+ }
+ } else {
+ GtkWidget *content_box;
+ progress_widget_data_t *progress_data;
+
+ content_box = gtk_dialog_get_content_area(GTK_DIALOG(progress_dialog->dialog));
+ progress_data = find_progress_data_by_name(GTK_CONTAINER(content_box), progress_id);
+ if (progress_data != NULL) {
+ if (message != NULL) {
+ gtk_label_set_text(GTK_LABEL(progress_data->label), message);
+ }
+ if (isnan(fraction) != 1) {
+ if (isinf(fraction) != 0) {
+ if (progress_data->activity_id == 0U) {
+
gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progress_data->progress));
+ progress_data->activity_id =
+ g_timeout_add(ACTIVITY_DURATION, (GSourceFunc)
progress_activity, progress_data->progress);
+ }
+ } else {
+ if (progress_data->activity_id != 0U) {
+ g_source_remove(progress_data->activity_id);
+ progress_data->activity_id = 0U;
+ }
+
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress_data->progress), fraction);
+ }
+ }
+ if (finished) {
+ gtk_revealer_set_reveal_child(GTK_REVEALER(progress_data->revealer), FALSE);
+ gtk_widget_set_name(progress_data->revealer, "_none_");
+ progress_data->fadeout_id = g_timeout_add(FADER_DURATION, (GSourceFunc)
remove_progress_widget, progress_data);
+ }
+ }
+ }
+}
+
+
+static gboolean
+progress_activity(GtkProgressBar *progress)
{
- g_free(progress_data->progress_id);
- g_free(progress_data->message);
- g_free(progress_data);
+ gtk_progress_bar_pulse(progress);
+ return TRUE;
}
diff --git a/libbalsa/libbalsa-progress.h b/libbalsa/libbalsa-progress.h
index 5790512..ce33105 100644
--- a/libbalsa/libbalsa-progress.h
+++ b/libbalsa/libbalsa-progress.h
@@ -28,50 +28,60 @@
#include <gtk/gtk.h>
-typedef struct _LibbalsaProgressData LibbalsaProgressData;
-
-/** \brief Progress update data
+/** \brief Progress dialogue
*
- * The data which shall be passed to libbalsa_progress_dialog_update() in order to update a progress
dialogue.
+ * Structure containing the actual progress dialogue widget and a mutex for protecting concurrent accesses.
As to initialise a
+ * variable of this type, put it either in static memory, or set the \ref ProgressDialog::dialog to NULL and
initialise \ref
+ * ProgressDialog::mutex.
*/
-struct _LibbalsaProgressData {
- GtkWidget *progress_dialog; /**< Progress dialogue as created by
libbalsa_progress_dialog_ensure(). */
- gchar *progress_id; /**< Progress identifier. */
- gboolean finished; /**< Indicates whether the progress element shall be removed
from the dialogue. When no
- * progress elements are left, the
dialogue is destroyed. */
- gchar *message; /**< Message which shall be printed above the
progress bar, or NULL to keep the current
- * message. */
- gdouble fraction; /**< Progress bar value, between 0.0 and 1.0, or NAN to keep
the current value. */
-};
+typedef struct {
+ GtkWidget *dialog;
+ GMutex mutex;
+} ProgressDialog;
/** \brief Ensure that a progress dialogue and progress section exists
*
- * \param progress_dialog address of an existing progress dialogue, shall be filled with NULL to create a
new one
+ * \param progress_dialog properly initialised progress dialogue
* \param dialog_title dialogue title, used only if a new dialogue is created
* \param parent parent window
* \param progress_id progress identifier, also used as section title, \em must be unique
*
- * If the passed progress dialogue address is NULL, a new dialogue is created.
+ * If the passed progress dialogue \ref ProgressDialog::dialog is NULL, a new dialogue is created.
*
* If no progress section with the passed id exists, it is appended. An already existing section is
revealed if necessary.
+ *
+ * \note This function may be called from a thread. In this case, the function will block in the thread
until the "real" work has
+ * been done in the main thread.
*/
-void libbalsa_progress_dialog_ensure(GtkWidget **progress_dialog,
- const gchar *dialog_title,
- GtkWindow *parent,
- const gchar *progress_id);
+void libbalsa_progress_dialog_ensure(ProgressDialog *progress_dialog,
+ const gchar *dialog_title,
+ GtkWindow *parent,
+ const gchar *progress_id);
-/** \brief Progress dialogue update callback
+/** \brief Progress dialogue update
*
- * \param user_data progress update information, cast'ed to LibbalsaProgressData *
- * \return always FALSE
+ * \param progress_dialog progress dialogue, initialised by libbalsa_progress_dialog_ensure()
+ * \param progress_id progress identifier passed to libbalsa_progress_dialog_ensure()
+ * \param finished indicates whether the progress element shall be removed from the dialogue. When no
progress elements are left,
+ * the dialogue is destroyed
+ * \param fraction progress bar value between 0.0 and 1.0, or INF to switch to activity mode, or NAN to keep
the current value
+ * \param message printf-like format string which shall be printed above the progress bar, or NULL to keep
the current message
+ * \param ... additional arguments for the message format string
*
- * This function shall be called with a pointer to an update information structure, typically from an idle
callback.
+ * Update the information of the passed progress dialogue.
*
- * \note The function will free the passed data.
+ * \note This function may be called from a thread. In this case, the "real" work is done in an idle
callback and may therefore
+ * be performed only after this function returns.
*/
-gboolean libbalsa_progress_dialog_update(gpointer user_data);
+void libbalsa_progress_dialog_update(ProgressDialog *progress_dialog,
+ const gchar *progress_id,
+ gboolean finished,
+ gdouble fraction,
+ const gchar *message,
+ ...)
+ G_GNUC_PRINTF(5, 6);
#endif /* LIBBALSA_PROGRESS_H_ */
diff --git a/libbalsa/mailbox.c b/libbalsa/mailbox.c
index df907af..3ce0f9a 100644
--- a/libbalsa/mailbox.c
+++ b/libbalsa/mailbox.c
@@ -194,8 +194,8 @@ libbalsa_mailbox_class_init(LibBalsaMailboxClass * klass)
G_STRUCT_OFFSET(LibBalsaMailboxClass,
progress_notify),
NULL, NULL,
- libbalsa_VOID__INT_INT_INT_STRING, G_TYPE_NONE,
- 4, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_STRING);
+ libbalsa_VOID__INT_DOUBLE_STRING, G_TYPE_NONE,
+ 3U, G_TYPE_INT, G_TYPE_DOUBLE, G_TYPE_STRING);
object_class->dispose = libbalsa_mailbox_dispose;
object_class->finalize = libbalsa_mailbox_finalize;
@@ -667,16 +667,28 @@ libbalsa_mailbox_set_unread_messages_flag(LibBalsaMailbox * mailbox,
there has been a progress in current operation.
*/
void
-libbalsa_mailbox_progress_notify(LibBalsaMailbox * mailbox,
- int type, int prog, int tot, const gchar* msg)
+libbalsa_mailbox_progress_notify(LibBalsaMailbox *mailbox,
+ LibBalsaMailboxNotify action,
+ gdouble fraction,
+ const gchar *message,
+ ...)
{
+ gchar *full_msg;
+
g_return_if_fail(mailbox != NULL);
g_return_if_fail(LIBBALSA_IS_MAILBOX(mailbox));
- /* OK to emit in a subthread, because the handler expects it. */
- g_signal_emit(G_OBJECT(mailbox),
- libbalsa_mailbox_signals[PROGRESS_NOTIFY],
- 0, type, prog, tot, msg);
+ if (message != NULL) {
+ va_list args;
+
+ va_start(args, message);
+ full_msg = g_strdup_vprintf(message, args);
+ va_end(args);
+ } else {
+ full_msg = NULL;
+ }
+ g_signal_emit(G_OBJECT(mailbox), libbalsa_mailbox_signals[PROGRESS_NOTIFY], 0, (gint) action, fraction,
full_msg);
+ g_free(full_msg);
}
void
diff --git a/libbalsa/mailbox.h b/libbalsa/mailbox.h
index 58b6ba9..834c41a 100644
--- a/libbalsa/mailbox.h
+++ b/libbalsa/mailbox.h
@@ -90,12 +90,9 @@ typedef enum {
} LibBalsaMailboxSortType;
typedef enum {
- LIBBALSA_NTFY_SOURCE,
- LIBBALSA_NTFY_FINISHED,
- LIBBALSA_NTFY_MSGINFO,
- LIBBALSA_NTFY_PROGRESS,
- LIBBALSA_NTFY_UPDATECONFIG,
- LIBBALSA_NTFY_ERROR
+ LIBBALSA_NTFY_INIT,
+ LIBBALSA_NTFY_UPDATE,
+ LIBBALSA_NTFY_FINISHED
} LibBalsaMailboxNotify;
@@ -272,8 +269,7 @@ struct _LibBalsaMailboxClass {
/* Signals */
void (*changed) (LibBalsaMailbox * mailbox);
void (*message_expunged) (LibBalsaMailbox * mailbox, guint seqno);
- void (*progress_notify) (LibBalsaMailbox * mailbox, int type,
- int prog, int tot, const gchar* msg);
+ void (*progress_notify) (LibBalsaMailbox * mailbox, gint action, gdouble fraction, gchar *message);
/* Virtual Functions */
gboolean (*open_mailbox) (LibBalsaMailbox * mailbox, GError **err);
@@ -351,9 +347,12 @@ void libbalsa_mailbox_check(LibBalsaMailbox * mailbox);
void libbalsa_mailbox_changed(LibBalsaMailbox * mailbox);
void libbalsa_mailbox_set_unread_messages_flag(LibBalsaMailbox * mailbox,
gboolean has_unread);
-void libbalsa_mailbox_progress_notify(LibBalsaMailbox * mailbox,
- int type, int prog, int tot,
- const gchar* msg);
+void libbalsa_mailbox_progress_notify(LibBalsaMailbox *mailbox,
+ LibBalsaMailboxNotify action,
+ gdouble
fraction,
+ const gchar *message,
+ ...)
+ G_GNUC_PRINTF(4, 5);
/** Message access functions.
*/
diff --git a/libbalsa/mailbox_pop3.c b/libbalsa/mailbox_pop3.c
index b3bf0ae..199a7da 100644
--- a/libbalsa/mailbox_pop3.c
+++ b/libbalsa/mailbox_pop3.c
@@ -25,6 +25,7 @@
#include <glib.h>
#include <string.h>
+#include <math.h>
#include "libbalsa.h"
#include "libbalsa-conf.h"
@@ -356,7 +357,7 @@ pop_handler_close(pop_handler_t *handler,
/* ===================================================================
- Functions supporting asynchronous retrival of messages.
+ Functions supporting asynchronous retrieval of messages.
*/
struct fetch_data {
LibBalsaMailbox *mailbox;
@@ -373,15 +374,14 @@ struct fetch_data {
static void
notify_progress(const struct fetch_data *fd)
{
+ gdouble fraction;
gchar *recvbuf;
- gchar *msgbuf;
+ fraction = (gdouble) fd->received / (gdouble) fd->total_size;
recvbuf = libbalsa_size_to_gchar(fd->received);
- msgbuf = g_strdup_printf(_("Message %lu of %lu (%s of %s)"), (unsigned long) fd->msgno, (unsigned
long) fd->total_messages,
- recvbuf, fd->total_size_msg);
+ libbalsa_mailbox_progress_notify(fd->mailbox, LIBBALSA_NTFY_UPDATE, fraction, _("Message %lu of %lu
(%s of %s)"),
+ (unsigned long) fd->msgno, (unsigned long) fd->total_messages, recvbuf, fd->total_size_msg);
g_free(recvbuf);
- libbalsa_mailbox_progress_notify(LIBBALSA_MAILBOX(fd->mailbox), LIBBALSA_NTFY_PROGRESS, fd->received,
fd->total_size, msgbuf);
- g_free(msgbuf);
}
static gboolean
@@ -505,6 +505,7 @@ libbalsa_mailbox_pop3_startup(LibBalsaServer *server,
g_signal_connect(G_OBJECT(pop), "auth", G_CALLBACK(libbalsa_server_get_auth), server);
/* connect server */
+ libbalsa_mailbox_progress_notify(LIBBALSA_MAILBOX(mbox), LIBBALSA_NTFY_INIT, INFINITY, _("Connecting
%s…"), server->host);
if (!net_client_pop_connect(pop, NULL, &error)) {
libbalsa_information(LIBBALSA_INFORMATION_ERROR, _("POP3 mailbox %s: cannot connect %s: %s"),
name, server->host,
error->message);
@@ -514,6 +515,7 @@ libbalsa_mailbox_pop3_startup(LibBalsaServer *server,
}
/* load message list */
+ libbalsa_mailbox_progress_notify(LIBBALSA_MAILBOX(mbox), LIBBALSA_NTFY_UPDATE, INFINITY, _("List
messages…"));
if (!net_client_pop_list(pop, msg_list, !mbox->delete_from_server, &error)) {
libbalsa_information(LIBBALSA_INFORMATION_ERROR, _("POP3 mailbox %s error: %s"), name,
error->message);
g_error_free(error);
@@ -613,7 +615,6 @@ libbalsa_mailbox_pop3_check(LibBalsaMailbox * mailbox)
{
LibBalsaMailboxPop3 *mbox = LIBBALSA_MAILBOX_POP3(mailbox);
LibBalsaServer *server;
- gchar *msgbuf;
NetClientPop *pop;
GList *msg_list;
@@ -623,10 +624,6 @@ libbalsa_mailbox_pop3_check(LibBalsaMailbox * mailbox)
server = LIBBALSA_MAILBOX_REMOTE_SERVER(mbox);
- msgbuf = g_strdup_printf("POP3: %s", mailbox->name);
- libbalsa_mailbox_progress_notify(mailbox, LIBBALSA_NTFY_SOURCE, 0, 0, msgbuf);
- g_free(msgbuf);
-
/* open the mailbox connection and get the messages list */
pop = libbalsa_mailbox_pop3_startup(server, mbox, mailbox->name, &msg_list);
@@ -637,7 +634,8 @@ libbalsa_mailbox_pop3_check(LibBalsaMailbox * mailbox)
gboolean result = TRUE;
GError *err = NULL;
- libbalsa_mailbox_progress_notify(mailbox, LIBBALSA_NTFY_PROGRESS, 0, 1, _("Connected"));
+ libbalsa_mailbox_progress_notify(mailbox, LIBBALSA_NTFY_UPDATE, INFINITY,
+ _("Connected to %s"), net_client_get_host(NET_CLIENT(pop)));
memset(&fd, 0, sizeof(fd));
/* nothing to do if no messages are on the server */
@@ -651,10 +649,9 @@ libbalsa_mailbox_pop3_check(LibBalsaMailbox * mailbox)
fd.mailbox = mailbox;
fd.total_size_msg = libbalsa_size_to_gchar(fd.total_size);
- msgbuf = g_strdup_printf(ngettext("%lu new message (%s)", "%lu new messages (%s)",
fd.total_messages),
- (unsigned long) fd.total_messages, fd.total_size_msg);
- libbalsa_mailbox_progress_notify(mailbox, LIBBALSA_NTFY_PROGRESS, 0, 1, msgbuf);
- g_free(msgbuf);
+ libbalsa_mailbox_progress_notify(mailbox, LIBBALSA_NTFY_UPDATE, 0.0,
+ ngettext("%lu new message (%s)", "%lu new messages (%s)", fd.total_messages),
+ (unsigned long) fd.total_messages, fd.total_size_msg);
if (mbox->filter) {
fd.filter_path = mbox->filter_cmd;
@@ -663,7 +660,8 @@ libbalsa_mailbox_pop3_check(LibBalsaMailbox * mailbox)
if (result) {
result = net_client_pop_retr(pop, msg_list, message_cb, &fd, &err);
if (result && mbox->delete_from_server) {
- libbalsa_mailbox_progress_notify(mailbox, LIBBALSA_NTFY_PROGRESS, 1,
1, _("Deleting messages on server…"));
+ libbalsa_mailbox_progress_notify(mailbox, LIBBALSA_NTFY_UPDATE,
INFINITY,
+ _("Deleting messages on server…"));
result = net_client_pop_dele(pop, msg_list, &err);
}
}
@@ -692,8 +690,8 @@ libbalsa_mailbox_pop3_check(LibBalsaMailbox * mailbox)
}
/* done - clean up */
- libbalsa_mailbox_progress_notify(mailbox, LIBBALSA_NTFY_PROGRESS, 0, 1, _("Finished"));
g_object_unref(G_OBJECT(pop));
+ libbalsa_mailbox_progress_notify(mailbox, LIBBALSA_NTFY_FINISHED, 1.0, _("Finished"));
}
}
diff --git a/libbalsa/send.c b/libbalsa/send.c
index 892cd16..75eca44 100644
--- a/libbalsa/send.c
+++ b/libbalsa/send.c
@@ -94,7 +94,7 @@ static guint send_mail_time = 0U;
static guint send_mail_timer_id = 0U;
static gint retrigger_send = 0; /* # of messages added to outbox while the smtp server was
locked, access via g_atomic_* */
-static GtkWidget *send_progress_dialog;
+static ProgressDialog send_progress_dialog;
/* end of state variables section */
@@ -538,6 +538,7 @@ libbalsa_message_send(LibBalsaMessage *message,
LibBalsaMailbox *fccbox,
LibBalsaFccboxFinder finder,
LibBalsaSmtpServer *smtp_server,
+ gboolean show_progress,
GtkWindow *parent,
gboolean flow,
GError **error)
@@ -555,7 +556,7 @@ libbalsa_message_send(LibBalsaMessage *message,
if (result == LIBBALSA_MESSAGE_CREATE_OK) {
if (libbalsa_smtp_server_trylock(smtp_server)) {
- lbs_process_queue(outbox, finder, smtp_server, parent);
+ lbs_process_queue(outbox, finder, smtp_server, show_progress ? parent : NULL);
} else {
g_atomic_int_inc(&retrigger_send);
}
@@ -620,21 +621,15 @@ send_message_data_cb(gchar *buffer,
gint ipercent;
smi->total_sent += read_res;
- fraction = (gfloat) smi->total_sent / (gfloat) smi->total_size;
+ fraction = (gdouble) smi->total_sent / (gdouble) smi->total_size;
g_debug("%s: s=%lu t=%lu %g", __func__, (unsigned long) smi->total_sent, (unsigned long)
smi->total_size, fraction);
if (fraction > 1.0) {
fraction = 1.0;
}
ipercent = (gint) (100.0 * (fraction + 0.5));
- if (ipercent > smi->last_report) {
- LibbalsaProgressData *progress;
-
- progress = g_new0(LibbalsaProgressData, 1U);
- progress->progress_id = g_strdup(smi->progress_id);
- progress->progress_dialog = send_progress_dialog;
- progress->message = g_strdup_printf(_("Message %u of %u"), smi->curr_msg, smi->msg_count);
- progress->fraction = fraction;
- g_idle_add(libbalsa_progress_dialog_update, progress);
+ if (!smi->no_dialog && (ipercent > smi->last_report)) {
+ libbalsa_progress_dialog_update(&send_progress_dialog, smi->progress_id, FALSE, fraction,
+ _("Message %u of %u"), smi->curr_msg, smi->msg_count);
smi->last_report = ipercent;
}
}
@@ -675,7 +670,8 @@ lbs_check_reachable_cb(GObject *object,
}
-/* note: the following function is called with the passed smtp server being locked */
+/* note: the following function is called with the passed smtp server being locked
+ * parent != NULL indicates that the progress dialogue shall be shown */
static void
lbs_process_queue(LibBalsaMailbox *outbox,
LibBalsaFccboxFinder finder,
@@ -849,6 +845,7 @@ lbs_process_queue_real(LibBalsaSmtpServer *smtp_server, SendQueueInfo *send_info
if (send_info->parent != NULL) {
libbalsa_progress_dialog_ensure(&send_progress_dialog, _("Sending Mail"),
send_info->parent,
send_message_info->progress_id);
+ send_message_info->no_dialog = FALSE;
} else {
send_message_info->no_dialog = TRUE;
}
@@ -876,6 +873,7 @@ void
libbalsa_process_queue(LibBalsaMailbox *outbox,
LibBalsaFccboxFinder finder,
GSList *smtp_servers,
+ gboolean show_progress,
GtkWindow *parent)
{
if (libbalsa_mailbox_open(outbox, NULL)) {
@@ -896,7 +894,7 @@ libbalsa_process_queue(LibBalsaMailbox *outbox,
LibBalsaSmtpServer *smtp_server = LIBBALSA_SMTP_SERVER(smtp_servers->data);
if (libbalsa_smtp_server_trylock(smtp_server)) {
- lbs_process_queue(outbox, finder, smtp_server, parent);
+ lbs_process_queue(outbox, finder, smtp_server, show_progress ? parent
: NULL);
}
}
} else {
@@ -947,14 +945,11 @@ balsa_send_message_success(MessageQueueItem *mqi,
if (fccurl != NULL) {
LibBalsaMailbox *fccbox = info->finder(fccurl);
GError *err = NULL;
- LibbalsaProgressData *progress;
- progress = g_new0(LibbalsaProgressData, 1U);
- progress->progress_id = g_strdup(info->progress_id);
- progress->progress_dialog = send_progress_dialog;
- progress->message = g_strdup_printf(_("Save message in %s…"), fccbox->name);
- progress->fraction = NAN;
- g_idle_add(libbalsa_progress_dialog_update, progress);
+ if (!info->no_dialog) {
+ libbalsa_progress_dialog_update(&send_progress_dialog, info->progress_id,
FALSE, NAN,
+ _("Save message in %s…"), fccbox->name);
+ }
libbalsa_message_change_flags(mqi->orig, 0, LIBBALSA_MESSAGE_FLAG_NEW |
LIBBALSA_MESSAGE_FLAG_FLAGGED);
libbalsa_mailbox_sync_storage(mqi->orig->mailbox, FALSE);
@@ -1005,23 +1000,19 @@ balsa_send_message_real(SendMessageInfo *info)
g_debug("%s: starting", __func__);
/* connect the SMTP server */
+ if (!info->no_dialog) {
+ libbalsa_progress_dialog_update(&send_progress_dialog, info->progress_id, FALSE, INFINITY,
+ _("Connecting %s…"), net_client_get_host(NET_CLIENT(info->session)));
+ }
result = net_client_smtp_connect(info->session, &greeting, &error);
g_debug("%s: connect = %d [%p]: '%s'", __func__, result, info->items, greeting);
g_free(greeting);
if (result) {
GList *this_msg;
- if (info->no_dialog) {
- libbalsa_information(LIBBALSA_INFORMATION_MESSAGE, _("Sending queued messages to %s"),
- libbalsa_smtp_server_get_name(info->smtp_server));
- } else {
- LibbalsaProgressData *progress;
-
- progress = g_new0(LibbalsaProgressData, 1U);
- progress->progress_id = g_strdup(info->progress_id);
- progress->progress_dialog = send_progress_dialog;
- progress->message = g_strdup_printf(_("Connected to %s"),
net_client_get_host(NET_CLIENT(info->session)));
- g_idle_add(libbalsa_progress_dialog_update, progress);
+ if (!info->no_dialog) {
+ libbalsa_progress_dialog_update(&send_progress_dialog, info->progress_id, FALSE, 0.0,
+ _("Connected to %s"), net_client_get_host(NET_CLIENT(info->session)));
}
for (this_msg = info->items; this_msg != NULL; this_msg = this_msg->next) {
@@ -1084,17 +1075,13 @@ balsa_send_message_real(SendMessageInfo *info)
/* close outbox in an idle callback, as it might affect the display */
g_idle_add((GSourceFunc) balsa_send_message_real_idle_cb, g_object_ref(info->outbox));
+ /* finalise the SMTP session (which may be slow) */
+ g_object_unref(G_OBJECT(info->session));
+ info->session = NULL;
+
/* clean up */
if (!info->no_dialog) {
- LibbalsaProgressData *progress;
-
- progress = g_new0(LibbalsaProgressData, 1U);
- progress->progress_id = g_strdup(info->progress_id);
- progress->progress_dialog = send_progress_dialog;
- progress->message = g_strdup_printf(_("Finished"));
- progress->fraction = 1.0;
- progress->finished = TRUE;
- g_idle_add(libbalsa_progress_dialog_update, progress);
+ libbalsa_progress_dialog_update(&send_progress_dialog, info->progress_id, TRUE, 1.0,
_("Finished"));
} else if (result) {
libbalsa_information(LIBBALSA_INFORMATION_MESSAGE,
ngettext("Transmitted %u message to %s", "Transmitted %u messages to %s", info->msg_count),
diff --git a/libbalsa/send.h b/libbalsa/send.h
index 48a38b8..93381e9 100644
--- a/libbalsa/send.h
+++ b/libbalsa/send.h
@@ -57,19 +57,20 @@ LibBalsaMsgCreateResult libbalsa_message_queue(LibBalsaMessage* message,
smtp_server,
gboolean flow,
GError ** error);
-LibBalsaMsgCreateResult libbalsa_message_send(LibBalsaMessage * message,
- LibBalsaMailbox * outbox,
- LibBalsaMailbox * fccbox,
+LibBalsaMsgCreateResult libbalsa_message_send(LibBalsaMessage *message,
+ LibBalsaMailbox *outbox,
+ LibBalsaMailbox *fccbox,
LibBalsaFccboxFinder finder,
- LibBalsaSmtpServer *
- smtp_server,
- GtkWindow * parent,
- gboolean flow,
- GError ** error);
-void libbalsa_process_queue(LibBalsaMailbox * outbox,
+ LibBalsaSmtpServer *smtp_server,
+ gboolean
show_progress,
+ GtkWindow *parent,
+ gboolean flow,
+ GError **error);
+void libbalsa_process_queue(LibBalsaMailbox *outbox,
LibBalsaFccboxFinder finder,
- GSList * smtp_servers,
- GtkWindow * parent);
+ GSList *smtp_servers,
+ gboolean show_progress,
+ GtkWindow *parent);
void libbalsa_auto_send_init(GSourceFunc auto_send_cb);
void libbalsa_auto_send_config(gboolean enable,
diff --git a/src/balsa-app.c b/src/balsa-app.c
index 9f9782a..8e9f9c8 100644
--- a/src/balsa-app.c
+++ b/src/balsa-app.c
@@ -253,7 +253,7 @@ static gboolean
send_queued_messages_auto_cb(gpointer data)
{
g_debug("%s: %p", __func__, data);
- libbalsa_process_queue(balsa_app.outbox, balsa_find_sentbox_by_url, balsa_app.smtp_servers, NULL);
+ libbalsa_process_queue(balsa_app.outbox, balsa_find_sentbox_by_url, balsa_app.smtp_servers, FALSE,
NULL);
return (data == NULL);
}
@@ -299,7 +299,8 @@ balsa_app_init(void)
balsa_app.sw_maximized = FALSE;
balsa_app.toolbar_wrap_button_text = TRUE;
- balsa_app.pwindow_option = WHILERETR;
+ balsa_app.send_progress_dialog = TRUE;
+ balsa_app.recv_progress_dialog = TRUE;
balsa_app.wordwrap = FALSE; /* default to format=flowed. */
balsa_app.wraplength = 72;
balsa_app.browse_wrap = FALSE; /* GtkTextView will wrap for us. */
@@ -441,7 +442,7 @@ balsa_app_destroy(void)
static gboolean
check_new_messages_auto_cb(gpointer data)
{
- check_new_messages_real(balsa_app.main_window, TYPE_BACKGROUND);
+ check_new_messages_real(balsa_app.main_window, TRUE);
if (balsa_app.debug)
fprintf(stderr, "Auto-checked for new messages…\n");
diff --git a/src/balsa-app.h b/src/balsa-app.h
index d63e26c..27a401d 100644
--- a/src/balsa-app.h
+++ b/src/balsa-app.h
@@ -237,7 +237,8 @@ extern struct BalsaApplication {
/* text color of URL's */
GdkRGBA url_color;
- guint pwindow_option;
+ gboolean send_progress_dialog;
+ gboolean recv_progress_dialog;
gboolean wordwrap;
gint wraplength;
gboolean browse_wrap;
diff --git a/src/balsa-message.c b/src/balsa-message.c
index d557ff3..1c13276 100644
--- a/src/balsa-message.c
+++ b/src/balsa-message.c
@@ -2478,6 +2478,7 @@ handle_mdn_request(GtkWindow *parent, LibBalsaMessage *message)
result = libbalsa_message_send(mdn, balsa_app.outbox, NULL,
balsa_find_sentbox_by_url,
mdn_ident->smtp_server,
+ balsa_app.send_progress_dialog,
parent,
TRUE, &error);
if (result != LIBBALSA_MESSAGE_CREATE_OK)
@@ -2618,6 +2619,7 @@ mdn_dialog_response(GtkWidget * dialog, gint response, gpointer user_data)
libbalsa_message_send(send_msg, balsa_app.outbox, NULL,
balsa_find_sentbox_by_url,
mdn_ident->smtp_server,
+ balsa_app.send_progress_dialog,
gtk_window_get_transient_for
((GtkWindow *) dialog),
TRUE, &error);
diff --git a/src/balsa-mime-widget-message.c b/src/balsa-mime-widget-message.c
index 9a023d8..7f581f8 100644
--- a/src/balsa-mime-widget-message.c
+++ b/src/balsa-mime-widget-message.c
@@ -378,6 +378,7 @@ extbody_send_mail(GtkWidget * button, LibBalsaMessageBody * mime_body)
result = libbalsa_message_send(message, balsa_app.outbox, NULL,
balsa_find_sentbox_by_url,
balsa_app.current_ident->smtp_server,
+ balsa_app.send_progress_dialog,
GTK_WINDOW(gtk_widget_get_toplevel
(button)),
FALSE, &err);
diff --git a/src/balsa-mime-widget-vcalendar.c b/src/balsa-mime-widget-vcalendar.c
index 4438fe0..34e70cb 100644
--- a/src/balsa-mime-widget-vcalendar.c
+++ b/src/balsa-mime-widget-vcalendar.c
@@ -325,6 +325,7 @@ vevent_reply(GObject * button, GtkWidget * box)
result = libbalsa_message_send(message, balsa_app.outbox, NULL,
balsa_find_sentbox_by_url,
ident->smtp_server,
+ balsa_app.send_progress_dialog,
GTK_WINDOW(gtk_widget_get_toplevel
((GtkWidget *) button)),
FALSE, &error);
diff --git a/src/main-window.c b/src/main-window.c
index a935b75..5d1f461 100644
--- a/src/main-window.c
+++ b/src/main-window.c
@@ -31,6 +31,7 @@
#include "main-window.h"
#include <string.h>
+#include <math.h>
#include <gdk/gdkkeysyms.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
@@ -65,7 +66,7 @@
#include "save-restore.h"
#include "toolbar-prefs.h"
#include "toolbar-factory.h"
-#include "threads.h"
+#include "libbalsa-progress.h"
#include "filter.h"
#include "filter-funcs.h"
@@ -91,14 +92,12 @@ static GtkTargetEntry notebook_drop_types[NUM_DROP_TYPES] = {
};
/* Define thread-related globals, including dialogs */
-GtkWidget *progress_dialog = NULL;
-GtkWidget *progress_dialog_source = NULL;
-GtkWidget *progress_dialog_message = NULL;
-GtkWidget *progress_dialog_bar = NULL;
-static int quiet_check=0;
+static ProgressDialog progress_dialog;
struct check_messages_thread_info {
BalsaWindow *window;
+ gboolean with_progress_dialog;
+ gboolean with_activity_bar;
GSList *list;
};
static void bw_check_messages_thread(struct check_messages_thread_info
@@ -123,7 +122,7 @@ static void bw_idle_remove(BalsaWindow * window);
static gboolean bw_idle_cb(BalsaWindow * window);
-static void bw_check_mailbox_list(BalsaWindow * window, GList * list);
+static void bw_check_mailbox_list(struct check_messages_thread_info *info, GList * list);
static gboolean bw_add_mbox_to_checklist(GtkTreeModel * model,
GtkTreePath * path,
GtkTreeIter * iter,
@@ -192,6 +191,9 @@ G_DEFINE_TYPE (BalsaWindow, balsa_window, GTK_TYPE_APPLICATION_WINDOW)
static guint window_signals[LAST_SIGNAL] = { 0 };
+/* note: access with g_atomic_* functions, not checking mail when 1 */
+static gint checking_mail = 1;
+
static void
balsa_window_class_init(BalsaWindowClass * klass)
{
@@ -1040,7 +1042,7 @@ get_new_mail_activated(GSimpleAction * action,
{
BalsaWindow *window = BALSA_WINDOW(user_data);
- check_new_messages_real(window, TYPE_CALLBACK);
+ check_new_messages_real(window, FALSE);
if (balsa_app.check_mail_auto) {
/* restart the timer */
@@ -1055,6 +1057,7 @@ send_queued_mail_activated(GSimpleAction * action,
{
libbalsa_process_queue(balsa_app.outbox, balsa_find_sentbox_by_url,
balsa_app.smtp_servers,
+ balsa_app.send_progress_dialog,
(GtkWindow *) balsa_app.main_window);
}
@@ -2360,7 +2363,7 @@ balsa_window_new()
G_CALLBACK(bw_is_active_notify), NULL);
/* set initial state of Get-New-Mail button */
- bw_action_set_enabled(window, "get-new-mail", !checking_mail);
+ bw_action_set_enabled(window, "get-new-mail", g_atomic_int_get(&checking_mail) == 1);
g_timeout_add_seconds(30, (GSourceFunc) bw_close_mailbox_on_timer, window);
@@ -3183,20 +3186,75 @@ bw_is_open_mailbox(LibBalsaMailbox *m)
*
*/
static void
-bw_check_mailbox_list(BalsaWindow * window, GList * mailbox_list)
+bw_check_mailbox_progress_cb(LibBalsaMailbox* mailbox, gint action, gdouble fraction, const gchar *message)
+{
+ gchar *progress_id;
+
+ progress_id = g_strdup_printf("POP3: %s", mailbox->name);
+ if (action == LIBBALSA_NTFY_INIT) {
+ libbalsa_progress_dialog_ensure(&progress_dialog, _("Checking Mail…"),
GTK_WINDOW(balsa_app.main_window), progress_id);
+ }
+ libbalsa_progress_dialog_update(&progress_dialog, progress_id, action == LIBBALSA_NTFY_FINISHED,
fraction, "%s", message);
+ g_free(progress_id);
+}
+
+static void
+bw_check_mailbox(LibBalsaMailbox *mailbox)
+{
+ libbalsa_mailbox_check(mailbox);
+ g_thread_exit(NULL);
+}
+
+typedef struct {
+ GObject *object;
+ GThread *thread;
+ gulong notify;
+} bw_pop_mbox_t;
+
+static void
+bw_check_mailbox_done(bw_pop_mbox_t *bw_pop_mbox)
{
- if (window && !window->network_available) {
+ if (bw_pop_mbox->thread != NULL) {
+ g_thread_join(bw_pop_mbox->thread);
+ g_debug("joined thread %p", bw_pop_mbox->thread);
+ }
+ if (bw_pop_mbox->notify > 0U) {
+ g_signal_handler_disconnect(bw_pop_mbox->object, bw_pop_mbox->notify);
+ }
+ g_object_unref(bw_pop_mbox->object);
+}
+
+static void
+bw_check_mailbox_list(struct check_messages_thread_info *info, GList *mailbox_list)
+{
+ GList *check_mbx = NULL;
+
+ if ((info->window != NULL) && !info->window->network_available) {
return;
}
for ( ; mailbox_list; mailbox_list = mailbox_list->next) {
- LibBalsaMailbox *mailbox =
- BALSA_MAILBOX_NODE(mailbox_list->data)->mailbox;
+ LibBalsaMailbox *mailbox = BALSA_MAILBOX_NODE(mailbox_list->data)->mailbox;
+ LibBalsaMailboxPop3 *pop3 = LIBBALSA_MAILBOX_POP3(mailbox);
+ bw_pop_mbox_t *bw_pop_mbox;
+
+ bw_pop_mbox = g_malloc0(sizeof(bw_pop_mbox_t));
+ bw_pop_mbox->object = g_object_ref(mailbox);
libbalsa_mailbox_pop3_set_inbox(mailbox, balsa_app.inbox);
- libbalsa_mailbox_pop3_set_msg_size_limit
- (LIBBALSA_MAILBOX_POP3(mailbox), balsa_app.msg_size_limit*1024);
- libbalsa_mailbox_check(mailbox);
+ libbalsa_mailbox_pop3_set_msg_size_limit(pop3, balsa_app.msg_size_limit * 1024);
+ if (info->with_progress_dialog) {
+ bw_pop_mbox->notify =
+ g_signal_connect(G_OBJECT(mailbox), "progress-notify",
G_CALLBACK(bw_check_mailbox_progress_cb), mailbox);
+ }
+ bw_pop_mbox->thread = g_thread_new(NULL, (GThreadFunc) bw_check_mailbox, mailbox);
+ g_debug("launched thread %p for checking POP3 mailbox %s", bw_pop_mbox->thread, mailbox->name);
+ check_mbx = g_list_prepend(check_mbx, bw_pop_mbox);
}
+
+ /* join all threads, i.e. proceed only after all threads have finished, and disconnect progress notify
handlers */
+ g_list_foreach(check_mbx, (GFunc) bw_check_mailbox_done, NULL);
+ g_debug("all POP3 mailbox threads done");
+ g_list_free_full(check_mbx, (GDestroyNotify) g_free);
}
/*Callback to check a mailbox in a balsa-mblist */
@@ -3233,69 +3291,6 @@ bw_imap_check_test(const gchar * path)
strcmp(path, "INBOX") == 0 : balsa_app.check_imap;
}
-static void
-bw_mailbox_check(LibBalsaMailbox * mailbox, BalsaWindow * window);
-
-static void
-bw_progress_dialog_destroy_cb(GtkWidget * widget, gpointer data)
-{
- progress_dialog = NULL;
- progress_dialog_source = NULL;
- progress_dialog_message = NULL;
- progress_dialog_bar = NULL;
-}
-static void
-bw_progress_dialog_response_cb(GtkWidget* dialog, gint response)
-{
- if(response == GTK_RESPONSE_CLOSE)
- /* this should never be done in response handler, but... */
- gtk_widget_destroy(dialog);
-}
-
-/* ensure_check_mail_dialog:
- make sure that mail checking dialog exists.
-*/
-static void
-ensure_check_mail_dialog(BalsaWindow * window)
-{
- GtkBox *content_box;
-
- if (progress_dialog && GTK_IS_WIDGET(progress_dialog))
- gtk_widget_destroy(GTK_WIDGET(progress_dialog));
-
- progress_dialog =
- gtk_dialog_new_with_buttons(_("Checking Mail…"),
- GTK_WINDOW(window),
- GTK_DIALOG_DESTROY_WITH_PARENT |
- libbalsa_dialog_flags(),
- _("_Hide"), GTK_RESPONSE_CLOSE,
- NULL);
-#if HAVE_MACOSX_DESKTOP
- libbalsa_macosx_menu_for_parent(progress_dialog, GTK_WINDOW(window));
-#endif
- gtk_window_set_role(GTK_WINDOW(progress_dialog), "progress_dialog");
-
- g_signal_connect(G_OBJECT(progress_dialog), "destroy",
- G_CALLBACK(bw_progress_dialog_destroy_cb), NULL);
- g_signal_connect(G_OBJECT(progress_dialog), "response",
- G_CALLBACK(bw_progress_dialog_response_cb), NULL);
-
- content_box =
- GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(progress_dialog)));
- progress_dialog_source = gtk_label_new(_("Checking Mail…"));
- gtk_box_pack_start(content_box, progress_dialog_source,
- FALSE, FALSE, 0);
-
- progress_dialog_message = gtk_label_new("");
- gtk_box_pack_start(content_box, progress_dialog_message,
- FALSE, FALSE, 0);
-
- progress_dialog_bar = gtk_progress_bar_new();
- gtk_box_pack_start(content_box, progress_dialog_bar,
- FALSE, FALSE, 0);
- gtk_window_set_default_size(GTK_WINDOW(progress_dialog), 250, 100);
- gtk_widget_show_all(progress_dialog);
-}
/*
* Callbacks
@@ -3306,7 +3301,7 @@ ensure_check_mail_dialog(BalsaWindow * window)
or NULL.
*/
void
-check_new_messages_real(BalsaWindow * window, int type)
+check_new_messages_real(BalsaWindow * window, gboolean background_check)
{
GSList *list;
struct check_messages_thread_info *info;
@@ -3317,36 +3312,34 @@ check_new_messages_real(BalsaWindow * window, int type)
list = NULL;
/* Only Run once -- If already checking mail, return. */
- g_mutex_lock(&checking_mail_lock);
- if (checking_mail) {
- g_mutex_unlock(&checking_mail_lock);
- fprintf(stderr, "Already Checking Mail!\n");
- if (progress_dialog)
- gtk_window_present(GTK_WINDOW(progress_dialog));
+ if (!g_atomic_int_dec_and_test(&checking_mail)) {
+ g_atomic_int_inc(&checking_mail);
+ g_debug("Already Checking Mail!");
+ g_mutex_lock(&progress_dialog.mutex);
+ if (progress_dialog.dialog != NULL) {
+ gtk_window_present(GTK_WINDOW(progress_dialog.dialog));
+ }
+ g_mutex_unlock(&progress_dialog.mutex);
return;
}
- checking_mail = TRUE;
+
if (window)
bw_action_set_enabled(window, "get-new-mail", FALSE);
- quiet_check = (type == TYPE_CALLBACK)
- ? 0 : balsa_app.quiet_background_check;
-
- g_mutex_unlock(&checking_mail_lock);
-
- if (type == TYPE_CALLBACK &&
- (balsa_app.pwindow_option == WHILERETR ||
- (balsa_app.pwindow_option == UNTILCLOSED && progress_dialog)))
- ensure_check_mail_dialog(window);
-
gtk_tree_model_foreach(GTK_TREE_MODEL(balsa_app.mblist_tree_store),
(GtkTreeModelForeachFunc) bw_add_mbox_to_checklist,
&list);
- /* initiate threads */
+ /* initiate thread */
info = g_new(struct check_messages_thread_info, 1);
info->list = list;
+ info->with_progress_dialog = !background_check && balsa_app.recv_progress_dialog;
info->window = window ? g_object_ref(window) : window;
+ info->with_activity_bar = background_check && !balsa_app.quiet_background_check && (info->window !=
NULL);
+ if (info->with_activity_bar) {
+ balsa_window_increase_activity(info->window, _("Checking Mail…"));
+ }
+
get_mail_thread =
g_thread_new("bw_check_messages_thread",
(GThreadFunc) bw_check_messages_thread,
@@ -3362,7 +3355,7 @@ check_new_messages_real(BalsaWindow * window, int type)
static void
bw_check_new_messages(gpointer data)
{
- check_new_messages_real(data, TYPE_CALLBACK);
+ check_new_messages_real(data, FALSE);
if (balsa_app.check_mail_auto) {
/* restart the timer */
@@ -3409,31 +3402,30 @@ check_new_messages_count(LibBalsaMailbox * mailbox, gboolean notify)
/* this one is called only in the threaded code */
static void
-bw_mailbox_check(LibBalsaMailbox * mailbox, BalsaWindow * window)
+bw_mailbox_check(LibBalsaMailbox * mailbox, struct check_messages_thread_info *info)
{
- MailThreadMessage *threadmessage;
- gchar *string = NULL;
-
if (libbalsa_mailbox_get_subscribe(mailbox) == LB_MAILBOX_SUBSCRIBE_NO)
return;
+ g_debug("checking mailbox %s", mailbox->name);
if (LIBBALSA_IS_MAILBOX_IMAP(mailbox)) {
- if (window && !window->network_available) {
- return;
- }
-
- string = g_strdup_printf(_("IMAP mailbox: %s"), mailbox->url);
- if (balsa_app.debug)
- fprintf(stderr, "%s\n", string);
+ if ((info->window != NULL) && !info->window->network_available) {
+ return;
+ }
+
+ if (info->with_progress_dialog) {
+ libbalsa_progress_dialog_update(&progress_dialog, _("Mailboxes"), FALSE, INFINITY,
+ _("IMAP mailbox: %s"), mailbox->url);
+ }
} else if (LIBBALSA_IS_MAILBOX_LOCAL(mailbox)) {
- string = g_strdup_printf(_("Local mailbox: %s"), mailbox->name);
+ if (info->with_progress_dialog) {
+ libbalsa_progress_dialog_update(&progress_dialog, _("Mailboxes"), FALSE, INFINITY,
+ _("Local mailbox: %s"), mailbox->name);
+ }
} else {
- g_assert_not_reached();
+ g_assert_not_reached();
}
- MSGMAILTHREAD(threadmessage, LIBBALSA_NTFY_SOURCE, NULL, string, 0, 0);
- g_free(string);
-
libbalsa_mailbox_check(mailbox);
}
@@ -3454,21 +3446,27 @@ bw_check_messages_thread(struct check_messages_thread_info *info)
* and that the calling procedure will check for an existing lock
* and set checking_mail to true before calling.
*/
- MailThreadMessage *threadmessage;
- GSList *list = info->list;
-
- MSGMAILTHREAD(threadmessage, LIBBALSA_NTFY_SOURCE, NULL, "POP3", 0, 0);
- bw_check_mailbox_list(info->window, balsa_app.inbox_input);
-
- g_slist_foreach(list, (GFunc) bw_mailbox_check, info->window);
- g_slist_foreach(list, (GFunc) g_object_unref, NULL);
- g_slist_free(list);
+ bw_check_mailbox_list(info, balsa_app.inbox_input);
+
+ if (info->list!= NULL) {
+ GSList *list = info->list;
+
+ if (info->with_progress_dialog) {
+ libbalsa_progress_dialog_ensure(&progress_dialog, _("Checking Mail…"),
GTK_WINDOW(info->window), _("Mailboxes"));
+ }
+ g_slist_foreach(list, (GFunc) bw_mailbox_check, info);
+ g_slist_foreach(list, (GFunc) g_object_unref, NULL);
+ g_slist_free(list);
+ if (info->with_progress_dialog) {
+ libbalsa_progress_dialog_update(&progress_dialog, _("Mailboxes"), TRUE, 1.0, NULL);
+ }
+ }
- MSGMAILTHREAD(threadmessage, LIBBALSA_NTFY_FINISHED, NULL, "Finished",
- 0, 0);
+ if (info->with_activity_bar) {
+ balsa_window_decrease_activity(info->window, _("Checking Mail…"));
+ }
- g_mutex_lock(&checking_mail_lock);
- checking_mail = FALSE;
+ g_atomic_int_inc(&checking_mail);
if (info->window) {
g_idle_add((GSourceFunc) bw_check_messages_thread_idle_cb,
@@ -3477,151 +3475,11 @@ bw_check_messages_thread(struct check_messages_thread_info *info)
time(&info->window->last_check_time);
g_object_unref(info->window);
}
- g_mutex_unlock(&checking_mail_lock);
g_free(info);
g_thread_exit(0);
}
-/* mail_progress_notify_cb:
- called from the thread checking the new mail. Basically does the GUI
- interaction because checking thread cannot do it.
-*/
-gboolean
-mail_progress_notify_cb(GIOChannel * source, GIOCondition condition,
- BalsaWindow ** window)
-{
- const int MSG_BUFFER_SIZE = 512 * sizeof(MailThreadMessage *);
- MailThreadMessage *threadmessage;
- MailThreadMessage **currentpos;
- void *msgbuffer;
- ssize_t count;
- gfloat fraction;
- GtkStatusbar *statusbar;
- guint context_id;
-
- msgbuffer = g_malloc(MSG_BUFFER_SIZE);
- count = read(mail_thread_pipes[0], msgbuffer, MSG_BUFFER_SIZE);
-
- /* FIXME: imagine reading just half of the pointer. The sync is gone.. */
- if (count % sizeof(MailThreadMessage *)) {
- g_free(msgbuffer);
- return TRUE;
- }
-
- currentpos = (MailThreadMessage **) msgbuffer;
-
- if (quiet_check || !*window) {
- /* Eat messages */
- while (count) {
- threadmessage = *currentpos;
- g_free(threadmessage);
- currentpos++;
- count -= sizeof(void *);
- }
- g_free(msgbuffer);
- return TRUE;
- }
-
- statusbar = GTK_STATUSBAR((*window)->statusbar);
- context_id = gtk_statusbar_get_context_id(statusbar, "BalsaWindow mail progress");
-
- while (count) {
- threadmessage = *currentpos;
-
- if (balsa_app.debug)
- fprintf(stderr, "Message: %lu, %d, %s\n",
- (unsigned long) threadmessage,
- threadmessage->message_type,
- threadmessage->message_string);
-
- if (!progress_dialog)
- gtk_statusbar_pop(statusbar, context_id);
-
- switch (threadmessage->message_type) {
- case LIBBALSA_NTFY_SOURCE:
- if (progress_dialog) {
- gtk_label_set_text(GTK_LABEL(progress_dialog_source),
- threadmessage->message_string);
- gtk_label_set_text(GTK_LABEL(progress_dialog_message), "");
- gtk_widget_show_all(progress_dialog);
- } else
- gtk_statusbar_push(statusbar, context_id,
- threadmessage->message_string);
- break;
- case LIBBALSA_NTFY_MSGINFO:
- if (progress_dialog) {
- gtk_label_set_text(GTK_LABEL(progress_dialog_message),
- threadmessage->message_string);
- gtk_widget_show_all(progress_dialog);
- } else
- gtk_statusbar_push(statusbar, context_id,
- threadmessage->message_string);
- break;
- case LIBBALSA_NTFY_UPDATECONFIG:
- config_mailbox_update(threadmessage->mailbox);
- break;
-
- case LIBBALSA_NTFY_PROGRESS:
- fraction = (gfloat) threadmessage->num_bytes /
- (gfloat) threadmessage->tot_bytes;
- if (fraction > 1.0 || fraction < 0.0) {
- if (balsa_app.debug)
- fprintf(stderr,
- "progress bar fraction out of range %f\n",
- fraction);
- fraction = 1.0;
- }
- if (progress_dialog) {
- gtk_label_set_text(GTK_LABEL(progress_dialog_message),
- threadmessage->message_string);
- gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR
- (progress_dialog_bar),
- fraction);
- } else {
- gtk_statusbar_push(statusbar, context_id,
- threadmessage->message_string);
- gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR
- ((*window)->progress_bar),
- fraction);
- }
- break;
- case LIBBALSA_NTFY_FINISHED:
-
- if (balsa_app.pwindow_option == WHILERETR && progress_dialog) {
- gtk_widget_destroy(progress_dialog);
- } else if (progress_dialog) {
- gtk_label_set_text(GTK_LABEL(progress_dialog_source),
- _("Finished Checking."));
- gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR
- (progress_dialog_bar), 0.0);
- } else {
- gtk_statusbar_pop(statusbar, context_id);
- gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR
- ((*window)->progress_bar), 0.0);
- }
- break;
-
- case LIBBALSA_NTFY_ERROR:
- balsa_information(LIBBALSA_INFORMATION_ERROR,
- "%s",
- threadmessage->message_string);
- break;
-
- default:
- fprintf(stderr, " Unknown check mail message(%d): %s\n",
- threadmessage->message_type,
- threadmessage->message_string);
- }
- g_free(threadmessage);
- currentpos++;
- count -= sizeof(void *);
- }
- g_free(msgbuffer);
-
- return TRUE;
-}
-
/** Returns properly formatted string informing the user about the
amount of the new mail.
diff --git a/src/main-window.h b/src/main-window.h
index 731b4dc..0b5fd0d 100644
--- a/src/main-window.h
+++ b/src/main-window.h
@@ -42,12 +42,6 @@
(G_TYPE_INSTANCE_GET_CLASS ((window), BALSA_TYPE_WINDOW, \
BalsaWindowClass))
-/* Type values for mailbox checking */
-enum MailboxCheckType {
- TYPE_BACKGROUND,
- TYPE_CALLBACK
-};
-
typedef struct _BalsaWindow BalsaWindow;
typedef struct _BalsaWindowClass BalsaWindowClass;
typedef enum {
@@ -140,7 +134,7 @@ gboolean mail_progress_notify_cb(GIOChannel * source,
gboolean send_progress_notify_cb(GIOChannel * source,
GIOCondition condition,
BalsaWindow ** window);
-void check_new_messages_real(BalsaWindow * window, int type);
+void check_new_messages_real(BalsaWindow * window, gboolean background_check);
void check_new_messages_count(LibBalsaMailbox * mailbox, gboolean notify);
void empty_trash(BalsaWindow * window);
void update_view_menu(BalsaWindow * window);
diff --git a/src/main.c b/src/main.c
index 77eb9dd..77746dd 100644
--- a/src/main.c
+++ b/src/main.c
@@ -47,7 +47,6 @@
#include "information.h"
#include "imap-server.h"
#include "libbalsa-conf.h"
-#include "threads.h"
#include "libinit_balsa/assistant_init.h"
@@ -56,15 +55,6 @@
#include "libbalsa-gpgme-cb.h"
#endif
-/* Globals for Thread creation, messaging, pipe I/O */
-gboolean checking_mail;
-int mail_thread_pipes[2];
-GIOChannel *mail_thread_msg_send;
-GIOChannel *mail_thread_msg_receive;
-
-static void threads_init(void);
-static void threads_destroy(void);
-
static void config_init(gboolean check_only);
static void mailboxes_init(gboolean check_only);
static void balsa_cleanup(void);
@@ -103,7 +93,7 @@ accel_map_save(void)
static gboolean
balsa_main_check_new_messages(gpointer data)
{
- check_new_messages_real(data, TYPE_CALLBACK);
+ check_new_messages_real(data, FALSE);
return FALSE;
}
@@ -168,28 +158,6 @@ mailboxes_init(gboolean check_only)
}
}
-GMutex checking_mail_lock;
-
-static void
-threads_init(void)
-{
- if (pipe(mail_thread_pipes) < 0) {
- g_log("BALSA Init", G_LOG_LEVEL_DEBUG,
- "Error opening pipes.\n");
- }
- mail_thread_msg_send = g_io_channel_unix_new(mail_thread_pipes[1]);
- mail_thread_msg_receive =
- g_io_channel_unix_new(mail_thread_pipes[0]);
- g_io_add_watch(mail_thread_msg_receive, G_IO_IN,
- (GIOFunc) mail_progress_notify_cb,
- &balsa_app.main_window);
-}
-
-static void
-threads_destroy(void)
-{
- g_mutex_clear(&checking_mail_lock);
-}
/* initial_open_mailboxes:
open mailboxes on startup if requested so.
@@ -515,9 +483,6 @@ real_main(int argc, char *argv[])
setlocale(LC_ALL, "");
#endif
- /* initiate thread mutexs, variables */
- threads_init();
-
#ifdef HAVE_RUBRICA
/* initialise libxml */
LIBXML_TEST_VERSION
@@ -603,8 +568,6 @@ real_main(int argc, char *argv[])
balsa_cleanup();
accel_map_save();
- threads_destroy();
-
libbalsa_imap_server_close_all_connections();
return 0;
}
diff --git a/src/pref-manager.c b/src/pref-manager.c
index 781bd62..fb0ffae 100644
--- a/src/pref-manager.c
+++ b/src/pref-manager.c
@@ -108,7 +108,8 @@ typedef struct _PropertyUI {
GtkWidget *view_allheaders;
GtkWidget *debug; /* enable/disable debugging */
GtkWidget *empty_trash;
- GtkRadioButton *pwindow_type[NUM_PWINDOW_MODES];
+ GtkWidget *recv_progress_dlg;
+ GtkWidget *send_progress_dlg;
GtkWidget *wordwrap;
GtkWidget *wraplength;
GtkWidget *open_inbox_upon_startup;
@@ -402,12 +403,8 @@ apply_prefs(GtkDialog * pbox)
/*
* display page
*/
- for (i = 0; i < NUM_PWINDOW_MODES; i++)
- if (gtk_toggle_button_get_active
- (GTK_TOGGLE_BUTTON(pui->pwindow_type[i]))) {
- balsa_app.pwindow_option = pwindow_type[i];
- break;
- }
+ balsa_app.recv_progress_dialog = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->recv_progress_dlg));
+ balsa_app.send_progress_dialog = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->send_progress_dlg));
balsa_app.debug =
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->debug));
@@ -660,12 +657,8 @@ set_prefs(void)
unsigned i;
gchar *tmp;
- for (i = 0; i < NUM_PWINDOW_MODES; i++)
- if (balsa_app.pwindow_option == pwindow_type[i]) {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
- (pui->pwindow_type[i]), TRUE);
- break;
- }
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pui->recv_progress_dlg), balsa_app.recv_progress_dialog);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pui->send_progress_dlg), balsa_app.send_progress_dialog);
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER
(pui->mail_directory),
@@ -2702,19 +2695,10 @@ pm_grid_add_progress_group(GtkWidget * grid_widget)
{
GtkGrid *grid = (GtkGrid *) grid_widget;
gint row = pm_grid_get_next_row(grid);
- GSList *radio_group;
- gint i;
pm_grid_attach(grid, pm_group_label(_("Display progress dialog")), 0, row, 3, 1);
-
- radio_group = NULL;
- for (i = 0; i < NUM_PWINDOW_MODES; i++) {
- pui->pwindow_type[i] =
- GTK_RADIO_BUTTON(gtk_radio_button_new_with_label
- (radio_group, _(pwindow_type_label[i])));
- pm_grid_attach(grid, GTK_WIDGET(pui->pwindow_type[i]), 1, ++row, 2, 1);
- radio_group = gtk_radio_button_get_group(pui->pwindow_type[i]);
- }
+ pui->send_progress_dlg = pm_grid_attach_check(grid, 1, ++row, 2, 1, _("Display progress dialog when
sending messages"));
+ pui->recv_progress_dlg = pm_grid_attach_check(grid, 1, ++row, 2, 1, _("Display progress dialog when
retrieving messages"));
pm_grid_set_next_row(grid, ++row);
}
@@ -3375,11 +3359,10 @@ open_preferences_manager(GtkWidget * widget, gpointer data)
gtk_dialog_set_response_sensitive(GTK_DIALOG(property_box),
GTK_RESPONSE_APPLY, FALSE);
- for (i = 0; i < NUM_PWINDOW_MODES; i++) {
- g_signal_connect(G_OBJECT(pui->pwindow_type[i]), "clicked",
- G_CALLBACK(properties_modified_cb), property_box);
- }
-
+ g_signal_connect(G_OBJECT(pui->recv_progress_dlg), "toggled",
+ G_CALLBACK(properties_modified_cb), property_box);
+ g_signal_connect(G_OBJECT(pui->send_progress_dlg), "toggled",
+ G_CALLBACK(properties_modified_cb), property_box);
g_signal_connect(G_OBJECT(pui->previewpane), "toggled",
G_CALLBACK(properties_modified_cb), property_box);
g_signal_connect(G_OBJECT(pui->layout_type), "changed",
diff --git a/src/save-restore.c b/src/save-restore.c
index 50e0243..5906516 100644
--- a/src/save-restore.c
+++ b/src/save-restore.c
@@ -37,7 +37,6 @@
#include "filter-funcs.h"
#include "mailbox-filter.h"
#include "libbalsa-conf.h"
-#include "threads.h"
#include "smtp-server.h"
#include "send.h"
@@ -369,28 +368,6 @@ gint config_folder_update(BalsaMailboxNode * mbnode)
return res;
} /* config_folder_update */
-static void
-pop3_progress_notify(LibBalsaMailbox* mailbox, int msg_type, int prog, int tot,
- const char* msg)
-{
- MailThreadMessage *message;
-
- message = g_new(MailThreadMessage, 1);
- message->message_type = msg_type;
- memcpy(message->message_string, msg, strlen(msg) + 1);
- message->num_bytes = prog;
- message->tot_bytes = tot;
-
- /* FIXME: There is potential for a timeout with
- * the server here, if we don't get the lock back
- * soon enough.. But it prevents the main thread from
- * blocking on the mutt_lock, andthe pipe filling up.
- * This would give us a deadlock.
- */
- if (write(mail_thread_pipes[1], (void *) &message, sizeof(void *))
- != sizeof(void *))
- g_warning("pipe error");
-}
/* Initialize the specified mailbox, creating the internal data
structures which represent the mailbox. */
@@ -415,9 +392,6 @@ config_mailbox_init(const gchar * prefix)
}
if (LIBBALSA_IS_MAILBOX_POP3(mailbox)) {
- g_signal_connect(G_OBJECT(mailbox),
- "progress-notify", G_CALLBACK(pop3_progress_notify),
- mailbox);
balsa_app.inbox_input =
g_list_prepend(balsa_app.inbox_input,
balsa_mailbox_node_new_from_mailbox(mailbox));
@@ -787,8 +761,9 @@ config_global_load(void)
balsa_app.show_sos_bar =
libbalsa_conf_get_bool("ShowSOSbar=true");
- /* ... Progress Window Dialog */
- balsa_app.pwindow_option = d_get_gint("ProgressWindow", WHILERETR);
+ /* ... Progress Window Dialogs */
+ balsa_app.recv_progress_dialog = libbalsa_conf_get_bool("ShowRecvProgressDlg=true");
+ balsa_app.send_progress_dialog = libbalsa_conf_get_bool("ShowSendProgressDlg=true");
/* ... deleting messages: defaults enshrined here */
filter_mask = libbalsa_mailbox_get_filter(NULL);
@@ -1275,7 +1250,8 @@ config_save(void)
libbalsa_conf_set_bool("ShowPreviewPane", balsa_app.previewpane);
libbalsa_conf_set_bool("ShowMailboxList", balsa_app.show_mblist);
libbalsa_conf_set_bool("ShowTabs", balsa_app.show_notebook_tabs);
- libbalsa_conf_set_int("ProgressWindow", balsa_app.pwindow_option);
+ libbalsa_conf_set_bool("ShowRecvProgressDlg", balsa_app.recv_progress_dialog);
+ libbalsa_conf_set_bool("ShowSendProgressDlg", balsa_app.send_progress_dialog);
libbalsa_conf_set_int("LayoutType", balsa_app.layout_type);
libbalsa_conf_set_bool("ViewMessageOnOpen", balsa_app.view_message_on_open);
libbalsa_conf_set_bool("AskBeforeSelect", balsa_app.ask_before_select);
diff --git a/src/sendmsg-window.c b/src/sendmsg-window.c
index df8bd91..1b1bec2 100644
--- a/src/sendmsg-window.c
+++ b/src/sendmsg-window.c
@@ -59,7 +59,6 @@
#include "balsa-message.h"
#include "balsa-index.h"
#include "balsa-icons.h"
-#include "threads.h"
#include "missing.h"
#include "ab-window.h"
@@ -5244,6 +5243,7 @@ send_message_handler(BalsaSendmsg * bsmsg, gboolean queue_only)
result = libbalsa_message_send(message, balsa_app.outbox, fcc,
balsa_find_sentbox_by_url,
bsmsg->ident->smtp_server,
+ balsa_app.send_progress_dialog,
GTK_WINDOW(balsa_app.main_window),
bsmsg->flow, &error);
if (result == LIBBALSA_MESSAGE_CREATE_OK) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]