diff options
author | Matthew Barnes <mbarnes@src.gnome.org> | 2008-09-23 05:03:28 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@src.gnome.org> | 2008-09-23 05:03:28 +0800 |
commit | 73c370019c4de89d4c901ee8c25cc0cbb55992fb (patch) | |
tree | 26609470a1148d3bd364cbce5d5ab2f41e0e23d4 /shell | |
parent | 6b2295c93a40f6010d94399666a8e099aded8e85 (diff) | |
download | gsoc2013-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.am | 2 | ||||
-rw-r--r-- | shell/e-shell-content.c | 411 | ||||
-rw-r--r-- | shell/e-shell-content.h | 17 | ||||
-rw-r--r-- | shell/e-shell-sidebar.h | 2 | ||||
-rw-r--r-- | shell/e-shell-switcher.h | 2 | ||||
-rw-r--r-- | shell/e-shell-view.h | 3 | ||||
-rw-r--r-- | shell/e-shell-window-actions.c | 193 | ||||
-rw-r--r-- | shell/e-shell-window-actions.h | 4 | ||||
-rw-r--r-- | shell/e-shell-window-private.c | 6 | ||||
-rw-r--r-- | shell/e-shell-window-private.h | 5 |
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 |