[evolution] I#14 - Add 'in Current Folder and Subfolders' search option
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] I#14 - Add 'in Current Folder and Subfolders' search option
- Date: Tue, 12 Jun 2018 08:50:01 +0000 (UTC)
commit f95b34ccd6c43e2044f87ffccc4b4a95b2924c08
Author: Milan Crha <mcrha redhat com>
Date: Tue Jun 12 10:50:36 2018 +0200
I#14 - Add 'in Current Folder and Subfolders' search option
Closes https://gitlab.gnome.org/GNOME/evolution/issues/14
src/modules/mail/e-mail-shell-view-actions.c | 9 +-
src/modules/mail/e-mail-shell-view-actions.h | 2 +
src/modules/mail/e-mail-shell-view-private.c | 22 +--
src/modules/mail/e-mail-shell-view-private.h | 2 +
src/modules/mail/e-mail-shell-view.c | 236 +++++++++++++++++++++++++++
5 files changed, 256 insertions(+), 15 deletions(-)
---
diff --git a/src/modules/mail/e-mail-shell-view-actions.c b/src/modules/mail/e-mail-shell-view-actions.c
index 73988f8c9f..259e3536bb 100644
--- a/src/modules/mail/e-mail-shell-view-actions.c
+++ b/src/modules/mail/e-mail-shell-view-actions.c
@@ -2223,7 +2223,14 @@ static GtkRadioActionEntry mail_scope_entries[] = {
N_("Current Folder"),
NULL,
NULL, /* XXX Add a tooltip! */
- MAIL_SCOPE_CURRENT_FOLDER }
+ MAIL_SCOPE_CURRENT_FOLDER },
+
+ { "mail-scope-current-folder-and-subfolders",
+ NULL,
+ N_("Current Folder and Subfolders"),
+ NULL,
+ NULL, /* XXX Add a tooltip! */
+ MAIL_SCOPE_CURRENT_FOLDER_AND_SUBFOLDERS }
};
void
diff --git a/src/modules/mail/e-mail-shell-view-actions.h b/src/modules/mail/e-mail-shell-view-actions.h
index bf6c65e43f..0c13472e3f 100644
--- a/src/modules/mail/e-mail-shell-view-actions.h
+++ b/src/modules/mail/e-mail-shell-view-actions.h
@@ -254,6 +254,8 @@
E_SHELL_WINDOW_ACTION ((window), "mail-scope-current-account")
#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_CURRENT_FOLDER(window) \
E_SHELL_WINDOW_ACTION ((window), "mail-scope-current-folder")
+#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_CURRENT_FOLDER_AND_SUBFOLDERS(window) \
+ E_SHELL_WINDOW_ACTION ((window), "mail-scope-current-folder-and-subfolders")
#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_CURRENT_MESSAGE(window) \
E_SHELL_WINDOW_ACTION ((window), "mail-scope-current-message")
#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_BODY_CONTAINS(window) \
diff --git a/src/modules/mail/e-mail-shell-view-private.c b/src/modules/mail/e-mail-shell-view-private.c
index a964dbc47b..46b8ab3c19 100644
--- a/src/modules/mail/e-mail-shell-view-private.c
+++ b/src/modules/mail/e-mail-shell-view-private.c
@@ -758,20 +758,10 @@ e_mail_shell_view_private_dispose (EMailShellView *mail_shell_view)
g_clear_object (&priv->opening_folder);
}
- if (priv->search_account_all != NULL) {
- g_object_unref (priv->search_account_all);
- priv->search_account_all = NULL;
- }
-
- if (priv->search_account_current != NULL) {
- g_object_unref (priv->search_account_current);
- priv->search_account_current = NULL;
- }
-
- if (priv->search_account_cancel != NULL) {
- g_object_unref (priv->search_account_cancel);
- priv->search_account_cancel = NULL;
- }
+ g_clear_object (&priv->search_folder_and_subfolders);
+ g_clear_object (&priv->search_account_all);
+ g_clear_object (&priv->search_account_current);
+ g_clear_object (&priv->search_account_cancel);
g_slist_free_full (priv->selected_uids, (GDestroyNotify) camel_pstring_free);
priv->selected_uids = NULL;
@@ -827,6 +817,10 @@ e_mail_shell_view_restore_state (EMailShellView *mail_shell_view)
if (vee_folder != NULL && folder == CAMEL_FOLDER (vee_folder))
goto exit;
+ vee_folder = mail_shell_view->priv->search_folder_and_subfolders;
+ if (vee_folder != NULL && folder == CAMEL_FOLDER (vee_folder))
+ goto exit;
+
folder_uri = e_mail_folder_uri_from_folder (folder);
new_state_group = g_strdup_printf ("Folder %s", folder_uri);
old_state_group = e_shell_searchbar_get_state_group (searchbar);
diff --git a/src/modules/mail/e-mail-shell-view-private.h b/src/modules/mail/e-mail-shell-view-private.h
index b9aac71bdf..f373e249bc 100644
--- a/src/modules/mail/e-mail-shell-view-private.h
+++ b/src/modules/mail/e-mail-shell-view-private.h
@@ -104,6 +104,7 @@ enum {
/* Scope items are displayed in ascending order. */
enum {
MAIL_SCOPE_CURRENT_FOLDER,
+ MAIL_SCOPE_CURRENT_FOLDER_AND_SUBFOLDERS,
MAIL_SCOPE_CURRENT_ACCOUNT,
MAIL_SCOPE_ALL_ACCOUNTS
};
@@ -131,6 +132,7 @@ struct _EMailShellViewPrivate {
GCancellable *opening_folder;
/* Search folders for interactive search. */
+ CamelVeeFolder *search_folder_and_subfolders;
CamelVeeFolder *search_account_all;
CamelVeeFolder *search_account_current;
GCancellable *search_account_cancel;
diff --git a/src/modules/mail/e-mail-shell-view.c b/src/modules/mail/e-mail-shell-view.c
index 57ac524717..7e31592e7e 100644
--- a/src/modules/mail/e-mail-shell-view.c
+++ b/src/modules/mail/e-mail-shell-view.c
@@ -186,6 +186,120 @@ mail_shell_view_setup_search_results_folder (CamelFolder *folder,
return id;
}
+typedef struct {
+ MailMsg base;
+
+ CamelFolder *vfolder;
+ GCancellable *cancellable;
+ CamelFolder *root_folder;
+} SearchResultsWithSubfoldersMsg;
+
+static gchar *
+search_results_with_subfolders_desc (SearchResultsWithSubfoldersMsg *msg)
+{
+ return g_strdup (_("Searching"));
+}
+
+static void
+search_results_with_subfolders_exec (SearchResultsWithSubfoldersMsg *msg,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GList *folders = NULL;
+ CamelStore *root_store;
+ CamelFolderInfo *fi;
+ const CamelFolderInfo *cur;
+ const gchar *root_folder_name;
+
+ root_store = camel_folder_get_parent_store (msg->root_folder);
+ if (!root_store)
+ return;
+
+ root_folder_name = camel_folder_get_full_name (msg->root_folder);
+
+ fi = camel_store_get_folder_info_sync (root_store, root_folder_name,
+ CAMEL_STORE_FOLDER_INFO_RECURSIVE, cancellable, NULL);
+
+ cur = fi;
+ while (cur && !g_cancellable_is_cancelled (cancellable)) {
+ if ((cur->flags & CAMEL_FOLDER_NOSELECT) == 0) {
+ CamelFolder *folder;
+
+ folder = camel_store_get_folder_sync (root_store, cur->full_name, 0, cancellable,
NULL);
+ if (folder)
+ folders = g_list_prepend (folders, folder);
+ }
+
+ /* move to the next fi */
+ if (cur->child) {
+ cur = cur->child;
+ } else if (cur->next) {
+ cur = cur->next;
+ } else {
+ while (cur && !cur->next) {
+ cur = cur->parent;
+ }
+
+ if (cur)
+ cur = cur->next;
+ }
+ }
+
+ camel_folder_info_free (fi);
+
+ if (!g_cancellable_is_cancelled (cancellable)) {
+ CamelVeeFolder *vfolder = CAMEL_VEE_FOLDER (msg->vfolder);
+
+ folders = g_list_reverse (folders);
+
+ camel_vee_folder_set_folders (vfolder, folders, cancellable);
+ }
+
+ g_list_free_full (folders, g_object_unref);
+}
+
+static void
+search_results_with_subfolders_done (SearchResultsWithSubfoldersMsg *msg)
+{
+}
+
+static void
+search_results_with_subfolders_free (SearchResultsWithSubfoldersMsg *msg)
+{
+ g_object_unref (msg->vfolder);
+ g_object_unref (msg->root_folder);
+}
+
+static MailMsgInfo search_results_with_subfolders_setup_info = {
+ sizeof (SearchResultsWithSubfoldersMsg),
+ (MailMsgDescFunc) search_results_with_subfolders_desc,
+ (MailMsgExecFunc) search_results_with_subfolders_exec,
+ (MailMsgDoneFunc) search_results_with_subfolders_done,
+ (MailMsgFreeFunc) search_results_with_subfolders_free
+};
+
+static gint
+mail_shell_view_setup_search_results_folder_and_subfolders (CamelFolder *vfolder,
+ CamelFolder *root_folder,
+ GCancellable *cancellable)
+{
+ SearchResultsWithSubfoldersMsg *msg;
+ gint id;
+
+ if (!root_folder)
+ return 0;
+
+ msg = mail_msg_new (&search_results_with_subfolders_setup_info);
+ msg->vfolder = g_object_ref (vfolder);
+ msg->cancellable = cancellable;
+ msg->root_folder = g_object_ref (root_folder);
+
+ id = msg->base.seq;
+ mail_msg_slow_ordered_push (msg);
+
+ return id;
+}
+
static void
mail_shell_view_show_search_results_folder (EMailShellView *mail_shell_view,
CamelFolder *folder)
@@ -682,6 +796,9 @@ filter:
case MAIL_SCOPE_CURRENT_FOLDER:
goto execute;
+ case MAIL_SCOPE_CURRENT_FOLDER_AND_SUBFOLDERS:
+ goto current_and_subfolders;
+
case MAIL_SCOPE_CURRENT_ACCOUNT:
goto current_account;
@@ -693,6 +810,125 @@ filter:
goto execute;
}
+ current_and_subfolders:
+
+ /* Prepare search folder for current folder and its subfolders. */
+
+ /* If the search text is empty, cancel any
+ * account-wide searches still in progress. */
+ text = e_shell_searchbar_get_search_text (searchbar);
+ if ((text == NULL || *text == '\0') && !e_shell_view_get_search_rule (shell_view)) {
+ CamelStore *selected_store = NULL;
+ gchar *selected_folder_name = NULL;
+
+ if (priv->search_folder_and_subfolders != NULL) {
+ g_object_unref (priv->search_folder_and_subfolders);
+ priv->search_folder_and_subfolders = NULL;
+ }
+
+ if (priv->search_account_cancel != NULL) {
+ g_cancellable_cancel (priv->search_account_cancel);
+ g_object_unref (priv->search_account_cancel);
+ priv->search_account_cancel = NULL;
+ }
+
+ /* Reset the message list to the current folder tree
+ * selection. This needs to happen synchronously to
+ * avoid search conflicts, so we can't just grab the
+ * folder URI and let the asynchronous callbacks run
+ * after we've already kicked off the search. */
+ em_folder_tree_get_selected (
+ folder_tree, &selected_store, &selected_folder_name);
+ if (selected_store != NULL && selected_folder_name != NULL) {
+ folder = camel_store_get_folder_sync (
+ selected_store, selected_folder_name,
+ 0, NULL, NULL);
+ e_mail_reader_set_folder (reader, folder);
+ g_object_unref (folder);
+ }
+
+ g_clear_object (&selected_store);
+ g_free (selected_folder_name);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (combo_box), TRUE);
+
+ goto execute;
+ }
+
+ search_folder = priv->search_folder_and_subfolders;
+
+ /* Skip the search if we already have the results. */
+ if (search_folder != NULL) {
+ const gchar *vf_query;
+
+ vf_query = camel_vee_folder_get_expression (search_folder);
+ if (g_strcmp0 (query, vf_query) == 0)
+ goto current_folder_and_subfolders_setup;
+ }
+
+ /* Disable the scope combo while search is in progress. */
+ gtk_widget_set_sensitive (GTK_WIDGET (combo_box), FALSE);
+
+ /* If we already have a search folder, reuse it. */
+ if (search_folder != NULL) {
+ if (priv->search_account_cancel != NULL) {
+ g_cancellable_cancel (priv->search_account_cancel);
+ g_object_unref (priv->search_account_cancel);
+ priv->search_account_cancel = NULL;
+ }
+
+ camel_vee_folder_set_expression (search_folder, query);
+
+ goto current_folder_and_subfolders_setup;
+ }
+
+ /* Create a new search folder. */
+
+ /* FIXME Complete lack of error checking here. */
+ service = camel_session_ref_service (CAMEL_SESSION (session), E_MAIL_SESSION_VFOLDER_UID);
+ camel_service_connect_sync (service, NULL, NULL);
+
+ search_folder = (CamelVeeFolder *) camel_vee_folder_new (
+ CAMEL_STORE (service),
+ _("Current Folder and Subfolders Search"),
+ CAMEL_STORE_FOLDER_PRIVATE);
+ priv->search_folder_and_subfolders = search_folder;
+
+ g_object_unref (service);
+
+ camel_vee_folder_set_expression (search_folder, query);
+
+ current_folder_and_subfolders_setup:
+
+ if (folder != NULL && folder != CAMEL_FOLDER (search_folder)) {
+ /* Just use the folder */
+ } else {
+ CamelStore *selected_store = NULL;
+ gchar *selected_folder_name = NULL;
+
+ g_clear_object (&folder);
+
+ em_folder_tree_get_selected (folder_tree, &selected_store, &selected_folder_name);
+ if (selected_store != NULL && selected_folder_name != NULL) {
+ folder = camel_store_get_folder_sync (selected_store, selected_folder_name, 0, NULL,
NULL);
+ }
+
+ g_clear_object (&selected_store);
+ g_free (selected_folder_name);
+ }
+
+ priv->search_account_cancel = camel_operation_new ();
+
+ mail_shell_view_setup_search_results_folder_and_subfolders (
+ CAMEL_FOLDER (search_folder), folder,
+ priv->search_account_cancel);
+
+ mail_shell_view_show_search_results_folder (
+ E_MAIL_SHELL_VIEW (shell_view),
+ CAMEL_FOLDER (search_folder));
+
+ goto execute;
+
all_accounts:
/* Prepare search folder for all accounts. */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]