diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/addressbook/e-book-shell-view-actions.c | 26 | ||||
-rw-r--r-- | modules/calendar/e-cal-shell-view-actions.c | 26 | ||||
-rw-r--r-- | modules/calendar/e-memo-shell-view-actions.c | 26 | ||||
-rw-r--r-- | modules/calendar/e-task-shell-view-actions.c | 26 | ||||
-rw-r--r-- | modules/mail/e-mail-shell-view-actions.c | 89 | ||||
-rw-r--r-- | modules/mail/e-mail-shell-view-private.c | 59 | ||||
-rw-r--r-- | modules/mail/e-mail-shell-view-private.h | 10 | ||||
-rw-r--r-- | modules/mail/e-mail-shell-view.c | 385 |
8 files changed, 478 insertions, 169 deletions
diff --git a/modules/addressbook/e-book-shell-view-actions.c b/modules/addressbook/e-book-shell-view-actions.c index 32b227c723..c439fafec8 100644 --- a/modules/addressbook/e-book-shell-view-actions.c +++ b/modules/addressbook/e-book-shell-view-actions.c @@ -655,14 +655,6 @@ action_gal_save_custom_view_cb (GtkAction *action, gal_view_instance_save_as (view_instance); } -static void -action_search_filter_cb (GtkRadioAction *action, - GtkRadioAction *current, - EShellView *shell_view) -{ - e_shell_view_execute_search (shell_view); -} - static GtkActionEntry contact_entries[] = { { "address-book-copy", @@ -1022,9 +1014,6 @@ e_book_shell_view_actions_init (EBookShellView *book_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), - CONTACT_SEARCH_NAME_CONTAINS); /* Lockdown Printing Actions */ action_group = ACTION_GROUP (LOCKDOWN_PRINTING); @@ -1097,13 +1086,13 @@ e_book_shell_view_update_search_filter (EBookShellView *book_shell_view) action_group = ACTION_GROUP (CONTACTS_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, contact_filter_entries, G_N_ELEMENTS (contact_filter_entries), - CONTACT_FILTER_ANY_CATEGORY, - G_CALLBACK (action_search_filter_cb), - book_shell_view); + CONTACT_FILTER_ANY_CATEGORY, NULL, NULL); /* Retrieve the radio group from an action we just added. */ list = gtk_action_group_list_actions (action_group); @@ -1154,12 +1143,17 @@ e_book_shell_view_update_search_filter (EBookShellView *book_shell_view) } g_list_free (list); - /* Use any action in the group; doesn't matter which. */ book_shell_content = book_shell_view->priv->book_shell_content; searchbar = e_book_shell_content_get_searchbar (book_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 = CONTACT_FILTER_UNMATCHED; e_action_combo_box_add_separator_after (combo_box, ii); + + e_shell_view_unblock_execute_search (shell_view); } diff --git a/modules/calendar/e-cal-shell-view-actions.c b/modules/calendar/e-cal-shell-view-actions.c index 19fc7e6c53..03a6eb6bd3 100644 --- a/modules/calendar/e-cal-shell-view-actions.c +++ b/modules/calendar/e-cal-shell-view-actions.c @@ -1222,14 +1222,6 @@ action_gal_save_custom_view_cb (GtkAction *action, gal_view_instance_save_as (view_instance); } -static void -action_search_filter_cb (GtkRadioAction *action, - GtkRadioAction *current, - EShellView *shell_view) -{ - e_shell_view_execute_search (shell_view); -} - static GtkActionEntry calendar_entries[] = { { "calendar-copy", @@ -1719,9 +1711,6 @@ e_cal_shell_view_actions_init (ECalShellView *cal_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), - CALENDAR_SEARCH_SUMMARY_CONTAINS); /* Lockdown Printing Actions */ action_group = ACTION_GROUP (LOCKDOWN_PRINTING); @@ -1784,13 +1773,13 @@ e_cal_shell_view_update_search_filter (ECalShellView *cal_shell_view) action_group = ACTION_GROUP (CALENDAR_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, calendar_filter_entries, G_N_ELEMENTS (calendar_filter_entries), - CALENDAR_FILTER_ANY_CATEGORY, - G_CALLBACK (action_search_filter_cb), - cal_shell_view); + CALENDAR_FILTER_ANY_CATEGORY, NULL, NULL); /* Retrieve the radio group from an action we just added. */ list = gtk_action_group_list_actions (action_group); @@ -1841,10 +1830,13 @@ e_cal_shell_view_update_search_filter (ECalShellView *cal_shell_view) } g_list_free (list); - /* Use any action in the group; doesn't matter which. */ cal_shell_content = cal_shell_view->priv->cal_shell_content; searchbar = e_cal_shell_content_get_searchbar (cal_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 = CALENDAR_FILTER_UNMATCHED; @@ -1852,4 +1844,6 @@ e_cal_shell_view_update_search_filter (ECalShellView *cal_shell_view) ii = CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS; e_action_combo_box_add_separator_after (combo_box, ii); + + e_shell_view_unblock_execute_search (shell_view); } diff --git a/modules/calendar/e-memo-shell-view-actions.c b/modules/calendar/e-memo-shell-view-actions.c index 24aced8528..f53b8ff406 100644 --- a/modules/calendar/e-memo-shell-view-actions.c +++ b/modules/calendar/e-memo-shell-view-actions.c @@ -560,14 +560,6 @@ action_memo_view_cb (GtkRadioAction *action, gtk_orientable_set_orientation (orientable, orientation); } -static void -action_search_filter_cb (GtkRadioAction *action, - GtkRadioAction *current, - EShellView *shell_view) -{ - e_shell_view_execute_search (shell_view); -} - static GtkActionEntry memo_entries[] = { { "memo-delete", @@ -892,9 +884,6 @@ e_memo_shell_view_actions_init (EMemoShellView *memo_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), - MEMO_SEARCH_SUMMARY_CONTAINS); /* Lockdown Printing Actions */ action_group = ACTION_GROUP (LOCKDOWN_PRINTING); @@ -967,13 +956,13 @@ e_memo_shell_view_update_search_filter (EMemoShellView *memo_shell_view) action_group = ACTION_GROUP (MEMOS_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, memo_filter_entries, G_N_ELEMENTS (memo_filter_entries), - MEMO_FILTER_ANY_CATEGORY, - G_CALLBACK (action_search_filter_cb), - memo_shell_view); + MEMO_FILTER_ANY_CATEGORY, NULL, NULL); /* Retrieve the radio group from an action we just added. */ list = gtk_action_group_list_actions (action_group); @@ -1024,12 +1013,17 @@ e_memo_shell_view_update_search_filter (EMemoShellView *memo_shell_view) } g_list_free (list); - /* Use any action in the group; doesn't matter which. */ memo_shell_content = memo_shell_view->priv->memo_shell_content; searchbar = e_memo_shell_content_get_searchbar (memo_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 = MEMO_FILTER_UNMATCHED; e_action_combo_box_add_separator_after (combo_box, ii); + + e_shell_view_unblock_execute_search (shell_view); } diff --git a/modules/calendar/e-task-shell-view-actions.c b/modules/calendar/e-task-shell-view-actions.c index c18882dd2b..55873dd9f9 100644 --- a/modules/calendar/e-task-shell-view-actions.c +++ b/modules/calendar/e-task-shell-view-actions.c @@ -43,14 +43,6 @@ action_gal_save_custom_view_cb (GtkAction *action, } static void -action_search_filter_cb (GtkRadioAction *action, - GtkRadioAction *current, - EShellView *shell_view) -{ - e_shell_view_execute_search (shell_view); -} - -static void action_task_assign_cb (GtkAction *action, ETaskShellView *task_shell_view) { @@ -1091,9 +1083,6 @@ e_task_shell_view_actions_init (ETaskShellView *task_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), - TASK_SEARCH_SUMMARY_CONTAINS); /* Lockdown Printing Actions */ action_group = ACTION_GROUP (LOCKDOWN_PRINTING); @@ -1166,13 +1155,13 @@ e_task_shell_view_update_search_filter (ETaskShellView *task_shell_view) action_group = ACTION_GROUP (TASKS_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, task_filter_entries, G_N_ELEMENTS (task_filter_entries), - TASK_FILTER_ANY_CATEGORY, - G_CALLBACK (action_search_filter_cb), - task_shell_view); + TASK_FILTER_ANY_CATEGORY, NULL, NULL); /* Retrieve the radio group from an action we just added. */ list = gtk_action_group_list_actions (action_group); @@ -1223,10 +1212,13 @@ e_task_shell_view_update_search_filter (ETaskShellView *task_shell_view) } g_list_free (list); - /* Use any action in the group; doesn't matter which. */ task_shell_content = task_shell_view->priv->task_shell_content; searchbar = e_task_shell_content_get_searchbar (task_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 = TASK_FILTER_UNMATCHED; @@ -1234,4 +1226,6 @@ e_task_shell_view_update_search_filter (ETaskShellView *task_shell_view) ii = TASK_FILTER_TASKS_WITH_ATTACHMENTS; e_action_combo_box_add_separator_after (combo_box, ii); + + e_shell_view_unblock_execute_search (shell_view); } 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 ( |