aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2013-05-04 00:11:37 +0800
committerMilan Crha <mcrha@redhat.com>2013-05-04 00:11:37 +0800
commit7770e7c36560adb9ce3d4714e369ebcd46274b85 (patch)
tree2bb0b336e71f15a22369c3234014afe2ebb40b6f
parent5dfeb54af9639bc3a1df5e4262ec384d2abf5a9d (diff)
downloadgsoc2013-evolution-7770e7c36560adb9ce3d4714e369ebcd46274b85.tar
gsoc2013-evolution-7770e7c36560adb9ce3d4714e369ebcd46274b85.tar.gz
gsoc2013-evolution-7770e7c36560adb9ce3d4714e369ebcd46274b85.tar.bz2
gsoc2013-evolution-7770e7c36560adb9ce3d4714e369ebcd46274b85.tar.lz
gsoc2013-evolution-7770e7c36560adb9ce3d4714e369ebcd46274b85.tar.xz
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.ac3
-rw-r--r--mail/mail.error.xml14
-rw-r--r--modules/mail/e-mail-shell-view-actions.c336
-rw-r--r--modules/mail/e-mail-shell-view-actions.h2
-rw-r--r--modules/mail/e-mail-shell-view.c19
-rw-r--r--plugins/mark-all-read/Makefile.am31
-rw-r--r--plugins/mark-all-read/mark-all-read.c602
-rw-r--r--plugins/mark-all-read/org-gnome-mark-all-read.eplug.xml21
-rw-r--r--po/POTFILES.in2
-rw-r--r--ui/evolution-mail.ui1
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 &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 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'/>