From 10f4d89635e5693323031cc4408f02fcd148eb3e Mon Sep 17 00:00:00 2001 From: Javier Fernandez Garcia-Boente Date: Thu, 26 Apr 2007 19:15:21 +0000 Subject: [PATCH] * Implement Observer pattern using ModestProgressBarWidget. * Adds an observer to mail operation queue into main window to establish toolbar operation mode. pmo-trunk-r1680 --- src/maemo/modest-main-window.c | 112 ++++++++++++---- src/maemo/modest-progress-bar-widget.c | 227 ++++++++++++++++++++++++++------ src/maemo/modest-progress-bar-widget.h | 4 +- src/widgets/modest-header-view.c | 1 - 4 files changed, 277 insertions(+), 67 deletions(-) diff --git a/src/maemo/modest-main-window.c b/src/maemo/modest-main-window.c index 69bae99..67e0fbe 100644 --- a/src/maemo/modest-main-window.c +++ b/src/maemo/modest-main-window.c @@ -71,6 +71,11 @@ static void save_sizes (ModestMainWindow *self); static void modest_main_window_show_toolbar (ModestWindow *window, gboolean show_toolbar); +static void on_queue_changed (ModestMailOperationQueue *queue, + ModestMailOperation *mail_op, + ModestMailOperationQueueNotification type, + ModestMainWindow *self); + static void on_account_update (TnyAccountStore *account_store, gchar *account_name, gpointer user_data); @@ -107,10 +112,17 @@ struct _ModestMainWindowPrivate { GtkWidget *progress_bar; GSList *progress_widgets; + /* Tollbar items */ + GtkWidget *progress_toolitem; + GtkWidget *cancel_toolitem; + GtkWidget *sort_toolitem; + GtkWidget *refresh_toolitem; + /* On-demand widgets */ GtkWidget *accounts_popup; GtkWidget *details_widget; + ModestHeaderView *header_view; ModestFolderView *folder_view; @@ -345,6 +357,12 @@ connect_signals (ModestMainWindow *self) NULL); g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self); + /* Mail Operation Queue */ + g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()), + "queue-changed", + G_CALLBACK (on_queue_changed), + self); + /* Track changes in the device name */ g_signal_connect (G_OBJECT(modest_runtime_get_conf ()), "key_changed", @@ -643,14 +661,19 @@ modest_main_window_show_toolbar (ModestWindow *self, /* Add ProgressBar (Transfer toolbar) */ priv->progress_bar = modest_progress_bar_widget_new (); gtk_widget_set_no_show_all (priv->progress_bar, TRUE); - modest_progress_bar_widget_set_status (MODEST_PROGRESS_BAR_WIDGET(priv->progress_bar), 0); placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView"); insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder)); tool_item = GTK_WIDGET (gtk_tool_item_new ()); +/* gtk_widget_set_no_show_all (tool_item, TRUE); */ gtk_container_add (GTK_CONTAINER (tool_item), priv->progress_bar); /* gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE); */ /* gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE); */ gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index); + + priv->progress_toolitem = tool_item; + priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel"); + priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive"); + priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort"); /* Add it to the observers list */ priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar); @@ -992,45 +1015,84 @@ static void set_toolbar_mode (ModestMainWindow *self, ModestToolBarModes mode) { - ModestMainWindowPrivate *priv; ModestWindowPrivate *parent_priv; - GtkAction *action; - gboolean transfer_mode= FALSE; - gboolean normal_mode= FALSE; - + ModestMainWindowPrivate *priv; + GtkAction *sort_action, *refresh_action, *cancel_action; g_return_if_fail (MODEST_IS_MAIN_WINDOW (self)); priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self); - parent_priv = MODEST_WINDOW_GET_PRIVATE (self); + parent_priv = MODEST_WINDOW_GET_PRIVATE(self); + + cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel"); + sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort"); + refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive"); switch (mode) { case TOOLBAR_MODE_NORMAL: - normal_mode = TRUE; - transfer_mode = FALSE; +/* gtk_action_set_visible (sort_action, TRUE); */ +/* gtk_action_set_visible (refresh_action, TRUE); */ +/* gtk_action_set_visible (cancel_action, FALSE); */ +/* gtk_widget_hide (priv->progress_toolitem); */ +/* gtk_widget_hide (priv->progress_bar); */ + gtk_widget_show (priv->sort_toolitem); + gtk_widget_show (priv->refresh_toolitem); gtk_widget_hide (priv->progress_bar); + gtk_widget_hide (priv->cancel_toolitem); break; case TOOLBAR_MODE_TRANSFER: - normal_mode = FALSE; - transfer_mode = TRUE; +/* gtk_action_set_visible (sort_action, FALSE); */ +/* gtk_action_set_visible (refresh_action, FALSE); */ +/* gtk_action_set_visible (cancel_action, TRUE); */ +/* gtk_widget_show (priv->progress_toolitem); */ +/* gtk_widget_show (priv->progress_bar); */ + gtk_widget_hide (priv->sort_toolitem); + gtk_widget_hide (priv->refresh_toolitem); gtk_widget_show (priv->progress_bar); + gtk_widget_show (priv->cancel_toolitem); break; default: - normal_mode = TRUE; - transfer_mode = FALSE; +/* gtk_action_set_visible (sort_action, TRUE); */ +/* gtk_action_set_visible (refresh_action, TRUE); */ +/* gtk_action_set_visible (cancel_action, FALSE); */ +/* gtk_widget_hide (priv->progress_toolitem); */ +/* gtk_widget_hide (priv->progress_bar); */ + gtk_widget_show (priv->sort_toolitem); + gtk_widget_show (priv->refresh_toolitem); gtk_widget_hide (priv->progress_bar); + gtk_widget_hide (priv->cancel_toolitem); } +} - /* Transfer mode toolitems */ - action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel"); - if (action != NULL) - gtk_action_set_visible (action, transfer_mode); - - /* Normal mode toolitems */ - action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort"); - if (action != NULL) - gtk_action_set_visible (action, normal_mode); - action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive"); - if (action != NULL) - gtk_action_set_visible (action, normal_mode); +static void +on_queue_changed (ModestMailOperationQueue *queue, + ModestMailOperation *mail_op, + ModestMailOperationQueueNotification type, + ModestMainWindow *self) +{ + GSList *tmp; + ModestMainWindowPrivate *priv; + + priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self); + + tmp = priv->progress_widgets; + + switch (type) { + case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED: + set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER); + while (tmp) { + modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data), + mail_op); + tmp = g_slist_next (tmp); + } + break; + case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED: + set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL); + while (tmp) { + modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data), + mail_op); + tmp = g_slist_next (tmp); + } + break; + } } diff --git a/src/maemo/modest-progress-bar-widget.c b/src/maemo/modest-progress-bar-widget.c index a229d75..38f63fb 100644 --- a/src/maemo/modest-progress-bar-widget.c +++ b/src/maemo/modest-progress-bar-widget.c @@ -37,14 +37,35 @@ 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 on_progress_changed (ModestMailOperation *mail_op, + ModestProgressBarWidget *self); + +static gboolean progressbar_clean (GtkProgressBar *bar); + /* 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; + + GtkWidget *progress_bar; }; #define MODEST_PROGRESS_BAR_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ @@ -56,6 +77,16 @@ 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; +} + + GType modest_progress_bar_widget_get_type (void) { @@ -73,9 +104,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; } @@ -108,9 +150,15 @@ modest_progress_bar_widget_init (ModestProgressBarWidget *obj) ModestProgressBarWidgetPrivate *priv; priv = MODEST_PROGRESS_BAR_WIDGET_GET_PRIVATE(obj); - priv->bar = NULL; + priv->progress_bar = NULL; } +static void +destroy_observable_data (ObservableData *data) +{ + g_signal_handler_disconnect (data->mail_op, data->signal_handler); + g_object_unref (data->mail_op); +} static void modest_progress_bar_widget_finalize (GObject *obj) @@ -118,6 +166,124 @@ modest_progress_bar_widget_finalize (GObject *obj) G_OBJECT_CLASS(parent_class)->finalize (obj); } + +static void +modest_progress_bar_add_operation (ModestProgressObject *self, + ModestMailOperation *mail_op) +{ + ModestProgressBarWidget *me; + ObservableData *data; + ModestProgressBarWidgetPrivate *priv; + + 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); + + if (priv->observables == NULL) { + priv->current = mail_op; + } + priv->observables = g_slist_append (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; + GSList *link; + + me = MODEST_PROGRESS_BAR_WIDGET (self); + priv = MODEST_PROGRESS_BAR_WIDGET_GET_PRIVATE (me); + + link = g_slist_find_custom (priv->observables, + mail_op, + (GCompareFunc) compare_observable_data); + + /* Remove the item */ + if (link) { + priv->observables = g_slist_remove_link (priv->observables, link); + destroy_observable_data ((ObservableData *) link->data); + } + + /* Update the current mail operation */ + if (priv->current == mail_op) { + if (priv->observables) + priv->current = ((ObservableData *) priv->observables->data)->mail_op; + else + priv->current = NULL; + + /* Refresh the view */ + progressbar_clean (GTK_PROGRESS_BAR (priv->progress_bar)); + } +} + +static void +on_progress_changed (ModestMailOperation *mail_op, + ModestProgressBarWidget *self) +{ + ModestProgressBarWidgetPrivate *priv; + gboolean determined = FALSE; + guint id = 0; + + 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; + gint done = modest_mail_operation_get_task_done (mail_op); + gint total = modest_mail_operation_get_task_total (mail_op); + + switch (id) { + case STATUS_RECEIVING: + if (determined) + msg = g_strdup_printf(_("mcen_me_receiving"), done, total); + else + msg = g_strdup(_("mail_me_receiving")); + break; + case STATUS_SENDING: + if (determined) + msg = g_strdup_printf(_("mcen_me_sending"), done, total); + else + msg = g_strdup(_("mail_me_sending")); + break; + + case STATUS_OPENING: + msg = g_strdup(_("mail_me_opening")); + break; + default: + g_return_if_reached(); + } + + modest_progress_bar_widget_set_progress (self, msg, done, 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 () { @@ -132,15 +298,15 @@ modest_progress_bar_widget_new () priv = MODEST_PROGRESS_BAR_WIDGET_GET_PRIVATE(self); /* Build GtkProgressBar */ - priv->bar = gtk_progress_bar_new (); + priv->progress_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); + gtk_progress_set_text_alignment (GTK_PROGRESS (priv->progress_bar), 0.0, 0.5); + gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (priv->progress_bar), PANGO_ELLIPSIZE_END); + gtk_widget_size_request (priv->progress_bar, &req); /* Add progress bar widget */ - gtk_box_pack_start (GTK_BOX(self), priv->bar, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX(self), priv->progress_bar, TRUE, TRUE, 2); gtk_widget_show_all (GTK_WIDGET(self)); return GTK_WIDGET(self); @@ -148,40 +314,23 @@ modest_progress_bar_widget_new () void -modest_progress_bar_widget_set_status (ModestProgressBarWidget *self, - guint id) +modest_progress_bar_widget_set_progress (ModestProgressBarWidget *self, + const gchar *message, + gint done, + gint total) { ModestProgressBarWidgetPrivate *priv; - gchar *status = NULL; - gboolean determined = FALSE; - guint d1 = 0, d2 = 0; - - priv = MODEST_PROGRESS_BAR_WIDGET_GET_PRIVATE(self); - - 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(); - } - 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); - /* free*/ - g_free(status); + /* Set progress */ + if (total != 0) + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->progress_bar), + (gdouble)done/(gdouble)total); + else + gtk_progress_bar_pulse (GTK_PROGRESS_BAR (priv->progress_bar)); + + /* Set text */ + gtk_progress_bar_set_text (GTK_PROGRESS_BAR (priv->progress_bar), message); } + diff --git a/src/maemo/modest-progress-bar-widget.h b/src/maemo/modest-progress-bar-widget.h index f3674e4..c4a5754 100644 --- a/src/maemo/modest-progress-bar-widget.h +++ b/src/maemo/modest-progress-bar-widget.h @@ -31,7 +31,7 @@ #define __MODEST_PROGRESS_BAR_WIDGET_H__ #include -#include +#include "modest-progress-object.h" G_BEGIN_DECLS @@ -69,7 +69,7 @@ GType modest_progress_bar_widget_get_type (void) G_GNUC_CONST; GtkWidget* modest_progress_bar_widget_new (); -void modest_progress_bar_widget_set_status (ModestProgressBarWidget *self, guint id); +void modest_progress_bar_widget_set_progress (ModestProgressBarWidget *self, const gchar *msg, gint done, gint total); diff --git a/src/widgets/modest-header-view.c b/src/widgets/modest-header-view.c index 7a08798..c2265ba 100644 --- a/src/widgets/modest-header-view.c +++ b/src/widgets/modest-header-view.c @@ -831,7 +831,6 @@ modest_header_view_set_folder_intern (ModestHeaderView *self, TnyFolder *folder) /* Set new model */ modest_header_view_set_model (GTK_TREE_VIEW (self), sortable); g_object_unref (G_OBJECT (sortable)); - g_object_unref (G_OBJECT (folder)); } void -- 1.7.9.5