From 1386f3b566f5b5c9aa2ea4d0a5a6157502a45b4f Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Mon, 2 Apr 2007 08:29:13 +0000 Subject: [PATCH] * Added Progress Object * Added Gnome info bar * Ported mail operation calls to the new design * Removed non-common code from UI actions pmo-trunk-r1470 --- src/Makefile.am | 2 + src/gnome/Makefile.am | 5 +- src/gnome/modest-gnome-info-bar.c | 322 ++++++++++++++++++++++++++++++++ src/gnome/modest-gnome-info-bar.h | 69 +++++++ src/gnome/modest-main-window-ui.h | 2 +- src/gnome/modest-main-window.c | 132 +++++++++---- src/modest-mail-operation-queue.c | 51 ++++- src/modest-mail-operation-queue.h | 10 + src/modest-mail-operation.c | 369 ++++++++++++++++++++++++------------- src/modest-mail-operation.h | 51 +++-- src/modest-marshal.list | 1 + src/modest-progress-object.c | 80 ++++++++ src/modest-progress-object.h | 66 +++++++ src/modest-ui-actions.c | 150 ++++----------- src/modest-ui-actions.h | 6 - src/widgets/Makefile.am | 3 +- src/widgets/modest-folder-view.c | 88 ++++----- src/widgets/modest-header-view.c | 96 ++++++---- src/widgets/modest-main-window.h | 2 - 19 files changed, 1111 insertions(+), 394 deletions(-) create mode 100644 src/gnome/modest-gnome-info-bar.c create mode 100644 src/gnome/modest-gnome-info-bar.h create mode 100644 src/modest-progress-object.c create mode 100644 src/modest-progress-object.h diff --git a/src/Makefile.am b/src/Makefile.am index 5ead243..2b7a7bc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -56,6 +56,8 @@ modest_SOURCES=\ modest-pair.c\ modest-pair.h\ modest-platform.h\ + modest-progress-object.c\ + modest-progress-object.h\ modest-protocol-info.c\ modest-protocol-info.h\ modest-runtime.c\ diff --git a/src/gnome/Makefile.am b/src/gnome/Makefile.am index a951862..70c9d0b 100644 --- a/src/gnome/Makefile.am +++ b/src/gnome/Makefile.am @@ -27,13 +27,16 @@ libmodest_ui_la_SOURCES= \ modest-account-assistant.c \ modest-account-assistant.h \ modest-account-view-window.c \ - modest-address-book.c \ + modest-address-book.c \ modest-msg-edit-window.c \ modest-icon-names.h \ + modest-gnome-info-bar.c \ + modest-gnome-info-bar.h \ modest-main-window.c \ modest-main-window-ui.h \ modest-msg-view-window.c \ modest-platform.c \ + modest-platform.c \ modest-store-widget.c \ modest-store-widget.h \ modest-transport-widget.c \ diff --git a/src/gnome/modest-gnome-info-bar.c b/src/gnome/modest-gnome-info-bar.c new file mode 100644 index 0000000..bb16282 --- /dev/null +++ b/src/gnome/modest-gnome-info-bar.c @@ -0,0 +1,322 @@ +/* modest-gnome-bar.c */ + +/* insert (c)/licensing information) */ + +#include "modest-gnome-info-bar.h" +#include +#include +/* include other impl specific header files */ + +/* 'private'/'protected' functions */ +static void modest_gnome_info_bar_class_init (ModestGnomeInfoBarClass *klass); +static void modest_gnome_info_bar_init (ModestGnomeInfoBar *obj); +static void modest_gnome_info_bar_finalize (GObject *obj); + +static void modest_gnome_info_bar_add_operation (ModestProgressObject *self, + ModestMailOperation *mail_op); + +static void modest_gnome_info_bar_remove_operation (ModestProgressObject *self, + ModestMailOperation *mail_op); + +static void on_progress_changed (ModestMailOperation *mail_op, + ModestGnomeInfoBar *self); + +static gboolean progressbar_clean (GtkProgressBar *bar); +static gboolean statusbar_clean (GtkStatusbar *bar); + +/* list my signals */ +enum { + /* MY_SIGNAL_1, */ + /* MY_SIGNAL_2, */ + LAST_SIGNAL +}; + +typedef struct _ObservableData ObservableData; +struct _ObservableData { + guint signal_handler; + ModestMailOperation *mail_op; +}; + +typedef struct _ModestGnomeInfoBarPrivate ModestGnomeInfoBarPrivate; +struct _ModestGnomeInfoBarPrivate { + GSList *observables; + ModestMailOperation *current; + + GtkWidget *status_bar; + GtkWidget *progress_bar; + + guint status_bar_timeout; + guint progress_bar_timeout; +}; + +#define MODEST_GNOME_INFO_BAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ + MODEST_TYPE_GNOME_INFO_BAR, \ + ModestGnomeInfoBarPrivate)) +/* globals */ +static GtkHBoxClass *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_gnome_info_bar_add_operation; + klass->remove_operation_func = modest_gnome_info_bar_remove_operation; +} + +GType +modest_gnome_info_bar_get_type (void) +{ + static GType my_type = 0; + if (!my_type) { + static const GTypeInfo my_info = { + sizeof(ModestGnomeInfoBarClass), + NULL, /* base init */ + NULL, /* base finalize */ + (GClassInitFunc) modest_gnome_info_bar_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof(ModestGnomeInfoBar), + 1, /* n_preallocs */ + (GInstanceInitFunc) modest_gnome_info_bar_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_HBOX, + "ModestGnomeInfoBar", + &my_info, 0); + + g_type_add_interface_static (my_type, MODEST_TYPE_PROGRESS_OBJECT, + &modest_progress_object_info); + } + return my_type; +} + +static void +modest_gnome_info_bar_class_init (ModestGnomeInfoBarClass *klass) +{ + GObjectClass *gobject_class; + gobject_class = (GObjectClass*) klass; + + parent_class = g_type_class_peek_parent (klass); + gobject_class->finalize = modest_gnome_info_bar_finalize; + + g_type_class_add_private (gobject_class, sizeof(ModestGnomeInfoBarPrivate)); +} + +static void +modest_gnome_info_bar_init (ModestGnomeInfoBar *obj) +{ + ModestGnomeInfoBarPrivate *priv = MODEST_GNOME_INFO_BAR_GET_PRIVATE(obj); + + priv->observables = NULL; + priv->current = NULL; + + /* Status bar */ + priv->status_bar = gtk_statusbar_new (); + gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (priv->status_bar), FALSE); + + /* Progress bar */ + priv->progress_bar = gtk_progress_bar_new (); + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->progress_bar), 1.0); + gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (priv->progress_bar), + PANGO_ELLIPSIZE_END); + + /* Timeouts */ + priv->status_bar_timeout = 0; + priv->progress_bar_timeout = 0; + + /* Pack */ + gtk_box_pack_start (GTK_BOX (obj), priv->status_bar, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (obj), priv->progress_bar, FALSE, FALSE, 0); +} + +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_gnome_info_bar_finalize (GObject *obj) +{ + ModestGnomeInfoBarPrivate *priv; + + priv = MODEST_GNOME_INFO_BAR_GET_PRIVATE(obj); + if (priv->observables) { + GSList *tmp; + + for (tmp = priv->observables; tmp; tmp = g_slist_next (tmp)) { + destroy_observable_data ((ObservableData *) tmp->data); + g_free (tmp->data); + } + g_slist_free (priv->observables); + priv->observables = NULL; + } + + if (priv->status_bar_timeout > 0) { + g_source_remove (priv->status_bar_timeout); + priv->status_bar_timeout = 0; + } + + if (priv->progress_bar_timeout > 0) { + g_source_remove (priv->progress_bar_timeout); + priv->progress_bar_timeout = 0; + } + + G_OBJECT_CLASS(parent_class)->finalize (obj); +} + +GtkWidget * +modest_gnome_info_bar_new (void) +{ + return GTK_WIDGET (g_object_new (MODEST_TYPE_GNOME_INFO_BAR, NULL)); +} + +static void +modest_gnome_info_bar_add_operation (ModestProgressObject *self, + ModestMailOperation *mail_op) +{ + ModestGnomeInfoBar *me; + ObservableData *data; + ModestGnomeInfoBarPrivate *priv; + + me = MODEST_GNOME_INFO_BAR (self); + priv = MODEST_GNOME_INFO_BAR_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_gnome_info_bar_remove_operation (ModestProgressObject *self, + ModestMailOperation *mail_op) +{ + ModestGnomeInfoBar *me; + ModestGnomeInfoBarPrivate *priv; + GSList *link; + + me = MODEST_GNOME_INFO_BAR (self); + priv = MODEST_GNOME_INFO_BAR_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, + ModestGnomeInfoBar *self) +{ + ModestGnomeInfoBarPrivate *priv; + + priv = MODEST_GNOME_INFO_BAR_GET_PRIVATE (self); + + /* If the mail operation is the currently shown one */ + if (priv->current == mail_op) { + gchar *msg = NULL; + + msg = g_strdup_printf ("Mail operation %d of %d", + modest_mail_operation_get_task_done (mail_op), + modest_mail_operation_get_task_total (mail_op)); + modest_gnome_info_bar_set_message (self, msg); + 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; +} + +static gboolean +statusbar_clean (GtkStatusbar *bar) +{ + gtk_statusbar_push (bar, 0, ""); + return FALSE; +} + +void +modest_gnome_info_bar_set_message (ModestGnomeInfoBar *self, + const gchar *message) +{ + ModestGnomeInfoBarPrivate *priv; + + priv = MODEST_GNOME_INFO_BAR_GET_PRIVATE (self); + + /* Set a message. Clean it after 2.5 seconds */ + gtk_statusbar_push (GTK_STATUSBAR (priv->status_bar), 0, message); + priv->status_bar_timeout = g_timeout_add (2500, + (GSourceFunc) statusbar_clean, + priv->status_bar); +} + +void +modest_gnome_info_bar_set_progress (ModestGnomeInfoBar *self, + const gchar *message, + gint done, + gint total) +{ + ModestGnomeInfoBarPrivate *priv; + + priv = MODEST_GNOME_INFO_BAR_GET_PRIVATE (self); + + /* 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/gnome/modest-gnome-info-bar.h b/src/gnome/modest-gnome-info-bar.h new file mode 100644 index 0000000..bee3024 --- /dev/null +++ b/src/gnome/modest-gnome-info-bar.h @@ -0,0 +1,69 @@ +/* modest-gnome-bar.h */ +/* insert (c)/licensing information) */ + +#ifndef __MODEST_GNOME_INFO_BAR_H__ +#define __MODEST_GNOME_INFO_BAR_H__ + +#include +#include "modest-progress-object.h" +/* other include files */ + +G_BEGIN_DECLS + +/* convenience macros */ +#define MODEST_TYPE_GNOME_INFO_BAR (modest_gnome_info_bar_get_type()) +#define MODEST_GNOME_INFO_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MODEST_TYPE_GNOME_INFO_BAR,ModestGnomeInfoBar)) +#define MODEST_GNOME_INFO_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MODEST_TYPE_GNOME_INFO_BAR,ModestProgressObject)) +#define MODEST_IS_GNOME_INFO_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MODEST_TYPE_GNOME_INFO_BAR)) +#define MODEST_IS_GNOME_INFO_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MODEST_TYPE_GNOME_INFO_BAR)) +#define MODEST_GNOME_INFO_BAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MODEST_TYPE_GNOME_INFO_BAR,ModestGnomeInfoBarClass)) + +typedef struct _ModestGnomeInfoBar ModestGnomeInfoBar; +typedef struct _ModestGnomeInfoBarClass ModestGnomeInfoBarClass; + +struct _ModestGnomeInfoBar { + GtkHBox parent; +}; + +struct _ModestGnomeInfoBarClass { + GtkHBoxClass parent_class; +}; + +/* member functions */ +GType modest_gnome_info_bar_get_type (void) G_GNUC_CONST; + +/* typical parameter-less _new function */ +GtkWidget* modest_gnome_info_bar_new (void); + +/** + * modest_gnome_info_bar_new: + * @void: + * + * Sets a text in the status bar of the widget + * + * Return value: + **/ +void modest_gnome_info_bar_set_message (ModestGnomeInfoBar *self, + const gchar *message); + + +/** + * modest_gnome_info_bar_set_progress: + * @self: + * @message: + * @done: + * @total: + * + * Causes the progress bar of the widget to fill in the amount of work + * done of a given total. If message is supplied then it'll be + * superimposed on the progress bar + **/ +void modest_gnome_info_bar_set_progress (ModestGnomeInfoBar *self, + const gchar *message, + gint done, + gint total); + +G_END_DECLS + +#endif /* __MODEST_GNOME_INFO_BAR_H__ */ + diff --git a/src/gnome/modest-main-window-ui.h b/src/gnome/modest-main-window-ui.h index ce2f341..61a51ea 100644 --- a/src/gnome/modest-main-window-ui.h +++ b/src/gnome/modest-main-window-ui.h @@ -72,7 +72,7 @@ static const GtkActionEntry modest_action_entries [] = { { "ActionsReplyAll", MODEST_STOCK_REPLY_ALL, N_("Reply to all"), NULL, N_("Reply to all"), G_CALLBACK (modest_ui_actions_on_reply_all) }, { "ActionsForward", MODEST_STOCK_FORWARD, N_("_Forward"), NULL, N_("Forward a message"), G_CALLBACK (modest_ui_actions_on_forward) }, { "ActionsBounce", NULL, N_("_Bounce"), NULL, N_("Bounce a message"), NULL }, - { "ActionsSendReceive", GTK_STOCK_REFRESH, N_("Send/Receive"), NULL, N_("Send and receive messages"), NULL }, + { "ActionsSendReceive", GTK_STOCK_REFRESH, N_("Send/Receive"), NULL, N_("Send and receive messages"), G_CALLBACK (modest_ui_actions_on_send_receive) }, { "ActionsDelete", GTK_STOCK_DELETE, N_("Delete message"), NULL, N_("Delete messages"), G_CALLBACK (modest_ui_actions_on_delete) }, { "ActionsFolderNew", NULL, N_("New Folder"), NULL, N_("Create a new folder"), G_CALLBACK (modest_ui_actions_on_new_folder) }, { "ActionsFolderDelete", NULL, N_("Delete Folder"), NULL, N_("Delete the folder"), G_CALLBACK (modest_ui_actions_on_delete_folder) }, diff --git a/src/gnome/modest-main-window.c b/src/gnome/modest-main-window.c index b8cc009..fde4d4c 100644 --- a/src/gnome/modest-main-window.c +++ b/src/gnome/modest-main-window.c @@ -45,6 +45,7 @@ #include #include "modest-mail-operation.h" #include "modest-icon-names.h" +#include "modest-gnome-info-bar.h" /* 'private'/'protected' functions */ static void modest_main_window_class_init (ModestMainWindowClass *klass); @@ -69,6 +70,16 @@ static gboolean show_context_popup_menu (ModestMainWindow *windo static void connect_signals (ModestMainWindow *self); +static void on_queue_changed (ModestMailOperationQueue *queue, + ModestMailOperation *mail_op, + ModestMailOperationQueueNotification type, + ModestMainWindow *self); + +static void on_header_status_update (ModestHeaderView *header_view, + const gchar *msg, + gint num, + gint total, + ModestMainWindow *main_window); /* list my signals */ enum { @@ -80,12 +91,12 @@ enum { typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate; struct _ModestMainWindowPrivate { - GtkWidget *folder_paned; - GtkWidget *msg_paned; - GtkWidget *main_paned; + GtkWidget *folder_paned; + GtkWidget *msg_paned; + GtkWidget *main_paned; - GtkWidget *online_toggle; - GtkWidget *folder_info_label; + GtkWidget *online_toggle; + GtkWidget *folder_info_label; ModestHeaderView *header_view; ModestFolderView *folder_view; @@ -94,6 +105,8 @@ struct _ModestMainWindowPrivate { GtkWidget *status_bar; GtkWidget *progress_bar; + GSList *progress_widgets; + GtkWidget *main_bar; }; @@ -166,10 +179,11 @@ modest_main_window_init (ModestMainWindow *obj) priv->folder_paned = NULL; priv->msg_paned = NULL; priv->main_paned = NULL; + priv->progress_widgets = NULL; account_store = TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()); - /* online/offline combo */ + /* online/offline toggle */ priv->online_toggle = gtk_toggle_button_new (); online = tny_device_is_online (modest_runtime_get_device()); icon = gtk_image_new_from_icon_name (online ? GTK_STOCK_CONNECT : GTK_STOCK_DISCONNECT, @@ -177,20 +191,16 @@ modest_main_window_init (ModestMainWindow *obj) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(priv->online_toggle), online); gtk_button_set_image (GTK_BUTTON(priv->online_toggle),icon); - /* label with number of items, unread items for - the current folder */ - priv->folder_info_label = gtk_label_new (NULL); - - /* status bar */ - priv->status_bar = gtk_statusbar_new (); - gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR(priv->status_bar), - FALSE); + /* Paned */ + priv->folder_paned = gtk_vpaned_new (); + priv->main_paned = gtk_hpaned_new (); + priv->msg_paned = gtk_vpaned_new (); - /* progress bar */ - priv->progress_bar = gtk_progress_bar_new (); - gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(priv->progress_bar), 1.0); - gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR(priv->progress_bar), - PANGO_ELLIPSIZE_END); + /* Main bar */ + priv->folder_info_label = gtk_label_new (NULL); + priv->main_bar = modest_gnome_info_bar_new (); + priv->progress_widgets = g_slist_prepend (priv->progress_widgets, + priv->main_bar); /* msg preview */ priv->msg_preview = MODEST_MSG_VIEW(modest_msg_view_new (NULL)); @@ -241,10 +251,6 @@ modest_main_window_get_child_widget (ModestMainWindow *self, widget = (GtkWidget*)priv->folder_view; break; case MODEST_WIDGET_TYPE_MSG_PREVIEW: widget = (GtkWidget*)priv->msg_preview; break; - case MODEST_WIDGET_TYPE_STATUS_BAR: - widget = (GtkWidget*)priv->status_bar; break; - case MODEST_WIDGET_TYPE_PROGRESS_BAR: - widget = (GtkWidget*)priv->progress_bar; break; default: g_return_val_if_reached (NULL); return NULL; @@ -391,7 +397,7 @@ connect_signals (ModestMainWindow *self) /* header view */ g_signal_connect (G_OBJECT(priv->header_view), "status_update", - G_CALLBACK(modest_ui_actions_on_header_status_update), self); + G_CALLBACK(on_header_status_update), self); g_signal_connect (G_OBJECT(priv->header_view), "header_selected", G_CALLBACK(modest_ui_actions_on_header_selected), self); g_signal_connect (G_OBJECT(priv->header_view), "header_activated", @@ -422,6 +428,12 @@ connect_signals (ModestMainWindow *self) G_CALLBACK(on_connection_changed), self); g_signal_connect (G_OBJECT(priv->online_toggle), "toggled", G_CALLBACK(on_online_toggle_toggled), self); + + /* Mail Operation Queue */ + g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()), + "queue-changed", + G_CALLBACK (on_queue_changed), + self); /* window */ g_signal_connect (G_OBJECT(self), "destroy", G_CALLBACK(on_destroy), NULL); @@ -474,7 +486,6 @@ modest_main_window_new (void) priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self); parent_priv = MODEST_WINDOW_GET_PRIVATE(self); - /* ***************** */ parent_priv->ui_manager = gtk_ui_manager_new(); action_group = gtk_action_group_new ("ModestMainWindowActions"); @@ -495,7 +506,6 @@ modest_main_window_new (void) g_error_free (error); error = NULL; } - /* *************** */ /* Add accelerators */ gtk_window_add_accel_group (GTK_WINDOW (obj), @@ -505,29 +515,25 @@ modest_main_window_new (void) parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar"); parent_priv->menubar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar"); - gtk_toolbar_set_tooltips (GTK_TOOLBAR (parent_priv->toolbar), TRUE); + gtk_toolbar_set_tooltips (GTK_TOOLBAR (parent_priv->toolbar), TRUE); folder_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->folder_view), FALSE); - header_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->header_view), FALSE); + header_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->header_view), FALSE); - /* paned */ - priv->folder_paned = gtk_vpaned_new (); - priv->msg_paned = gtk_vpaned_new (); - priv->main_paned = gtk_hpaned_new (); + /* Paned */ preview_scroll = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (preview_scroll), + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (preview_scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_paned_add1 (GTK_PANED(priv->main_paned), folder_win); gtk_paned_add2 (GTK_PANED(priv->main_paned), priv->msg_paned); gtk_paned_add1 (GTK_PANED(priv->msg_paned), header_win); - gtk_container_add (GTK_CONTAINER (preview_scroll), + gtk_container_add (GTK_CONTAINER (preview_scroll), GTK_WIDGET(priv->msg_preview)); gtk_paned_add2 (GTK_PANED(priv->msg_paned), preview_scroll); - /* status bar / progress */ + /* Main Bar */ status_hbox = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX(status_hbox), priv->folder_info_label, FALSE,FALSE, 6); - gtk_box_pack_start (GTK_BOX(status_hbox), priv->status_bar, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX(status_hbox), priv->progress_bar,FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX(status_hbox), priv->main_bar, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX(status_hbox), priv->online_toggle,FALSE, FALSE, 0); /* putting it all together... */ @@ -633,3 +639,55 @@ show_context_popup_menu (ModestMainWindow *window, } return TRUE; } + +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: + 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: + while (tmp) { + modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data), + mail_op); + tmp = g_slist_next (tmp); + } + break; + } +} + +static void +on_header_status_update (ModestHeaderView *header_view, + const gchar *msg, gint num, + gint total, ModestMainWindow *self) +{ + ModestMainWindowPrivate *priv; + gchar *txt; + + priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self); + + /* Set progress */ + txt = g_strdup_printf (_("Downloading %d of %d"), num, total); + modest_gnome_info_bar_set_progress (MODEST_GNOME_INFO_BAR (priv->main_bar), + (const gchar*) txt, + num, total); + g_free (txt); + + /* Set status message */ + modest_gnome_info_bar_set_message (MODEST_GNOME_INFO_BAR (priv->main_bar), msg); +} diff --git a/src/modest-mail-operation-queue.c b/src/modest-mail-operation-queue.c index a273b83..cf536b9 100644 --- a/src/modest-mail-operation-queue.c +++ b/src/modest-mail-operation-queue.c @@ -28,7 +28,9 @@ */ #include "config.h" +#include "modest-marshal.h" #include "modest-mail-operation-queue.h" +#include "modest-runtime.h" /* 'private'/'protected' functions */ static void modest_mail_operation_queue_class_init (ModestMailOperationQueueClass *klass); @@ -43,9 +45,8 @@ static void modest_mail_operation_queue_cancel_no_block (ModestMailOpera /* list my signals */ enum { - /* MY_SIGNAL_1, */ - /* MY_SIGNAL_2, */ - LAST_SIGNAL + QUEUE_CHANGED_SIGNAL, + NUM_SIGNALS }; typedef struct _ModestMailOperationQueuePrivate ModestMailOperationQueuePrivate; @@ -59,8 +60,7 @@ struct _ModestMailOperationQueuePrivate { /* globals */ static GObjectClass *parent_class = NULL; -/* uncomment the following if you have defined any signals */ -/* static guint signals[LAST_SIGNAL] = {0}; */ +static guint signals[NUM_SIGNALS] = {0}; GType modest_mail_operation_queue_get_type (void) @@ -98,6 +98,24 @@ modest_mail_operation_queue_class_init (ModestMailOperationQueueClass *klass) gobject_class->finalize = modest_mail_operation_queue_finalize; g_type_class_add_private (gobject_class, sizeof(ModestMailOperationQueuePrivate)); + + /** + * ModestMailOperationQueue::queue-changed + * @self: the #ModestMailOperationQueue that emits the signal + * @mail_op: the #ModestMailOperation affected + * @type: the type of change in the queue + * @user_data: user data set when the signal handler was connected + * + * Emitted whenever the contents of the queue change + */ + signals[QUEUE_CHANGED_SIGNAL] = + g_signal_new ("queue-changed", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ModestMailOperationQueueClass, queue_changed), + NULL, NULL, + modest_marshal_VOID__POINTER_INT, + G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_INT); } static void @@ -154,6 +172,10 @@ modest_mail_operation_queue_add (ModestMailOperationQueue *self, g_mutex_lock (priv->queue_lock); g_queue_push_tail (priv->op_queue, g_object_ref (mail_op)); g_mutex_unlock (priv->queue_lock); + + /* Notify observers */ + g_signal_emit (self, signals[QUEUE_CHANGED_SIGNAL], 0, + mail_op, MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED); } void @@ -170,6 +192,25 @@ modest_mail_operation_queue_remove (ModestMailOperationQueue *self, g_mutex_lock (priv->queue_lock); g_queue_remove (priv->op_queue, mail_op); g_mutex_unlock (priv->queue_lock); + + /* HACK see the documentation of the function. Remove this + call when tinymail provides accurate progress values */ + _modest_mail_operation_notify_end (mail_op); + + /* Notify observers */ + g_signal_emit (self, signals[QUEUE_CHANGED_SIGNAL], 0, + mail_op, MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED); + + /* TODO: errors? */ + { + const GError *err = modest_mail_operation_get_error (mail_op); + if (err) + g_warning (err->message); + } + + /* Free object */ + g_object_unref (G_OBJECT (mail_op)); + modest_runtime_verify_object_death (mail_op, ""); } diff --git a/src/modest-mail-operation-queue.h b/src/modest-mail-operation-queue.h index 7a0759e..bbc33c0 100644 --- a/src/modest-mail-operation-queue.h +++ b/src/modest-mail-operation-queue.h @@ -45,6 +45,11 @@ G_BEGIN_DECLS #define MODEST_IS_MAIL_OPERATION_QUEUE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MODEST_TYPE_MAIL_OPERATION_QUEUE)) #define MODEST_MAIL_OPERATION_QUEUE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MODEST_TYPE_MAIL_OPERATION_QUEUE,ModestMailOperationQueueClass)) +typedef enum _ModestMailOperationQueueNotification { + MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED, + MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED +} ModestMailOperationQueueNotification; + typedef struct _ModestMailOperationQueue ModestMailOperationQueue; typedef struct _ModestMailOperationQueueClass ModestMailOperationQueueClass; @@ -54,6 +59,11 @@ struct _ModestMailOperationQueue { struct _ModestMailOperationQueueClass { GObjectClass parent_class; + + /* Signals */ + void (*queue_changed) (ModestMailOperationQueue *self, + ModestMailOperation *mail_op, + ModestMailOperationQueueNotification type); }; /* member functions */ diff --git a/src/modest-mail-operation.c b/src/modest-mail-operation.c index c4d5b05..cdde44a 100644 --- a/src/modest-mail-operation.c +++ b/src/modest-mail-operation.c @@ -54,15 +54,6 @@ static void modest_mail_operation_class_init (ModestMailOperationClass *klass); static void modest_mail_operation_init (ModestMailOperation *obj); static void modest_mail_operation_finalize (GObject *obj); -static void status_update_cb (TnyFolder *folder, - const gchar *what, - gint status, - gint oftotal, - gpointer user_data); -static void folder_refresh_cb (TnyFolder *folder, - gboolean canceled, - GError **err, - gpointer user_data); static void update_folders_cb (TnyFolderStore *self, TnyList *list, GError **err, @@ -101,6 +92,15 @@ typedef struct _RefreshFolderAsyncHelper } RefreshFolderAsyncHelper; +typedef struct _XFerMsgAsyncHelper +{ + ModestMailOperation *mail_op; + TnyList *headers; + TnyFolder *dest_folder; + +} XFerMsgAsyncHelper; + + /* globals */ static GObjectClass *parent_class = NULL; @@ -149,7 +149,7 @@ modest_mail_operation_class_init (ModestMailOperationClass *klass) * Emitted when the progress of a mail operation changes */ signals[PROGRESS_CHANGED_SIGNAL] = - g_signal_new ("progress_changed", + g_signal_new ("progress-changed", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (ModestMailOperationClass, progress_changed), @@ -202,6 +202,7 @@ modest_mail_operation_send_mail (ModestMailOperation *self, g_return_if_fail (MODEST_IS_MAIL_OPERATION (self)); g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account)); + g_return_if_fail (TNY_IS_MSG (msg)); send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account)); if (!TNY_IS_SEND_QUEUE(send_queue)) @@ -216,6 +217,9 @@ modest_mail_operation_send_mail (ModestMailOperation *self, } else g_message ("modest: message added to send queue"); } + + /* Notify the queue */ + modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self); } void @@ -253,79 +257,46 @@ modest_mail_operation_send_new_mail (ModestMailOperation *self, g_printerr ("modest: failed to create a new msg\n"); return; } - + + /* Call mail operation */ modest_mail_operation_send_mail (self, transport_account, new_msg); - g_object_unref (G_OBJECT(new_msg)); + /* Free */ + g_object_unref (G_OBJECT (new_msg)); } static void -status_update_cb (TnyFolder *folder, const gchar *what, gint status, gint oftotal, gpointer user_data) +recurse_folders (TnyFolderStore *store, TnyFolderStoreQuery *query, TnyList *all_folders) { - g_print ("%s status: %d, of total %d\n", what, status, oftotal); -} + TnyIterator *iter; + TnyList *folders = tny_simple_list_new (); -static void -folder_refresh_cb (TnyFolder *folder, gboolean canceled, GError **err, gpointer user_data) -{ - ModestMailOperation *self = NULL; - ModestMailOperationPrivate *priv = NULL; - RefreshFolderAsyncHelper *helper; + tny_folder_store_get_folders (store, folders, query, NULL); + iter = tny_list_create_iterator (folders); - helper = (RefreshFolderAsyncHelper *) user_data; - self = MODEST_MAIL_OPERATION (helper->mail_op); - priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self); + while (!tny_iterator_is_done (iter)) { - if ((canceled && *err) || *err) { - priv->error = g_error_copy (*err); - helper->failed++; - } else if (canceled) { - helper->canceled++; - g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR, - MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED, - _("Error trying to refresh folder %s. Operation canceled"), - tny_folder_get_name (folder)); - } else { - priv->done++; - } + TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter); - if (priv->done == priv->total) - priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS; - else if ((priv->done + helper->canceled + helper->failed) == priv->total) { - if (helper->failed == priv->total) - priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; - else if (helper->failed == priv->total) - priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED; - else - priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS; - } - tny_iterator_next (helper->iter); - if (tny_iterator_is_done (helper->iter)) { - TnyList *list; - list = tny_iterator_get_list (helper->iter); - g_object_unref (G_OBJECT (helper->iter)); - g_object_unref (G_OBJECT (list)); - g_slice_free (RefreshFolderAsyncHelper, helper); - } else { - TnyFolder *folder = TNY_FOLDER (tny_iterator_get_current (helper->iter)); - if (folder) { - g_message ("modest: refreshing folder %s", - tny_folder_get_name (folder)); - tny_folder_refresh_async (folder, folder_refresh_cb, status_update_cb, helper); - g_object_unref (G_OBJECT(folder)); // FIXME: don't unref yet - } + tny_list_prepend (all_folders, G_OBJECT (folder)); + + recurse_folders (folder, query, all_folders); + + g_object_unref (G_OBJECT (folder)); + + tny_iterator_next (iter); } - g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL); + g_object_unref (G_OBJECT (iter)); + g_object_unref (G_OBJECT (folders)); } - static void update_folders_cb (TnyFolderStore *folder_store, TnyList *list, GError **err, gpointer user_data) { ModestMailOperation *self; ModestMailOperationPrivate *priv; - RefreshFolderAsyncHelper *helper; - TnyFolder *folder; + TnyIterator *iter; + TnyList *all_folders; self = MODEST_MAIL_OPERATION (user_data); priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self); @@ -333,27 +304,58 @@ update_folders_cb (TnyFolderStore *folder_store, TnyList *list, GError **err, gp if (*err) { priv->error = g_error_copy (*err); priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; - return; + goto out; } - priv->total = tny_list_get_length (list); - priv->done = 0; - priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS; + /* Get all the folders We can do it synchronously because + we're already running in a different thread than the UI */ + all_folders = tny_list_copy (list); + iter = tny_list_create_iterator (all_folders); + while (!tny_iterator_is_done (iter)) { + TnyFolderStore *folder = TNY_FOLDER_STORE (tny_iterator_get_current (iter)); - helper = g_slice_new0 (RefreshFolderAsyncHelper); - helper->mail_op = self; - helper->iter = tny_list_create_iterator (list); - helper->failed = 0; - helper->canceled = 0; - - /* Async refresh folders */ - folder = TNY_FOLDER (tny_iterator_get_current (helper->iter)); - if (folder) { - g_message ("modest: refreshing folder %s", tny_folder_get_name (folder)); - tny_folder_refresh_async (folder, folder_refresh_cb, - status_update_cb, helper); + recurse_folders (folder, NULL, all_folders); + tny_iterator_next (iter); } - //g_object_unref (G_OBJECT(folder)); /* FIXME -==> don't unref yet... */ + g_object_unref (G_OBJECT (iter)); + + /* Refresh folders */ + iter = tny_list_create_iterator (all_folders); + priv->total = tny_list_get_length (all_folders); + + while (!tny_iterator_is_done (iter) && !priv->error) { + + TnyFolderStore *folder = TNY_FOLDER_STORE (tny_iterator_get_current (iter)); + + /* Refresh the folder */ + tny_folder_refresh (TNY_FOLDER (folder), &(priv->error)); + + if (priv->error) { + priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; + } else { + /* Update status and notify */ + priv->done++; + g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL); + } + + g_object_unref (G_OBJECT (folder)); + + tny_iterator_next (iter); + } + + g_object_unref (G_OBJECT (iter)); + out: + g_object_unref (G_OBJECT (list)); + + /* Check if the operation was a success */ + if (priv->done == priv->total && !priv->error) + priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS; + + /* Free */ + g_object_unref (G_OBJECT (folder_store)); + + /* Notify the queue */ + modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self); } gboolean @@ -362,25 +364,24 @@ modest_mail_operation_update_account (ModestMailOperation *self, { ModestMailOperationPrivate *priv; TnyList *folders; - TnyFolderStoreQuery *query; g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), FALSE); g_return_val_if_fail (TNY_IS_STORE_ACCOUNT(store_account), FALSE); + /* Pick async call reference */ + g_object_ref (store_account); + priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self); + priv->total = 0; + priv->done = 0; + priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS; + /* Get subscribed folders & refresh them */ folders = TNY_LIST (tny_simple_list_new ()); - query = NULL; //tny_folder_store_query_new (); - /* FIXME: is this needed? */ -// tny_device_force_online (TNY_DEVICE(modest_runtime_get_device())); - - /* FIXME: let query be NULL: do it for all */ - //tny_folder_store_query_add_item (query, NULL, TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED); tny_folder_store_get_folders_async (TNY_FOLDER_STORE (store_account), - folders, update_folders_cb, query, self); - //g_object_unref (query); /* FIXME */ + folders, update_folders_cb, NULL, self); return TRUE; } @@ -476,7 +477,6 @@ modest_mail_operation_create_folder (ModestMailOperation *self, { ModestMailOperationPrivate *priv; TnyFolder *new_folder = NULL; - //TnyStoreAccount *store_account; g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent), NULL); g_return_val_if_fail (name, NULL); @@ -487,12 +487,8 @@ modest_mail_operation_create_folder (ModestMailOperation *self, new_folder = tny_folder_store_create_folder (parent, name, &(priv->error)); CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED, return NULL); -/* /\* Subscribe to folder *\/ */ -/* if (!tny_folder_is_subscribed (new_folder)) { */ -/* store_account = TNY_STORE_ACCOUNT (tny_folder_get_account (TNY_FOLDER (parent))); */ -/* tny_store_account_subscribe (store_account, new_folder); */ -/* g_object_unref (G_OBJECT (store_account)); */ -/* } */ + /* Notify the queue */ + modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self); return new_folder; } @@ -533,6 +529,9 @@ modest_mail_operation_remove_folder (ModestMailOperation *self, g_object_unref (G_OBJECT (parent)); } g_object_unref (G_OBJECT (account)); + + /* Notify the queue */ + modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self); } void @@ -550,11 +549,15 @@ modest_mail_operation_rename_folder (ModestMailOperation *self, /* FIXME: better error handling */ if (strrchr (name, '/') != NULL) - return; + goto out; /* Rename. Camel handles folder subscription/unsubscription */ tny_folder_set_name (folder, name, &(priv->error)); - CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED, return); + CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED, goto out); + + out: + /* Notify the queue */ + modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self); } TnyFolder * @@ -564,6 +567,7 @@ modest_mail_operation_xfer_folder (ModestMailOperation *self, gboolean delete_original) { ModestMailOperationPrivate *priv; + TnyFolder *new_folder; g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL); g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent), NULL); @@ -571,11 +575,16 @@ modest_mail_operation_xfer_folder (ModestMailOperation *self, priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self); - return tny_folder_copy (folder, - parent, - tny_folder_get_name (folder), - delete_original, - &(priv->error)); + new_folder = tny_folder_copy (folder, + parent, + tny_folder_get_name (folder), + delete_original, + &(priv->error)); + + /* Notify the queue */ + modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self); + + return new_folder; } @@ -589,11 +598,16 @@ modest_mail_operation_remove_msg (ModestMailOperation *self, gboolean remove_to_trash) { TnyFolder *folder; + ModestMailOperationPrivate *priv; + g_return_if_fail (MODEST_IS_MAIL_OPERATION (self)); g_return_if_fail (TNY_IS_HEADER (header)); + priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self); folder = tny_header_get_folder (header); + priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS; + /* Delete or move to trash */ if (remove_to_trash) { TnyFolder *trash_folder; @@ -618,20 +632,34 @@ modest_mail_operation_remove_msg (ModestMailOperation *self, g_object_unref (G_OBJECT (store_account)); } else { - tny_folder_remove_msg (folder, header, NULL); /* FIXME */ - tny_folder_sync(folder, TRUE, NULL); /* FIXME */ + tny_folder_remove_msg (folder, header, &(priv->error)); + if (!priv->error) + tny_folder_sync(folder, TRUE, &(priv->error)); } + /* Set status */ + if (!priv->error) + priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS; + else + priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; + /* Free */ - g_object_unref (folder); + g_object_unref (G_OBJECT (folder)); + + /* Notify the queue */ + modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self); } static void transfer_msgs_cb (TnyFolder *folder, GError **err, gpointer user_data) { + XFerMsgAsyncHelper *helper; + ModestMailOperation *self; ModestMailOperationPrivate *priv; - priv = MODEST_MAIL_OPERATION_GET_PRIVATE(user_data); + helper = (XFerMsgAsyncHelper *) user_data; + self = helper->mail_op; + priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self); if (*err) { priv->error = g_error_copy (*err); @@ -642,10 +670,17 @@ transfer_msgs_cb (TnyFolder *folder, GError **err, gpointer user_data) priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS; } - g_signal_emit (G_OBJECT (user_data), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL); + /* Free */ + g_object_unref (helper->headers); + g_object_unref (helper->dest_folder); + g_object_unref (folder); + g_free (helper); + + /* Notify the queue */ + modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self); } -gboolean +void modest_mail_operation_xfer_msg (ModestMailOperation *self, TnyHeader *header, TnyFolder *folder, @@ -654,28 +689,116 @@ modest_mail_operation_xfer_msg (ModestMailOperation *self, ModestMailOperationPrivate *priv; TnyFolder *src_folder; TnyList *headers; + XFerMsgAsyncHelper *helper; - g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), FALSE); - g_return_val_if_fail (TNY_IS_HEADER (header), FALSE); - g_return_val_if_fail (TNY_IS_FOLDER (folder), FALSE); + g_return_if_fail (MODEST_IS_MAIL_OPERATION (self)); + g_return_if_fail (TNY_IS_HEADER (header)); + g_return_if_fail (TNY_IS_FOLDER (folder)); + + /* Pick references for async calls */ + g_object_ref (folder); - src_folder = tny_header_get_folder (header); headers = tny_simple_list_new (); + tny_list_prepend (headers, G_OBJECT (header)); priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self); priv->total = 1; priv->done = 0; priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS; - tny_list_prepend (headers, G_OBJECT (header)); - tny_folder_transfer_msgs_async (src_folder, headers, folder, - delete_original, transfer_msgs_cb, - g_object_ref(self)); + /* Create the helper */ + helper = g_malloc0 (sizeof (XFerMsgAsyncHelper)); + helper->mail_op = self; + helper->dest_folder = folder; + helper->headers = headers; + + src_folder = tny_header_get_folder (header); + tny_folder_transfer_msgs_async (src_folder, + headers, + folder, + delete_original, + transfer_msgs_cb, + helper); +} + +static void +on_refresh_folder (TnyFolder *folder, + gboolean cancelled, + GError **error, + gpointer user_data) +{ + ModestMailOperation *self; + ModestMailOperationPrivate *priv; + + self = MODEST_MAIL_OPERATION (user_data); + priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self); + + if (*error) { + priv->error = g_error_copy (*error); + priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; + goto out; + } + + if (cancelled) { + priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED; + g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR, + MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND, + _("Error trying to refresh the contents of %s"), + tny_folder_get_name (folder)); + goto out; + } + + priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS; + out: /* Free */ - /* FIXME: don't free 'm yet */ - ///g_object_unref (headers); - ///g_object_unref (src_folder); + g_object_unref (folder); - return TRUE; + /* Notify the queue */ + modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self); +} + +static void +on_refresh_folder_status_update (TnyFolder *folder, const gchar *msg, + gint num, gint total, gpointer user_data) +{ + ModestMailOperation *self; + ModestMailOperationPrivate *priv; + + self = MODEST_MAIL_OPERATION (user_data); + priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self); + + priv->done = num; + priv->total = total; + + if (num == 1 && total == 100) + return; + + g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL); +} + +void +modest_mail_operation_refresh_folder (ModestMailOperation *self, + TnyFolder *folder) +{ + ModestMailOperationPrivate *priv; + + priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self); + + /* Pick a reference */ + g_object_ref (folder); + + priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS; + + /* Refresh the folder */ + tny_folder_refresh_async (folder, + on_refresh_folder, + on_refresh_folder_status_update, + self); +} + +void +_modest_mail_operation_notify_end (ModestMailOperation *self) +{ + g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL); } diff --git a/src/modest-mail-operation.h b/src/modest-mail-operation.h index c5f49fb..a2c318d 100644 --- a/src/modest-mail-operation.h +++ b/src/modest-mail-operation.h @@ -135,15 +135,17 @@ void modest_mail_operation_send_new_mail (ModestMailOperation *self, * #ModestMailOperationQueue and then free it. The caller will be * notified by the "progress_changed" signal each time the progress of * the operation changes. + * + * Note that the store account passed as parametter will be freed by + * the mail operation so you must pass a new reference + * * Example * * queue = modest_tny_platform_factory_get_modest_mail_operation_queue_instance (fact) * mail_op = modest_mail_operation_new (); - * g_signal_connect (G_OBJECT (mail_op), "progress_changed", G_CALLBACK(on_progress_changed), queue); - * if (modest_mail_operation_update_account (mail_op, account)) - * { - * modest_mail_operation_queue_add (queue, mail_op); - * } + * g_signal_connect (G_OBJECT (mail_op), "progress_changed", G_CALLBACK(on_progress_changed), NULL); + * modest_mail_operation_queue_add (queue, mail_op); + * modest_mail_operation_update_account (mail_op, account) * g_object_unref (G_OBJECT (mail_op)); * * @@ -246,17 +248,16 @@ TnyFolder* modest_mail_operation_xfer_folder (ModestMailOperation *self, * * queue = modest_tny_platform_factory_get_modest_mail_operation_queue_instance (fact); * mail_op = modest_mail_operation_new (); - * if (modest_mail_operation_xfer_msg (mail_op, header, folder, TRUE)) - * { - * g_signal_connect (G_OBJECT (mail_op), "progress_changed", G_CALLBACK(on_progress_changed), queue); - * modest_mail_operation_queue_add (queue, mail_op); - * } + * modest_mail_operation_queue_add (queue, mail_op); + * g_signal_connect (G_OBJECT (mail_op), "progress_changed", G_CALLBACK(on_progress_changed), queue); + * + * modest_mail_operation_xfer_msg (mail_op, header, folder, TRUE); + * * g_object_unref (G_OBJECT (mail_op)); * * - * Returns: TRUE if the mail operation could be started, or FALSE otherwise **/ -gboolean modest_mail_operation_xfer_msg (ModestMailOperation *self, +void modest_mail_operation_xfer_msg (ModestMailOperation *self, TnyHeader *header, TnyFolder *folder, gboolean delete_original); @@ -313,7 +314,7 @@ guint modest_mail_operation_get_task_total (ModestMailOperation *self); * * Returns: TRUE if the operation is finished, FALSE otherwise **/ -gboolean modest_mail_operation_is_finished (ModestMailOperation *self); +gboolean modest_mail_operation_is_finished (ModestMailOperation *self); /** * modest_mail_operation_is_finished: @@ -344,7 +345,29 @@ const GError* modest_mail_operation_get_error (ModestMailOperation * * Returns: TRUE if the operation was succesfully canceled, FALSE otherwise **/ -gboolean modest_mail_operation_cancel (ModestMailOperation *self); +gboolean modest_mail_operation_cancel (ModestMailOperation *self); + +/** + * modest_mail_operation_refresh_folder + * @self: a #ModestMailOperation + * @folder: the #TnyFolder to refresh + * + * Refreshes the contents of a folder + */ +void modest_mail_operation_refresh_folder (ModestMailOperation *self, + TnyFolder *folder); + +/** + * + * This function is a workarround. It emits the progress-changed + * signal. It's used by the mail operation queue to notify the + * observers attached to that signal that the operation finished. We + * need to use that for the moment because tinymail does not give us + * the progress of a given operation very well. So we must delete it + * when tinymail has that functionality and remove the call to it in + * the queue as well. + */ +void _modest_mail_operation_notify_end (ModestMailOperation *self); G_END_DECLS diff --git a/src/modest-marshal.list b/src/modest-marshal.list index 85f3d34..efa3bdf 100644 --- a/src/modest-marshal.list +++ b/src/modest-marshal.list @@ -6,3 +6,4 @@ VOID:STRING,INT VOID:STRING,INT,INT VOID:STRING,BOOL VOID:STRING,STRING,BOOL +VOID:POINTER,INT diff --git a/src/modest-progress-object.c b/src/modest-progress-object.c new file mode 100644 index 0000000..11d1c5c --- /dev/null +++ b/src/modest-progress-object.c @@ -0,0 +1,80 @@ +/* Copyright (c) 2006, Nokia Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Nokia Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "modest-progress-object.h" + +static void modest_progress_object_base_init (gpointer g_class); + +void +modest_progress_object_add_operation (ModestProgressObject *self, + ModestMailOperation *mail_op) +{ + return MODEST_PROGRESS_OBJECT_GET_IFACE (self)->add_operation_func (self, mail_op); +} + +void +modest_progress_object_remove_operation (ModestProgressObject *self, + ModestMailOperation *mail_op) +{ + return MODEST_PROGRESS_OBJECT_GET_IFACE (self)->remove_operation_func (self, mail_op); +} + +static void +modest_progress_object_base_init (gpointer g_class) +{ + static gboolean initialized = FALSE; + if (!initialized) { + /* create interface signals here */ + initialized = TRUE; + } +} +GType +modest_progress_object_get_type (void) +{ + static GType my_type = 0; + if (!my_type) { + static const GTypeInfo my_info = { + sizeof(ModestProgressObjectIface), + modest_progress_object_base_init, /* base init */ + NULL, /* base finalize */ + NULL, /* class_init */ + NULL, /* class finalize */ + NULL, /* class data */ + 0, + 0, /* n_preallocs */ + NULL, /* instance init */ + }; + my_type = g_type_register_static (G_TYPE_INTERFACE, + "ModestProgressObject", + &my_info, 0); + g_type_interface_add_prerequisite (my_type, G_TYPE_OBJECT); + } + return my_type; +} + diff --git a/src/modest-progress-object.h b/src/modest-progress-object.h new file mode 100644 index 0000000..6ced675 --- /dev/null +++ b/src/modest-progress-object.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2006, Nokia Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Nokia Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MODEST_PROGRESS_OBJECT_H__ +#define __MODEST_PROGRESS_OBJECT_H__ + +/* other include files */ +#include "modest-mail-operation.h" + +G_BEGIN_DECLS + +/* convenience macros */ +#define MODEST_TYPE_PROGRESS_OBJECT (modest_progress_object_get_type()) +#define MODEST_PROGRESS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MODEST_TYPE_PROGRESS_OBJECT,ModestProgressObject)) +#define MODEST_IS_PROGRESS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MODEST_TYPE_PROGRESS_OBJECT)) +#define MODEST_PROGRESS_OBJECT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst),MODEST_TYPE_PROGRESS_OBJECT,ModestProgressObjectIface)) + +typedef struct _ModestProgressObject ModestProgressObject; +typedef struct _ModestProgressObjectIface ModestProgressObjectIface; + +struct _ModestProgressObjectIface { + GTypeInterface parent; + + /* the 'vtable': declare function pointers here, eg.: */ + void (*add_operation_func) (ModestProgressObject *self, ModestMailOperation *mail_op); + void (*remove_operation_func) (ModestProgressObject *self, ModestMailOperation *mail_op); +}; + +GType modest_progress_object_get_type (void) G_GNUC_CONST; + +void modest_progress_object_add_operation (ModestProgressObject *self, + ModestMailOperation *mail_op); + +void modest_progress_object_remove_operation (ModestProgressObject *self, + ModestMailOperation *mail_op); + + +G_END_DECLS + +#endif /* __MODEST_PROGRESS_OBJECT_H__ */ diff --git a/src/modest-ui-actions.c b/src/modest-ui-actions.c index 7aec591..57e10fe 100644 --- a/src/modest-ui-actions.c +++ b/src/modest-ui-actions.c @@ -158,26 +158,24 @@ modest_ui_actions_on_delete (GtkAction *action, ModestWindow *win) header = TNY_HEADER (tny_iterator_get_current (iter)); /* TODO: thick grain mail operation involving a list of objects. Composite pattern ??? */ - mail_op = modest_mail_operation_new (); - /* TODO: add confirmation dialog */ + mail_op = modest_mail_operation_new (); + modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), + mail_op); - /* Move to trash. TODO: Still not supported */ + /* Always delete. TODO: Move to trash still not supported */ modest_mail_operation_remove_msg (mail_op, header, FALSE); - if (modest_mail_operation_get_status (mail_op) != - MODEST_MAIL_OPERATION_STATUS_SUCCESS) { - const GError *error; - error = modest_mail_operation_get_error (mail_op); - if (error) - g_warning (error->message); - } - + /* Frees */ g_object_unref (G_OBJECT (mail_op)); - g_object_unref (header); + g_object_unref (G_OBJECT (header)); + tny_iterator_next (iter); } while (!tny_iterator_is_done (iter)); + + /* Free iter */ + g_object_unref (G_OBJECT (iter)); } } @@ -560,11 +558,14 @@ modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win) return; } + /* Create the mail operation */ mail_op = modest_mail_operation_new (); + modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op); modest_mail_operation_update_account (mail_op, TNY_STORE_ACCOUNT(tny_account)); - g_object_unref (G_OBJECT(tny_account)); - /* g_object_unref (G_OBJECT(mail_op)); FIXME: this is still in use... */ + /* Frees */ + g_object_unref (G_OBJECT (tny_account)); + g_object_unref (G_OBJECT (mail_op)); } @@ -585,7 +586,8 @@ modest_ui_actions_toggle_view (GtkAction *action, ModestMainWindow *main_window) conf = modest_runtime_get_conf (); /* what is saved/restored is depending on the style; thus; we save with - * old style, then update the style, and restore for this new style*/ + * old style, then update the style, and restore for this new style + */ modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view"); if (modest_header_view_get_style @@ -814,56 +816,6 @@ modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view, } } - -/****************************************************/ -/* - * below some stuff to clearup statusbar messages after 1,5 seconds.... - */ -static gboolean -progress_bar_clean (GtkWidget *bar) -{ - if (GTK_IS_PROGRESS_BAR(bar)) { - gtk_progress_bar_set_text (GTK_PROGRESS_BAR(bar), ""); - gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(bar), 1.0); - } - return FALSE; -} - -static gboolean -statusbar_clean (GtkWidget *bar) -{ - if (GTK_IS_STATUSBAR(bar)) - gtk_statusbar_push (GTK_STATUSBAR(bar), 0, ""); - return FALSE; -} - - -static void -statusbar_push (ModestMainWindow *main_window, guint context_id, const gchar *msg) -{ - if (!msg) - return; - - GtkWidget *progress_bar, *status_bar; - - progress_bar = modest_main_window_get_child_widget (main_window, - MODEST_WIDGET_TYPE_PROGRESS_BAR); - status_bar = modest_main_window_get_child_widget (main_window, - MODEST_WIDGET_TYPE_STATUS_BAR); - if (progress_bar) { - gtk_widget_show (progress_bar); - g_timeout_add (3000, (GSourceFunc)progress_bar_clean, progress_bar); - } - - if (status_bar) { - gtk_widget_show (status_bar); - gtk_statusbar_push (GTK_STATUSBAR(status_bar), 0, msg); - g_timeout_add (2500, (GSourceFunc)statusbar_clean, status_bar); - } - -} -/****************************************************************************/ - void modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type, ModestWindow *win) @@ -913,37 +865,6 @@ modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemTyp gdk_threads_leave (); } - - -void -modest_ui_actions_on_header_status_update (ModestHeaderView *header_view, - const gchar *msg, gint num, - gint total, ModestMainWindow *main_window) -{ - char* txt; - GtkWidget *progress_bar; - - g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window)); - - progress_bar = modest_main_window_get_child_widget (main_window, - MODEST_WIDGET_TYPE_PROGRESS_BAR); - if (!progress_bar) - return; - - if (total != 0) - gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar), - (gdouble)num/(gdouble)total); - else - gtk_progress_bar_pulse (GTK_PROGRESS_BAR(progress_bar)); - - txt = g_strdup_printf (_("Downloading %d of %d"), num, total); - gtk_progress_bar_set_text (GTK_PROGRESS_BAR(progress_bar), txt); - g_free (txt); - - statusbar_push (main_window, 0, msg); -} - - void modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link, ModestWindow *win) @@ -1012,8 +933,11 @@ modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window) return; } from = modest_account_mgr_get_from_string (account_mgr, account_name); - + + /* Create the mail operation */ mail_operation = modest_mail_operation_new (); + modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation); + modest_mail_operation_send_new_mail (mail_operation, transport_account, from, @@ -1027,13 +951,12 @@ modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window) /* Frees */ g_free (from); g_free (account_name); - g_object_unref (G_OBJECT (mail_operation)); g_object_unref (G_OBJECT (transport_account)); + g_object_unref (G_OBJECT (mail_operation)); modest_msg_edit_window_free_msg_data (edit_window, data); /* Save settings and close the window */ - /* save_settings (edit_window) */ gtk_widget_destroy (GTK_WIDGET (edit_window)); } @@ -1228,18 +1151,16 @@ modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_windo ModestMailOperation *mail_op; mail_op = modest_mail_operation_new (); + modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), + mail_op); + new_folder = modest_mail_operation_create_folder (mail_op, TNY_FOLDER_STORE (parent_folder), (const gchar *) folder_name); - if (new_folder) { + if (new_folder) g_object_unref (new_folder); - } else { - const GError *error; - error = modest_mail_operation_get_error (mail_op); - if (error) - g_warning ("Error adding a subfolder: %s\n", error->message); - } g_object_unref (mail_op); + g_free (folder_name); } g_object_unref (parent_folder); } @@ -1268,19 +1189,17 @@ modest_ui_actions_on_rename_folder (GtkAction *action, if (folder_name != NULL && strlen (folder_name) > 0) { ModestMailOperation *mail_op; - const GError *error; mail_op = modest_mail_operation_new (); + modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), + mail_op); + modest_mail_operation_rename_folder (mail_op, folder, (const gchar *) folder_name); - error = modest_mail_operation_get_error (mail_op); - if (error) - /* TODO: notify error ? */ - g_warning ("Could not rename a folder: %s\n", error->message); - g_object_unref (mail_op); + g_free (folder_name); } g_object_unref (folder); } @@ -1292,7 +1211,6 @@ delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) TnyFolder *folder; ModestMailOperation *mail_op; GtkWidget *folder_view; - const GError *error; g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window)); @@ -1304,12 +1222,10 @@ delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)); mail_op = modest_mail_operation_new (); + modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), + mail_op); modest_mail_operation_remove_folder (mail_op, folder, move_to_trash); - error = modest_mail_operation_get_error (mail_op); - if (error) - g_warning ("%s\n", error->message); - g_object_unref (G_OBJECT (mail_op)); g_object_unref (G_OBJECT (folder)); } diff --git a/src/modest-ui-actions.h b/src/modest-ui-actions.h index 2add3e1..6c26497 100644 --- a/src/modest-ui-actions.h +++ b/src/modest-ui-actions.h @@ -83,12 +83,6 @@ void modest_ui_actions_on_item_not_found (ModestHeaderView *header ModestItemType type, ModestWindow *window); -void modest_ui_actions_on_header_status_update (ModestHeaderView *header_view, - const gchar *msg, - gint num, - gint total, - ModestMainWindow *main_window); - void modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link, ModestWindow *win); diff --git a/src/widgets/Makefile.am b/src/widgets/Makefile.am index 1a49d87..cb0ff4e 100644 --- a/src/widgets/Makefile.am +++ b/src/widgets/Makefile.am @@ -28,7 +28,6 @@ libmodest_widgets_la_SOURCES= \ modest-combo-box.h \ modest-folder-view.c \ modest-folder-view.h \ - modest-header-view-priv.h \ modest-header-view-render.c \ modest-header-view.c \ modest-header-view.h \ @@ -47,7 +46,7 @@ libmodest_widgets_la_SOURCES= \ modest-tny-stream-gtkhtml.c \ modest-tny-stream-gtkhtml.h \ modest-window.c \ - modest-window.h + modest-window.h LDADD = \ $(MODEST_GSTUFF_LIBS) \ diff --git a/src/widgets/modest-folder-view.c b/src/widgets/modest-folder-view.c index 62904fd..4e90143 100644 --- a/src/widgets/modest-folder-view.c +++ b/src/widgets/modest-folder-view.c @@ -770,32 +770,31 @@ typedef struct _DndHelper { /* * This function is the callback of the - * modest_mail_operation_xfer_msg() call. We check here if the message - * was correctly asynchronously transfered + * modest_mail_operation_xfer_msg() and + * modest_mail_operation_xfer_folder() calls. We check here if the + * message/folder was correctly asynchronously transferred. The reason + * to use the same callback is that the code is the same, it only has + * to check that the operation went fine and then finalize the drag + * and drop action */ static void on_progress_changed (ModestMailOperation *mail_op, gpointer user_data) { - ModestMailOperationQueue *queue; - gboolean success = FALSE; + gboolean success; DndHelper *helper; helper = (DndHelper *) user_data; + if (!modest_mail_operation_is_finished (mail_op)) + return; + if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) { success = TRUE; } else { - const GError *error; - error = modest_mail_operation_get_error (mail_op); - g_warning ("Error transferring messages: %s\n", error->message); + success = FALSE; } - /* Remove the mail operation */ - queue = modest_runtime_get_mail_operation_queue (); - modest_mail_operation_queue_remove (queue, mail_op); - g_object_unref (G_OBJECT (mail_op)); - /* Notify the drag source. Never call delete, the monitor will do the job if needed */ gtk_drag_finish (helper->context, success, FALSE, helper->time); @@ -818,9 +817,7 @@ drag_and_drop_from_header_view (GtkTreeModel *source_model, { TnyHeader *header; TnyFolder *folder; - ModestMailOperationQueue *queue; ModestMailOperation *mail_op; - gboolean started; GtkTreeIter source_iter, dest_iter; /* Get header */ @@ -836,23 +833,13 @@ drag_and_drop_from_header_view (GtkTreeModel *source_model, &folder, -1); /* Transfer message */ - queue = modest_runtime_get_mail_operation_queue (); mail_op = modest_mail_operation_new (); - started = modest_mail_operation_xfer_msg (mail_op, header, - folder, helper->delete_source); - if (started) { - g_signal_connect (G_OBJECT (mail_op), "progress_changed", - G_CALLBACK (on_progress_changed), helper); - modest_mail_operation_queue_add (queue, mail_op); - } else { - const GError *error; - error = modest_mail_operation_get_error (mail_op); - if (error) - g_warning ("Error trying to transfer messages: %s\n", - error->message); + modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), + mail_op); + g_signal_connect (G_OBJECT (mail_op), "progress-changed", + G_CALLBACK (on_progress_changed), helper); - g_slice_free (DndHelper, helper); - } + modest_mail_operation_xfer_msg (mail_op, header, folder, helper->delete_source); /* Frees */ g_object_unref (G_OBJECT (mail_op)); @@ -873,20 +860,21 @@ drag_and_drop_from_folder_view (GtkTreeModel *source_model, DndHelper *helper) { ModestMailOperation *mail_op; - const GError *error; GtkTreeIter parent_iter, iter; - TnyFolder *folder; TnyFolderStore *parent_folder; - gboolean success = FALSE; + TnyFolder *folder; /* Check if the drag is possible */ - if (!gtk_tree_path_compare (helper->source_row, dest_row)) - goto out; - - if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (dest_model), + if (!gtk_tree_path_compare (helper->source_row, dest_row) || + !gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (dest_model), dest_row, - selection_data)) - goto out; + selection_data)) { + + gtk_drag_finish (helper->context, FALSE, FALSE, helper->time); + gtk_tree_path_free (helper->source_row); + g_slice_free (DndHelper, helper); + return; + } /* Get data */ gtk_tree_model_get_iter (source_model, &parent_iter, dest_row); @@ -900,26 +888,20 @@ drag_and_drop_from_folder_view (GtkTreeModel *source_model, /* Do the mail operation */ mail_op = modest_mail_operation_new (); - modest_mail_operation_xfer_folder (mail_op, folder, parent_folder, + modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), + mail_op); + g_signal_connect (G_OBJECT (mail_op), "progress-changed", + G_CALLBACK (on_progress_changed), helper); + + modest_mail_operation_xfer_folder (mail_op, + folder, + parent_folder, helper->delete_source); + /* Frees */ g_object_unref (G_OBJECT (parent_folder)); g_object_unref (G_OBJECT (folder)); - - error = modest_mail_operation_get_error (mail_op); - if (error) { - g_warning ("Error transferring folder: %s\n", error->message); - g_object_unref (G_OBJECT (mail_op)); - goto out; - } g_object_unref (G_OBJECT (mail_op)); - success = TRUE; - out: - gtk_drag_finish (helper->context, success, FALSE, helper->time); - - /* Free the helper */ - gtk_tree_path_free (helper->source_row); - g_slice_free (DndHelper, helper); } /* diff --git a/src/widgets/modest-header-view.c b/src/widgets/modest-header-view.c index 0cc2325..e6ddf2d 100644 --- a/src/widgets/modest-header-view.c +++ b/src/widgets/modest-header-view.c @@ -631,40 +631,54 @@ modest_header_view_set_model (GtkTreeView *header_view, GtkTreeModel *model) } static void -on_refresh_folder (TnyFolder *folder, - gboolean cancelled, - GError **error, - gpointer user_data) +on_progress_changed (ModestMailOperation *mail_op, + ModestHeaderView *self) { - if (cancelled) { -/* GtkTreeSelection *selection; */ -/* selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (user_data)); */ -/* gtk_tree_selection_unselect_all (selection); */ - g_warning ("Operation cancelled %s\n", (*error) ? (*error)->message : "unknown"); - return; - } -} - - -static void -on_refresh_folder_status_update (TnyFolder *folder, const gchar *msg, - gint num, gint total, gpointer user_data) -{ - ModestHeaderView *self; + GtkTreeModel *sortable; ModestHeaderViewPrivate *priv; + GList *cols, *cursor; + TnyList *headers; - self = MODEST_HEADER_VIEW(user_data); - priv = MODEST_HEADER_VIEW_GET_PRIVATE(self); + if (!modest_mail_operation_is_finished (mail_op)) + return; - /* FIXME: this is a hack ==> tinymail gives us this when - * it has nothing better to do */ - if (num == 1 && total == 100) + if (modest_mail_operation_get_error (mail_op)) return; - g_signal_emit (G_OBJECT(self), signals[STATUS_UPDATE_SIGNAL], - 0, msg, num, total); -} + priv = MODEST_HEADER_VIEW_GET_PRIVATE(self); + + headers = TNY_LIST (tny_gtk_header_list_model_new ()); + tny_gtk_header_list_model_set_folder (TNY_GTK_HEADER_LIST_MODEL(headers), + priv->folder, TRUE); + + sortable = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL(headers)); + g_object_unref (G_OBJECT (headers)); + + /* install our special sorting functions */ + cursor = cols = gtk_tree_view_get_columns (GTK_TREE_VIEW(self)); + while (cursor) { + gint col_id = GPOINTER_TO_INT (g_object_get_data(G_OBJECT(cursor->data), + MODEST_HEADER_VIEW_COLUMN)); + gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(sortable), + col_id, + (GtkTreeIterCompareFunc) cmp_rows, + cursor->data, NULL); + cursor = g_list_next(cursor); + } + g_list_free (cols); + + /* Set new model */ + modest_header_view_set_model (GTK_TREE_VIEW (self), sortable); + g_object_unref (G_OBJECT (sortable)); + + /* Add a folder observer */ + g_mutex_lock (priv->monitor_lock); + priv->monitor = TNY_FOLDER_MONITOR (tny_folder_monitor_new (priv->folder)); + tny_folder_monitor_add_list (priv->monitor, TNY_LIST (headers)); + tny_folder_monitor_start (priv->monitor); + g_mutex_unlock (priv->monitor_lock); +} TnyFolder* modest_header_view_get_folder (ModestHeaderView *self) @@ -731,6 +745,7 @@ void modest_header_view_set_folder (ModestHeaderView *self, TnyFolder *folder) { ModestHeaderViewPrivate *priv; + priv = MODEST_HEADER_VIEW_GET_PRIVATE(self); if (priv->folder) { @@ -739,16 +754,31 @@ modest_header_view_set_folder (ModestHeaderView *self, TnyFolder *folder) } if (folder) { + ModestMailOperation *mail_op; + modest_header_view_set_folder_intern (self, folder); + + /* Pick my reference. Nothing to do with the mail operation */ priv->folder = g_object_ref (folder); - tny_folder_refresh_async (folder, - on_refresh_folder, - on_refresh_folder_status_update, - self); /* no message selected */ - g_signal_emit (G_OBJECT(self), signals[HEADER_SELECTED_SIGNAL], 0, - NULL); + g_signal_emit (G_OBJECT(self), signals[HEADER_SELECTED_SIGNAL], 0, NULL); + + /* Create the mail operation */ + mail_op = modest_mail_operation_new (); + modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), + mail_op); + + /* Register a mail operation observer */ + g_signal_connect (mail_op, "progress-changed", + G_CALLBACK (on_progress_changed), self); + + /* Refresh the folder asynchronously */ + modest_mail_operation_refresh_folder (mail_op, folder); + + /* Free */ + g_object_unref (mail_op); + } else { g_mutex_lock (priv->monitor_lock); modest_header_view_set_model (GTK_TREE_VIEW (self), NULL); diff --git a/src/widgets/modest-main-window.h b/src/widgets/modest-main-window.h index 02df4db..79993f7 100644 --- a/src/widgets/modest-main-window.h +++ b/src/widgets/modest-main-window.h @@ -88,8 +88,6 @@ typedef enum { MODEST_WIDGET_TYPE_HEADER_VIEW, MODEST_WIDGET_TYPE_FOLDER_VIEW, MODEST_WIDGET_TYPE_MSG_PREVIEW, - MODEST_WIDGET_TYPE_STATUS_BAR, - MODEST_WIDGET_TYPE_PROGRESS_BAR, MODEST_WIDGET_TYPE_NUM, } ModestWidgetType; -- 1.7.9.5