aboutsummaryrefslogtreecommitdiffstats
path: root/shell
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@src.gnome.org>2008-09-23 05:03:28 +0800
committerMatthew Barnes <mbarnes@src.gnome.org>2008-09-23 05:03:28 +0800
commit73c370019c4de89d4c901ee8c25cc0cbb55992fb (patch)
tree26609470a1148d3bd364cbce5d5ab2f41e0e23d4 /shell
parent6b2295c93a40f6010d94399666a8e099aded8e85 (diff)
downloadgsoc2013-evolution-73c370019c4de89d4c901ee8c25cc0cbb55992fb.tar.gz
gsoc2013-evolution-73c370019c4de89d4c901ee8c25cc0cbb55992fb.tar.zst
gsoc2013-evolution-73c370019c4de89d4c901ee8c25cc0cbb55992fb.zip
Search UI is kinda sorta working. Still some outstanding issues.
svn path=/branches/kill-bonobo/; revision=36427
Diffstat (limited to 'shell')
-rw-r--r--shell/Makefile.am2
-rw-r--r--shell/e-shell-content.c411
-rw-r--r--shell/e-shell-content.h17
-rw-r--r--shell/e-shell-sidebar.h2
-rw-r--r--shell/e-shell-switcher.h2
-rw-r--r--shell/e-shell-view.h3
-rw-r--r--shell/e-shell-window-actions.c193
-rw-r--r--shell/e-shell-window-actions.h4
-rw-r--r--shell/e-shell-window-private.c6
-rw-r--r--shell/e-shell-window-private.h5
10 files changed, 534 insertions, 111 deletions
diff --git a/shell/Makefile.am b/shell/Makefile.am
index 3afa351426..0603f603fa 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -17,7 +17,7 @@ INCLUDES = \
-DEVOLUTION_GLADEDIR=\""$(gladedir)"\" \
-DEVOLUTION_HELPDIR=\""$(evolutionhelpdir)"\" \
-DEVOLUTION_MODULEDIR=\""$(moduledir)"\" \
- -DEVOLUTION_RULEDIR=\""$(ruledir)"\" \
+ -DEVOLUTION_RULEDIR=\""$(privdatadir)"\" \
-DEVOLUTION_UIDIR=\""$(evolutionuidir)"\" \
-DEVOLUTION_TOOLSDIR=\""$(privlibexecdir)"\" \
-DPREFIX=\""$(prefix)"\" \
diff --git a/shell/e-shell-content.c b/shell/e-shell-content.c
index 95cdc2d1cc..c16344ac15 100644
--- a/shell/e-shell-content.c
+++ b/shell/e-shell-content.c
@@ -22,6 +22,7 @@
#include <glib/gi18n.h>
+#include <filter/rule-editor.h>
#include <widgets/misc/e-action-combo-box.h>
#include <widgets/misc/e-icon-entry.h>
@@ -38,7 +39,9 @@ struct _EShellContentPrivate {
gpointer shell_view; /* weak pointer */
RuleContext *search_context;
- FilterRule *current_query;
+ FilterRule *search_rule;
+ gchar *system_filename;
+ gchar *user_filename;
/* Container for the following widgets */
GtkWidget *search_bar;
@@ -52,9 +55,6 @@ struct _EShellContentPrivate {
GtkWidget *scope_combo_box;
GtkStateType search_state;
-
- GtkRadioAction *search_action;
- GtkWidget *search_popup_menu;
};
enum {
@@ -62,8 +62,8 @@ enum {
PROP_FILTER_ACTION,
PROP_FILTER_VALUE,
PROP_FILTER_VISIBLE,
- PROP_SEARCH_ACTION,
PROP_SEARCH_CONTEXT,
+ PROP_SEARCH_RULE,
PROP_SEARCH_TEXT,
PROP_SEARCH_VALUE,
PROP_SEARCH_VISIBLE,
@@ -76,42 +76,68 @@ enum {
static gpointer parent_class;
static void
-shell_content_entry_activated_cb (EShellContent *shell_content,
- GtkWidget *entry)
+shell_content_dialog_rule_changed (GtkWidget *dialog,
+ FilterRule *rule)
+{
+ gboolean sensitive;
+
+ sensitive = (rule != NULL) && (rule->parts != NULL);
+
+ gtk_dialog_set_response_sensitive (
+ GTK_DIALOG (dialog), GTK_RESPONSE_OK, sensitive);
+ gtk_dialog_set_response_sensitive (
+ GTK_DIALOG (dialog), GTK_RESPONSE_APPLY, sensitive);
+}
+
+static void
+action_search_execute_cb (GtkAction *action,
+ EShellContent *shell_content)
{
- EShellWindow *shell_window;
EShellView *shell_view;
- GtkAction *action;
+ EShellWindow *shell_window;
+ EIconEntry *icon_entry;
+ GtkWidget *child;
+ GtkStateType visual_state;
+ const gchar *search_text;
+
+ /* EShellView subclasses are responsible for actually
+ * executing the search. This is all cosmetic stuff. */
shell_view = e_shell_content_get_shell_view (shell_content);
shell_window = e_shell_view_get_shell_window (shell_view);
- /* Verify the shell view is active before proceeding. */
if (!e_shell_view_is_active (shell_view))
return;
- action = E_SHELL_WINDOW_ACTION_SEARCH_EXECUTE (shell_window);
- gtk_action_activate (action);
+ icon_entry = E_ICON_ENTRY (shell_content->priv->search_entry);
+ search_text = e_shell_content_get_search_text (shell_content);
+
+ if (search_text != NULL && *search_text != '\0')
+ visual_state = GTK_STATE_SELECTED;
+ else
+ visual_state = GTK_STATE_NORMAL;
+
+ e_icon_entry_set_visual_state (icon_entry, visual_state);
+
+ action = E_SHELL_WINDOW_ACTION_SEARCH_CLEAR (shell_window);
+ gtk_action_set_sensitive (action, TRUE);
+
+ action = E_SHELL_WINDOW_ACTION_SEARCH_SAVE (shell_window);
+ gtk_action_set_sensitive (action, TRUE);
+
+ /* Direct the focus away from the search entry, so that a
+ * focus-in event is required before the text can be changed.
+ * This will reset the entry to the appropriate visual state. */
+ gtk_widget_grab_focus (gtk_bin_get_child (GTK_BIN (shell_content)));
}
static void
-shell_content_entry_changed_cb (EShellContent *shell_content,
- GtkWidget *entry)
+shell_content_entry_activated_cb (EShellContent *shell_content,
+ GtkWidget *entry)
{
EShellWindow *shell_window;
EShellView *shell_view;
- GtkStateType state;
GtkAction *action;
- gboolean sensitive;
- const gchar *text;
-
- text = gtk_entry_get_text (GTK_ENTRY (entry));
- state = shell_content->priv->search_state;
-
- if (text != NULL && *text != '\0')
- sensitive = (state != GTK_STATE_INSENSITIVE);
- else
- sensitive = (state == GTK_STATE_SELECTED);
shell_view = e_shell_content_get_shell_view (shell_content);
shell_window = e_shell_view_get_shell_window (shell_view);
@@ -120,8 +146,8 @@ shell_content_entry_changed_cb (EShellContent *shell_content,
if (!e_shell_view_is_active (shell_view))
return;
- action = E_SHELL_WINDOW_ACTION_SEARCH_CLEAR (shell_window);
- gtk_action_set_sensitive (action, sensitive);
+ action = E_SHELL_WINDOW_ACTION_SEARCH_EXECUTE (shell_window);
+ gtk_action_activate (action);
}
static gboolean
@@ -129,11 +155,16 @@ shell_content_entry_focus_in_cb (EShellContent *shell_content,
GdkEventFocus *focus_event,
GtkWidget *entry)
{
- if (shell_content->priv->search_state == GTK_STATE_INSENSITIVE) {
+ EIconEntry *icon_entry;
+ GtkStateType visual_state;
+
+ icon_entry = E_ICON_ENTRY (shell_content->priv->search_entry);
+ visual_state = e_icon_entry_get_visual_state (icon_entry);
+
+ if (visual_state == GTK_STATE_INSENSITIVE)
gtk_entry_set_text (GTK_ENTRY (entry), "");
- gtk_widget_modify_text (entry, GTK_STATE_NORMAL, NULL);
- shell_content->priv->search_state = GTK_STATE_NORMAL;
- }
+
+ e_icon_entry_set_visual_state (icon_entry, GTK_STATE_NORMAL);
return FALSE;
}
@@ -152,8 +183,25 @@ shell_content_entry_key_press_cb (EShellContent *shell_content,
GdkEventKey *key_event,
GtkWidget *entry)
{
- /* FIXME */
- return FALSE;
+ EShellView *shell_view;
+ EShellWindow *shell_window;
+ GtkAction *action;
+ guint mask;
+
+ mask = gtk_accelerator_get_default_mod_mask ();
+ if ((key_event->state & mask) != GDK_MOD1_MASK)
+ return FALSE;
+
+ if (key_event->keyval != GDK_Down)
+ return FALSE;
+
+ shell_view = e_shell_content_get_shell_view (shell_content);
+ shell_window = e_shell_view_get_shell_window (shell_view);
+
+ action = E_SHELL_WINDOW_ACTION_SEARCH_OPTIONS (shell_window);
+ gtk_action_activate (action);
+
+ return TRUE;
}
static void
@@ -194,14 +242,14 @@ shell_content_init_search_context (EShellContent *shell_content)
rule_context_add_rule, rule_context_next_rule);
rule_context_load (context, system_filename, user_filename);
- /* Ownership of the strings is passed to the rule context.
- * XXX Not sure why this is necessary. */
+ /* XXX Not sure why this is necessary. */
g_object_set_data_full (
- G_OBJECT (context), "system", system_filename, g_free);
+ G_OBJECT (context), "system",
+ g_strdup (system_filename), g_free);
g_object_set_data_full (
- G_OBJECT (context), "user", user_filename, g_free);
+ G_OBJECT (context), "user",
+ g_strdup (user_filename), g_free);
- /* XXX I don't really understand what this does. */
rule = filter_rule_new ();
part = rule_context_next_part (context, NULL);
if (part == NULL)
@@ -212,6 +260,8 @@ shell_content_init_search_context (EShellContent *shell_content)
filter_rule_add_part (rule, filter_part_clone (part));
shell_content->priv->search_context = context;
+ shell_content->priv->system_filename = system_filename;
+ shell_content->priv->user_filename = user_filename;
}
static void
@@ -252,8 +302,8 @@ shell_content_set_property (GObject *object,
g_value_get_boolean (value));
return;
- case PROP_SEARCH_ACTION:
- e_shell_content_set_search_action (
+ case PROP_SEARCH_RULE:
+ e_shell_content_set_search_rule (
E_SHELL_CONTENT (object),
g_value_get_object (value));
return;
@@ -329,15 +379,15 @@ shell_content_get_property (GObject *object,
E_SHELL_CONTENT (object)));
return;
- case PROP_SEARCH_ACTION:
+ case PROP_SEARCH_CONTEXT:
g_value_set_object (
- value, e_shell_content_get_search_action (
+ value, e_shell_content_get_search_context (
E_SHELL_CONTENT (object)));
return;
- case PROP_SEARCH_CONTEXT:
+ case PROP_SEARCH_RULE:
g_value_set_object (
- value, e_shell_content_get_search_context (
+ value, e_shell_content_get_search_rule (
E_SHELL_CONTENT (object)));
return;
@@ -435,16 +485,51 @@ shell_content_dispose (GObject *object)
priv->scope_combo_box = NULL;
}
- if (priv->search_action != NULL) {
- g_object_unref (priv->search_action);
- priv->search_action = NULL;
- }
-
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
+shell_content_finalize (GObject *object)
+{
+ EShellContentPrivate *priv;
+
+ priv = E_SHELL_CONTENT_GET_PRIVATE (object);
+
+ g_free (priv->system_filename);
+ g_free (priv->user_filename);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+shell_content_constructed (GObject *object)
+{
+ EShellView *shell_view;
+ EShellWindow *shell_window;
+ EShellContent *shell_content;
+ EIconEntry *icon_entry;
+ GtkAction *action;
+
+ shell_content = E_SHELL_CONTENT (object);
+ shell_view = e_shell_content_get_shell_view (shell_content);
+ shell_window = e_shell_view_get_shell_window (shell_view);
+ icon_entry = E_ICON_ENTRY (shell_content->priv->search_entry);
+
+ action = E_SHELL_WINDOW_ACTION_SEARCH_CLEAR (shell_window);
+ e_icon_entry_add_action_end (icon_entry, action);
+
+ action = E_SHELL_WINDOW_ACTION_SEARCH_EXECUTE (shell_window);
+ g_signal_connect (
+ action, "activate",
+ G_CALLBACK (action_search_execute_cb), shell_content);
+
+ action = E_SHELL_WINDOW_ACTION_SEARCH_OPTIONS (shell_window);
+ e_icon_entry_add_action_start (icon_entry, action);
+}
+
+static void
shell_content_realize (GtkWidget *widget)
{
EShellContent *shell_content;
@@ -569,6 +654,8 @@ shell_content_class_init (EShellContentClass *class)
object_class->set_property = shell_content_set_property;
object_class->get_property = shell_content_get_property;
object_class->dispose = shell_content_dispose;
+ object_class->finalize = shell_content_finalize;
+ object_class->constructed = shell_content_constructed;
widget_class = GTK_WIDGET_CLASS (class);
widget_class->realize = shell_content_realize;
@@ -614,23 +701,23 @@ shell_content_class_init (EShellContentClass *class)
g_object_class_install_property (
object_class,
- PROP_SEARCH_ACTION,
+ PROP_SEARCH_CONTEXT,
g_param_spec_object (
- "search-action",
+ "search-context",
NULL,
NULL,
- GTK_TYPE_RADIO_ACTION,
- G_PARAM_READWRITE));
+ RULE_TYPE_CONTEXT,
+ G_PARAM_READABLE));
g_object_class_install_property (
object_class,
- PROP_SEARCH_CONTEXT,
+ PROP_SEARCH_RULE,
g_param_spec_object (
- "search-context",
+ "search-rule",
NULL,
NULL,
- RULE_TYPE_CONTEXT,
- G_PARAM_READABLE));
+ FILTER_TYPE_RULE,
+ G_PARAM_READWRITE));
g_object_class_install_property (
object_class,
@@ -793,9 +880,6 @@ shell_content_init (EShellContent *shell_content)
widget, "activate",
G_CALLBACK (shell_content_entry_activated_cb), shell_content);
g_signal_connect_swapped (
- widget, "changed",
- G_CALLBACK (shell_content_entry_changed_cb), shell_content);
- g_signal_connect_swapped (
widget, "focus-in-event",
G_CALLBACK (shell_content_entry_focus_in_cb), shell_content);
g_signal_connect_swapped (
@@ -924,35 +1008,38 @@ e_shell_content_set_filter_visible (EShellContent *shell_content,
}
}
-GtkRadioAction *
-e_shell_content_get_search_action (EShellContent *shell_content)
+RuleContext *
+e_shell_content_get_search_context (EShellContent *shell_content)
+{
+ g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL);
+
+ return shell_content->priv->search_context;
+}
+
+FilterRule *
+e_shell_content_get_search_rule (EShellContent *shell_content)
{
g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL);
- return shell_content->priv->search_action;
+ return shell_content->priv->search_rule;
}
void
-e_shell_content_set_search_action (EShellContent *shell_content,
- GtkRadioAction *search_action)
+e_shell_content_set_search_rule (EShellContent *shell_content,
+ FilterRule *search_rule)
{
g_return_if_fail (E_IS_SHELL_CONTENT (shell_content));
- if (search_action != NULL) {
- g_return_if_fail (GTK_IS_RADIO_ACTION (search_action));
- g_object_ref (search_action);
+ if (search_rule != NULL) {
+ g_return_if_fail (IS_FILTER_RULE (search_rule));
+ g_object_ref (search_rule);
}
- shell_content->priv->search_action = search_action;
- g_object_notify (G_OBJECT (shell_content), "search-action");
-}
-
-RuleContext *
-e_shell_content_get_search_context (EShellContent *shell_content)
-{
- g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL);
+ if (shell_content->priv->search_rule != NULL)
+ g_object_unref (shell_content->priv->search_rule);
- return shell_content->priv->search_context;
+ shell_content->priv->search_rule = search_rule;
+ g_object_notify (G_OBJECT (shell_content), "search-rule");
}
const gchar *
@@ -1108,3 +1195,173 @@ e_shell_content_set_scope_visible (EShellContent *shell_content,
g_object_notify (G_OBJECT (shell_content), "scope-visible");
}
+
+void
+e_shell_content_run_advanced_search_dialog (EShellContent *shell_content)
+{
+ EShellView *shell_view;
+ EShellWindow *shell_window;
+ GtkAction *action;
+ GtkWidget *dialog;
+ GtkWidget *widget;
+ FilterRule *rule;
+ RuleContext *context;
+ const gchar *user_filename;
+ gint response;
+
+ g_return_if_fail (E_IS_SHELL_CONTENT (shell_content));
+
+ shell_view = e_shell_content_get_shell_view (shell_content);
+ shell_window = e_shell_view_get_shell_window (shell_view);
+ user_filename = shell_content->priv->user_filename;
+
+ rule = e_shell_content_get_search_rule (shell_content);
+
+ if (rule == NULL)
+ rule = filter_rule_new ();
+ else
+ rule = filter_rule_clone (rule);
+
+ context = e_shell_content_get_search_context (shell_content);
+ widget = filter_rule_get_widget (rule, context);
+ filter_rule_set_source (rule, FILTER_SOURCE_INCOMING);
+
+ dialog = gtk_dialog_new_with_buttons (
+ _("Advanced Search"), GTK_WINDOW (shell_window),
+ GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_APPLY,
+ GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 7);
+ gtk_container_set_border_width (GTK_CONTAINER (widget), 3);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 300);
+
+ gtk_box_pack_start (
+ GTK_BOX (GTK_DIALOG (dialog)->vbox), widget, TRUE, TRUE, 0);
+
+ g_signal_connect_swapped (
+ rule, "changed", G_CALLBACK (
+ shell_content_dialog_rule_changed), dialog);
+
+ shell_content_dialog_rule_changed (dialog, rule);
+
+run:
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ if (response != GTK_RESPONSE_OK && response != GTK_RESPONSE_APPLY)
+ goto exit;
+
+ if (!filter_rule_validate (rule))
+ goto run;
+
+ e_shell_content_set_search_rule (shell_content, rule);
+
+ action = E_SHELL_WINDOW_ACTION_SEARCH_EXECUTE (shell_window);
+ gtk_action_activate (action);
+
+ if (response == GTK_RESPONSE_APPLY) {
+ if (!rule_context_find_rule (context, rule->name, rule->source))
+ rule_context_add_rule (context, rule);
+ rule_context_save (context, user_filename);
+ goto run;
+ }
+
+exit:
+ g_object_unref (rule);
+ gtk_widget_destroy (dialog);
+}
+
+void
+e_shell_content_run_edit_searches_dialog (EShellContent *shell_content)
+{
+ RuleContext *context;
+ RuleEditor *editor;
+ const gchar *user_filename;
+
+ g_return_if_fail (E_IS_SHELL_CONTENT (shell_content));
+
+ context = e_shell_content_get_search_context (shell_content);
+ user_filename = shell_content->priv->user_filename;
+
+ editor = rule_editor_new (
+ context, FILTER_SOURCE_INCOMING, _("Searches"));
+ gtk_window_set_title (GTK_WINDOW (editor), _("Searches"));
+
+ if (gtk_dialog_run (GTK_DIALOG (editor)) == GTK_RESPONSE_OK)
+ rule_context_save (context, user_filename);
+
+ gtk_widget_destroy (GTK_WIDGET (editor));
+}
+
+void
+e_shell_content_run_save_search_dialog (EShellContent *shell_content)
+{
+ EShellView *shell_view;
+ EShellWindow *shell_window;
+ GtkWidget *dialog;
+ GtkWidget *widget;
+ FilterRule *rule;
+ RuleContext *context;
+ const gchar *search_text;
+ const gchar *user_filename;
+ gchar *search_name;
+ gint response;
+
+ g_return_if_fail (E_IS_SHELL_CONTENT (shell_content));
+
+ shell_view = e_shell_content_get_shell_view (shell_content);
+ shell_window = e_shell_view_get_shell_window (shell_view);
+ user_filename = shell_content->priv->user_filename;
+
+ rule = e_shell_content_get_search_rule (shell_content);
+ g_return_if_fail (IS_FILTER_RULE (rule));
+ rule = filter_rule_clone (rule);
+
+ search_text = e_shell_content_get_search_text (shell_content);
+ if (search_text == NULL || *search_text == '\0')
+ search_text = "''";
+
+ search_name = g_strdup_printf ("%s %s", rule->name, search_text);
+ filter_rule_set_name (rule, search_name);
+ g_free (search_name);
+
+ context = e_shell_content_get_search_context (shell_content);
+ widget = filter_rule_get_widget (rule, context);
+ filter_rule_set_source (rule, FILTER_SOURCE_INCOMING);
+
+ dialog = gtk_dialog_new_with_buttons (
+ _("Save Search"), GTK_WINDOW (shell_window),
+ GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 7);
+ gtk_container_set_border_width (GTK_CONTAINER (widget), 3);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 500, 300);
+
+ gtk_box_pack_start (
+ GTK_BOX (GTK_DIALOG (dialog)->vbox), widget, TRUE, TRUE, 0);
+
+ g_signal_connect_swapped (
+ rule, "changed", G_CALLBACK (
+ shell_content_dialog_rule_changed), dialog);
+
+ shell_content_dialog_rule_changed (dialog, rule);
+
+run:
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ if (response != GTK_RESPONSE_OK)
+ goto exit;
+
+ if (!filter_rule_validate (rule))
+ goto run;
+
+ rule_context_add_rule (context, rule);
+ rule_context_save (context, user_filename);
+
+exit:
+ g_object_unref (rule);
+ gtk_widget_destroy (dialog);
+}
diff --git a/shell/e-shell-content.h b/shell/e-shell-content.h
index 6f4c83338a..1763bf4b22 100644
--- a/shell/e-shell-content.h
+++ b/shell/e-shell-content.h
@@ -21,7 +21,8 @@
#ifndef E_SHELL_CONTENT_H
#define E_SHELL_CONTENT_H
-#include <gtk/gtk.h>
+#include <e-shell-common.h>
+#include <filter/filter-rule.h>
#include <filter/rule-context.h>
/* Standard GObject macros */
@@ -81,13 +82,11 @@ gboolean e_shell_content_get_filter_visible
void e_shell_content_set_filter_visible
(EShellContent *shell_content,
gboolean filter_visible);
-GtkRadioAction *e_shell_content_get_search_action
- (EShellContent *shell_content);
-void e_shell_content_set_search_action
- (EShellContent *shell_content,
- GtkRadioAction *search_action);
RuleContext * e_shell_content_get_search_context
(EShellContent *shell_content);
+FilterRule * e_shell_content_get_search_rule (EShellContent *shell_content);
+void e_shell_content_set_search_rule (EShellContent *shell_content,
+ FilterRule *search_rule);
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);
@@ -116,6 +115,12 @@ void e_shell_content_save_search_dialog
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);
+void e_shell_content_run_advanced_search_dialog
+ (EShellContent *shell_content);
+void e_shell_content_run_edit_searches_dialog
+ (EShellContent *shell_content);
+void e_shell_content_run_save_search_dialog
+ (EShellContent *shell_content);
G_END_DECLS
diff --git a/shell/e-shell-sidebar.h b/shell/e-shell-sidebar.h
index a6a67a40cc..9a27cba6b5 100644
--- a/shell/e-shell-sidebar.h
+++ b/shell/e-shell-sidebar.h
@@ -21,7 +21,7 @@
#ifndef E_SHELL_SIDEBAR_H
#define E_SHELL_SIDEBAR_H
-#include <gtk/gtk.h>
+#include <e-shell-common.h>
/* Standard GObject macros */
#define E_TYPE_SHELL_SIDEBAR \
diff --git a/shell/e-shell-switcher.h b/shell/e-shell-switcher.h
index 67201279d2..499372f81e 100644
--- a/shell/e-shell-switcher.h
+++ b/shell/e-shell-switcher.h
@@ -21,7 +21,7 @@
#ifndef E_SHELL_SWITCHER_H
#define E_SHELL_SWITCHER_H
-#include <gtk/gtk.h>
+#include <e-shell-common.h>
/* Standard GObject macros */
#define E_TYPE_SHELL_SWITCHER \
diff --git a/shell/e-shell-view.h b/shell/e-shell-view.h
index 32fd4333f0..92382a9a49 100644
--- a/shell/e-shell-view.h
+++ b/shell/e-shell-view.h
@@ -72,6 +72,9 @@ struct _EShellViewClass {
/* A unique instance is created for each subclass. */
GalViewCollection *view_collection;
+ /* Path to the search entry popup menu. */
+ const gchar *search_options_path;
+
/* Factory Methods */
GtkWidget * (*new_shell_content) (EShellView *shell_view);
GtkWidget * (*new_shell_sidebar) (EShellView *shell_view);
diff --git a/shell/e-shell-window-actions.c b/shell/e-shell-window-actions.c
index f03c775b3d..5375774702 100644
--- a/shell/e-shell-window-actions.c
+++ b/shell/e-shell-window-actions.c
@@ -674,6 +674,29 @@ action_contents_cb (GtkAction *action,
}
static void
+action_custom_rule_cb (GtkAction *action,
+ EShellWindow *shell_window)
+{
+ FilterRule *rule;
+ EShellView *shell_view;
+ EShellContent *shell_content;
+ const gchar *view_name;
+
+ rule = g_object_get_data (G_OBJECT (action), "rule");
+ g_return_if_fail (rule != NULL);
+
+ view_name = e_shell_window_get_active_view (shell_window);
+ shell_view = e_shell_window_get_view (shell_window, view_name);
+ shell_content = e_shell_view_get_shell_content (shell_view);
+
+ rule = g_object_get_data (G_OBJECT (action), "rule");
+ g_return_if_fail (IS_FILTER_RULE (rule));
+
+ e_shell_content_set_search_rule (shell_content, rule);
+ gtk_action_activate (ACTION (SEARCH_EXECUTE));
+}
+
+static void
action_faq_cb (GtkAction *action,
EShellWindow *shell_window)
{
@@ -841,65 +864,85 @@ static void
action_search_advanced_cb (GtkAction *action,
EShellWindow *shell_window)
{
+ EShellView *shell_view;
+ EShellContent *shell_content;
+ const gchar *view_name;
+
+ view_name = e_shell_window_get_active_view (shell_window);
+ shell_view = e_shell_window_get_view (shell_window, view_name);
+ shell_content = e_shell_view_get_shell_content (shell_view);
+
+ e_shell_content_run_advanced_search_dialog (shell_content);
+ e_shell_window_update_search_menu (shell_window);
}
static void
action_search_clear_cb (GtkAction *action,
EShellWindow *shell_window)
{
- EShellContent *shell_content;
EShellView *shell_view;
+ EShellContent *shell_content;
const gchar *view_name;
view_name = e_shell_window_get_active_view (shell_window);
shell_view = e_shell_window_get_view (shell_window, view_name);
shell_content = e_shell_view_get_shell_content (shell_view);
- e_shell_content_set_search_text (shell_content, "");
+
+ e_shell_content_set_search_rule (shell_content, NULL);
+ e_shell_content_set_search_text (shell_content, NULL);
+
+ gtk_action_activate (ACTION (SEARCH_EXECUTE));
+
+ e_shell_window_update_search_menu (shell_window);
}
static void
action_search_edit_cb (GtkAction *action,
EShellWindow *shell_window)
{
- EShellContent *shell_content;
EShellView *shell_view;
- RuleContext *context;
- RuleEditor *editor;
- const gchar *filename;
+ EShellContent *shell_content;
const gchar *view_name;
view_name = e_shell_window_get_active_view (shell_window);
shell_view = e_shell_window_get_view (shell_window, view_name);
shell_content = e_shell_view_get_shell_content (shell_view);
- context = e_shell_content_get_search_context (shell_content);
- g_return_if_fail (context != NULL);
-
- /* XXX I don't know why the RuleContext can't just store
- * system and user file names properly. Fix this? */
- filename = g_object_get_data (G_OBJECT (context), "user");
- g_return_if_fail (filename != NULL);
- editor = rule_editor_new (
- context, FILTER_SOURCE_INCOMING, _("Searches"));
- gtk_window_set_title (GTK_WINDOW (editor), _("Searches"));
-
- if (gtk_dialog_run (GTK_DIALOG (editor)) == GTK_RESPONSE_OK)
- rule_context_save (context, filename);
-
- gtk_widget_destroy (GTK_WIDGET (editor));
+ e_shell_content_run_edit_searches_dialog (shell_content);
+ e_shell_window_update_search_menu (shell_window);
}
static void
-action_search_execute_cb (GtkAction *action,
+action_search_options_cb (GtkAction *action,
EShellWindow *shell_window)
{
- gtk_action_set_sensitive (action, FALSE);
+ EShellView *shell_view;
+ EShellViewClass *shell_view_class;
+ const gchar *view_name;
+ const gchar *widget_path;
+
+ view_name = e_shell_window_get_active_view (shell_window);
+ shell_view = e_shell_window_get_view (shell_window, view_name);
+ shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view);
+
+ widget_path = shell_view_class->search_options_path;
+ e_shell_window_show_popup_menu (shell_window, widget_path, NULL);
}
static void
action_search_save_cb (GtkAction *action,
EShellWindow *shell_window)
{
+ EShellView *shell_view;
+ EShellContent *shell_content;
+ const gchar *view_name;
+
+ view_name = e_shell_window_get_active_view (shell_window);
+ shell_view = e_shell_window_get_view (shell_window, view_name);
+ shell_content = e_shell_view_get_shell_content (shell_view);
+
+ e_shell_content_run_save_search_dialog (shell_content);
+ e_shell_window_update_search_menu (shell_window);
}
static void
@@ -1172,7 +1215,14 @@ static GtkActionEntry shell_entries[] = {
N_("_Find Now"),
NULL,
N_("Execute the current search parameters"),
- G_CALLBACK (action_search_execute_cb) },
+ NULL }, /* Handled by EShellContent and subclasses. */
+
+ { "search-options",
+ GTK_STOCK_FIND,
+ NULL,
+ NULL,
+ N_("Click here to change the search type"),
+ G_CALLBACK (action_search_options_cb) },
{ "search-save",
NULL,
@@ -1507,6 +1557,11 @@ e_shell_window_actions_init (EShellWindow *shell_window)
gtk_action_group_set_translation_domain (action_group, domain);
gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
+ /* Custom Rule Actions (empty) */
+ action_group = shell_window->priv->custom_rule_actions;
+ gtk_action_group_set_translation_domain (action_group, domain);
+ gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
+
/* Switcher Actions (empty) */
action_group = shell_window->priv->switcher_actions;
gtk_action_group_set_translation_domain (action_group, domain);
@@ -1805,3 +1860,93 @@ e_shell_window_update_view_menu (EShellWindow *shell_window)
action = ACTION (GAL_SAVE_CUSTOM_VIEW);
gtk_action_set_visible (action, visible);
}
+
+void
+e_shell_window_update_search_menu (EShellWindow *shell_window)
+{
+ EShellContent *shell_content;
+ EShellView *shell_view;
+ EShellViewClass *shell_view_class;
+ RuleContext *context;
+ FilterRule *rule;
+ GtkUIManager *ui_manager;
+ GtkActionGroup *action_group;
+ GList *list, *iter;
+ const gchar *source;
+ const gchar *view_name;
+ gboolean sensitive;
+ guint merge_id;
+ gint ii = 0;
+
+ ui_manager = e_shell_window_get_ui_manager (shell_window);
+ view_name = e_shell_window_get_active_view (shell_window);
+ shell_view = e_shell_window_get_view (shell_window, view_name);
+ shell_content = e_shell_view_get_shell_content (shell_view);
+ context = e_shell_content_get_search_context (shell_content);
+ shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view);
+ source = FILTER_SOURCE_INCOMING;
+
+ /* Update sensitivity of search actions. */
+
+ sensitive = (e_shell_content_get_search_rule (shell_content) != NULL);
+ gtk_action_set_sensitive (ACTION (SEARCH_CLEAR), sensitive);
+ gtk_action_set_sensitive (ACTION (SEARCH_SAVE), sensitive);
+
+ sensitive = (shell_view_class->search_options_path != NULL);
+ gtk_action_set_sensitive (ACTION (SEARCH_OPTIONS), sensitive);
+
+ /* Add custom rules to the Search menu. */
+
+ action_group = shell_window->priv->custom_rule_actions;
+ merge_id = shell_window->priv->custom_rule_merge_id;
+
+ /* Unmerge the previous menu. */
+ gtk_ui_manager_remove_ui (ui_manager, merge_id);
+
+ /* XXX Annoying that GTK+ doesn't provide a function for this.
+ * http://bugzilla.gnome.org/show_bug.cgi?id=550485 */
+ list = gtk_action_group_list_actions (action_group);
+ for (iter = list; iter != NULL; iter = iter->next)
+ gtk_action_group_remove_action (action_group, iter->data);
+ g_list_free (list);
+
+ rule = rule_context_next_rule (context, NULL, source);
+ while (rule != NULL) {
+ GtkAction *action;
+ gchar *action_name;
+ gchar *action_label;
+
+ action_name = g_strdup_printf ("custom-rule-%d", ii++);
+ if (ii < 10)
+ action_label = g_strdup_printf (
+ "_%d. %s", ii, rule->name);
+ else
+ action_label = g_strdup (rule->name);
+
+ action = gtk_action_new (
+ action_name, action_label,
+ _("Execute these search parameters"), NULL);
+
+ g_object_set_data_full (
+ G_OBJECT (action),
+ "rule", g_object_ref (rule),
+ (GDestroyNotify) g_object_unref);
+
+ g_signal_connect (
+ action, "activate",
+ G_CALLBACK (action_custom_rule_cb), shell_window);
+
+ gtk_action_group_add_action (action_group, action);
+
+ gtk_ui_manager_add_ui (
+ ui_manager, merge_id,
+ "/main-menu/search-menu/custom-rules",
+ action_name, action_name,
+ GTK_UI_MANAGER_AUTO, FALSE);
+
+ g_free (action_name);
+ g_free (action_label);
+
+ rule = rule_context_next_rule (context, rule, source);
+ }
+}
diff --git a/shell/e-shell-window-actions.h b/shell/e-shell-window-actions.h
index 2e3595f0f7..858c8541ce 100644
--- a/shell/e-shell-window-actions.h
+++ b/shell/e-shell-window-actions.h
@@ -64,6 +64,8 @@
E_SHELL_WINDOW_ACTION ((window), "search-edit")
#define E_SHELL_WINDOW_ACTION_SEARCH_EXECUTE(window) \
E_SHELL_WINDOW_ACTION ((window), "search-execute")
+#define E_SHELL_WINDOW_ACTION_SEARCH_OPTIONS(window) \
+ E_SHELL_WINDOW_ACTION ((window), "search-options")
#define E_SHELL_WINDOW_ACTION_SEARCH_SAVE(window) \
E_SHELL_WINDOW_ACTION ((window), "search-save")
#define E_SHELL_WINDOW_ACTION_SEND_RECEIVE(window) \
@@ -88,6 +90,8 @@
E_SHELL_WINDOW_ACTION ((window), "work-online")
/* Action Groups */
+#define E_SHELL_WINDOW_ACTION_GROUP_CUSTOM_RULES(window) \
+ E_SHELL_WINDOW_ACTION_GROUP ((window), "custom-rules")
#define E_SHELL_WINDOW_ACTION_GROUP_GAL_VIEW(window) \
E_SHELL_WINDOW_ACTION_GROUP ((window), "gal-view")
#define E_SHELL_WINDOW_ACTION_GROUP_NEW_ITEM(window) \
diff --git a/shell/e-shell-window-private.c b/shell/e-shell-window-private.c
index 8bfdefc536..782616cea4 100644
--- a/shell/e-shell-window-private.c
+++ b/shell/e-shell-window-private.c
@@ -191,11 +191,15 @@ e_shell_window_private_init (EShellWindow *shell_window)
priv->gal_view_actions = gtk_action_group_new ("gal-view");
priv->new_item_actions = gtk_action_group_new ("new-item");
priv->new_source_actions = gtk_action_group_new ("new-source");
+ priv->custom_rule_actions = gtk_action_group_new ("custom-rules");
priv->switcher_actions = gtk_action_group_new ("switcher");
priv->loaded_views = loaded_views;
priv->active_view = "unknown";
merge_id = gtk_ui_manager_new_merge_id (priv->ui_manager);
+ priv->custom_rule_merge_id = merge_id;
+
+ merge_id = gtk_ui_manager_new_merge_id (priv->ui_manager);
priv->gal_view_merge_id = merge_id;
e_shell_window_actions_init (shell_window);
@@ -369,6 +373,7 @@ e_shell_window_private_dispose (EShellWindow *shell_window)
DISPOSE (priv->gal_view_actions);
DISPOSE (priv->new_item_actions);
DISPOSE (priv->new_source_actions);
+ DISPOSE (priv->custom_rule_actions);
DISPOSE (priv->switcher_actions);
g_hash_table_remove_all (priv->loaded_views);
@@ -426,6 +431,7 @@ e_shell_window_switch_to_view (EShellWindow *shell_window,
e_shell_window_update_title (shell_window);
e_shell_window_update_new_menu (shell_window);
e_shell_window_update_view_menu (shell_window);
+ e_shell_window_update_search_menu (shell_window);
/* Notify all loaded views. */
list = g_hash_table_get_values (shell_window->priv->loaded_views);
diff --git a/shell/e-shell-window-private.h b/shell/e-shell-window-private.h
index e496a9834e..ed784b2ac7 100644
--- a/shell/e-shell-window-private.h
+++ b/shell/e-shell-window-private.h
@@ -28,7 +28,6 @@
#include <e-util/e-util.h>
#include <e-util/gconf-bridge.h>
-#include <filter/rule-editor.h>
#include <widgets/misc/e-menu-tool-button.h>
#include <widgets/misc/e-online-button.h>
#include <widgets/misc/e-search-bar.h>
@@ -73,7 +72,9 @@ struct _EShellWindowPrivate {
GtkActionGroup *gal_view_actions;
GtkActionGroup *new_item_actions;
GtkActionGroup *new_source_actions;
+ GtkActionGroup *custom_rule_actions;
GtkActionGroup *switcher_actions;
+ guint custom_rule_merge_id;
guint gal_view_merge_id;
/*** Shell Views ***/
@@ -118,6 +119,8 @@ void e_shell_window_update_icon (EShellWindow *shell_window);
void e_shell_window_update_title (EShellWindow *shell_window);
void e_shell_window_update_new_menu (EShellWindow *shell_window);
void e_shell_window_update_view_menu (EShellWindow *shell_window);
+void e_shell_window_update_search_menu
+ (EShellWindow *shell_window);
G_END_DECLS