X-Git-Url: http://git.maemo.org/git/?p=modest;a=blobdiff_plain;f=src%2Fmaemo%2Fmodest-progress-bar-widget.c;h=fd6708fab1a9e8c5168e6eaae92bbf905ce5451c;hp=a229d75905cc228eadbbb3f2713bce3d37250ffb;hb=fcbc6a6dfa1a10921d2ca889256a21b192adbe98;hpb=7c0c35878201fec6167f53a941fbf4d9a3ed14d2 diff --git a/src/maemo/modest-progress-bar-widget.c b/src/maemo/modest-progress-bar-widget.c index a229d75..fd6708f 100644 --- a/src/maemo/modest-progress-bar-widget.c +++ b/src/maemo/modest-progress-bar-widget.c @@ -32,30 +32,82 @@ #include #include "modest-progress-bar-widget.h" #include +#include "modest-platform.h" +#include "modest-runtime.h" /* 'private'/'protected' functions */ static void modest_progress_bar_widget_class_init (ModestProgressBarWidgetClass *klass); static void modest_progress_bar_widget_init (ModestProgressBarWidget *obj); static void modest_progress_bar_widget_finalize (GObject *obj); + +static void modest_progress_bar_add_operation (ModestProgressObject *self, + ModestMailOperation *mail_op); + +static void modest_progress_bar_remove_operation (ModestProgressObject *self, + ModestMailOperation *mail_op); + +static void modest_progress_bar_cancel_current_operation (ModestProgressObject *self); + +static void modest_progress_bar_cancel_all_operations (ModestProgressObject *self); + +static guint modest_progress_bar_num_pending_operations (ModestProgressObject *self); + +static void on_progress_changed (ModestMailOperation *mail_op, + ModestMailOperationState *state, + ModestProgressBarWidget *self); + +static gboolean progressbar_clean (GtkProgressBar *bar); + +#define XALIGN 0.5 +#define YALIGN 0.5 +#define XSPACE 1 +#define YSPACE 0 + +#define LOWER 0 +#define UPPER 150 + /* list my signals */ /* enum { */ /* LAST_SIGNAL */ /* }; */ +typedef struct _ObservableData ObservableData; +struct _ObservableData { + guint signal_handler; + ModestMailOperation *mail_op; +}; + typedef struct _ModestProgressBarWidgetPrivate ModestProgressBarWidgetPrivate; struct _ModestProgressBarWidgetPrivate { - GtkWidget *bar; + GSList *observables; + ModestMailOperation *current; + guint count; + GtkWidget *progress_bar; }; #define MODEST_PROGRESS_BAR_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ MODEST_TYPE_PROGRESS_BAR_WIDGET, \ ModestProgressBarWidgetPrivate)) + /* globals */ static GtkContainerClass *parent_class = NULL; /* uncomment the following if you have defined any signals */ /* static guint signals[LAST_SIGNAL] = {0}; */ +static void +modest_progress_object_init (gpointer g, gpointer iface_data) +{ + ModestProgressObjectIface *klass = (ModestProgressObjectIface *)g; + + klass->add_operation_func = modest_progress_bar_add_operation; + klass->remove_operation_func = modest_progress_bar_remove_operation; + klass->cancel_current_operation_func = modest_progress_bar_cancel_current_operation; + klass->cancel_all_operations_func = modest_progress_bar_cancel_all_operations; + klass->num_pending_operations_func = modest_progress_bar_num_pending_operations; +} + + GType modest_progress_bar_widget_get_type (void) { @@ -73,9 +125,20 @@ modest_progress_bar_widget_get_type (void) (GInstanceInitFunc) modest_progress_bar_widget_init, NULL }; + + static const GInterfaceInfo modest_progress_object_info = + { + (GInterfaceInitFunc) modest_progress_object_init, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + my_type = g_type_register_static (GTK_TYPE_VBOX, "ModestProgressBarWidget", &my_info, 0); + + g_type_add_interface_static (my_type, MODEST_TYPE_PROGRESS_OBJECT, + &modest_progress_object_info); } return my_type; } @@ -103,85 +166,318 @@ modest_progress_bar_widget_class_init (ModestProgressBarWidgetClass *klass) } static void -modest_progress_bar_widget_init (ModestProgressBarWidget *obj) +modest_progress_bar_widget_init (ModestProgressBarWidget *self) { - ModestProgressBarWidgetPrivate *priv; - priv = MODEST_PROGRESS_BAR_WIDGET_GET_PRIVATE(obj); - priv->bar = NULL; -} + ModestProgressBarWidgetPrivate *priv; + GtkWidget *align = NULL; + GtkRequisition req; + GtkAdjustment *adj; + + priv = MODEST_PROGRESS_BAR_WIDGET_GET_PRIVATE(self); + + /* Alignment */ + align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE); + /* Build GtkProgressBar */ + adj = (GtkAdjustment *) gtk_adjustment_new (0, LOWER, UPPER, 0, 0, 0); + priv->progress_bar = gtk_progress_bar_new_with_adjustment (adj); + req.width = 228; + req.height = 64; + gtk_progress_set_text_alignment (GTK_PROGRESS (priv->progress_bar), 0, 0.5); + gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (priv->progress_bar), PANGO_ELLIPSIZE_END); + gtk_progress_bar_set_pulse_step (GTK_PROGRESS_BAR (priv->progress_bar), 0.05); + gtk_widget_size_request (priv->progress_bar, &req); + gtk_container_add (GTK_CONTAINER (align), priv->progress_bar); + gtk_widget_size_request (align, &req); + + /* Add progress bar widget */ + gtk_box_pack_start (GTK_BOX(self), align, TRUE, TRUE, 0); + gtk_widget_show_all (GTK_WIDGET(self)); +} static void modest_progress_bar_widget_finalize (GObject *obj) { + ModestProgressBarWidgetPrivate *priv; + + priv = MODEST_PROGRESS_BAR_WIDGET_GET_PRIVATE(obj); + if (priv->observables) { + GSList *tmp; + + for (tmp = priv->observables; tmp; tmp = g_slist_next (tmp)) { + ObservableData *ob_data = tmp->data; + g_signal_handler_disconnect (ob_data->mail_op, ob_data->signal_handler); + g_object_unref (ob_data->mail_op); + g_free (ob_data); + } + g_slist_free (priv->observables); + priv->observables = NULL; + } + G_OBJECT_CLASS(parent_class)->finalize (obj); } -GtkWidget* -modest_progress_bar_widget_new () + +static void +modest_progress_bar_add_operation (ModestProgressObject *self, + ModestMailOperation *mail_op) { - GObject *obj; - ModestProgressBarWidget *self; + ModestProgressBarWidget *me = NULL; + ObservableData *data = NULL; + ModestProgressBarWidgetPrivate *priv = NULL; + + me = MODEST_PROGRESS_BAR_WIDGET (self); + priv = MODEST_PROGRESS_BAR_WIDGET_GET_PRIVATE (me); + + data = g_malloc0 (sizeof (ObservableData)); + data->mail_op = g_object_ref (mail_op); + data->signal_handler = g_signal_connect (data->mail_op, + "progress-changed", + G_CALLBACK (on_progress_changed), + me); + /* Set curent operation */ + if (priv->current == NULL) { + priv->current = mail_op; + + priv->count = 0; + + /* Call progress_change handler to initialize progress message */ + modest_progress_bar_widget_set_undetermined_progress (MODEST_PROGRESS_BAR_WIDGET(self), mail_op); + } + + /* Add operation to obserbable objects list */ + priv->observables = g_slist_prepend (priv->observables, data); +} + +static gint +compare_observable_data (ObservableData *data1, ObservableData *data2) +{ + if (data1->mail_op == data2->mail_op) + return 0; + else + return 1; +} + +static void +modest_progress_bar_remove_operation (ModestProgressObject *self, + ModestMailOperation *mail_op) +{ + ModestProgressBarWidget *me; ModestProgressBarWidgetPrivate *priv; - GtkRequisition req; + GSList *link; + ObservableData *tmp_data = NULL; + gboolean is_current; + + me = MODEST_PROGRESS_BAR_WIDGET (self); + priv = MODEST_PROGRESS_BAR_WIDGET_GET_PRIVATE (me); + + is_current = (priv->current == mail_op); + + /* Find item */ + tmp_data = g_malloc0 (sizeof (ObservableData)); + tmp_data->mail_op = mail_op; + link = g_slist_find_custom (priv->observables, + tmp_data, + (GCompareFunc) compare_observable_data); + + /* Remove the item */ + if (link) { + ObservableData *ob_data = link->data; + g_signal_handler_disconnect (ob_data->mail_op, ob_data->signal_handler); + g_object_unref (ob_data->mail_op); + g_free (ob_data); + priv->observables = g_slist_delete_link (priv->observables, link); + tmp_data->mail_op = NULL; + link = NULL; + } + /* Update the current mail operation */ + if (is_current) { + if (priv->observables) + priv->current = ((ObservableData *) priv->observables->data)->mail_op; + else + priv->current = NULL; - obj = g_object_new(MODEST_TYPE_PROGRESS_BAR_WIDGET, NULL); - self = MODEST_PROGRESS_BAR_WIDGET(obj); - priv = MODEST_PROGRESS_BAR_WIDGET_GET_PRIVATE(self); + /* Refresh the view */ + progressbar_clean (GTK_PROGRESS_BAR (priv->progress_bar)); + } - /* Build GtkProgressBar */ - priv->bar = gtk_progress_bar_new (); - req.width = 50; - req.height = 64; - gtk_progress_set_text_alignment (GTK_PROGRESS (priv->bar), 0.0, 0.5); - gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (priv->bar), PANGO_ELLIPSIZE_END); - gtk_widget_size_request (priv->bar, &req); + /* free */ + g_free(tmp_data); +} + +static guint +modest_progress_bar_num_pending_operations (ModestProgressObject *self) +{ + ModestProgressBarWidget *me; + ModestProgressBarWidgetPrivate *priv; - /* Add progress bar widget */ - gtk_box_pack_start (GTK_BOX(self), priv->bar, TRUE, TRUE, 2); - gtk_widget_show_all (GTK_WIDGET(self)); + me = MODEST_PROGRESS_BAR_WIDGET (self); + priv = MODEST_PROGRESS_BAR_WIDGET_GET_PRIVATE (me); + + return g_slist_length(priv->observables); +} - return GTK_WIDGET(self); +static void +modest_progress_bar_cancel_current_operation (ModestProgressObject *self) +{ + ModestProgressBarWidget *me; + ModestProgressBarWidgetPrivate *priv; + + me = MODEST_PROGRESS_BAR_WIDGET (self); + priv = MODEST_PROGRESS_BAR_WIDGET_GET_PRIVATE (me); + + if (priv->current == NULL) return; + + modest_mail_operation_cancel (priv->current); } +static void +modest_progress_bar_cancel_all_operations (ModestProgressObject *self) +{ + ModestProgressBarWidget *me; + ModestProgressBarWidgetPrivate *priv; -void -modest_progress_bar_widget_set_status (ModestProgressBarWidget *self, - guint id) + me = MODEST_PROGRESS_BAR_WIDGET (self); + priv = MODEST_PROGRESS_BAR_WIDGET_GET_PRIVATE (me); + + /* Cancel all the mail operations */ + modest_mail_operation_queue_cancel_all (modest_runtime_get_mail_operation_queue ()); +} + +static void +on_progress_changed (ModestMailOperation *mail_op, + ModestMailOperationState *state, + ModestProgressBarWidget *self) { ModestProgressBarWidgetPrivate *priv; - gchar *status = NULL; gboolean determined = FALSE; - guint d1 = 0, d2 = 0; - priv = MODEST_PROGRESS_BAR_WIDGET_GET_PRIVATE(self); + priv = MODEST_PROGRESS_BAR_WIDGET_GET_PRIVATE (self); + + /* If the mail operation is the currently shown one */ + if (priv->current == mail_op) { + gchar *msg = NULL; + + determined = (state->done > 0 && state->total > 1) && + !(state->done == 1 && state->total == 100); - switch (id) { - case STATUS_RECEIVING: - if (determined) - status = g_strdup_printf(_("mcen_me_receiving"), d1, d2); - else - status = g_strdup(_("mail_me_receiving")); - break; - case STATUS_SENDING: - if (determined) - status = g_strdup_printf(_("mcen_me_sending"), d1, d2); - else - status = g_strdup(_("mail_me_sending")); - break; - - case STATUS_OPENING: - status = g_strdup(_("mail_me_opening")); - break; - default: - g_return_if_reached(); + switch (state->op_type) { + case MODEST_MAIL_OPERATION_TYPE_RECEIVE: + if (determined) + msg = g_strdup_printf(_("mcen_me_receiving"), + state->done, state->total); + else + msg = g_strdup(_("mail_me_receiving")); + break; + case MODEST_MAIL_OPERATION_TYPE_SEND: + if (determined) + msg = g_strdup_printf(_("mcen_me_sending"), state->done, + state->total); + else + msg = g_strdup(_("mail_me_sending")); + break; + + case MODEST_MAIL_OPERATION_TYPE_OPEN: + msg = g_strdup(_("mail_me_opening")); + break; + default: + msg = g_strdup(""); + } + + /* If we have byte information use it */ + if ((state->bytes_done != 0) && (state->bytes_total != 0)) + modest_progress_bar_widget_set_progress (self, msg, + state->bytes_done, + state->bytes_total); + else + modest_progress_bar_widget_set_progress (self, msg, + state->done, + state->total); + g_free (msg); } +} + +static gboolean +progressbar_clean (GtkProgressBar *bar) +{ + gtk_progress_bar_set_fraction (bar, 0); + gtk_progress_bar_set_text (bar, 0); + return FALSE; +} + + +GtkWidget* +modest_progress_bar_widget_new () +{ + return GTK_WIDGET (g_object_new (MODEST_TYPE_PROGRESS_BAR_WIDGET, NULL)); +} + + +void +modest_progress_bar_widget_set_progress (ModestProgressBarWidget *self, + const gchar *message, + gint done, + gint total) +{ + ModestProgressBarWidgetPrivate *priv; + gboolean determined = FALSE; + + g_return_if_fail (MODEST_IS_PROGRESS_BAR_WIDGET(self)); + g_return_if_fail (done <= total); - gtk_progress_bar_set_text (GTK_PROGRESS_BAR(priv->bar), status); - gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(priv->bar), 0.5); + priv = MODEST_PROGRESS_BAR_WIDGET_GET_PRIVATE (self); + + priv->count++; + + /* Set progress. Tinymail sometimes returns us 1/100 when it + does not have any clue, NOTE that 1/100 could be also a + valid progress (we will loose it), but it will be recovered + once the done is greater than 1 */ + determined = (done > 0 && total > 1) && + !(done == 1 && total == 100); +/* if ((done == 0 && total == 0) || */ +/* (done == 1 && total == 100)) { */ + if (!determined) { + gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (priv->progress_bar), /* Deprecated */ + GTK_PROGRESS_CONTINUOUS); + gtk_progress_bar_pulse (GTK_PROGRESS_BAR (priv->progress_bar)); +/* printf ("debug: %s:\n undetermined progress (%i) changed (%i/%i) : %i\n", __FUNCTION__, */ +/* (int) priv->progress_bar, */ +/* done, */ +/* total, */ +/* priv->count); */ + } else { + gdouble percent = 0; + if (total != 0) /* Avoid division by zero. */ + percent = (gdouble)done/(gdouble)total; + + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->progress_bar), + percent); + +/* printf ("debug: %s:\n determined progress (%i) changed (%i/%i) : %i\n", __FUNCTION__, */ +/* (int) priv->progress_bar, */ +/* done, */ +/* total, */ +/* priv->count); */ + } - /* free*/ - g_free(status); + /* Set text */ + gtk_progress_bar_set_text (GTK_PROGRESS_BAR (priv->progress_bar), message); +} + + +void +modest_progress_bar_widget_set_undetermined_progress (ModestProgressBarWidget *self, + ModestMailOperation *mail_op) +{ + ModestMailOperationState *state = NULL; + + state = g_malloc0(sizeof(ModestMailOperationState)); + state->done = 0; + state->total = 0; + state->op_type = modest_mail_operation_get_type_operation (mail_op); + on_progress_changed (mail_op, state, self); + g_free(state); }