diff options
author | Milan Crha <mcrha@redhat.com> | 2013-05-04 00:11:37 +0800 |
---|---|---|
committer | Milan Crha <mcrha@redhat.com> | 2013-05-04 00:11:37 +0800 |
commit | 7770e7c36560adb9ce3d4714e369ebcd46274b85 (patch) | |
tree | 2bb0b336e71f15a22369c3234014afe2ebb40b6f | |
parent | 5dfeb54af9639bc3a1df5e4262ec384d2abf5a9d (diff) | |
download | gsoc2013-evolution-7770e7c36560adb9ce3d4714e369ebcd46274b85.tar.gz gsoc2013-evolution-7770e7c36560adb9ce3d4714e369ebcd46274b85.tar.zst gsoc2013-evolution-7770e7c36560adb9ce3d4714e369ebcd46274b85.zip |
Merge [mark-all-read] plugin into core code
During fixes on bug #602428, rather than do everything twice,
I merged the plugin into the core code, thus it should be easier
to maintain as well.
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | mail/mail.error.xml | 14 | ||||
-rw-r--r-- | modules/mail/e-mail-shell-view-actions.c | 336 | ||||
-rw-r--r-- | modules/mail/e-mail-shell-view-actions.h | 2 | ||||
-rw-r--r-- | modules/mail/e-mail-shell-view.c | 19 | ||||
-rw-r--r-- | plugins/mark-all-read/Makefile.am | 31 | ||||
-rw-r--r-- | plugins/mark-all-read/mark-all-read.c | 602 | ||||
-rw-r--r-- | plugins/mark-all-read/org-gnome-mark-all-read.eplug.xml | 21 | ||||
-rw-r--r-- | po/POTFILES.in | 2 | ||||
-rw-r--r-- | ui/evolution-mail.ui | 1 |
10 files changed, 340 insertions, 691 deletions
diff --git a/configure.ac b/configure.ac index eccc0ad9ca..8e75f0e11f 100644 --- a/configure.ac +++ b/configure.ac @@ -1286,7 +1286,7 @@ AC_ARG_ENABLE([plugins], [enable_plugins="$enableval"],[enable_plugins=all]) dnl Add any new plugins here -plugins_base_always="mark-all-read publish-calendar" +plugins_base_always="publish-calendar" plugins_base="$plugins_base_always" dist_plugins_base="$plugins_base_always" @@ -1664,7 +1664,6 @@ plugins/image-inline/Makefile plugins/mail-notification/Makefile plugins/mail-to-task/Makefile plugins/mailing-list-actions/Makefile -plugins/mark-all-read/Makefile plugins/pst-import/Makefile plugins/publish-calendar/Makefile plugins/save-calendar/Makefile diff --git a/mail/mail.error.xml b/mail/mail.error.xml index 3f1f29599e..d523b543af 100644 --- a/mail/mail.error.xml +++ b/mail/mail.error.xml @@ -386,10 +386,11 @@ An mbox account will be created to preserve the old mbox folders. You can delete </error> <error id="ask-mark-all-read-sub" type="question" default="GTK_RESPONSE_NO"> - <_primary>Do you want to mark all messages as read?</_primary> - <_secondary xml:space="preserve">This will mark all messages as read in the selected folder and its subfolders.</_secondary> - <button stock="gtk-no" response="GTK_RESPONSE_NO"/> - <button stock="gtk-yes" response="GTK_RESPONSE_YES"/> + <_primary>Also mark messages in subfolders?</_primary> + <_secondary xml:space="preserve">Do you want to mark messages as read in the current folder only, or in the current folder as well as all subfolders?</_secondary> + <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/> + <button _label="In Current Folder and _Subfolders" response="GTK_RESPONSE_YES"/> + <button _label="In Current _Folder Only" response="GTK_RESPONSE_NO"/> </error> <error id="ask-reply-close-browser" type="question" default="GTK_RESPONSE_NO"> @@ -488,6 +489,11 @@ An mbox account will be created to preserve the old mbox folders. You can delete <_secondary>The reported error was "{0}".</_secondary> </error> + <error id="mark-all-read" type="error"> + <_primary>Failed to mark messages as read.</_primary> + <_secondary>The reported error was "{0}".</_secondary> + </error> + <error id="remove-attachments" type="error"> <_primary>Failed to remove attachments from messages.</_primary> <_secondary>The reported error was "{0}".</_secondary> diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c index 3af5fac4ee..75fc61e161 100644 --- a/modules/mail/e-mail-shell-view-actions.c +++ b/modules/mail/e-mail-shell-view-actions.c @@ -417,26 +417,285 @@ action_mail_folder_expunge_cb (GtkAction *action, g_free (selected_folder_name); } +typedef struct _AsyncContext { + EActivity *activity; + EMailShellView *mail_shell_view; + gboolean can_subfolders; + GQueue folder_names; +} AsyncContext; + static void -action_mail_folder_mark_all_as_read_cb (GtkAction *action, - EMailShellView *mail_shell_view) +async_context_free (AsyncContext *context) +{ + if (context->activity != NULL) + g_object_unref (context->activity); + + if (context->mail_shell_view != NULL) + g_object_unref (context->mail_shell_view); + + /* This should be empty already, unless an error occurred... */ + while (!g_queue_is_empty (&context->folder_names)) + g_free (g_queue_pop_head (&context->folder_names)); + + g_slice_free (AsyncContext, context); +} + +static void +mark_all_read_thread (GSimpleAsyncResult *simple, + GObject *object, + GCancellable *cancellable) +{ + AsyncContext *context; + CamelStore *store; + CamelFolder *folder; + GPtrArray *uids; + gint ii; + GError *error = NULL; + + context = g_simple_async_result_get_op_res_gpointer (simple); + store = CAMEL_STORE (object); + + while (!g_queue_is_empty (&context->folder_names) && !error) { + gchar *folder_name = g_queue_pop_head (&context->folder_names); + + folder = camel_store_get_folder_sync (store, folder_name, 0, cancellable, &error); + + g_free (folder_name); + + if (!folder) + break; + + camel_folder_freeze (folder); + + uids = camel_folder_get_uids (folder); + + for (ii = 0; ii < uids->len; ii++) + camel_folder_set_message_flags ( + folder, uids->pdata[ii], + CAMEL_MESSAGE_SEEN, + CAMEL_MESSAGE_SEEN); + + camel_folder_thaw (folder); + + camel_folder_free_uids (folder, uids); + g_object_unref (folder); + } + + if (error) + g_simple_async_result_take_error (simple, error); +} + +static void +mark_all_read_done_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + AsyncContext *context; + GError *local_error = NULL; + + g_return_if_fail ( + g_simple_async_result_is_valid ( + result, source, mark_all_read_thread)); + + simple = G_SIMPLE_ASYNC_RESULT (result); + context = g_simple_async_result_get_op_res_gpointer (simple); + + if (g_simple_async_result_propagate_error (simple, &local_error) && + local_error && + !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + EAlertSink *alert_sink; + + alert_sink = e_activity_get_alert_sink (context->activity); + + e_alert_submit ( + alert_sink, "mail:mark-all-read", + local_error->message, NULL); + } + + g_clear_error (&local_error); + + e_activity_set_state (context->activity, E_ACTIVITY_COMPLETED); +} + +static void +mark_all_read_collect_folder_names (GQueue *folder_names, + CamelFolderInfo *folder_info) +{ + while (folder_info != NULL) { + if (folder_info->child != NULL) + mark_all_read_collect_folder_names ( + folder_names, folder_info->child); + + g_queue_push_tail ( + folder_names, g_strdup (folder_info->full_name)); + + folder_info = folder_info->next; + } +} + +enum { + MARK_ALL_READ_CANCEL, + MARK_ALL_READ_CURRENT_ONLY, + MARK_ALL_READ_WITH_SUBFOLDERS +}; + +static gint +mark_all_read_prompt_user (EMailShellView *mail_shell_view, + gboolean with_subfolders) { EShellView *shell_view; EShellWindow *shell_window; - EMailShellContent *mail_shell_content; - EMailReader *reader; - EMailView *mail_view; - CamelFolder *folder; GtkWindow *parent; - GtkWidget *message_list; - GPtrArray *uids; - const gchar *key; - guint ii; shell_view = E_SHELL_VIEW (mail_shell_view); shell_window = e_shell_view_get_shell_window (shell_view); parent = GTK_WINDOW (shell_window); + if (with_subfolders) { + switch (e_alert_run_dialog_for_args (parent, + "mail:ask-mark-all-read-sub", NULL)) { + case GTK_RESPONSE_YES: + return MARK_ALL_READ_WITH_SUBFOLDERS; + case GTK_RESPONSE_NO: + return MARK_ALL_READ_CURRENT_ONLY; + default: + break; + } + } else if (em_utils_prompt_user (parent, + "prompt-on-mark-all-read", + "mail:ask-mark-all-read", NULL)) + return MARK_ALL_READ_CURRENT_ONLY; + + return MARK_ALL_READ_CANCEL; +} + +static void +mark_all_read_got_folder_info (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + CamelStore *store = CAMEL_STORE (source); + AsyncContext *context = user_data; + EAlertSink *alert_sink; + GCancellable *cancellable; + GSimpleAsyncResult *simple; + CamelFolderInfo *folder_info; + gint response; + GError *error = NULL; + + alert_sink = e_activity_get_alert_sink (context->activity); + cancellable = e_activity_get_cancellable (context->activity); + + folder_info = camel_store_get_folder_info_finish ( + store, result, &error); + + if (e_activity_handle_cancellation (context->activity, error)) { + g_warn_if_fail (folder_info == NULL); + async_context_free (context); + g_error_free (error); + return; + + } else if (error != NULL) { + g_warn_if_fail (folder_info == NULL); + e_alert_submit ( + alert_sink, "mail:mark-all-read", + error->message, NULL); + async_context_free (context); + g_error_free (error); + return; + } + + g_return_if_fail (folder_info != NULL); + + response = mark_all_read_prompt_user (context->mail_shell_view, + context->can_subfolders && folder_info->child != NULL); + + if (response == MARK_ALL_READ_CURRENT_ONLY) + g_queue_push_tail ( + &context->folder_names, + g_strdup (folder_info->full_name)); + + if (response == MARK_ALL_READ_WITH_SUBFOLDERS) + mark_all_read_collect_folder_names (&context->folder_names, folder_info); + + camel_store_free_folder_info (store, folder_info); + + if (g_queue_is_empty (&context->folder_names)) { + e_activity_set_state (context->activity, E_ACTIVITY_COMPLETED); + async_context_free (context); + return; + } + + simple = g_simple_async_result_new ( + source, mark_all_read_done_cb, + context, mark_all_read_thread); + + g_simple_async_result_set_op_res_gpointer ( + simple, context, (GDestroyNotify) async_context_free); + + g_simple_async_result_run_in_thread ( + simple, mark_all_read_thread, + G_PRIORITY_DEFAULT, cancellable); + + g_object_unref (simple); +} + +static void +e_mail_shell_view_actions_mark_all_read (EMailShellView *mail_shell_view, + CamelStore *store, + const gchar *folder_name, + gboolean can_subfolders) +{ + EShellView *shell_view; + EShellBackend *shell_backend; + EShellContent *shell_content; + EAlertSink *alert_sink; + GCancellable *cancellable; + AsyncContext *context; + + g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); + g_return_if_fail (CAMEL_IS_STORE (store)); + g_return_if_fail (folder_name != NULL); + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + + context = g_slice_new0 (AsyncContext); + context->mail_shell_view = g_object_ref (mail_shell_view); + context->can_subfolders = can_subfolders; + context->activity = e_activity_new (); + g_queue_init (&context->folder_names); + + alert_sink = E_ALERT_SINK (shell_content); + e_activity_set_alert_sink (context->activity, alert_sink); + + cancellable = camel_operation_new (); + e_activity_set_cancellable (context->activity, cancellable); + + camel_operation_push_message (cancellable, _("Marking messages as read...")); + + e_shell_backend_add_activity (shell_backend, context->activity); + + camel_store_get_folder_info ( + store, folder_name, + can_subfolders ? CAMEL_STORE_FOLDER_INFO_RECURSIVE : 0, + G_PRIORITY_DEFAULT, cancellable, + mark_all_read_got_folder_info, context); + + g_object_unref (cancellable); +} + +static void +action_mail_folder_mark_all_as_read_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellContent *mail_shell_content; + EMailReader *reader; + EMailView *mail_view; + CamelFolder *folder; + mail_shell_content = mail_shell_view->priv->mail_shell_content; mail_view = e_mail_shell_content_get_mail_view (mail_shell_content); @@ -445,24 +704,46 @@ action_mail_folder_mark_all_as_read_cb (GtkAction *action, folder = e_mail_reader_get_folder (reader); g_return_if_fail (folder != NULL); - key = "prompt-on-mark-all-read"; - - if (!em_utils_prompt_user (parent, key, "mail:ask-mark-all-read", NULL)) + if (folder->summary && + camel_folder_summary_get_unread_count (folder->summary) == 0) return; - message_list = e_mail_reader_get_message_list (reader); - g_return_if_fail (message_list != NULL); + e_mail_shell_view_actions_mark_all_read ( + mail_shell_view, + camel_folder_get_parent_store (folder), + camel_folder_get_full_name (folder), + FALSE); +} + +static void +action_mail_popup_folder_mark_all_as_read_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShellSidebar *shell_sidebar; + EMFolderTree *folder_tree; + CamelStore *store; + gchar *folder_name; - uids = message_list_get_uids (MESSAGE_LIST (message_list)); + shell_sidebar = e_shell_view_get_shell_sidebar (E_SHELL_VIEW (mail_shell_view)); - camel_folder_freeze (folder); - for (ii = 0; ii < uids->len; ii++) - camel_folder_set_message_flags ( - folder, uids->pdata[ii], - CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); - camel_folder_thaw (folder); + g_object_get (shell_sidebar, "folder-tree", &folder_tree, NULL); - em_utils_uids_free (uids); + /* This action should only be activatable if a folder is selected. */ + if (!em_folder_tree_get_selected (folder_tree, &store, &folder_name)) { + g_object_unref (folder_tree); + g_return_if_reached (); + } + + g_object_unref (folder_tree); + + e_mail_shell_view_actions_mark_all_read ( + mail_shell_view, + store, + folder_name, + TRUE); + + g_object_unref (store); + g_free (folder_name); } static void @@ -1320,7 +1601,7 @@ static GtkActionEntry mail_entries[] = { G_CALLBACK (action_mail_folder_expunge_cb) }, { "mail-folder-mark-all-as-read", - "mail-read", + "mail-mark-read", N_("Mar_k All Messages as Read"), "<Control>slash", N_("Mark all messages in the folder as read"), @@ -1419,6 +1700,13 @@ static GtkActionEntry mail_entries[] = { N_("Subscribe or unsubscribe to folders on remote servers"), G_CALLBACK (action_mail_tools_subscriptions_cb) }, + { "mail-popup-folder-mark-all-as-read", + "mail-mark-read", + N_("Mar_k All Messages as Read"), + NULL, + N_("Mark all messages in the folder as read"), + G_CALLBACK (action_mail_popup_folder_mark_all_as_read_cb) }, + { "mail-send-receive", "mail-send-receive", N_("Send / _Receive"), diff --git a/modules/mail/e-mail-shell-view-actions.h b/modules/mail/e-mail-shell-view-actions.h index ff0829b662..109dfce4d3 100644 --- a/modules/mail/e-mail-shell-view-actions.h +++ b/modules/mail/e-mail-shell-view-actions.h @@ -139,6 +139,8 @@ E_SHELL_WINDOW_ACTION ((window), "mail-next-thread") #define E_SHELL_WINDOW_ACTION_MAIL_NEXT_UNREAD(window) \ E_SHELL_WINDOW_ACTION ((window), "mail-next-unread") +#define E_SHELL_WINDOW_ACTION_MAIL_POPUP_FOLDER_MARK_ALL_AS_READ(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-popup-folder-mark-all-as-read") #define E_SHELL_WINDOW_ACTION_MAIL_PREVIEW(window) \ E_SHELL_WINDOW_ACTION ((window), "mail-preview") #define E_SHELL_WINDOW_ACTION_MAIL_PREVIOUS(window) \ diff --git a/modules/mail/e-mail-shell-view.c b/modules/mail/e-mail-shell-view.c index 285bb5db1f..14b3a83c22 100644 --- a/modules/mail/e-mail-shell-view.c +++ b/modules/mail/e-mail-shell-view.c @@ -766,7 +766,8 @@ static void has_unread_mail (GtkTreeModel *model, GtkTreeIter *parent, gboolean is_root, - gboolean *has_unread) + gboolean *has_unread_root, + gboolean *has_unread) { guint unread = 0; GtkTreeIter iter, child; @@ -792,8 +793,11 @@ has_unread_mail (GtkTreeModel *model, *has_unread = *has_unread || (unread > 0 && unread != ~((guint)0)); - if (*has_unread) + if (*has_unread) { + if (has_unread_root) + *has_unread_root = TRUE; return; + } if (!gtk_tree_model_iter_children (model, &iter, parent)) return; @@ -809,7 +813,7 @@ has_unread_mail (GtkTreeModel *model, break; if (gtk_tree_model_iter_children (model, &child, &iter)) - has_unread_mail (model, &child, FALSE, has_unread); + has_unread_mail (model, &child, FALSE, NULL, has_unread); } while (gtk_tree_model_iter_next (model, &iter) && !*has_unread); } @@ -839,6 +843,7 @@ mail_shell_view_update_actions (EShellView *shell_view) gboolean folder_is_store; gboolean folder_is_trash; gboolean folder_is_virtual; + gboolean folder_has_unread = FALSE; gboolean folder_has_unread_rec = FALSE; gboolean folder_tree_and_message_list_agree = TRUE; gboolean store_is_builtin; @@ -920,7 +925,7 @@ mail_shell_view_update_actions (EShellView *shell_view) GTK_TREE_MODEL (model), &iter, path); has_unread_mail ( GTK_TREE_MODEL (model), &iter, - TRUE, &folder_has_unread_rec); + TRUE, &folder_has_unread, &folder_has_unread_rec); gtk_tree_path_free (path); } @@ -1008,9 +1013,13 @@ mail_shell_view_update_actions (EShellView *shell_view) gtk_action_set_sensitive (action, sensitive); action = ACTION (MAIL_FOLDER_MARK_ALL_AS_READ); - sensitive = folder_has_unread_rec && !folder_is_store; + sensitive = folder_has_unread && !folder_is_store; gtk_action_set_sensitive (action, sensitive); + action = ACTION (MAIL_POPUP_FOLDER_MARK_ALL_AS_READ); + sensitive = folder_has_unread_rec && !folder_is_store; + gtk_action_set_visible (action, sensitive); + action = ACTION (MAIL_MANAGE_SUBSCRIPTIONS); sensitive = folder_is_store && store_is_subscribable; gtk_action_set_sensitive (action, sensitive); diff --git a/plugins/mark-all-read/Makefile.am b/plugins/mark-all-read/Makefile.am deleted file mode 100644 index 2ed1397664..0000000000 --- a/plugins/mark-all-read/Makefile.am +++ /dev/null @@ -1,31 +0,0 @@ -@EVO_PLUGIN_RULE@ - -plugin_DATA = org-gnome-mark-all-read.eplug - -plugin_LTLIBRARIES = liborg-gnome-mark-all-read.la - -liborg_gnome_mark_all_read_la_CPPFLAGS = \ - $(AM_CPPFLAGS) \ - -I$(top_srcdir) \ - $(EVOLUTION_DATA_SERVER_CFLAGS) \ - $(GNOME_PLATFORM_CFLAGS) \ - $(GTKHTML_CFLAGS) - -liborg_gnome_mark_all_read_la_SOURCES = mark-all-read.c - -liborg_gnome_mark_all_read_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED) - -liborg_gnome_mark_all_read_la_LIBADD = \ - $(top_builddir)/e-util/libeutil.la \ - $(top_builddir)/mail/libevolution-mail.la \ - $(top_builddir)/shell/libeshell.la \ - $(EVOLUTION_DATA_SERVER_LIBS) \ - $(GNOME_PLATFORM_LIBS) \ - $(GTKHTML_LIBS) - -EXTRA_DIST = org-gnome-mark-all-read.eplug.xml - -BUILT_SOURCES = $(plugin_DATA) -CLEANFILES = $(BUILT_SOURCES) - --include $(top_srcdir)/git.mk diff --git a/plugins/mark-all-read/mark-all-read.c b/plugins/mark-all-read/mark-all-read.c deleted file mode 100644 index d04553d0bb..0000000000 --- a/plugins/mark-all-read/mark-all-read.c +++ /dev/null @@ -1,602 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Chenthill Palanisamy <pchenthill@novell.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <gtk/gtk.h> -#include <glib/gi18n.h> - -#include <libemail-engine/e-mail-folder-utils.h> - -#include <mail/em-folder-tree.h> -#include <mail/em-utils.h> - -#include <shell/e-shell-sidebar.h> -#include <shell/e-shell-view.h> -#include <shell/e-shell-window.h> - -#define PRIMARY_TEXT \ - N_("Also mark messages in subfolders?") -#define SECONDARY_TEXT \ - N_("Do you want to mark messages as read in the current folder " \ - "only, or in the current folder as well as all subfolders?") - -typedef struct _AsyncContext AsyncContext; - -struct _AsyncContext { - EActivity *activity; - GQueue folder_names; -}; - -enum { - MARK_ALL_READ_CANCEL, - MARK_ALL_READ_CURRENT_FOLDER, - MARK_ALL_READ_WITH_SUBFOLDERS -}; - -gboolean e_plugin_ui_init (GtkUIManager *ui_manager, - EShellView *shell_view); -gint e_plugin_lib_enable (EPlugin *ep, - gint enable); - -static void -async_context_free (AsyncContext *context) -{ - if (context->activity != NULL) - g_object_unref (context->activity); - - /* This should be empty already, but just to be sure... */ - while (!g_queue_is_empty (&context->folder_names)) - g_free (g_queue_pop_head (&context->folder_names)); - - g_slice_free (AsyncContext, context); -} - -gint -e_plugin_lib_enable (EPlugin *ep, - gint enable) -{ - return 0; -} - -static void -button_clicked_cb (GtkButton *button, - GtkDialog *dialog) -{ - gpointer response; - - response = g_object_get_data (G_OBJECT (button), "response"); - gtk_dialog_response (dialog, GPOINTER_TO_INT (response)); -} - -static gint -prompt_user (gboolean has_subfolders) -{ - GtkWidget *container; - GtkWidget *dialog; - GtkWidget *grid; - GtkWidget *widget; - GtkWidget *vbox; - gchar *markup; - gint response, ret; - - if (!has_subfolders) { - EShell *shell; - GtkWindow *parent; - - shell = e_shell_get_default (); - parent = e_shell_get_active_window (shell); - - return em_utils_prompt_user ( - parent, "prompt-on-mark-all-read", "mail:ask-mark-all-read", NULL) ? - MARK_ALL_READ_CURRENT_FOLDER : MARK_ALL_READ_CANCEL; - } - - dialog = gtk_dialog_new (); - widget = gtk_dialog_get_action_area (GTK_DIALOG (dialog)); - gtk_widget_hide (widget); - gtk_window_set_title (GTK_WINDOW (dialog), ""); - gtk_container_set_border_width (GTK_CONTAINER (dialog), 12); - vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); - - /* Grid */ - widget = gtk_grid_new (); - gtk_grid_set_row_spacing (GTK_GRID (widget), 12); - gtk_grid_set_column_spacing (GTK_GRID (widget), 12); - gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0); - gtk_widget_show (widget); - - grid = widget; - - /* Question Icon */ - widget = gtk_image_new_from_stock ( - GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG); - gtk_widget_set_valign (widget, GTK_ALIGN_START); - gtk_grid_attach (GTK_GRID (grid), widget, 0, 0, 1, 3); - gtk_widget_show (widget); - - /* Primary Text */ - markup = g_markup_printf_escaped ( - "<big><b>%s</b></big>", gettext (PRIMARY_TEXT)); - widget = gtk_label_new (markup); - gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE); - gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); - gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0); - gtk_grid_attach (GTK_GRID (grid), widget, 1, 0, 1, 1); - gtk_widget_show (widget); - g_free (markup); - - /* Secondary Text */ - widget = gtk_label_new (gettext (SECONDARY_TEXT)); - gtk_widget_set_vexpand (widget, TRUE); - gtk_widget_set_valign (widget, GTK_ALIGN_START); - gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE); - gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0); - gtk_grid_attach (GTK_GRID (grid), widget, 1, 1, 1, 1); - gtk_widget_show (widget); - - /* Action Area */ - widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); - gtk_widget_set_halign (widget, GTK_ALIGN_END); - gtk_grid_attach (GTK_GRID (grid), widget, 1, 2, 1, 1); - gtk_widget_show (widget); - - container = widget; - - /* Cancel button */ - widget = gtk_button_new_from_stock (GTK_STOCK_CANCEL); - g_object_set_data ( - G_OBJECT (widget), "response", - GINT_TO_POINTER (GTK_RESPONSE_CANCEL)); - g_signal_connect ( - widget, "clicked", - G_CALLBACK (button_clicked_cb), dialog); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - gtk_widget_show (widget); - - /* To Translators: It's a response button caption on a question - * "Do you want to mark messages as read in the current folder - * only, or in the current folder as well as all subfolders?" */ - widget = gtk_button_new_with_mnemonic ( - _("In Current Folder and _Subfolders")); - g_object_set_data ( - G_OBJECT (widget), "response", - GINT_TO_POINTER (GTK_RESPONSE_YES)); - g_signal_connect ( - widget, "clicked", - G_CALLBACK (button_clicked_cb), dialog); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - gtk_widget_show (widget); - - /* To Translators: It's a response button caption on a question - * "Do you want to mark messages as read in the current folder - * only, or in the current folder as well as all subfolders?" */ - widget = gtk_button_new_with_mnemonic ( - _("In Current _Folder Only")); - g_object_set_data ( - G_OBJECT (widget), "response", - GINT_TO_POINTER (GTK_RESPONSE_NO)); - g_signal_connect ( - widget, "clicked", - G_CALLBACK (button_clicked_cb), dialog); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - gtk_widget_show (widget); - - response = gtk_dialog_run (GTK_DIALOG (dialog)); - - gtk_widget_destroy (dialog); - - if (response == GTK_RESPONSE_YES) - ret = MARK_ALL_READ_WITH_SUBFOLDERS; - else if (response == GTK_RESPONSE_NO) - ret = MARK_ALL_READ_CURRENT_FOLDER; - else - ret = MARK_ALL_READ_CANCEL; - - return ret; -} - -static gboolean -scan_folder_tree_for_unread_helper (GtkTreeModel *model, - GtkTreeIter *iter, - GtkTreePath *path, - gboolean is_first_node, - gint initial_depth, - gint *relative_depth) -{ - /* This is based on gtk_tree_model_foreach(). Unfortunately - * that function insists on traversing the entire tree model. */ - - do { - GtkTreeIter child; - gboolean folder_has_unread; - gboolean is_draft = FALSE; - gboolean is_store = FALSE; - gboolean is_trash; - gboolean is_virtual; - guint unread = 0; - guint folder_flags = 0; - guint folder_type; - - gtk_tree_model_get ( - model, iter, - COL_UINT_FLAGS, &folder_flags, - COL_UINT_UNREAD, &unread, - COL_BOOL_IS_STORE, &is_store, - COL_BOOL_IS_DRAFT, &is_draft, -1); - - folder_type = (folder_flags & CAMEL_FOLDER_TYPE_MASK); - is_virtual = ((folder_flags & CAMEL_FOLDER_VIRTUAL) != 0); - is_trash = (folder_type == CAMEL_FOLDER_TYPE_TRASH); - - folder_has_unread = - !is_store && !is_draft && - (!is_virtual || !is_trash) && - unread > 0 && unread != ~((guint) 0); - - if (folder_has_unread) { - gint current_depth; - - current_depth = gtk_tree_path_get_depth (path); - *relative_depth = current_depth - initial_depth + 1; - - /* If we find unread messages in a child of the - * selected folder, short-circuit the recursion. */ - if (*relative_depth > 1) - return TRUE; - } - - if (gtk_tree_model_iter_children (model, &child, iter)) { - gtk_tree_path_down (path); - - if (scan_folder_tree_for_unread_helper ( - model, &child, path, FALSE, - initial_depth, relative_depth)) - return TRUE; - - gtk_tree_path_up (path); - } - - /* do not check sibling nodes of the selected folder */ - if (is_first_node) - break; - - gtk_tree_path_next (path); - - } while (gtk_tree_model_iter_next (model, iter)); - - return FALSE; -} - -static gint -scan_folder_tree_for_unread (const gchar *folder_uri) -{ - GtkTreeRowReference *reference; - EMFolderTreeModel *model; - gint relative_depth = 0; - - /* Traverses the selected folder and its children and returns - * the relative depth of the furthest child folder containing - * unread mail. Except, we abort the traversal as soon as we - * find a child folder with unread messages. So the possible - * return values are: - * - * Depth = 0: No unread mail found. - * Depth = 1: Unread mail only in selected folder. - * Depth = 2: Unread mail in one of the child folders. - */ - - if (folder_uri == NULL) - return 0; - - model = em_folder_tree_model_get_default (); - reference = em_folder_tree_model_lookup_uri (model, folder_uri); - - if (gtk_tree_row_reference_valid (reference)) { - GtkTreePath *path; - GtkTreeIter iter; - - path = gtk_tree_row_reference_get_path (reference); - gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path); - - scan_folder_tree_for_unread_helper ( - GTK_TREE_MODEL (model), &iter, path, TRUE, - gtk_tree_path_get_depth (path), &relative_depth); - - gtk_tree_path_free (path); - } - - return relative_depth; -} - -static void -collect_folder_names (GQueue *folder_names, - CamelFolderInfo *folder_info) -{ - while (folder_info != NULL) { - if (folder_info->child != NULL) - collect_folder_names ( - folder_names, folder_info->child); - - g_queue_push_tail ( - folder_names, g_strdup (folder_info->full_name)); - - folder_info = folder_info->next; - } -} - -static void -mar_got_folder (CamelStore *store, - GAsyncResult *result, - AsyncContext *context) -{ - EAlertSink *alert_sink; - GCancellable *cancellable; - CamelFolder *folder; - gchar *folder_name; - GError *error = NULL; - GPtrArray *uids; - gint ii; - - alert_sink = e_activity_get_alert_sink (context->activity); - cancellable = e_activity_get_cancellable (context->activity); - - folder = camel_store_get_folder_finish (store, result, &error); - - if (e_activity_handle_cancellation (context->activity, error)) { - g_warn_if_fail (folder == NULL); - async_context_free (context); - g_error_free (error); - return; - - } else if (error != NULL) { - g_warn_if_fail (folder == NULL); - e_alert_submit ( - alert_sink, "mail:folder-open", - error->message, NULL); - async_context_free (context); - g_error_free (error); - return; - } - - g_return_if_fail (CAMEL_IS_FOLDER (folder)); - - camel_folder_freeze (folder); - - uids = camel_folder_get_uids (folder); - - for (ii = 0; ii < uids->len; ii++) - camel_folder_set_message_flags ( - folder, uids->pdata[ii], - CAMEL_MESSAGE_SEEN, - CAMEL_MESSAGE_SEEN); - - camel_folder_free_uids (folder, uids); - - camel_folder_thaw (folder); - g_object_unref (folder); - - /* If the folder name queue is empty, we're done. */ - if (g_queue_is_empty (&context->folder_names)) { - e_activity_set_state (context->activity, E_ACTIVITY_COMPLETED); - async_context_free (context); - return; - } - - folder_name = g_queue_pop_head (&context->folder_names); - - camel_store_get_folder ( - store, folder_name, 0, - G_PRIORITY_DEFAULT, cancellable, - (GAsyncReadyCallback) mar_got_folder, context); - - g_free (folder_name); -} - -static void -mar_got_folder_info (CamelStore *store, - GAsyncResult *result, - AsyncContext *context) -{ - EAlertSink *alert_sink; - GCancellable *cancellable; - CamelFolderInfo *folder_info; - gchar *folder_name; - gint response; - GError *error = NULL; - - alert_sink = e_activity_get_alert_sink (context->activity); - cancellable = e_activity_get_cancellable (context->activity); - - folder_info = camel_store_get_folder_info_finish ( - store, result, &error); - - if (e_activity_handle_cancellation (context->activity, error)) { - g_warn_if_fail (folder_info == NULL); - async_context_free (context); - g_error_free (error); - return; - - /* XXX This EAlert primary text isn't technically correct since - * we're just collecting folder tree info and haven't actually - * opened any folders yet, but the user doesn't need to know. */ - } else if (error != NULL) { - g_warn_if_fail (folder_info == NULL); - e_alert_submit ( - alert_sink, "mail:folder-open", - error->message, NULL); - async_context_free (context); - g_error_free (error); - return; - } - - g_return_if_fail (folder_info != NULL); - - response = prompt_user (folder_info->child != NULL); - - if (response == MARK_ALL_READ_CURRENT_FOLDER) - g_queue_push_tail ( - &context->folder_names, - g_strdup (folder_info->full_name)); - - if (response == MARK_ALL_READ_WITH_SUBFOLDERS) - collect_folder_names (&context->folder_names, folder_info); - - camel_store_free_folder_info (store, folder_info); - - /* If the user cancelled, we're done. */ - if (g_queue_is_empty (&context->folder_names)) { - e_activity_set_state (context->activity, E_ACTIVITY_COMPLETED); - async_context_free (context); - return; - } - - folder_name = g_queue_pop_head (&context->folder_names); - - camel_store_get_folder ( - store, folder_name, 0, - G_PRIORITY_DEFAULT, cancellable, - (GAsyncReadyCallback) mar_got_folder, context); - - g_free (folder_name); -} - -static void -action_mail_mark_read_recursive_cb (GtkAction *action, - EShellView *shell_view) -{ - EAlertSink *alert_sink; - GCancellable *cancellable; - EShellBackend *shell_backend; - EShellContent *shell_content; - EShellSidebar *shell_sidebar; - EMFolderTree *folder_tree; - AsyncContext *context; - CamelStore *store; - gchar *folder_name; - - shell_backend = e_shell_view_get_shell_backend (shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - - g_object_get (shell_sidebar, "folder-tree", &folder_tree, NULL); - - /* This action should only be activatable if a folder is selected. */ - if (!em_folder_tree_get_selected (folder_tree, &store, &folder_name)) - g_return_if_reached (); - - g_object_unref (folder_tree); - - /* Open the selected folder asynchronously. */ - - context = g_slice_new0 (AsyncContext); - context->activity = e_activity_new (); - g_queue_init (&context->folder_names); - - alert_sink = E_ALERT_SINK (shell_content); - e_activity_set_alert_sink (context->activity, alert_sink); - - cancellable = camel_operation_new (); - e_activity_set_cancellable (context->activity, cancellable); - - e_shell_backend_add_activity (shell_backend, context->activity); - - camel_store_get_folder_info ( - store, folder_name, - CAMEL_STORE_FOLDER_INFO_FAST | - CAMEL_STORE_FOLDER_INFO_RECURSIVE, - G_PRIORITY_DEFAULT, cancellable, - (GAsyncReadyCallback) mar_got_folder_info, context); - - g_object_unref (cancellable); - - g_object_unref (store); - g_free (folder_name); -} - -static GtkActionEntry entries[] = { - - { "mail-mark-read-recursive", - "mail-mark-read", - N_("Mark Me_ssages as Read"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_mail_mark_read_recursive_cb) } -}; - -static void -update_actions_cb (EShellView *shell_view, - gpointer user_data) -{ - GtkActionGroup *action_group; - EShellSidebar *shell_sidebar; - EShellWindow *shell_window; - EMFolderTree *folder_tree; - GtkAction *action; - gchar *folder_uri; - gboolean visible; - - g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); - - shell_window = e_shell_view_get_shell_window (shell_view); - action_group = e_shell_window_get_action_group (shell_window, "mail"); - - action = gtk_action_group_get_action (action_group, entries[0].name); - g_return_if_fail (action != NULL); - - shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - g_object_get (shell_sidebar, "folder-tree", &folder_tree, NULL); - folder_uri = em_folder_tree_get_selected_uri (folder_tree); - - visible = em_folder_tree_get_selected (folder_tree, NULL, NULL) - && scan_folder_tree_for_unread (folder_uri) > 0; - gtk_action_set_visible (action, visible); - - g_object_unref (folder_tree); - g_free (folder_uri); -} - -gboolean -e_plugin_ui_init (GtkUIManager *ui_manager, - EShellView *shell_view) -{ - EShellWindow *shell_window; - GtkActionGroup *action_group; - - shell_window = e_shell_view_get_shell_window (shell_view); - action_group = e_shell_window_get_action_group (shell_window, "mail"); - - /* Add actions to the "mail" action group. */ - gtk_action_group_add_actions ( - action_group, entries, - G_N_ELEMENTS (entries), shell_view); - - g_signal_connect ( - shell_view, "update-actions", - G_CALLBACK (update_actions_cb), NULL); - - return TRUE; -} diff --git a/plugins/mark-all-read/org-gnome-mark-all-read.eplug.xml b/plugins/mark-all-read/org-gnome-mark-all-read.eplug.xml deleted file mode 100644 index a254e1e4db..0000000000 --- a/plugins/mark-all-read/org-gnome-mark-all-read.eplug.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0"?> -<e-plugin-list> - <e-plugin id="org.gnome.evolution.mail.folder.mark_all_read" - type="shlib" - domain="@GETTEXT_PACKAGE@" - _name="Mark All Read" - location="@PLUGINDIR@/liborg-gnome-mark-all-read@SOEXT@"> - <author name="Chenthill Palanisamy" email="pchenthill@novell.com"/> - <_description>Mark all messages in a folder as read.</_description> - - <hook class="org.gnome.evolution.ui:1.0"> - <ui-manager id="org.gnome.evolution.mail"> - <popup name="mail-folder-popup"> - <placeholder name="mail-folder-popup-actions"> - <menuitem action="mail-mark-read-recursive"/> - </placeholder> - </popup> - </ui-manager> - </hook> - </e-plugin> -</e-plugin-list> diff --git a/po/POTFILES.in b/po/POTFILES.in index 61b9e6a58c..454fe6b285 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -488,8 +488,6 @@ plugins/mail-notification/mail-notification.c plugins/mail-notification/org-gnome-mail-notification.eplug.xml plugins/mail-to-task/mail-to-task.c plugins/mail-to-task/org-gnome-mail-to-task.eplug.xml -plugins/mark-all-read/mark-all-read.c -plugins/mark-all-read/org-gnome-mark-all-read.eplug.xml plugins/pst-import/org-gnome-pst-import.eplug.xml plugins/pst-import/pst-importer.c plugins/publish-calendar/org-gnome-publish-calendar.eplug.xml diff --git a/ui/evolution-mail.ui b/ui/evolution-mail.ui index 6da260acaa..f9701dd35a 100644 --- a/ui/evolution-mail.ui +++ b/ui/evolution-mail.ui @@ -72,6 +72,7 @@ </toolbar> <popup name='mail-folder-popup'> <placeholder name='mail-folder-popup-actions'/> + <menuitem action='mail-popup-folder-mark-all-as-read'/> <separator/> <menuitem action='mail-popup-folder-new'/> <menuitem action='mail-popup-folder-copy'/> |