aboutsummaryrefslogtreecommitdiffstats
path: root/modules/mail
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2010-02-03 23:01:58 +0800
committerMatthew Barnes <mbarnes@redhat.com>2010-02-07 02:46:40 +0800
commit31e449ebed6a136e643ec3bf4c0d9f1b3fc87897 (patch)
treed3ab719626888d56370eee15e2bcc64c2cdbb072 /modules/mail
parentc211d932475c1b53f118bceda65bc4915e90140a (diff)
downloadgsoc2013-evolution-31e449ebed6a136e643ec3bf4c0d9f1b3fc87897.tar.gz
gsoc2013-evolution-31e449ebed6a136e643ec3bf4c0d9f1b3fc87897.tar.zst
gsoc2013-evolution-31e449ebed6a136e643ec3bf4c0d9f1b3fc87897.zip
Implement account-wide search scope in mail.
Also, let EShellSearchbar handle search state persistence.
Diffstat (limited to 'modules/mail')
-rw-r--r--modules/mail/e-mail-shell-view-actions.c89
-rw-r--r--modules/mail/e-mail-shell-view-private.c59
-rw-r--r--modules/mail/e-mail-shell-view-private.h10
-rw-r--r--modules/mail/e-mail-shell-view.c385
4 files changed, 438 insertions, 105 deletions
diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c
index 6b72c7796d..766489fbe2 100644
--- a/modules/mail/e-mail-shell-view-actions.c
+++ b/modules/mail/e-mail-shell-view-actions.c
@@ -848,74 +848,6 @@ action_mail_view_cb (GtkRadioAction *action,
gtk_orientable_set_orientation (orientable, orientation);
}
-static void
-action_search_filter_cb (GtkRadioAction *action,
- GtkRadioAction *current,
- EShellView *shell_view)
-{
- EShellContent *shell_content;
- EMailReader *reader;
- GKeyFile *key_file;
- const gchar *folder_uri;
-
- shell_content = e_shell_view_get_shell_content (shell_view);
- key_file = e_shell_view_get_state_key_file (shell_view);
-
- reader = E_MAIL_READER (shell_content);
- folder_uri = e_mail_reader_get_folder_uri (reader);
-
- if (folder_uri != NULL) {
- const gchar *key;
- const gchar *string;
- gchar *group_name;
-
- key = STATE_KEY_SEARCH_FILTER;
- string = gtk_action_get_name (GTK_ACTION (current));
- group_name = g_strdup_printf ("Folder %s", folder_uri);
-
- g_key_file_set_string (key_file, group_name, key, string);
- e_shell_view_set_state_dirty (shell_view);
-
- g_free (group_name);
- }
-
- e_shell_view_execute_search (shell_view);
-}
-
-static void
-action_search_scope_cb (GtkRadioAction *action,
- GtkRadioAction *current,
- EShellView *shell_view)
-{
- EShellContent *shell_content;
- EMailReader *reader;
- GKeyFile *key_file;
- const gchar *folder_uri;
-
- shell_content = e_shell_view_get_shell_content (shell_view);
- key_file = e_shell_view_get_state_key_file (shell_view);
-
- reader = E_MAIL_READER (shell_content);
- folder_uri = e_mail_reader_get_folder_uri (reader);
-
- if (folder_uri != NULL) {
- const gchar *key;
- const gchar *string;
- gchar *group_name;
-
- key = STATE_KEY_SEARCH_SCOPE;
- string = gtk_action_get_name (GTK_ACTION (current));
- group_name = g_strdup_printf ("Folder %s", folder_uri);
-
- g_key_file_set_string (key_file, group_name, key, string);
- e_shell_view_set_state_dirty (shell_view);
-
- g_free (group_name);
- }
-
- e_shell_view_execute_search (shell_view);
-}
-
static GtkActionEntry mail_entries[] = {
{ "mail-account-disable",
@@ -1449,8 +1381,7 @@ e_mail_shell_view_actions_init (EMailShellView *mail_shell_view)
gtk_action_group_add_radio_actions (
action_group, mail_scope_entries,
G_N_ELEMENTS (mail_scope_entries),
- MAIL_SCOPE_CURRENT_FOLDER,
- G_CALLBACK (action_search_scope_cb), mail_shell_view);
+ MAIL_SCOPE_CURRENT_FOLDER, NULL, NULL);
action = ACTION (MAIL_SCOPE_ALL_ACCOUNTS);
combo_box = e_shell_searchbar_get_scope_combo_box (searchbar);
@@ -1462,9 +1393,6 @@ e_mail_shell_view_actions_init (EMailShellView *mail_shell_view)
gtk_action_set_visible (action, FALSE);
e_shell_searchbar_set_search_option (
searchbar, GTK_RADIO_ACTION (action));
- gtk_radio_action_set_current_value (
- GTK_RADIO_ACTION (action),
- MAIL_SEARCH_SUBJECT_OR_ADDRESSES_CONTAIN);
/* Bind GObject properties for GConf keys. */
@@ -1716,13 +1644,13 @@ e_mail_shell_view_update_search_filter (EMailShellView *mail_shell_view)
action_group = ACTION_GROUP (MAIL_FILTER);
e_action_group_remove_all_actions (action_group);
- /* Add the standard filter actions. */
+ /* Add the standard filter actions. No callback is needed
+ * because changes in the EActionComboBox are detected and
+ * handled by EShellSearchbar. */
gtk_action_group_add_radio_actions (
action_group, mail_filter_entries,
G_N_ELEMENTS (mail_filter_entries),
- MAIL_FILTER_ALL_MESSAGES,
- G_CALLBACK (action_search_filter_cb),
- mail_shell_view);
+ MAIL_FILTER_ALL_MESSAGES, NULL, NULL);
/* Retrieve the radio group from an action we just added. */
list = gtk_action_group_list_actions (action_group);
@@ -1763,10 +1691,13 @@ e_mail_shell_view_update_search_filter (EMailShellView *mail_shell_view)
ii++;
}
- /* Use any action in the group; doesn't matter which. */
mail_shell_content = mail_shell_view->priv->mail_shell_content;
searchbar = e_mail_shell_content_get_searchbar (mail_shell_content);
combo_box = e_shell_searchbar_get_filter_combo_box (searchbar);
+
+ e_shell_view_block_execute_search (shell_view);
+
+ /* Use any action in the group; doesn't matter which. */
e_action_combo_box_set_action (combo_box, radio_action);
ii = MAIL_FILTER_UNREAD_MESSAGES;
@@ -1775,5 +1706,7 @@ e_mail_shell_view_update_search_filter (EMailShellView *mail_shell_view)
ii = MAIL_FILTER_READ_MESSAGES;
e_action_combo_box_add_separator_after (combo_box, ii);
+ e_shell_view_unblock_execute_search (shell_view);
+
g_object_unref (tree_model);
}
diff --git a/modules/mail/e-mail-shell-view-private.c b/modules/mail/e-mail-shell-view-private.c
index 377811e518..125432c7f7 100644
--- a/modules/mail/e-mail-shell-view-private.c
+++ b/modules/mail/e-mail-shell-view-private.c
@@ -416,6 +416,7 @@ void
e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
{
EMailShellViewPrivate *priv = mail_shell_view->priv;
+ EMailShellContent *mail_shell_content;
EMailShellSidebar *mail_shell_sidebar;
EShell *shell;
EShellView *shell_view;
@@ -424,8 +425,10 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
EShellSettings *shell_settings;
EShellSidebar *shell_sidebar;
EShellWindow *shell_window;
+ EShellSearchbar *searchbar;
EMFormatHTMLDisplay *html_display;
EMFolderTree *folder_tree;
+ EActionComboBox *combo_box;
ERuleContext *context;
EFilterRule *rule = NULL;
GtkTreeSelection *selection;
@@ -472,6 +475,16 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_tree));
+ mail_shell_content = E_MAIL_SHELL_CONTENT (shell_content);
+ searchbar = e_mail_shell_content_get_searchbar (mail_shell_content);
+ combo_box = e_shell_searchbar_get_scope_combo_box (searchbar);
+
+ /* The folder tree and scope combo box are both insensitive
+ * when searching beyond the currently selected folder. */
+ e_mutual_binding_new (
+ folder_tree, "sensitive",
+ combo_box, "sensitive");
+
web_view = E_WEB_VIEW (EM_FORMAT_HTML (html_display)->html);
g_signal_connect_swapped (
@@ -616,6 +629,21 @@ e_mail_shell_view_private_dispose (EMailShellView *mail_shell_view)
for (ii = 0; ii < MAIL_NUM_SEARCH_RULES; ii++)
DISPOSE (priv->search_rules[ii]);
+
+ if (priv->search_account_all != NULL) {
+ camel_object_unref (priv->search_account_all);
+ priv->search_account_all = NULL;
+ }
+
+ if (priv->search_account_current != NULL) {
+ camel_object_unref (priv->search_account_current);
+ priv->search_account_current = NULL;
+ }
+
+ if (priv->search_account_cancel != NULL) {
+ camel_operation_unref (priv->search_account_cancel);
+ priv->search_account_cancel = NULL;
+ }
}
void
@@ -630,8 +658,11 @@ e_mail_shell_view_restore_state (EMailShellView *mail_shell_view)
EMailShellContent *mail_shell_content;
EShellSearchbar *searchbar;
EMailReader *reader;
+ CamelFolder *folder;
+ CamelVeeFolder *vee_folder;
+ const gchar *old_state_group;
const gchar *folder_uri;
- gchar *group_name;
+ gchar *new_state_group;
/* XXX Move this to EMailShellContent. */
@@ -641,14 +672,34 @@ e_mail_shell_view_restore_state (EMailShellView *mail_shell_view)
searchbar = e_mail_shell_content_get_searchbar (mail_shell_content);
reader = E_MAIL_READER (mail_shell_content);
+ folder = e_mail_reader_get_folder (reader);
folder_uri = e_mail_reader_get_folder_uri (reader);
if (folder_uri == NULL)
return;
- group_name = g_strdup_printf ("Folder %s", folder_uri);
- e_shell_searchbar_restore_state (searchbar, group_name);
- g_free (group_name);
+ /* Do not restore state if we're running a "Current Account"
+ * or "All Accounts" search, since we don't want the search
+ * criteria to be destroyed in those cases. */
+
+ vee_folder = mail_shell_view->priv->search_account_all;
+ if (vee_folder != NULL && folder == CAMEL_FOLDER (vee_folder))
+ return;
+
+ vee_folder = mail_shell_view->priv->search_account_current;
+ if (vee_folder != NULL && folder == CAMEL_FOLDER (vee_folder))
+ return;
+
+ new_state_group = g_strdup_printf ("Folder %s", folder_uri);
+ old_state_group = e_shell_searchbar_get_state_group (searchbar);
+
+ /* Avoid loading search state unnecessarily. */
+ if (g_strcmp0 (new_state_group, old_state_group) != 0) {
+ e_shell_searchbar_set_state_group (searchbar, new_state_group);
+ e_shell_searchbar_load_state (searchbar);
+ }
+
+ g_free (new_state_group);
}
/* Helper for e_mail_shell_view_create_filter_from_selected() */
diff --git a/modules/mail/e-mail-shell-view-private.h b/modules/mail/e-mail-shell-view-private.h
index 44a02eddbd..9cdd71d13c 100644
--- a/modules/mail/e-mail-shell-view-private.h
+++ b/modules/mail/e-mail-shell-view-private.h
@@ -28,6 +28,9 @@
#include <gtkhtml/gtkhtml.h>
#include <camel/camel-disco-store.h>
#include <camel/camel-offline-store.h>
+#include <camel/camel-operation.h>
+#include <camel/camel-vee-folder.h>
+#include <camel/camel-vee-store.h>
#include <camel/camel-vtrash-folder.h>
#include <camel/camel-search-private.h> /* for camel_search_word */
@@ -58,6 +61,8 @@
#include "mail-config.h"
#include "mail-ops.h"
#include "mail-send-recv.h"
+#include "mail-session.h"
+#include "mail-tools.h"
#include "mail-vfolder.h"
#include "message-list.h"
@@ -147,6 +152,11 @@ struct _EMailShellViewPrivate {
/* EShell::prepare-for-quit */
gulong prepare_for_quit_handler_id;
+ /* Search folders for interactive search. */
+ CamelVeeFolder *search_account_all;
+ CamelVeeFolder *search_account_current;
+ CamelOperation *search_account_cancel;
+
guint show_deleted : 1;
};
diff --git a/modules/mail/e-mail-shell-view.c b/modules/mail/e-mail-shell-view.c
index 6016a14717..ce3c285a37 100644
--- a/modules/mail/e-mail-shell-view.c
+++ b/modules/mail/e-mail-shell-view.c
@@ -25,6 +25,114 @@
static gpointer parent_class;
static GType mail_shell_view_type;
+/* ETable spec for search results */
+static const gchar *SEARCH_RESULTS_STATE =
+"<ETableState>"
+" <column source=\"0\"/>"
+" <column source=\"3\"/>"
+" <column source=\"1\"/>"
+" <column source=\"14\"/>"
+" <column source=\"5\"/>"
+" <column source=\"7\"/>"
+" <column source=\"13\"/>"
+" <grouping>"
+" <leaf column=\"7\" ascending=\"false\"/>"
+" </grouping>"
+"</ETableState>";
+
+typedef struct {
+ MailMsg base;
+
+ CamelFolder *folder;
+ CamelOperation *cancel;
+ GList *folder_list;
+} SearchResultsMsg;
+
+static gchar *
+search_results_desc (SearchResultsMsg *msg)
+{
+ return g_strdup (_("Searching"));
+}
+
+static void
+search_results_exec (SearchResultsMsg *msg)
+{
+ GList *copied_list;
+
+ camel_operation_register (msg->cancel);
+
+ copied_list = g_list_copy (msg->folder_list);
+ g_list_foreach (copied_list, (GFunc) camel_object_ref, NULL);
+
+ camel_vee_folder_set_folders (
+ CAMEL_VEE_FOLDER (msg->folder), copied_list);
+
+ g_list_foreach (copied_list, (GFunc) camel_object_unref, NULL);
+ g_list_free (copied_list);
+}
+
+static void
+search_results_done (SearchResultsMsg *msg)
+{
+}
+
+static void
+search_results_free (SearchResultsMsg *msg)
+{
+ camel_object_unref (msg->folder);
+
+ g_list_foreach (msg->folder_list, (GFunc) camel_object_unref, NULL);
+ g_list_free (msg->folder_list);
+}
+
+static MailMsgInfo search_results_setup_info = {
+ sizeof (SearchResultsMsg),
+ (MailMsgDescFunc) search_results_desc,
+ (MailMsgExecFunc) search_results_exec,
+ (MailMsgDoneFunc) search_results_done,
+ (MailMsgFreeFunc) search_results_free
+};
+
+static gint
+mail_shell_view_setup_search_results_folder (CamelFolder *folder,
+ GList *folder_list,
+ CamelOperation *cancel)
+{
+ SearchResultsMsg *msg;
+ gint id;
+
+ camel_object_ref (folder);
+
+ msg = mail_msg_new (&search_results_setup_info);
+ msg->folder = folder;
+ msg->cancel = cancel;
+ msg->folder_list = folder_list;
+
+ 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,
+ const gchar *folder_uri)
+{
+ GtkWidget *message_list;
+ EMailReader *reader;
+
+ reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content);
+ message_list = e_mail_reader_get_message_list (reader);
+
+ message_list_freeze (MESSAGE_LIST (message_list));
+
+ e_mail_reader_set_folder (reader, folder, folder_uri);
+ e_tree_set_state (E_TREE (message_list), SEARCH_RESULTS_STATE);
+
+ message_list_thaw (MESSAGE_LIST (message_list));
+}
+
static void
mail_shell_view_dispose (GObject *object)
{
@@ -88,36 +196,47 @@ mail_shell_view_execute_search (EShellView *shell_view)
{
EMailShellViewPrivate *priv;
EMailShellContent *mail_shell_content;
+ EMailShellSidebar *mail_shell_sidebar;
EShell *shell;
EShellWindow *shell_window;
+ EShellBackend *shell_backend;
EShellContent *shell_content;
+ EShellSidebar *shell_sidebar;
EShellSettings *shell_settings;
EShellSearchbar *searchbar;
EActionComboBox *combo_box;
+ EMFolderTree *folder_tree;
+ GtkTreeSelection *selection;
GtkWidget *message_list;
EFilterRule *rule;
EMailReader *reader;
+ CamelVeeFolder *search_folder;
CamelFolder *folder;
+ CamelStore *store;
GtkAction *action;
GtkTreeModel *model;
GtkTreePath *path;
GtkTreeIter tree_iter;
GString *string;
- GList *iter;
+ GList *list, *iter;
GSList *search_strings = NULL;
const gchar *folder_uri;
+ const gchar *data_dir;
const gchar *text;
gboolean valid;
gchar *query;
gchar *temp;
gchar *tag;
+ gchar *uri;
const gchar *use_tag;
gint value;
priv = E_MAIL_SHELL_VIEW_GET_PRIVATE (shell_view);
shell_window = e_shell_view_get_shell_window (shell_view);
+ 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);
shell = e_shell_window_get_shell (shell_window);
shell_settings = e_shell_get_shell_settings (shell);
@@ -125,33 +244,16 @@ mail_shell_view_execute_search (EShellView *shell_view)
mail_shell_content = E_MAIL_SHELL_CONTENT (shell_content);
searchbar = e_mail_shell_content_get_searchbar (mail_shell_content);
+ mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar);
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_tree));
+
reader = E_MAIL_READER (shell_content);
folder = e_mail_reader_get_folder (reader);
folder_uri = e_mail_reader_get_folder_uri (reader);
message_list = e_mail_reader_get_message_list (reader);
- if (folder_uri != NULL) {
- GKeyFile *key_file;
- const gchar *key;
- const gchar *string;
- gchar *group_name;
-
- key_file = e_shell_view_get_state_key_file (shell_view);
-
- key = STATE_KEY_SEARCH_TEXT;
- string = e_shell_searchbar_get_search_text (searchbar);
- group_name = g_strdup_printf ("Folder %s", folder_uri);
-
- if (string != NULL && *string != '\0')
- g_key_file_set_string (
- key_file, group_name, key, string);
- else
- g_key_file_remove_key (
- key_file, group_name, key, NULL);
- e_shell_view_set_state_dirty (shell_view);
-
- g_free (group_name);
- }
+ data_dir = e_shell_backend_get_data_dir (shell_backend);
/* This returns a new object reference. */
model = e_shell_settings_get_object (
@@ -357,6 +459,243 @@ filter:
break;
}
+ /* Apply selected scope. */
+
+ combo_box = e_shell_searchbar_get_scope_combo_box (searchbar);
+ value = e_action_combo_box_get_current_value (combo_box);
+ switch (value) {
+ case MAIL_SCOPE_CURRENT_FOLDER:
+ goto execute;
+
+ case MAIL_SCOPE_CURRENT_ACCOUNT:
+ goto current_account;
+
+ case MAIL_SCOPE_ALL_ACCOUNTS:
+ goto all_accounts;
+
+ default:
+ g_warn_if_reached ();
+ goto execute;
+ }
+
+all_accounts:
+
+ /* Prepare search folder for all accounts. */
+
+ /* 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') {
+ if (priv->search_account_all != NULL) {
+ camel_object_unref (priv->search_account_all);
+ priv->search_account_all = NULL;
+ }
+
+ if (priv->search_account_cancel != NULL) {
+ camel_operation_cancel (priv->search_account_cancel);
+ camel_operation_unref (priv->search_account_cancel);
+ priv->search_account_cancel = NULL;
+ }
+
+ /* Simulate a folder tree selection change, so the
+ * message list is reset to the correct folder via
+ * our EMFolderTree::folder-selected handler. */
+ g_signal_emit_by_name (selection, "changed");
+
+ gtk_widget_set_sensitive (GTK_WIDGET (combo_box), TRUE);
+
+ goto execute;
+ }
+
+ search_folder = priv->search_account_all;
+
+ /* Skip the search if we already have the results. */
+ if (search_folder != NULL)
+ if (g_strcmp0 (query, search_folder->expression) == 0)
+ goto execute;
+
+ /* 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) {
+ camel_operation_cancel (priv->search_account_cancel);
+ camel_operation_unref (priv->search_account_cancel);
+ priv->search_account_cancel = NULL;
+ }
+
+ camel_vee_folder_set_expression (search_folder, query);
+
+ goto execute;
+ }
+
+ /* Create a new search folder. */
+
+ list = NULL; /* list of CamelFolders */
+
+ /* FIXME Using data_dir like this is not portable. */
+ uri = g_strdup_printf ("vfolder:%s/vfolder", data_dir);
+ store = camel_session_get_store (session, uri, NULL);
+ g_free (uri);
+
+ search_folder = (CamelVeeFolder *) camel_vee_folder_new (
+ store, _("All Account Search"), CAMEL_STORE_VEE_FOLDER_AUTO);
+ priv->search_account_all = search_folder;
+
+ /* Add local folders. */
+ iter = mail_vfolder_get_sources_local ();
+ while (iter != NULL) {
+ CamelException ex;
+
+ camel_exception_init (&ex);
+
+ folder_uri = iter->data;
+ folder = mail_tool_uri_to_folder (folder_uri, 0, &ex);
+
+ if (folder != NULL)
+ list = g_list_append (list, folder);
+ else
+ g_warning ("Could not open vfolder source: %s", folder_uri);
+
+ camel_exception_clear (&ex);
+ iter = g_list_next (iter);
+ }
+
+ /* Add remote folders. */
+ iter = mail_vfolder_get_sources_remote ();
+ while (iter != NULL) {
+ CamelException ex;
+
+ camel_exception_init (&ex);
+
+ folder_uri = iter->data;
+ folder = mail_tool_uri_to_folder (folder_uri, 0, &ex);
+
+ if (folder != NULL)
+ list = g_list_append (list, folder);
+ else
+ g_warning ("Could not open vfolder source: %s", folder_uri);
+
+ camel_exception_clear (&ex);
+ iter = g_list_next (iter);
+ }
+
+ camel_vee_folder_set_expression (search_folder, query);
+
+ priv->search_account_cancel = camel_operation_new (NULL, NULL);
+
+ /* This takes ownership of the folder list. */
+ mail_shell_view_setup_search_results_folder (
+ CAMEL_FOLDER (search_folder), list,
+ priv->search_account_cancel);
+
+ uri = mail_tools_folder_to_url (CAMEL_FOLDER (search_folder));
+
+ mail_shell_view_show_search_results_folder (
+ E_MAIL_SHELL_VIEW (shell_view),
+ CAMEL_FOLDER (search_folder), uri);
+
+ g_free (uri);
+
+ goto execute;
+
+current_account:
+
+ /* Prepare search folder for current account only. */
+
+ /* 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') {
+ if (priv->search_account_current != NULL) {
+ camel_object_unref (priv->search_account_current);
+ priv->search_account_current = NULL;
+ }
+
+ if (priv->search_account_cancel != NULL) {
+ camel_operation_cancel (priv->search_account_cancel);
+ camel_operation_unref (priv->search_account_cancel);
+ priv->search_account_cancel = NULL;
+ }
+
+ /* Simulate a folder tree selection change, so the
+ * message list is reset to the correct folder via
+ * our EMFolderTree::folder-selected handler. */
+ g_signal_emit_by_name (selection, "changed");
+
+ gtk_widget_set_sensitive (GTK_WIDGET (combo_box), TRUE);
+
+ goto execute;
+ }
+
+ search_folder = priv->search_account_current;
+
+ /* Skip the search if we already have the results. */
+ if (search_folder != NULL)
+ if (g_strcmp0 (query, search_folder->expression) == 0)
+ goto execute;
+
+ /* 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) {
+ camel_operation_cancel (priv->search_account_cancel);
+ camel_operation_unref (priv->search_account_cancel);
+ priv->search_account_cancel = NULL;
+ }
+
+ camel_vee_folder_set_expression (search_folder, query);
+
+ goto execute;
+ }
+
+ /* Create a new search folder. */
+
+ store = folder->parent_store;
+ list = NULL; /* list of CamelFolders */
+
+ if (store->folders != NULL) {
+ GPtrArray *array;
+ guint ii;
+
+ array = camel_object_bag_list (store->folders);
+ for (ii = 0; ii < array->len; ii++)
+ list = g_list_append (list, array->pdata[ii]);
+ }
+
+ /* FIXME Using data_dir like this is not portable. */
+ uri = g_strdup_printf ("vfolder:%s/vfolder", data_dir);
+ store = camel_session_get_store (session, uri, NULL);
+ g_free (uri);
+
+ search_folder = (CamelVeeFolder *) camel_vee_folder_new (
+ store, _("Account Search"), CAMEL_STORE_VEE_FOLDER_AUTO);
+ priv->search_account_current = search_folder;
+
+ camel_vee_folder_set_expression (search_folder, query);
+
+ priv->search_account_cancel = camel_operation_new (NULL, NULL);
+
+ /* This takes ownership of the folder list. */
+ mail_shell_view_setup_search_results_folder (
+ CAMEL_FOLDER (search_folder), list,
+ priv->search_account_cancel);
+
+ uri = mail_tools_folder_to_url (CAMEL_FOLDER (search_folder));
+
+ mail_shell_view_show_search_results_folder (
+ E_MAIL_SHELL_VIEW (shell_view),
+ CAMEL_FOLDER (search_folder), uri);
+
+ g_free (uri);
+
+execute:
+
+ /* Finally, execute the search. */
+
message_list_set_search (MESSAGE_LIST (message_list), query);
e_mail_shell_content_set_search_strings (