[evolution] Bug #579599 - Let the Advanced Search work again



commit aa813bd7cadffa0110ddeeecd2b8df9d367db6e1
Author: Milan Crha <mcrha redhat com>
Date:   Thu Nov 19 15:40:50 2009 +0100

    Bug #579599 - Let the Advanced Search work again

 modules/addressbook/e-book-shell-view-actions.c |   40 ++----
 modules/addressbook/e-book-shell-view-actions.h |    2 +
 modules/addressbook/e-book-shell-view-private.h |    1 +
 modules/addressbook/e-book-shell-view.c         |   67 +++++-----
 modules/calendar/e-cal-shell-view-actions.c     |   40 ++----
 modules/calendar/e-cal-shell-view-actions.h     |    2 +
 modules/calendar/e-cal-shell-view-private.h     |    1 +
 modules/calendar/e-cal-shell-view.c             |   65 +++++----
 modules/calendar/e-memo-shell-view-actions.c    |   40 ++----
 modules/calendar/e-memo-shell-view-actions.h    |    2 +
 modules/calendar/e-memo-shell-view-private.h    |    1 +
 modules/calendar/e-memo-shell-view.c            |   67 +++++-----
 modules/calendar/e-task-shell-view-actions.c    |   40 ++----
 modules/calendar/e-task-shell-view-actions.h    |    2 +
 modules/calendar/e-task-shell-view-private.h    |    1 +
 modules/calendar/e-task-shell-view.c            |   67 +++++-----
 modules/mail/e-mail-shell-view-actions.c        |   68 ++-------
 modules/mail/e-mail-shell-view-actions.h        |    2 +
 modules/mail/e-mail-shell-view-private.h        |    1 +
 modules/mail/e-mail-shell-view.c                |   30 ++---
 shell/e-shell-content.c                         |  170 ++++++++++++++++++++---
 shell/e-shell-content.h                         |    7 +
 shell/e-shell-window-actions.c                  |   15 ++
 ui/evolution-calendars.ui                       |    1 +
 ui/evolution-contacts.ui                        |    1 +
 ui/evolution-mail.ui                            |    1 +
 ui/evolution-memos.ui                           |    1 +
 ui/evolution-tasks.ui                           |    1 +
 widgets/misc/e-hinted-entry.c                   |    1 +
 29 files changed, 421 insertions(+), 316 deletions(-)
---
diff --git a/modules/addressbook/e-book-shell-view-actions.c b/modules/addressbook/e-book-shell-view-actions.c
index 41b88ef..85db9d5 100644
--- a/modules/addressbook/e-book-shell-view-actions.c
+++ b/modules/addressbook/e-book-shell-view-actions.c
@@ -599,29 +599,6 @@ exit:
 }
 
 static void
-action_contact_search_cb (GtkRadioAction *action,
-                          GtkRadioAction *current,
-                          EBookShellView *book_shell_view)
-{
-	EShellView *shell_view;
-	EShellContent *shell_content;
-	const gchar *search_hint;
-
-	/* XXX Figure out a way to handle this in EShellContent
-	 *     instead of every shell view having to handle it.
-	 *     The problem is EShellContent does not know what
-	 *     the search option actions are for this view.  It
-	 *     would have to dig up the popup menu and retrieve
-	 *     the action for each menu item.  Seems messy. */
-
-	shell_view = E_SHELL_VIEW (book_shell_view);
-	shell_content = e_shell_view_get_shell_content (shell_view);
-
-	search_hint = gtk_action_get_label (GTK_ACTION (current));
-	e_shell_content_set_search_hint (shell_content, search_hint);
-}
-
-static void
 action_contact_select_all_cb (GtkAction *action,
                               EBookShellView *book_shell_view)
 {
@@ -994,6 +971,13 @@ static GtkRadioActionEntry contact_filter_entries[] = {
 
 static GtkRadioActionEntry contact_search_entries[] = {
 
+	{ "contact-search-advanced-hidden",
+	  NULL,
+	  N_("Advanced search"),
+	  NULL,
+	  NULL,
+	  CONTACT_SEARCH_ADVANCED },
+
 	{ "contact-search-any-field-contains",
 	  NULL,
 	  N_("Any field contains"),
@@ -1074,6 +1058,7 @@ e_book_shell_view_actions_init (EBookShellView *book_shell_view)
 	GtkActionGroup *action_group;
 	GConfBridge *bridge;
 	GtkAction *action;
+	GtkRadioAction *radio_action;
 	GObject *object;
 	const gchar *key;
 
@@ -1101,8 +1086,13 @@ e_book_shell_view_actions_init (EBookShellView *book_shell_view)
 	gtk_action_group_add_radio_actions (
 		action_group, contact_search_entries,
 		G_N_ELEMENTS (contact_search_entries),
-		CONTACT_SEARCH_NAME_CONTAINS,
-		G_CALLBACK (action_contact_search_cb), book_shell_view);
+		-1, NULL, NULL);
+
+	/* Advanced Search action */
+	radio_action = GTK_RADIO_ACTION (ACTION (CONTACT_SEARCH_ADVANCED_HIDDEN));
+	e_shell_content_set_search_radio_action (e_shell_view_get_shell_content (shell_view), radio_action);
+	gtk_action_set_visible (GTK_ACTION (radio_action), FALSE);
+	gtk_radio_action_set_current_value (radio_action, CONTACT_SEARCH_NAME_CONTAINS);
 
 	/* Lockdown Printing Actions */
 	action_group = ACTION_GROUP (LOCKDOWN_PRINTING);
diff --git a/modules/addressbook/e-book-shell-view-actions.h b/modules/addressbook/e-book-shell-view-actions.h
index e5eea1f..98cd8b6 100644
--- a/modules/addressbook/e-book-shell-view-actions.h
+++ b/modules/addressbook/e-book-shell-view-actions.h
@@ -81,6 +81,8 @@
 	E_SHELL_WINDOW_ACTION ((window), "contact-view-vertical")
 
 /* Search Actions */
+#define E_SHELL_WINDOW_ACTION_CONTACT_SEARCH_ADVANCED_HIDDEN(window) \
+	E_SHELL_WINDOW_ACTION ((window), "contact-search-advanced-hidden")
 #define E_SHELL_WINDOW_ACTION_CONTACT_SEARCH_ANY_FIELD_CONTAINS(window) \
 	E_SHELL_WINDOW_ACTION ((window), "contact-search-any-field-contains")
 #define E_SHELL_WINDOW_ACTION_CONTACT_SEARCH_EMAIL_BEGINS_WITH(window) \
diff --git a/modules/addressbook/e-book-shell-view-private.h b/modules/addressbook/e-book-shell-view-private.h
index c1aa300..6d513aa 100644
--- a/modules/addressbook/e-book-shell-view-private.h
+++ b/modules/addressbook/e-book-shell-view-private.h
@@ -91,6 +91,7 @@ enum {
 
 /* List these in the order to be displayed. */
 enum {
+	CONTACT_SEARCH_ADVANCED = -1,
 	CONTACT_SEARCH_NAME_CONTAINS,
 	CONTACT_SEARCH_EMAIL_BEGINS_WITH,
 	CONTACT_SEARCH_ANY_FIELD_CONTAINS
diff --git a/modules/addressbook/e-book-shell-view.c b/modules/addressbook/e-book-shell-view.c
index e7d26d7..663f2a1 100644
--- a/modules/addressbook/e-book-shell-view.c
+++ b/modules/addressbook/e-book-shell-view.c
@@ -128,11 +128,8 @@ book_shell_view_execute_search (EShellView *shell_view)
 	EShellWindow *shell_window;
 	EShellContent *shell_content;
 	GtkRadioAction *action;
-	GString *string;
 	EAddressbookView *view;
 	EAddressbookModel *model;
-	const gchar *format;
-	const gchar *text;
 	gchar *query;
 	gchar *temp;
 	gint value;
@@ -140,40 +137,51 @@ book_shell_view_execute_search (EShellView *shell_view)
 	priv = E_BOOK_SHELL_VIEW_GET_PRIVATE (shell_view);
 
 	shell_content = e_shell_view_get_shell_content (shell_view);
-	text = e_shell_content_get_search_text (shell_content);
-
 	shell_window = e_shell_view_get_shell_window (shell_view);
 	action = GTK_RADIO_ACTION (ACTION (CONTACT_SEARCH_ANY_FIELD_CONTAINS));
 	value = gtk_radio_action_get_current_value (action);
 
-	if (text == NULL || *text == '\0') {
-		text = "";
-		value = CONTACT_SEARCH_ANY_FIELD_CONTAINS;
-	}
+	if (value == CONTACT_SEARCH_ADVANCED) {
+		query = e_shell_content_get_search_rule_as_string (shell_content);
 
-	switch (value) {
-		case CONTACT_SEARCH_NAME_CONTAINS:
-			format = "(contains \"full_name\" %s)";
-			break;
+		if (!query)
+			query = g_strdup ("");
+	} else {
+		const gchar *text;
+		const gchar *format;
+		GString *string;
 
-		case CONTACT_SEARCH_EMAIL_BEGINS_WITH:
-			format = "(beginswith \"email\" %s)";
-			break;
+		text = e_shell_content_get_search_text (shell_content);
 
-		default:
+		if (text == NULL || *text == '\0') {
 			text = "";
-			/* fall through */
+			value = CONTACT_SEARCH_ANY_FIELD_CONTAINS;
+		}
 
-		case CONTACT_SEARCH_ANY_FIELD_CONTAINS:
-			format = "(contains \"x-evolution-any-field\" %s)";
-			break;
-	}
+		switch (value) {
+			case CONTACT_SEARCH_NAME_CONTAINS:
+				format = "(contains \"full_name\" %s)";
+				break;
+
+			case CONTACT_SEARCH_EMAIL_BEGINS_WITH:
+				format = "(beginswith \"email\" %s)";
+				break;
 
-	/* Build the query. */
-	string = g_string_new ("");
-	e_sexp_encode_string (string, text);
-	query = g_strdup_printf (format, string->str);
-	g_string_free (string, TRUE);
+			default:
+				text = "";
+				/* fall through */
+
+			case CONTACT_SEARCH_ANY_FIELD_CONTAINS:
+				format = "(contains \"x-evolution-any-field\" %s)";
+				break;
+		}
+
+		/* Build the query. */
+		string = g_string_new ("");
+		e_sexp_encode_string (string, text);
+		query = g_strdup_printf (format, string->str);
+		g_string_free (string, TRUE);
+	}
 
 	/* Apply selected filter. */
 	value = e_shell_content_get_filter_value (shell_content);
@@ -207,11 +215,6 @@ book_shell_view_execute_search (EShellView *shell_view)
 		}
 	}
 
-	/* XXX This is wrong.  We need to programmatically construct an
-	 *     EFilterRule, tell it to build code, and pass the resulting
-	 *     expression string to EAddressbookModel. */
-	e_shell_content_set_search_rule (shell_content, NULL);
-
 	/* Submit the query. */
 	book_shell_content = E_BOOK_SHELL_CONTENT (shell_content);
 	view = e_book_shell_content_get_current_view (book_shell_content);
diff --git a/modules/calendar/e-cal-shell-view-actions.c b/modules/calendar/e-cal-shell-view-actions.c
index bc0fcc0..e88fae7 100644
--- a/modules/calendar/e-cal-shell-view-actions.c
+++ b/modules/calendar/e-cal-shell-view-actions.c
@@ -363,29 +363,6 @@ action_calendar_rename_cb (GtkAction *action,
 }
 
 static void
-action_calendar_search_cb (GtkRadioAction *action,
-                           GtkRadioAction *current,
-                           ECalShellView *cal_shell_view)
-{
-	EShellView *shell_view;
-	EShellContent *shell_content;
-	const gchar *search_hint;
-
-	/* XXX Figure out a way to handle this in EShellContent
-	 *     instead of every shell view having to handle it.
-	 *     The problem is EShellContent does not know what
-	 *     the search option actions are for this view.  It
-	 *     would have to dig up the popup menu and retrieve
-	 *     the action for each menu item.  Seems messy. */
-
-	shell_view = E_SHELL_VIEW (cal_shell_view);
-	shell_content = e_shell_view_get_shell_content (shell_view);
-
-	search_hint = gtk_action_get_label (GTK_ACTION (current));
-	e_shell_content_set_search_hint (shell_content, search_hint);
-}
-
-static void
 action_calendar_select_one_cb (GtkAction *action,
                                ECalShellView *cal_shell_view)
 {
@@ -1588,6 +1565,13 @@ static GtkRadioActionEntry calendar_filter_entries[] = {
 
 static GtkRadioActionEntry calendar_search_entries[] = {
 
+	{ "calendar-search-advanced-hidden",
+	  NULL,
+	  N_("Advanced search"),
+	  NULL,
+	  NULL,
+	  CALENDAR_SEARCH_ADVANCED },
+
 	{ "calendar-search-any-field-contains",
 	  NULL,
 	  N_("Any field contains"),
@@ -1648,6 +1632,7 @@ e_cal_shell_view_actions_init (ECalShellView *cal_shell_view)
 	EShellWindow *shell_window;
 	GtkActionGroup *action_group;
 	GtkAction *action;
+	GtkRadioAction *radio_action;
 
 	shell_view = E_SHELL_VIEW (cal_shell_view);
 	shell_window = e_shell_view_get_shell_window (shell_view);
@@ -1667,8 +1652,13 @@ e_cal_shell_view_actions_init (ECalShellView *cal_shell_view)
 	gtk_action_group_add_radio_actions (
 		action_group, calendar_search_entries,
 		G_N_ELEMENTS (calendar_search_entries),
-		CALENDAR_SEARCH_SUMMARY_CONTAINS,
-		G_CALLBACK (action_calendar_search_cb), cal_shell_view);
+		-1, NULL, NULL);
+
+	/* Advanced Search action */
+	radio_action = GTK_RADIO_ACTION (ACTION (CALENDAR_SEARCH_ADVANCED_HIDDEN));
+	e_shell_content_set_search_radio_action (e_shell_view_get_shell_content (shell_view), radio_action);
+	gtk_action_set_visible (GTK_ACTION (radio_action), FALSE);
+	gtk_radio_action_set_current_value (radio_action, CALENDAR_SEARCH_SUMMARY_CONTAINS);
 
 	/* Lockdown Printing Actions */
 	action_group = ACTION_GROUP (LOCKDOWN_PRINTING);
diff --git a/modules/calendar/e-cal-shell-view-actions.h b/modules/calendar/e-cal-shell-view-actions.h
index e056493..840985b 100644
--- a/modules/calendar/e-cal-shell-view-actions.h
+++ b/modules/calendar/e-cal-shell-view-actions.h
@@ -151,6 +151,8 @@
 	E_SHELL_WINDOW_ACTION ((window), "calendar-filter-next-7-days-appointments")
 #define E_SHELL_WINDOW_ACTION_CALENDAR_FILTER_UNMATCHED(window) \
 	E_SHELL_WINDOW_ACTION ((window), "calendar-filter-unmatched")
+#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_ADVANCED_HIDDEN(window) \
+	E_SHELL_WINDOW_ACTION ((window), "calendar-search-advanced-hidden")
 #define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_ANY_FIELD_CONTAINS(window) \
 	E_SHELL_WINDOW_ACTION ((window), "calendar-search-any-field-contains")
 #define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_DESCRIPTION_CONTAINS(window) \
diff --git a/modules/calendar/e-cal-shell-view-private.h b/modules/calendar/e-cal-shell-view-private.h
index 1f447bc..c92fb8c 100644
--- a/modules/calendar/e-cal-shell-view-private.h
+++ b/modules/calendar/e-cal-shell-view-private.h
@@ -95,6 +95,7 @@ enum {
 
 /* Search items are displayed in ascending order. */
 enum {
+	CALENDAR_SEARCH_ADVANCED = -1,
 	CALENDAR_SEARCH_SUMMARY_CONTAINS,
 	CALENDAR_SEARCH_DESCRIPTION_CONTAINS,
 	CALENDAR_SEARCH_ANY_FIELD_CONTAINS
diff --git a/modules/calendar/e-cal-shell-view.c b/modules/calendar/e-cal-shell-view.c
index 44e0883..f767f92 100644
--- a/modules/calendar/e-cal-shell-view.c
+++ b/modules/calendar/e-cal-shell-view.c
@@ -62,9 +62,6 @@ cal_shell_view_execute_search (EShellView *shell_view)
 	GnomeCalendar *calendar;
 	ECalendar *date_navigator;
 	GtkRadioAction *action;
-	GString *string;
-	const gchar *format;
-	const gchar *text;
 	time_t start_range;
 	time_t end_range;
 	gboolean range_search;
@@ -80,36 +77,47 @@ cal_shell_view_execute_search (EShellView *shell_view)
 	action = GTK_RADIO_ACTION (ACTION (CALENDAR_SEARCH_ANY_FIELD_CONTAINS));
 	value = gtk_radio_action_get_current_value (action);
 
-	text = e_shell_content_get_search_text (shell_content);
+	if (value == CALENDAR_SEARCH_ADVANCED) {
+		query = e_shell_content_get_search_rule_as_string (shell_content);
 
-	if (text == NULL || *text == '\0') {
-		text = "";
-		value = CALENDAR_SEARCH_SUMMARY_CONTAINS;
-	}
+		if (!query)
+			query = g_strdup ("");
+	} else {
+		const gchar *format;
+		const gchar *text;
+		GString *string;
 
-	switch (value) {
-		default:
+		text = e_shell_content_get_search_text (shell_content);
+
+		if (text == NULL || *text == '\0') {
 			text = "";
-			/* fall through */
+			value = CALENDAR_SEARCH_SUMMARY_CONTAINS;
+		}
 
-		case CALENDAR_SEARCH_SUMMARY_CONTAINS:
-			format = "(contains? \"summary\" %s)";
-			break;
+		switch (value) {
+			default:
+				text = "";
+				/* fall through */
 
-		case CALENDAR_SEARCH_DESCRIPTION_CONTAINS:
-			format = "(contains? \"description\" %s)";
-			break;
+			case CALENDAR_SEARCH_SUMMARY_CONTAINS:
+				format = "(contains? \"summary\" %s)";
+				break;
 
-		case CALENDAR_SEARCH_ANY_FIELD_CONTAINS:
-			format = "(contains? \"any\" %s)";
-			break;
-	}
+			case CALENDAR_SEARCH_DESCRIPTION_CONTAINS:
+				format = "(contains? \"description\" %s)";
+				break;
 
-	/* Build the query. */
-	string = g_string_new ("");
-	e_sexp_encode_string (string, text);
-	query = g_strdup_printf (format, string->str);
-	g_string_free (string, TRUE);
+			case CALENDAR_SEARCH_ANY_FIELD_CONTAINS:
+				format = "(contains? \"any\" %s)";
+				break;
+		}
+
+		/* Build the query. */
+		string = g_string_new ("");
+		e_sexp_encode_string (string, text);
+		query = g_strdup_printf (format, string->str);
+		g_string_free (string, TRUE);
+	}
 
 	range_search = FALSE;
 	start_range = end_range = 0;
@@ -178,11 +186,6 @@ cal_shell_view_execute_search (EShellView *shell_view)
 		}
 	}
 
-	/* XXX This is wrong.  We need to programmatically construct an
-	 *     EFilterRule, tell it to build code, and pass the resulting
-	 *     expressing string to ECalModel. */
-	e_shell_content_set_search_rule (shell_content, NULL);
-
 	cal_shell_sidebar = E_CAL_SHELL_SIDEBAR (shell_sidebar);
 	date_navigator = e_cal_shell_sidebar_get_date_navigator (cal_shell_sidebar);
 
diff --git a/modules/calendar/e-memo-shell-view-actions.c b/modules/calendar/e-memo-shell-view-actions.c
index 80ebca2..57420cd 100644
--- a/modules/calendar/e-memo-shell-view-actions.c
+++ b/modules/calendar/e-memo-shell-view-actions.c
@@ -526,29 +526,6 @@ action_memo_save_as_cb (GtkAction *action,
 }
 
 static void
-action_memo_search_cb (GtkRadioAction *action,
-                       GtkRadioAction *current,
-                       EMemoShellView *memo_shell_view)
-{
-	EShellView *shell_view;
-	EShellContent *shell_content;
-	const gchar *search_hint;
-
-	/* XXX Figure out a way to handle this in EShellContent
-	 *     instead of every shell view having to handle it.
-	 *     The problem is EShellContent does not know what
-	 *     the search option actions are for this view.  It
-	 *     would have to dig up the popup menu and retrieve
-	 *     the action for each menu item.  Seems messy. */
-
-	shell_view = E_SHELL_VIEW (memo_shell_view);
-	shell_content = e_shell_view_get_shell_content (shell_view);
-
-	search_hint = gtk_action_get_label (GTK_ACTION (current));
-	e_shell_content_set_search_hint (shell_content, search_hint);
-}
-
-static void
 action_memo_view_cb (GtkRadioAction *action,
                      GtkRadioAction *current,
                      EMemoShellView *memo_shell_view)
@@ -800,6 +777,13 @@ static GtkRadioActionEntry memo_filter_entries[] = {
 
 static GtkRadioActionEntry memo_search_entries[] = {
 
+	{ "memo-search-advanced-hidden",
+	  NULL,
+	  N_("Advanced search"),
+	  NULL,
+	  NULL,
+	  MEMO_SEARCH_ADVANCED },
+
 	{ "memo-search-any-field-contains",
 	  NULL,
 	  N_("Any field contains"),
@@ -880,6 +864,7 @@ e_memo_shell_view_actions_init (EMemoShellView *memo_shell_view)
 	GtkActionGroup *action_group;
 	GConfBridge *bridge;
 	GtkAction *action;
+	GtkRadioAction *radio_action;
 	GObject *object;
 	const gchar *key;
 
@@ -907,8 +892,13 @@ e_memo_shell_view_actions_init (EMemoShellView *memo_shell_view)
 	gtk_action_group_add_radio_actions (
 		action_group, memo_search_entries,
 		G_N_ELEMENTS (memo_search_entries),
-		MEMO_SEARCH_SUMMARY_CONTAINS,
-		G_CALLBACK (action_memo_search_cb), memo_shell_view);
+		-1, NULL, NULL);
+
+	/* Advanced Search action */
+	radio_action = GTK_RADIO_ACTION (ACTION (MEMO_SEARCH_ADVANCED_HIDDEN));
+	e_shell_content_set_search_radio_action (e_shell_view_get_shell_content (shell_view), radio_action);
+	gtk_action_set_visible (GTK_ACTION (radio_action), FALSE);
+	gtk_radio_action_set_current_value (radio_action, MEMO_SEARCH_SUMMARY_CONTAINS);
 
 	/* Lockdown Printing Actions */
 	action_group = ACTION_GROUP (LOCKDOWN_PRINTING);
diff --git a/modules/calendar/e-memo-shell-view-actions.h b/modules/calendar/e-memo-shell-view-actions.h
index d43d023..9fe4d69 100644
--- a/modules/calendar/e-memo-shell-view-actions.h
+++ b/modules/calendar/e-memo-shell-view-actions.h
@@ -75,6 +75,8 @@
 	E_SHELL_WINDOW_ACTION ((window), "memo-filter-any-category")
 #define E_SHELL_WINDOW_ACTION_MEMO_FILTER_UNMATCHED(window) \
 	E_SHELL_WINDOW_ACTION ((window), "memo-filter-unmatched")
+#define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_ADVANCED_HIDDEN(window) \
+	E_SHELL_WINDOW_ACTION ((window), "memo-search-advanced-hidden")
 #define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_ANY_FIELD_CONTAINS(window) \
 	E_SHELL_WINDOW_ACTION ((window), "memo-search-any-field-contains")
 #define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_DESCRIPTION_CONTAINS(window) \
diff --git a/modules/calendar/e-memo-shell-view-private.h b/modules/calendar/e-memo-shell-view-private.h
index 3755694..1818ba0 100644
--- a/modules/calendar/e-memo-shell-view-private.h
+++ b/modules/calendar/e-memo-shell-view-private.h
@@ -81,6 +81,7 @@ enum {
 
 /* Search items are displayed in ascending order. */
 enum {
+	MEMO_SEARCH_ADVANCED = -1,
 	MEMO_SEARCH_SUMMARY_CONTAINS,
 	MEMO_SEARCH_DESCRIPTION_CONTAINS,
 	MEMO_SEARCH_ANY_FIELD_CONTAINS
diff --git a/modules/calendar/e-memo-shell-view.c b/modules/calendar/e-memo-shell-view.c
index 5cc8e15..5d932e1 100644
--- a/modules/calendar/e-memo-shell-view.c
+++ b/modules/calendar/e-memo-shell-view.c
@@ -58,51 +58,59 @@ memo_shell_view_execute_search (EShellView *shell_view)
 	EShellWindow *shell_window;
 	EShellContent *shell_content;
 	GtkRadioAction *action;
-	GString *string;
 	ECalComponentPreview *memo_preview;
 	EMemoTable *memo_table;
 	ECalModel *model;
-	const gchar *format;
-	const gchar *text;
 	gchar *query;
 	gchar *temp;
 	gint value;
 
 	shell_content = e_shell_view_get_shell_content (shell_view);
-	text = e_shell_content_get_search_text (shell_content);
-
 	shell_window = e_shell_view_get_shell_window (shell_view);
 	action = GTK_RADIO_ACTION (ACTION (MEMO_SEARCH_ANY_FIELD_CONTAINS));
 	value = gtk_radio_action_get_current_value (action);
 
-	if (text == NULL || *text == '\0') {
-		text = "";
-		value = MEMO_SEARCH_SUMMARY_CONTAINS;
-	}
+	if (value == MEMO_SEARCH_ADVANCED) {
+		query = e_shell_content_get_search_rule_as_string (shell_content);
 
-	switch (value) {
-		default:
+		if (!query)
+			query = g_strdup ("");
+	} else {
+		const gchar *format;
+		const gchar *text;
+		GString *string;
+
+		text = e_shell_content_get_search_text (shell_content);
+
+		if (text == NULL || *text == '\0') {
 			text = "";
-			/* fall through */
+			value = MEMO_SEARCH_SUMMARY_CONTAINS;
+		}
 
-		case MEMO_SEARCH_SUMMARY_CONTAINS:
-			format = "(contains? \"summary\" %s)";
-			break;
+		switch (value) {
+			default:
+				text = "";
+				/* fall through */
 
-		case MEMO_SEARCH_DESCRIPTION_CONTAINS:
-			format = "(contains? \"description\" %s)";
-			break;
+			case MEMO_SEARCH_SUMMARY_CONTAINS:
+				format = "(contains? \"summary\" %s)";
+				break;
 
-		case MEMO_SEARCH_ANY_FIELD_CONTAINS:
-			format = "(contains? \"any\" %s)";
-			break;
-	}
+			case MEMO_SEARCH_DESCRIPTION_CONTAINS:
+				format = "(contains? \"description\" %s)";
+				break;
 
-	/* Build the query. */
-	string = g_string_new ("");
-	e_sexp_encode_string (string, text);
-	query = g_strdup_printf (format, string->str);
-	g_string_free (string, TRUE);
+			case MEMO_SEARCH_ANY_FIELD_CONTAINS:
+				format = "(contains? \"any\" %s)";
+				break;
+		}
+
+		/* Build the query. */
+		string = g_string_new ("");
+		e_sexp_encode_string (string, text);
+		query = g_strdup_printf (format, string->str);
+		g_string_free (string, TRUE);
+	}
 
 	/* Apply selected filter. */
 	value = e_shell_content_get_filter_value (shell_content);
@@ -134,11 +142,6 @@ memo_shell_view_execute_search (EShellView *shell_view)
 		}
 	}
 
-	/* XXX This is wrong.  We need to programmatically construct an
-	 *     EFilterRule, tell it to build code, and pass the resulting
-	 *     expression string to ECalModel. */
-	e_shell_content_set_search_rule (shell_content, NULL);
-
 	/* Submit the query. */
 	memo_shell_content = E_MEMO_SHELL_CONTENT (shell_content);
 	memo_table = e_memo_shell_content_get_memo_table (memo_shell_content);
diff --git a/modules/calendar/e-task-shell-view-actions.c b/modules/calendar/e-task-shell-view-actions.c
index e5063c1..0e77efb 100644
--- a/modules/calendar/e-task-shell-view-actions.c
+++ b/modules/calendar/e-task-shell-view-actions.c
@@ -653,29 +653,6 @@ action_task_save_as_cb (GtkAction *action,
 }
 
 static void
-action_task_search_cb (GtkRadioAction *action,
-                       GtkRadioAction *current,
-                       ETaskShellView *task_shell_view)
-{
-	EShellView *shell_view;
-	EShellContent *shell_content;
-	const gchar *search_hint;
-
-	/* XXX Figure out a way to handle this in EShellContent
-	 *     instead of every shell view having to handle it.
-	 *     The problem is EShellContent does not know what
-	 *     the search option actions are for this view.  It
-	 *     would have to dig up the popup menu and retrieve
-	 *     the action for each menu item.  Seems messy. */
-
-	shell_view = E_SHELL_VIEW (task_shell_view);
-	shell_content = e_shell_view_get_shell_content (shell_view);
-
-	search_hint = gtk_action_get_label (GTK_ACTION (current));
-	e_shell_content_set_search_hint (shell_content, search_hint);
-}
-
-static void
 action_task_view_cb (GtkRadioAction *action,
                      GtkRadioAction *current,
                      ETaskShellView *task_shell_view)
@@ -1001,6 +978,13 @@ static GtkRadioActionEntry task_filter_entries[] = {
 
 static GtkRadioActionEntry task_search_entries[] = {
 
+	{ "task-search-advanced-hidden",
+	  NULL,
+	  N_("Advanced search"),
+	  NULL,
+	  NULL,
+	  TASK_SEARCH_ADVANCED },
+
 	{ "task-search-any-field-contains",
           NULL,
 	  N_("Any field contains"),
@@ -1081,6 +1065,7 @@ e_task_shell_view_actions_init (ETaskShellView *task_shell_view)
 	GtkActionGroup *action_group;
 	GConfBridge *bridge;
 	GtkAction *action;
+	GtkRadioAction *radio_action;
 	GObject *object;
 	const gchar *key;
 
@@ -1108,8 +1093,13 @@ e_task_shell_view_actions_init (ETaskShellView *task_shell_view)
 	gtk_action_group_add_radio_actions (
 		action_group, task_search_entries,
 		G_N_ELEMENTS (task_search_entries),
-		TASK_SEARCH_SUMMARY_CONTAINS,
-		G_CALLBACK (action_task_search_cb), task_shell_view);
+		-1, NULL, NULL);
+
+	/* Advanced Search action */
+	radio_action = GTK_RADIO_ACTION (ACTION (TASK_SEARCH_ADVANCED_HIDDEN));
+	e_shell_content_set_search_radio_action (e_shell_view_get_shell_content (shell_view), radio_action);
+	gtk_action_set_visible (GTK_ACTION (radio_action), FALSE);
+	gtk_radio_action_set_current_value (radio_action, TASK_SEARCH_SUMMARY_CONTAINS);
 
 	/* Lockdown Printing Actions */
 	action_group = ACTION_GROUP (LOCKDOWN_PRINTING);
diff --git a/modules/calendar/e-task-shell-view-actions.h b/modules/calendar/e-task-shell-view-actions.h
index daa70c3..6c2d5d5 100644
--- a/modules/calendar/e-task-shell-view-actions.h
+++ b/modules/calendar/e-task-shell-view-actions.h
@@ -93,6 +93,8 @@
 	E_SHELL_WINDOW_ACTION ((window), "task-filter-tasks-with-attachments")
 #define E_SHELL_WINDOW_ACTION_TASK_FILTER_UNMATCHED(window) \
 	E_SHELL_WINDOW_ACTION ((window), "task-filter-unmatched")
+#define E_SHELL_WINDOW_ACTION_TASK_SEARCH_ADVANCED_HIDDEN(window) \
+	E_SHELL_WINDOW_ACTION ((window), "task-search-advanced-hidden")
 #define E_SHELL_WINDOW_ACTION_TASK_SEARCH_ANY_FIELD_CONTAINS(window) \
 	E_SHELL_WINDOW_ACTION ((window), "task-search-any-field-contains")
 #define E_SHELL_WINDOW_ACTION_TASK_SEARCH_DESCRIPTION_CONTAINS(window) \
diff --git a/modules/calendar/e-task-shell-view-private.h b/modules/calendar/e-task-shell-view-private.h
index 38b03ae..fcbe852 100644
--- a/modules/calendar/e-task-shell-view-private.h
+++ b/modules/calendar/e-task-shell-view-private.h
@@ -90,6 +90,7 @@ enum {
 
 /* Search items are displayed in ascending order. */
 enum {
+	TASK_SEARCH_ADVANCED = -1,
 	TASK_SEARCH_SUMMARY_CONTAINS,
 	TASK_SEARCH_DESCRIPTION_CONTAINS,
 	TASK_SEARCH_ANY_FIELD_CONTAINS
diff --git a/modules/calendar/e-task-shell-view.c b/modules/calendar/e-task-shell-view.c
index 1bb2820..b7c2bc9 100644
--- a/modules/calendar/e-task-shell-view.c
+++ b/modules/calendar/e-task-shell-view.c
@@ -97,12 +97,9 @@ task_shell_view_execute_search (EShellView *shell_view)
 	EShellWindow *shell_window;
 	EShellContent *shell_content;
 	GtkRadioAction *action;
-	GString *string;
 	ECalComponentPreview *task_preview;
 	ECalendarTable *task_table;
 	ECalModel *model;
-	const gchar *format;
-	const gchar *text;
 	time_t start_range;
 	time_t end_range;
 	gchar *start, *end;
@@ -111,40 +108,51 @@ task_shell_view_execute_search (EShellView *shell_view)
 	gint value;
 
 	shell_content = e_shell_view_get_shell_content (shell_view);
-	text = e_shell_content_get_search_text (shell_content);
-
 	shell_window = e_shell_view_get_shell_window (shell_view);
 	action = GTK_RADIO_ACTION (ACTION (TASK_SEARCH_ANY_FIELD_CONTAINS));
 	value = gtk_radio_action_get_current_value (action);
 
-	if (text == NULL || *text == '\0') {
-		text = "";
-		value = TASK_SEARCH_SUMMARY_CONTAINS;
-	}
+	if (value == TASK_SEARCH_ADVANCED) {
+		query = e_shell_content_get_search_rule_as_string (shell_content);
 
-	switch (value) {
-		default:
+		if (!query)
+			query = g_strdup ("");
+	} else {
+		const gchar *format;
+		const gchar *text;
+		GString *string;
+
+		text = e_shell_content_get_search_text (shell_content);
+
+		if (text == NULL || *text == '\0') {
 			text = "";
-			/* fall through */
+			value = TASK_SEARCH_SUMMARY_CONTAINS;
+		}
 
-		case TASK_SEARCH_SUMMARY_CONTAINS:
-			format = "(contains? \"summary\" %s)";
-			break;
+		switch (value) {
+			default:
+				text = "";
+				/* fall through */
 
-		case TASK_SEARCH_DESCRIPTION_CONTAINS:
-			format = "(contains? \"description\" %s)";
-			break;
+			case TASK_SEARCH_SUMMARY_CONTAINS:
+				format = "(contains? \"summary\" %s)";
+				break;
 
-		case TASK_SEARCH_ANY_FIELD_CONTAINS:
-			format = "(contains? \"any\" %s)";
-			break;
-	}
+			case TASK_SEARCH_DESCRIPTION_CONTAINS:
+				format = "(contains? \"description\" %s)";
+				break;
 
-	/* Build the query. */
-	string = g_string_new ("");
-	e_sexp_encode_string (string, text);
-	query = g_strdup_printf (format, string->str);
-	g_string_free (string, TRUE);
+			case TASK_SEARCH_ANY_FIELD_CONTAINS:
+				format = "(contains? \"any\" %s)";
+				break;
+		}
+
+		/* Build the query. */
+		string = g_string_new ("");
+		e_sexp_encode_string (string, text);
+		query = g_strdup_printf (format, string->str);
+		g_string_free (string, TRUE);
+	}
 
 	/* Apply selected filter. */
 	value = e_shell_content_get_filter_value (shell_content);
@@ -246,11 +254,6 @@ task_shell_view_execute_search (EShellView *shell_view)
 		query = temp2;
 	}
 
-	/* XXX This is wrong.  We need to programmatically construct an
-	 *     EFilterRule, tell it to build code, and pass the resulting
-	 *     expression string to ECalModel. */
-	e_shell_content_set_search_rule (shell_content, NULL);
-
 	/* Submit the query. */
 	task_shell_content = E_TASK_SHELL_CONTENT (shell_content);
 	task_table = e_task_shell_content_get_task_table (task_shell_content);
diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c
index 3473d2a..4dce2de 100644
--- a/modules/mail/e-mail-shell-view-actions.c
+++ b/modules/mail/e-mail-shell-view-actions.c
@@ -648,29 +648,6 @@ action_mail_label_none_cb (GtkAction *action,
 }
 
 static void
-action_mail_search_cb (GtkRadioAction *action,
-                       GtkRadioAction *current,
-                       EMailShellView *mail_shell_view)
-{
-	EShellView *shell_view;
-	EShellContent *shell_content;
-	const gchar *search_hint;
-
-	/* XXX Figure out a way to handle this in EShellContent
-	 *     instead of every shell view having to handle it.
-	 *     The problem is EShellContent does not know what
-	 *     the search option actions are for this view.  It
-	 *     would have to dig up the popup menu and retrieve
-	 *     the action for each menu item.  Seems messy. */
-
-	shell_view = E_SHELL_VIEW (mail_shell_view);
-	shell_content = e_shell_view_get_shell_content (shell_view);
-
-	search_hint = gtk_action_get_label (GTK_ACTION (current));
-	e_shell_content_set_search_hint (shell_content, search_hint);
-}
-
-static void
 action_mail_show_hidden_cb (GtkAction *action,
                             EMailShellView *mail_shell_view)
 {
@@ -963,31 +940,6 @@ action_search_filter_cb (GtkRadioAction *action,
 }
 
 static void
-action_search_quick_cb (GtkAction *action,
-                        EMailShellView *mail_shell_view)
-{
-	EShellView *shell_view;
-	EShellWindow *shell_window;
-	EShellContent *shell_content;
-	EFilterRule *search_rule;
-	gint value;
-
-	/* Set the search rule in EShellContent so that "Create
-	 * Search Folder from Search" works for quick searches. */
-
-	shell_view = E_SHELL_VIEW (mail_shell_view);
-	shell_window = e_shell_view_get_shell_window (shell_view);
-	shell_content = e_shell_view_get_shell_content (shell_view);
-
-	action = ACTION (MAIL_SEARCH_SUBJECT_OR_ADDRESSES_CONTAIN);
-	value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action));
-	g_return_if_fail (value >= 0 && value < MAIL_NUM_SEARCH_RULES);
-	search_rule = mail_shell_view->priv->search_rules[value];
-
-	e_shell_content_set_search_rule (shell_content, search_rule);
-}
-
-static void
 action_search_scope_cb (GtkRadioAction *action,
                         GtkRadioAction *current,
                         EShellView *shell_view)
@@ -1445,6 +1397,13 @@ static GtkRadioActionEntry mail_filter_entries[] = {
 
 static GtkRadioActionEntry mail_search_entries[] = {
 
+	{ "mail-search-advanced-hidden",
+	  NULL,
+	  N_("Advanced search"),
+	  NULL,
+	  NULL,
+	  MAIL_SEARCH_ADVANCED },
+
 	{ "mail-search-body-contains",
 	  NULL,
 	  N_("Body contains"),
@@ -1548,8 +1507,7 @@ e_mail_shell_view_actions_init (EMailShellView *mail_shell_view)
 	gtk_action_group_add_radio_actions (
 		action_group, mail_search_entries,
 		G_N_ELEMENTS (mail_search_entries),
-		MAIL_SEARCH_SUBJECT_OR_ADDRESSES_CONTAIN,
-		G_CALLBACK (action_mail_search_cb), mail_shell_view);
+		-1, NULL, NULL);
 	gtk_action_group_add_radio_actions (
 		action_group, mail_scope_entries,
 		G_N_ELEMENTS (mail_scope_entries),
@@ -1560,6 +1518,12 @@ e_mail_shell_view_actions_init (EMailShellView *mail_shell_view)
 	e_shell_content_set_scope_action (shell_content, radio_action);
 	e_shell_content_set_scope_visible (shell_content, TRUE);
 
+	/* Advanced Search action */
+	radio_action = GTK_RADIO_ACTION (ACTION (MAIL_SEARCH_ADVANCED_HIDDEN));
+	e_shell_content_set_search_radio_action (shell_content, radio_action);
+	gtk_action_set_visible (GTK_ACTION (radio_action), FALSE);
+	gtk_radio_action_set_current_value (radio_action, MAIL_SEARCH_SUBJECT_OR_ADDRESSES_CONTAIN);
+
 	/* Bind GObject properties for GConf keys. */
 
 	bridge = gconf_bridge_get ();
@@ -1622,10 +1586,6 @@ e_mail_shell_view_actions_init (EMailShellView *mail_shell_view)
 	g_signal_connect (
 		ACTION (GAL_SAVE_CUSTOM_VIEW), "activate",
 		G_CALLBACK (action_gal_save_custom_view_cb), mail_shell_view);
-
-	g_signal_connect (
-		ACTION (SEARCH_QUICK), "activate",
-		G_CALLBACK (action_search_quick_cb), mail_shell_view);
 }
 
 /* Helper for e_mail_shell_view_update_popup_labels() */
diff --git a/modules/mail/e-mail-shell-view-actions.h b/modules/mail/e-mail-shell-view-actions.h
index 6ae2e24..0ddc294 100644
--- a/modules/mail/e-mail-shell-view-actions.h
+++ b/modules/mail/e-mail-shell-view-actions.h
@@ -159,6 +159,8 @@
 	E_SHELL_WINDOW_ACTION ((window), "mail-reply-list")
 #define E_SHELL_WINDOW_ACTION_MAIL_REPLY_SENDER(window) \
 	E_SHELL_WINDOW_ACTION ((window), "mail-reply-sender")
+#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_ADVANCED_HIDDEN(window) \
+	E_SHELL_WINDOW_ACTION ((window), "mail-search-advanced-hidden")
 #define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FOLDER_FROM_MAILING_LIST(window) \
 	E_SHELL_WINDOW_ACTION ((window), "mail-search-folder-from-mailing-list")
 #define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FOLDER_FROM_RECIPIENTS(window) \
diff --git a/modules/mail/e-mail-shell-view-private.h b/modules/mail/e-mail-shell-view-private.h
index 6142b6e..3c9ec88 100644
--- a/modules/mail/e-mail-shell-view-private.h
+++ b/modules/mail/e-mail-shell-view-private.h
@@ -108,6 +108,7 @@ enum {
 
 /* Search items are displayed in ascending order. */
 enum {
+	MAIL_SEARCH_ADVANCED = -1,
 	MAIL_SEARCH_SUBJECT_OR_ADDRESSES_CONTAIN,
 	MAIL_SEARCH_RECIPIENTS_CONTAIN,
 	MAIL_SEARCH_MESSAGE_CONTAINS,
diff --git a/modules/mail/e-mail-shell-view.c b/modules/mail/e-mail-shell-view.c
index 1241716..895bd33 100644
--- a/modules/mail/e-mail-shell-view.c
+++ b/modules/mail/e-mail-shell-view.c
@@ -94,7 +94,6 @@ mail_shell_view_execute_search (EShellView *shell_view)
 	EMailShellContent *mail_shell_content;
 	MessageList *message_list;
 	EFilterRule *rule;
-	EFilterRule *search_rule;
 	EMailReader *reader;
 	CamelFolder *folder;
 	GtkAction *action;
@@ -156,20 +155,29 @@ mail_shell_view_execute_search (EShellView *shell_view)
 	model = e_shell_settings_get_object (
 		shell_settings, "mail-label-list-store");
 
+	action = ACTION (MAIL_SEARCH_SUBJECT_OR_ADDRESSES_CONTAIN);
+	value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action));
+
 	text = e_shell_content_get_search_text (shell_content);
-	if (text == NULL || *text == '\0') {
-		query = g_strdup ("");
+	if (value == MAIL_SEARCH_ADVANCED || text == NULL || *text == '\0') {
+		query = e_shell_content_get_search_rule_as_string (shell_content);
+
+		if (!query)
+			query = g_strdup ("");
+
 		goto filter;
 	}
 
 	/* Replace variables in the selected rule with the
 	 * current search text and extract a query string. */
 
-	action = ACTION (MAIL_SEARCH_SUBJECT_OR_ADDRESSES_CONTAIN);
-	value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action));
 	g_return_if_fail (value >= 0 && value < MAIL_NUM_SEARCH_RULES);
 	rule = priv->search_rules[value];
 
+	/* Set the search rule in EShellContent so that "Create
+	 * Search Folder from Search" works for quick searches. */
+	e_shell_content_set_search_rule (shell_content, rule);
+
 	for (iter = rule->parts; iter != NULL; iter = iter->next) {
 		EFilterPart *part = iter->data;
 		EFilterElement *element = NULL;
@@ -337,18 +345,6 @@ filter:
 			break;
 	}
 
-	search_rule = e_shell_content_get_search_rule (shell_content);
-	if (search_rule != NULL) {
-		string = g_string_sized_new (1024);
-		e_filter_rule_build_code (search_rule, string);
-		temp = g_strconcat ("(and", string->str, query, ")", NULL);
-
-		g_free (query);
-		query = temp;
-
-		g_string_free (string, TRUE);
-	}
-
 	message_list_set_search (message_list, query);
 
 	e_mail_shell_content_set_search_strings (
diff --git a/shell/e-shell-content.c b/shell/e-shell-content.c
index 3c85fec..3640a2a 100644
--- a/shell/e-shell-content.c
+++ b/shell/e-shell-content.c
@@ -59,6 +59,7 @@ struct _EShellContentPrivate {
 	GtkWidget *search_entry;
 	GtkWidget *scope_label;
 	GtkWidget *scope_combo_box;
+	GtkRadioAction *search_radio; /* to be able to manage radio here */
 };
 
 enum {
@@ -74,6 +75,7 @@ enum {
 	PROP_SCOPE_ACTION,
 	PROP_SCOPE_VALUE,
 	PROP_SCOPE_VISIBLE,
+	PROP_SEARCH_RADIO_ACTION,
 	PROP_SHELL_VIEW
 };
 
@@ -94,17 +96,19 @@ shell_content_dialog_rule_changed (GtkWidget *dialog,
 }
 
 static void
-shell_content_execute_search_cb (EShellView *shell_view,
-                                 EShellContent *shell_content)
+shell_content_update_search_widgets (EShellContent *shell_content)
 {
+	EShellView *shell_view;
 	EShellWindow *shell_window;
 	GtkAction *action;
 	GtkWidget *widget;
 	const gchar *search_text;
 	gboolean sensitive;
 
-	if (!e_shell_view_is_active (shell_view))
-		return;
+	g_return_if_fail (shell_content != NULL);
+
+	shell_view = e_shell_content_get_shell_view (shell_content);
+	g_return_if_fail (shell_view != NULL);
 
 	/* EShellView subclasses are responsible for actually
 	 * executing the search.  This is all cosmetic stuff. */
@@ -113,7 +117,11 @@ shell_content_execute_search_cb (EShellView *shell_view,
 	shell_window = e_shell_view_get_shell_window (shell_view);
 	search_text = e_shell_content_get_search_text (shell_content);
 
-	if (search_text != NULL && *search_text != '\0') {
+	sensitive =
+		(search_text != NULL && *search_text != '\0') ||
+		(e_shell_content_get_search_rule (shell_content) != NULL);
+
+	if (sensitive) {
 		GtkStyle *style;
 		const GdkColor *color;
 
@@ -122,28 +130,30 @@ shell_content_execute_search_cb (EShellView *shell_view,
 		gtk_widget_modify_base (widget, GTK_STATE_NORMAL, color);
 
 		style = gtk_widget_get_style (widget);
-		color = &style->text[GTK_STATE_SELECTED];
+		color = &style->text[(search_text != NULL && *search_text != '\0') ? GTK_STATE_SELECTED : GTK_STATE_INSENSITIVE];
 		gtk_widget_modify_text (widget, GTK_STATE_NORMAL, color);
 	} else {
 		/* Text color will be updated when we move the focus. */
 		gtk_widget_modify_base (widget, GTK_STATE_NORMAL, NULL);
 	}
 
-	/* XXX The intent here is to distinguish between custom searches
-	 *     and stock searches (from the "Show" combo) and only enable
-	 *     the "search-clear" action for custom searches.  I'm not
-	 *     sure this logic is adequate though.  It needs to account
-	 *     for quick searches, advanced searches and saved searches.
-	 *     We'll probably wind up having to explicitly say whether
-	 *     the search is custom, but this is good enough for now. */
-	sensitive =
-		(search_text != NULL && *search_text != '\0') ||
-		(e_shell_content_get_search_rule (shell_content) != NULL);
 	action = E_SHELL_WINDOW_ACTION_SEARCH_CLEAR (shell_window);
 	gtk_action_set_sensitive (action, sensitive);
 
 	action = E_SHELL_WINDOW_ACTION_SEARCH_SAVE (shell_window);
-	gtk_action_set_sensitive (action, TRUE);
+	gtk_action_set_sensitive (action, sensitive);
+}
+
+static void
+shell_content_execute_search_cb (EShellView *shell_view,
+                                 EShellContent *shell_content)
+{
+	GtkWidget *widget;
+
+	shell_content_update_search_widgets (shell_content);
+
+	if (!e_shell_view_is_active (shell_view))
+		return;
 
 	/* Direct the focus away from the search entry, so that a
 	 * focus-in event is required before the text can be changed.
@@ -322,6 +332,25 @@ shell_content_init_search_context (EShellContent *shell_content)
 }
 
 static void
+shell_content_activate_advanced_search (EShellContent *shell_content)
+{
+	GtkRadioAction *radio_action;
+	const gchar *search_text;
+
+	g_return_if_fail (shell_content != NULL);
+	g_return_if_fail (shell_content->priv->search_entry != NULL);
+
+	/* cannot mix text search with an Advanced Search, thus unsetting search text */
+	search_text = e_shell_content_get_search_text (shell_content);
+	if (search_text)
+		e_shell_content_set_search_text (shell_content, NULL);
+
+	radio_action = e_shell_content_get_search_radio_action (shell_content);
+	if (radio_action)
+		g_object_set (G_OBJECT (radio_action), "current-value", -1, NULL);
+}
+
+static void
 shell_content_set_shell_view (EShellContent *shell_content,
                               EShellView *shell_view)
 {
@@ -401,6 +430,12 @@ shell_content_set_property (GObject *object,
 				g_value_get_boolean (value));
 			return;
 
+		case PROP_SEARCH_RADIO_ACTION:
+			e_shell_content_set_search_radio_action (
+				E_SHELL_CONTENT (object),
+				g_value_get_object (value));
+			return;
+
 		case PROP_SHELL_VIEW:
 			shell_content_set_shell_view (
 				E_SHELL_CONTENT (object),
@@ -484,6 +519,12 @@ shell_content_get_property (GObject *object,
 				E_SHELL_CONTENT (object)));
 			return;
 
+		case PROP_SEARCH_RADIO_ACTION:
+			g_value_set_object (
+				value, e_shell_content_get_search_radio_action (
+				E_SHELL_CONTENT (object)));
+			return;
+
 		case PROP_SHELL_VIEW:
 			g_value_set_object (
 				value, e_shell_content_get_shell_view (
@@ -512,6 +553,14 @@ shell_content_dispose (GObject *object)
 		priv->search_context = NULL;
 	}
 
+	if (priv->search_radio) {
+		/* actions are freed before contents, thus skip it here */
+		/*g_signal_handlers_disconnect_matched (
+			priv->search_radio, G_SIGNAL_MATCH_DATA, 0, 0, NULL,
+			NULL, object);*/
+		priv->search_radio = NULL;
+	}
+
 	/* Chain up to parent's dispose() method. */
 	G_OBJECT_CLASS (parent_class)->dispose (object);
 }
@@ -820,6 +869,16 @@ shell_content_class_init (EShellContentClass *class)
 			G_PARAM_READWRITE |
 			G_PARAM_CONSTRUCT));
 
+	g_object_class_install_property (
+		object_class,
+		PROP_SEARCH_RADIO_ACTION,
+		g_param_spec_object (
+			"search-radio-action",
+			NULL,
+			NULL,
+			GTK_TYPE_RADIO_ACTION,
+			G_PARAM_READWRITE));
+
 	/**
 	 * EShellContent:shell-view
 	 *
@@ -1197,9 +1256,30 @@ e_shell_content_set_search_rule (EShellContent *shell_content,
 
 	shell_content->priv->search_rule = search_rule;
 
+	shell_content_update_search_widgets (shell_content);
 	g_object_notify (G_OBJECT (shell_content), "search-rule");
 }
 
+/* free returned string with g_free */
+gchar *
+e_shell_content_get_search_rule_as_string (EShellContent *shell_content)
+{
+	EFilterRule *rule;
+	GString *str;
+
+	g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL);
+
+	rule = e_shell_content_get_search_rule (shell_content);
+
+	if (!rule)
+		return NULL;
+
+	str = g_string_new ("");
+	e_filter_rule_build_code (rule, str);
+
+	return g_string_free (str, FALSE);
+}
+
 const gchar *
 e_shell_content_get_search_text (EShellContent *shell_content)
 {
@@ -1224,6 +1304,7 @@ e_shell_content_set_search_text (EShellContent *shell_content,
 
 	e_hinted_entry_set_text (entry, search_text);
 
+	shell_content_update_search_widgets (shell_content);
 	g_object_notify (G_OBJECT (shell_content), "search-text");
 }
 
@@ -1329,6 +1410,57 @@ e_shell_content_set_scope_visible (EShellContent *shell_content,
 	g_object_notify (G_OBJECT (shell_content), "scope-visible");
 }
 
+static void
+search_radio_changed_cb (GtkRadioAction *action,
+                       GtkRadioAction *current,
+                       EShellContent *shell_content)
+{
+	gint current_value;
+	gchar *search_text;
+
+	e_shell_content_set_search_hint (shell_content, gtk_action_get_label (GTK_ACTION (current)));
+
+	current_value = gtk_radio_action_get_current_value (current);
+	search_text = g_strdup (e_shell_content_get_search_text (shell_content));
+
+	if (current_value != -1) {
+		e_shell_content_set_search_rule (shell_content, NULL);
+		e_shell_content_set_search_text (shell_content, search_text);
+		if (search_text && *search_text)
+			e_shell_view_execute_search (e_shell_content_get_shell_view (shell_content));
+	} else if (search_text) {
+		e_shell_content_set_search_text (shell_content, NULL);
+	}
+
+	g_free (search_text);
+}
+
+void
+e_shell_content_set_search_radio_action (EShellContent *shell_content, GtkRadioAction *search_action)
+{
+	g_return_if_fail (E_IS_SHELL_CONTENT (shell_content));
+
+	if (shell_content->priv->search_radio)
+		g_signal_handlers_disconnect_matched (
+			shell_content->priv->search_radio, G_SIGNAL_MATCH_DATA, 0, 0, NULL,
+			search_radio_changed_cb, shell_content);
+
+	shell_content->priv->search_radio = search_action;
+
+	if (shell_content->priv->search_radio)
+		g_signal_connect (shell_content->priv->search_radio, "changed", G_CALLBACK (search_radio_changed_cb), shell_content);
+
+	g_object_notify (G_OBJECT (shell_content), "search-radio-action");
+}
+
+GtkRadioAction *
+e_shell_content_get_search_radio_action (EShellContent *shell_content)
+{
+	g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL);
+
+	return shell_content->priv->search_radio;
+}
+
 void
 e_shell_content_run_advanced_search_dialog (EShellContent *shell_content)
 {
@@ -1389,6 +1521,7 @@ run:
 
 	e_shell_content_set_search_rule (shell_content, rule);
 
+	shell_content_activate_advanced_search (shell_content);
 	e_shell_view_execute_search (shell_view);
 
 	if (response == GTK_RESPONSE_APPLY) {
@@ -1553,7 +1686,8 @@ e_shell_content_restore_state (EShellContent *shell_content,
 
 	key = STATE_KEY_SEARCH_TEXT;
 	string = g_key_file_get_string (key_file, group_name, key, NULL);
-	e_shell_content_set_search_text (shell_content, string);
+	if (g_strcmp0 (string ? string : "", e_shell_content_get_search_text (shell_content)) != 0)
+		e_shell_content_set_search_text (shell_content, string);
 	g_free (string);
 
 	action = E_SHELL_WINDOW_ACTION_SEARCH_QUICK (shell_window);
diff --git a/shell/e-shell-content.h b/shell/e-shell-content.h
index 9449040..9ee9219 100644
--- a/shell/e-shell-content.h
+++ b/shell/e-shell-content.h
@@ -112,6 +112,8 @@ void		e_shell_content_set_search_hint	(EShellContent *shell_content,
 EFilterRule *	e_shell_content_get_search_rule	(EShellContent *shell_content);
 void		e_shell_content_set_search_rule (EShellContent *shell_content,
 						 EFilterRule *search_rule);
+gchar *		e_shell_content_get_search_rule_as_string
+						(EShellContent *shell_content);
 const gchar *	e_shell_content_get_search_text	(EShellContent *shell_content);
 void		e_shell_content_set_search_text	(EShellContent *shell_content,
 						 const gchar *search_text);
@@ -131,6 +133,11 @@ gboolean	e_shell_content_get_scope_visible
 void		e_shell_content_set_scope_visible
 						(EShellContent *shell_content,
 						 gboolean scope_visible);
+void		e_shell_content_set_search_radio_action
+						(EShellContent *shell_content,
+						 GtkRadioAction *search_action);
+GtkRadioAction *e_shell_content_get_search_radio_action
+						(EShellContent *shell_content);
 const gchar *	e_shell_content_get_view_id	(EShellContent *shell_content);
 void		e_shell_content_set_view_id	(EShellContent *shell_content,
 						 const gchar *view_id);
diff --git a/shell/e-shell-window-actions.c b/shell/e-shell-window-actions.c
index 1ba9a19..058e456 100644
--- a/shell/e-shell-window-actions.c
+++ b/shell/e-shell-window-actions.c
@@ -1044,6 +1044,7 @@ action_search_clear_cb (GtkAction *action,
 {
 	EShellView *shell_view;
 	EShellContent *shell_content;
+	GtkRadioAction *search_action;
 	const gchar *view_name;
 
 	view_name = e_shell_window_get_active_view (shell_window);
@@ -1053,6 +1054,11 @@ action_search_clear_cb (GtkAction *action,
 	e_shell_content_set_search_rule (shell_content, NULL);
 	e_shell_content_set_search_text (shell_content, NULL);
 
+	/* change from Advanced Search to the first one, so filling a text will do something */
+	search_action = e_shell_content_get_search_radio_action (shell_content);
+	if (search_action && gtk_radio_action_get_current_value (search_action) == -1)
+		gtk_radio_action_set_current_value (search_action, 0);
+
 	e_shell_view_execute_search (shell_view);
 
 	e_shell_window_update_search_menu (shell_window);
@@ -1118,11 +1124,20 @@ static void
 action_search_quick_cb (GtkAction *action,
                         EShellWindow *shell_window)
 {
+	EShellContent *shell_content;
 	EShellView *shell_view;
+	GtkRadioAction *radio_action;
 	const gchar *view_name;
 
 	view_name = e_shell_window_get_active_view (shell_window);
 	shell_view = e_shell_window_get_shell_view (shell_window, view_name);
+	shell_content = e_shell_view_get_shell_content (shell_view);
+
+	radio_action = e_shell_content_get_search_radio_action (shell_content);
+	if (radio_action && gtk_radio_action_get_current_value (radio_action) == -1) {
+		/* change Advanced Search to a default search type automatically */
+		gtk_radio_action_set_current_value (radio_action, 0);
+	}
 
 	e_shell_view_execute_search (shell_view);
 }
diff --git a/ui/evolution-calendars.ui b/ui/evolution-calendars.ui
index 04f4ac3..69d4263 100644
--- a/ui/evolution-calendars.ui
+++ b/ui/evolution-calendars.ui
@@ -139,6 +139,7 @@
     <menuitem action='calendar-taskpad-delete'/>
   </popup>
   <popup name='calendar-search-options'>
+    <menuitem action='calendar-search-advanced-hidden'/>
     <menuitem action='calendar-search-summary-contains'/>
     <menuitem action='calendar-search-description-contains'/>
     <menuitem action='calendar-search-any-field-contains'/>
diff --git a/ui/evolution-contacts.ui b/ui/evolution-contacts.ui
index 8b04c3b..864a5aa 100644
--- a/ui/evolution-contacts.ui
+++ b/ui/evolution-contacts.ui
@@ -83,6 +83,7 @@
     <menuitem action='contact-popup-delete'/>
   </popup>
   <popup name='contact-search-options'>
+    <menuitem action='contact-search-advanced-hidden'/>
     <menuitem action='contact-search-name-contains'/>
     <menuitem action='contact-search-email-begins-with'/>
     <menuitem action='contact-search-any-field-contains'/>
diff --git a/ui/evolution-mail.ui b/ui/evolution-mail.ui
index 60727be..0964971 100644
--- a/ui/evolution-mail.ui
+++ b/ui/evolution-mail.ui
@@ -126,6 +126,7 @@
     <placeholder name='mail-message-popup-actions'/>
   </popup>
   <popup name='mail-search-options'>
+    <menuitem action='mail-search-advanced-hidden'/>
     <menuitem action='mail-search-subject-or-addresses-contain'/>
     <menuitem action='mail-search-recipients-contain'/>
     <menuitem action='mail-search-message-contains'/>
diff --git a/ui/evolution-memos.ui b/ui/evolution-memos.ui
index 3afcd80..a303ae3 100644
--- a/ui/evolution-memos.ui
+++ b/ui/evolution-memos.ui
@@ -67,6 +67,7 @@
     <menuitem action='memo-list-popup-properties'/>
   </popup>
   <popup name='memo-search-options'>
+    <menuitem action='memo-search-advanced-hidden'/>
     <menuitem action='memo-search-summary-contains'/>
     <menuitem action='memo-search-description-contains'/>
     <menuitem action='memo-search-any-field-contains'/>
diff --git a/ui/evolution-tasks.ui b/ui/evolution-tasks.ui
index 8a17fd3..e2682b3 100644
--- a/ui/evolution-tasks.ui
+++ b/ui/evolution-tasks.ui
@@ -78,6 +78,7 @@
     <menuitem action='task-list-popup-properties'/>
   </popup>
   <popup name='task-search-options'>
+    <menuitem action='task-search-advanced-hidden'/>
     <menuitem action='task-search-summary-contains'/>
     <menuitem action='task-search-description-contains'/>
     <menuitem action='task-search-any-field-contains'/>
diff --git a/widgets/misc/e-hinted-entry.c b/widgets/misc/e-hinted-entry.c
index ca75e85..2851d75 100644
--- a/widgets/misc/e-hinted-entry.c
+++ b/widgets/misc/e-hinted-entry.c
@@ -197,6 +197,7 @@ hinted_entry_init (EHintedEntry *entry)
 {
 	entry->priv = E_HINTED_ENTRY_GET_PRIVATE (entry);
 	entry->priv->hint = g_strdup ("");  /* hint must never be NULL */
+	hinted_entry_show_hint (entry);
 }
 
 GType



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