[evolution] Merge [mark-all-read] plugin into core code



commit 7770e7c36560adb9ce3d4714e369ebcd46274b85
Author: Milan Crha <mcrha redhat com>
Date:   Fri May 3 18:11:37 2013 +0200

    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.

 configure.ac                                       |    3 +-
 mail/mail.error.xml                                |   14 +-
 modules/mail/e-mail-shell-view-actions.c           |  336 ++++++++++-
 modules/mail/e-mail-shell-view-actions.h           |    2 +
 modules/mail/e-mail-shell-view.c                   |   19 +-
 plugins/mark-all-read/Makefile.am                  |   31 -
 plugins/mark-all-read/mark-all-read.c              |  602 --------------------
 .../org-gnome-mark-all-read.eplug.xml              |   21 -
 po/POTFILES.in                                     |    2 -
 ui/evolution-mail.ui                               |    1 +
 10 files changed, 340 insertions(+), 691 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index eccc0ad..8e75f0e 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 3f1f295..d523b54 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 &quot;{0}&quot;.</_secondary>
   </error>
 
+  <error id="mark-all-read" type="error">
+    <_primary>Failed to mark messages as read.</_primary>
+    <_secondary>The reported error was &quot;{0}&quot;.</_secondary>
+  </error>
+
   <error id="remove-attachments" type="error">
     <_primary>Failed to remove attachments from messages.</_primary>
     <_secondary>The reported error was &quot;{0}&quot;.</_secondary>
diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c
index 3af5fac..75fc61e 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 ff0829b..109dfce 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 285bb5d..14b3a83 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/po/POTFILES.in b/po/POTFILES.in
index 61b9e6a..454fe6b 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 6da260a..f9701dd 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'/>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]