From 824365b716d6aedf5ef58ec1cb4b4c2248aee630 Mon Sep 17 00:00:00 2001 From: Javier Fernandez Garcia-Boente Date: Wed, 16 May 2007 16:20:08 +0000 Subject: [PATCH] * maemo/modest-main-window-ui.h - add handler for move_to toolbar button * maemo/modest-progress-bar-widget.c - avoid to show done=1 and total=100 progress, because these values are inital values for all mail operations. * modest-ui-actions.c - show confirmation dialog on delete message events from headers view - Add a user_callback function to xfer_msgs method in order to restore row_reference attribute on viewer window and set current message to first message of recenlty update treemodel. * modest-folder-view.c - fix bug about an incorrect unref over header object after added it to a tiny list. this header object will be unreferenced when tiny list was destroyed. * modest-mail-operation.c - call to recently created copy_folder_async tinymail operation. - define an user_callback for message transfer operations - fix bug on xfer_msgs operation, due an incorrect references management. pmo-trunk-r1892 --- src/maemo/modest-main-window-ui.h | 2 +- src/maemo/modest-msg-view-window.c | 70 ++++++++++++++++++++++ src/maemo/modest-progress-bar-widget.c | 8 ++- src/modest-mail-operation.c | 31 ++++++---- src/modest-mail-operation.h | 18 +++++- src/modest-ui-actions.c | 99 ++++++++++++++++++++++++-------- src/widgets/modest-folder-view.c | 5 +- src/widgets/modest-msg-view-window.h | 23 ++++++++ 8 files changed, 214 insertions(+), 42 deletions(-) diff --git a/src/maemo/modest-main-window-ui.h b/src/maemo/modest-main-window-ui.h index 586f1a3..87069ce 100644 --- a/src/maemo/modest-main-window-ui.h +++ b/src/maemo/modest-main-window-ui.h @@ -121,7 +121,7 @@ static const GtkActionEntry modest_action_entries [] = { { "ToolbarFindInMessage", GTK_STOCK_FIND, N_("qgn_toolb_gene_find"), NULL, NULL, NULL }, { "ToolbarMessageBack", GTK_STOCK_GO_BACK, N_("qgn_toolb_gene_back"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_prev) }, { "ToolbarMessageNext", GTK_STOCK_GO_FORWARD, N_("qgn_toolb_gene_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_next) }, - { "ToolbarMessageMoveTo", MODEST_TOOLBAR_ICON_MOVE_TO_FOLDER, N_("qgn_toolb_gene_movetofldr"), NULL, NULL, NULL }, + { "ToolbarMessageMoveTo", MODEST_TOOLBAR_ICON_MOVE_TO_FOLDER, N_("qgn_toolb_gene_movetofldr"), NULL, NULL, G_CALLBACK(modest_ui_actions_on_move_to) }, { "ToolbarCancel", GTK_STOCK_STOP, "", NULL, NULL, NULL }, }; diff --git a/src/maemo/modest-msg-view-window.c b/src/maemo/modest-msg-view-window.c index 8c148f9..4503d96 100644 --- a/src/maemo/modest-msg-view-window.c +++ b/src/maemo/modest-msg-view-window.c @@ -590,6 +590,29 @@ modest_msg_view_window_new (TnyMsg *msg, const gchar *account_name) +TnyHeader* +modest_msg_view_window_get_header (ModestMsgViewWindow *self) +{ + ModestMsgViewWindowPrivate *priv= NULL; + TnyHeader *header = NULL; + GtkTreeIter iter; + + g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), NULL); + priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self); + + /* Get current message iter */ + gtk_tree_model_get_iter (priv->header_model, + &iter, + gtk_tree_row_reference_get_path (priv->row_reference)); + + /* Get current message header */ + gtk_tree_model_get (priv->header_model, &iter, + TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN, + &header, -1); + + return header; +} + TnyMsg* modest_msg_view_window_get_message (ModestMsgViewWindow *self) { @@ -938,6 +961,53 @@ modest_msg_view_window_select_next_message (ModestMsgViewWindow *window) return FALSE; } +gboolean +modest_msg_view_window_select_first_message (ModestMsgViewWindow *self) +{ + ModestMsgViewWindowPrivate *priv = NULL; + ModestMailOperation *mail_op = NULL; + TnyHeader *header = NULL; + TnyHeaderFlags flags; + GtkTreePath *path = NULL; + GtkTreeIter iter; + + g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE); + priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self); + + path = gtk_tree_path_new_from_string ("0"); + + /* Update the row reference */ + /* Get first message */ + gtk_tree_model_get_iter (priv->header_model, &iter, path); + gtk_tree_model_get (priv->header_model, &iter, TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN, + &header, -1); + + g_return_val_if_fail (TNY_IS_HEADER (header), FALSE); + if (tny_header_get_flags (header) & TNY_HEADER_FLAG_DELETED) + return modest_msg_view_window_select_next_message (self); + + /* Update the row reference */ + gtk_tree_row_reference_free (priv->row_reference); + priv->row_reference = gtk_tree_row_reference_new (priv->header_model, path); + gtk_tree_path_free (path); + + /* Mark as read */ + flags = tny_header_get_flags (header); + if (!(flags & TNY_HEADER_FLAG_SEEN)) + tny_header_set_flags (header, flags | TNY_HEADER_FLAG_SEEN); + + /* New mail operation */ + mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(self)); + modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op); + modest_mail_operation_get_msg (mail_op, header, view_msg_cb, NULL); + g_object_unref (mail_op); + + /* Free */ +/* g_object_unref (header); */ + + return TRUE; +} + gboolean modest_msg_view_window_select_previous_message (ModestMsgViewWindow *window) { diff --git a/src/maemo/modest-progress-bar-widget.c b/src/maemo/modest-progress-bar-widget.c index e1116a1..a3af5c9 100644 --- a/src/maemo/modest-progress-bar-widget.c +++ b/src/maemo/modest-progress-bar-widget.c @@ -334,15 +334,17 @@ on_progress_changed (ModestMailOperation *mail_op, guint done = modest_mail_operation_get_task_done (mail_op); guint total = modest_mail_operation_get_task_total (mail_op); - determined = (done > 0 && total > 0); + determined = (done > 0 && total > 0) & !(done == 1 && total == 100); id = modest_mail_operation_get_id (mail_op); switch (id) { case MODEST_MAIL_OPERATION_ID_RECEIVE: if (determined) - msg = g_strdup_printf(_("mcen_me_receiving"), done, total); +/* msg = g_strdup_printf(_("mcen_me_receiving"), done, total); */ + msg = g_strdup_printf("Receiving %d/%d", done, total); else - msg = g_strdup(_("mail_me_receiving")); +/* msg = g_strdup(_("mail_me_receiving")); */ + msg = g_strdup("Receiving ..."); break; case MODEST_MAIL_OPERATION_ID_SEND: if (determined) diff --git a/src/modest-mail-operation.c b/src/modest-mail-operation.c index bdb69de..42c7e9f 100644 --- a/src/modest-mail-operation.c +++ b/src/modest-mail-operation.c @@ -116,7 +116,8 @@ typedef struct _XFerMsgAsyncHelper ModestMailOperation *mail_op; TnyList *headers; TnyFolder *dest_folder; - + XferMsgsAsynUserCallback user_callback; + gpointer user_data; } XFerMsgAsyncHelper; typedef struct _XFerFolderAsyncHelper @@ -967,6 +968,10 @@ modest_mail_operation_xfer_folder_async (ModestMailOperation *self, priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self); + /* Pick references for async calls */ + g_object_ref (folder); + g_object_ref (parent); + /* The moveable restriction is applied also to copy operation */ rules = modest_tny_folder_get_rules (TNY_FOLDER (parent)); if (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE) { @@ -1237,7 +1242,7 @@ modest_mail_operation_remove_msg (ModestMailOperation *self, g_object_unref (header); /* Move to trash */ - modest_mail_operation_xfer_msgs (self, headers, trash_folder, TRUE); + modest_mail_operation_xfer_msgs (self, headers, trash_folder, TRUE, NULL, NULL); g_object_unref (headers); /* g_object_unref (trash_folder); */ } else { @@ -1331,10 +1336,15 @@ transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError **err, gpointer priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS; } + /* If user defined callback function was defined, call it */ + if (helper->user_callback) { + helper->user_callback (priv->source, helper->user_data); + } + /* Free */ -/* g_object_unref (helper->headers); */ -/* g_object_unref (helper->dest_folder); */ -/* g_object_unref (helper->mail_op); */ + g_object_unref (helper->headers); + g_object_unref (helper->dest_folder); + g_object_unref (helper->mail_op); g_slice_free (XFerMsgAsyncHelper, helper); g_object_unref (folder); @@ -1346,7 +1356,9 @@ void modest_mail_operation_xfer_msgs (ModestMailOperation *self, TnyList *headers, TnyFolder *folder, - gboolean delete_original) + gboolean delete_original, + XferMsgsAsynUserCallback user_callback, + gpointer user_data) { ModestMailOperationPrivate *priv; TnyIterator *iter; @@ -1358,9 +1370,6 @@ modest_mail_operation_xfer_msgs (ModestMailOperation *self, g_return_if_fail (TNY_IS_LIST (headers)); g_return_if_fail (TNY_IS_FOLDER (folder)); - /* Pick references for async calls */ - g_object_ref (folder); - priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self); priv->total = 1; priv->done = 0; @@ -1368,9 +1377,11 @@ modest_mail_operation_xfer_msgs (ModestMailOperation *self, /* Create the helper */ helper = g_slice_new0 (XFerMsgAsyncHelper); - helper->mail_op = self; + helper->mail_op = g_object_ref(self); helper->dest_folder = g_object_ref(folder); helper->headers = g_object_ref(headers); + helper->user_callback = user_callback; + helper->user_data = user_data; /* Get source folder */ iter = tny_list_create_iterator (headers); diff --git a/src/modest-mail-operation.h b/src/modest-mail-operation.h index e75212e..bf10382 100644 --- a/src/modest-mail-operation.h +++ b/src/modest-mail-operation.h @@ -100,6 +100,18 @@ struct _ModestMailOperationClass { */ typedef void (*GetMsgAsynUserCallback) (const GObject *obj, const TnyMsg *msg, gpointer user_data); +/** + * XferMsgAsynUserCallback: + * + * @obj: a #GObject generic object which has created current mail operation. + * @user_data: generic data passed to user defined function. + * + * This function will be called after transfer_msgs_cb private function, which is + * used as tinymail operation callback. The private function fills private + * fields of mail operation and calls user defined callback if it exists. + */ +typedef void (*XferMsgsAsynUserCallback) (const GObject *obj, gpointer user_data); + /* member functions */ GType modest_mail_operation_get_type (void) G_GNUC_CONST; @@ -332,6 +344,8 @@ void modest_mail_operation_xfer_folder_async (ModestMailOperation *self, * @header_list: a #TnyList of #TnyHeader to transfer * @folder: the #TnyFolder where the messages will be transferred * @delete_original: whether or not delete the source messages + * @user_callback: a #XferMsgsAsynUserCallback function to call after tinymail callback execution. + * @user_data: generic user data which will be passed to @user_callback function. * * Asynchronously transfers messages from their current folder to * another one. The caller should add the #ModestMailOperation to a @@ -357,7 +371,9 @@ void modest_mail_operation_xfer_folder_async (ModestMailOperation *self, void modest_mail_operation_xfer_msgs (ModestMailOperation *self, TnyList *header_list, TnyFolder *folder, - gboolean delete_original); + gboolean delete_original, + XferMsgsAsynUserCallback user_callback, + gpointer user_data); /** * modest_mail_operation_remove_msg: diff --git a/src/modest-ui-actions.c b/src/modest-ui-actions.c index 57989ae..9e4b934 100644 --- a/src/modest-ui-actions.c +++ b/src/modest-ui-actions.c @@ -209,13 +209,12 @@ headers_action_delete (TnyHeader *header, ModestWindow *win, gpointer user_data) { - ModestMailOperation *mail_op; + ModestMailOperation *mail_op = NULL; - /* TODO: add confirmation dialog */ mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_DELETE, G_OBJECT(win)); modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op); - + /* Always delete. TODO: Move to trash still not supported */ modest_mail_operation_remove_msg (mail_op, header, FALSE); g_object_unref (G_OBJECT (mail_op)); @@ -224,20 +223,53 @@ headers_action_delete (TnyHeader *header, void modest_ui_actions_on_delete (GtkAction *action, ModestWindow *win) { + TnyList *header_list = NULL; + TnyIterator *iter = NULL; + TnyHeader *header = NULL; + gchar *message = NULL; + gchar *desc = NULL; + gint response; + g_return_if_fail (MODEST_IS_WINDOW(win)); - if (MODEST_IS_MSG_EDIT_WINDOW (win)) { - gboolean ret_value; - g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); - return; + header_list = get_selected_headers (win); + if (!header_list) return; + + /* Select message */ + if (tny_list_get_length(header_list) > 1) + message = g_strdup(_("emev_nc_delete_messages")); + else { + iter = tny_list_create_iterator (header_list); + header = TNY_HEADER (tny_iterator_get_current (iter)); + desc = g_strdup_printf ("%s", tny_header_get_subject (header)); + message = g_strdup_printf(_("emev_nc_delete_message"), desc); } + + /* Confirmation dialog */ + response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win), + message); + + + if (response == GTK_RESPONSE_OK) { + if (MODEST_IS_MSG_EDIT_WINDOW (win)) { + gboolean ret_value; + g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); + return; + } - /* Remove each header */ - do_headers_action (win, headers_action_delete, NULL); + /* Remove each header */ + do_headers_action (win, headers_action_delete, NULL); - if (MODEST_IS_MSG_VIEW_WINDOW (win)) { - gtk_widget_destroy (GTK_WIDGET(win)); - } + if (MODEST_IS_MSG_VIEW_WINDOW (win)) { + gtk_widget_destroy (GTK_WIDGET(win)); + } + } + + /* free */ + g_free(message); + g_free(desc); + g_object_unref (header_list); + g_object_unref (iter); } @@ -2266,6 +2298,20 @@ msgs_move_to_confirmation (GtkWindow *win, return response; } + +static void +tranasfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data) +{ + ModestMsgViewWindow *self = NULL; + gboolean found = FALSE; + + g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object)); + self = MODEST_MSG_VIEW_WINDOW (object); + + found = modest_msg_view_window_select_first_message (self); + g_return_if_fail (found); +} + /* * UI handler for the "Move to" action when invoked from the * ModestMainWindow @@ -2288,6 +2334,7 @@ modest_ui_actions_on_main_window_move_to (GtkAction *action, /* Create and run the dialog */ dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view); result = gtk_dialog_run (GTK_DIALOG(dialog)); + g_object_ref (tree_view); /* We do this to save an indentation level ;-) */ if (result != GTK_RESPONSE_ACCEPT) @@ -2308,10 +2355,10 @@ modest_ui_actions_on_main_window_move_to (GtkAction *action, modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op); - modest_mail_operation_xfer_folder (mail_op, - TNY_FOLDER (src_folder), - folder_store, - TRUE); + modest_mail_operation_xfer_folder_async (mail_op, + TNY_FOLDER (src_folder), + folder_store, + TRUE); g_object_unref (G_OBJECT (mail_op)); } @@ -2341,9 +2388,12 @@ modest_ui_actions_on_main_window_move_to (GtkAction *action, modest_mail_operation_xfer_msgs (mail_op, headers, TNY_FOLDER (folder_store), - TRUE); + TRUE, + NULL, + NULL); g_object_unref (G_OBJECT (mail_op)); } + g_object_unref (headers); } } g_object_unref (folder_store); @@ -2364,7 +2414,6 @@ modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, GtkWidget *dialog, *folder_view, *tree_view = NULL; gint result; ModestMainWindow *main_window; - TnyMsg *msg; TnyHeader *header; TnyList *headers; @@ -2376,6 +2425,7 @@ modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, /* Create and run the dialog */ dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view); result = gtk_dialog_run (GTK_DIALOG(dialog)); + g_object_ref (tree_view); if (result == GTK_RESPONSE_ACCEPT) { TnyFolderStore *folder_store; @@ -2384,12 +2434,10 @@ modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view)); /* Create header list */ - msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win)); - header = tny_msg_get_header (msg); + header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win)); headers = tny_simple_list_new (); tny_list_prepend (headers, G_OBJECT (header)); g_object_unref (header); - g_object_unref (msg); /* Ask user for confirmation. MSG-NOT404 */ response = msgs_move_to_confirmation (GTK_WINDOW (win), @@ -2409,11 +2457,12 @@ modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, modest_mail_operation_xfer_msgs (mail_op, headers, TNY_FOLDER (folder_store), - TRUE); + TRUE, + tranasfer_msgs_from_viewer_cb, + NULL); g_object_unref (G_OBJECT (mail_op)); - } else { - g_object_unref (headers); - } + } + g_object_unref (headers); g_object_unref (folder_store); } gtk_widget_destroy (dialog); diff --git a/src/widgets/modest-folder-view.c b/src/widgets/modest-folder-view.c index cd6e8bd..c91d4db 100644 --- a/src/widgets/modest-folder-view.c +++ b/src/widgets/modest-folder-view.c @@ -999,13 +999,13 @@ drag_and_drop_from_header_view (GtkTreeModel *source_model, should be reviewed in order to allow multiple drags*/ headers = tny_simple_list_new (); tny_list_append (headers, G_OBJECT (header)); - g_object_unref (header); - modest_mail_operation_xfer_msgs (mail_op, headers, folder, helper->delete_source); + modest_mail_operation_xfer_msgs (mail_op, headers, folder, helper->delete_source, NULL, NULL); /* Frees */ g_object_unref (G_OBJECT (mail_op)); g_object_unref (G_OBJECT (header)); g_object_unref (G_OBJECT (folder)); + g_object_unref (headers); } /* @@ -1395,6 +1395,7 @@ on_configuration_key_changed (ModestConf* conf, if (!key) return; + g_return_if_fail (MODEST_IS_FOLDER_VIEW (self)); priv = MODEST_FOLDER_VIEW_GET_PRIVATE(self); if (!strcmp (key, MODEST_CONF_DEVICE_NAME)) { diff --git a/src/widgets/modest-msg-view-window.h b/src/widgets/modest-msg-view-window.h index e74482b..b029a51 100644 --- a/src/widgets/modest-msg-view-window.h +++ b/src/widgets/modest-msg-view-window.h @@ -98,6 +98,18 @@ ModestWindow* modest_msg_view_window_new_with_header_model (TnyMsg *msg, /** + * modest_msg_view_window_get_header: + * @window: an #ModestMsgViewWindow instance + * + * get the message header in this msg view. Header instance is get + * from tree_model of headers list. + * + * Returns: a new #TnyHeader instance, or NULL in case of error + */ +TnyHeader* +modest_msg_view_window_get_header (ModestMsgViewWindow *self); + +/** * modest_msg_view_window_get_message: * @window: an #ModestMsgViewWindow instance * @@ -119,6 +131,17 @@ TnyMsg* modest_msg_view_window_get_message (ModestMsgViewWindow *win const gchar* modest_msg_view_window_get_message_uid (ModestMsgViewWindow *window); /** + * modest_msg_view_window_select_first_message: + * @window: a #ModestMsgViewWindow instance + * + * select the first message obtained from the header view this view + * was called from + * + * Returns: %TRUE if a new message is shown. + */ +gboolean modest_msg_view_window_select_first_message (ModestMsgViewWindow *window); + +/** * modest_msg_view_window_select_next_message: * @window: a #ModestMsgViewWindow instance * -- 1.7.9.5