diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2009-12-19 07:23:48 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2009-12-19 11:38:00 +0800 |
commit | 4cbbdedf522a6ac10df93a128bbf25f67173d66e (patch) | |
tree | fab7bf95e0927e4fa98c58a659e310afff7153ee /shell/e-shell-content.c | |
parent | a1efb837566cdac798cd8777dd34e06e9782cf61 (diff) | |
download | gsoc2013-evolution-4cbbdedf522a6ac10df93a128bbf25f67173d66e.tar.gz gsoc2013-evolution-4cbbdedf522a6ac10df93a128bbf25f67173d66e.tar.zst gsoc2013-evolution-4cbbdedf522a6ac10df93a128bbf25f67173d66e.zip |
Refactor the EShell search API.
Move the search interface to a new widget: EShellSearchbar
The current search rule is now stored in EShellView, and the search
context in EShellViewClass similar to GalViewCollection (since it's
class-specific, not instance-specific).
Also add a couple new signals to EShellView: "clear-search" and
"custom-search" ("custom" refers to an advanced search or a saved
search -- something more complex than a quick search).
Still working out a few kinks. The search entry is clearly trying to
be too many things. We need a different way of indicating that you're
looking at search results. Perhaps a search results banner similar to
Nautilus.
Diffstat (limited to 'shell/e-shell-content.c')
-rw-r--r-- | shell/e-shell-content.c | 1334 |
1 files changed, 127 insertions, 1207 deletions
diff --git a/shell/e-shell-content.c b/shell/e-shell-content.c index 6a883d5230..bc24b22222 100644 --- a/shell/e-shell-content.c +++ b/shell/e-shell-content.c @@ -31,6 +31,7 @@ #include "widgets/misc/e-hinted-entry.h" #include "e-shell-backend.h" +#include "e-shell-searchbar.h" #include "e-shell-view.h" #include "e-shell-window-actions.h" @@ -38,46 +39,18 @@ (G_TYPE_INSTANCE_GET_PRIVATE \ ((obj), E_TYPE_SHELL_CONTENT, EShellContentPrivate)) -#define STATE_KEY_SEARCH_FILTER "SearchFilter" -#define STATE_KEY_SEARCH_SCOPE "SearchScope" -#define STATE_KEY_SEARCH_TEXT "SearchText" - struct _EShellContentPrivate { gpointer shell_view; /* weak pointer */ - ERuleContext *search_context; - EFilterRule *search_rule; - gchar *system_filename; - gchar *user_filename; - - GtkWidget *search_bar; + GtkWidget *searchbar; - /* Search bar children (not referenced) */ - GtkWidget *filter_combo_box; - GtkWidget *search_entry; - GtkWidget *scope_combo_box; - GtkRadioAction *search_radio; /* to be able to manage radio here */ - - guint filter_visible : 1; - guint search_visible : 1; - guint scope_visible : 1; + /* Custom search rules. */ + gchar *user_filename; }; enum { PROP_0, - PROP_FILTER_ACTION, - PROP_FILTER_VALUE, - PROP_FILTER_VISIBLE, - PROP_SEARCH_CONTEXT, - PROP_SEARCH_HINT, - PROP_SEARCH_RULE, - PROP_SEARCH_TEXT, - PROP_SEARCH_VISIBLE, - PROP_SCOPE_ACTION, - PROP_SCOPE_VALUE, - PROP_SCOPE_VISIBLE, - PROP_SEARCH_RADIO_ACTION, PROP_SHELL_VIEW }; @@ -98,269 +71,6 @@ shell_content_dialog_rule_changed (GtkWidget *dialog, } static void -shell_content_update_search_widgets (EShellContent *shell_content) -{ - EShellView *shell_view; - EShellWindow *shell_window; - GtkAction *action; - GtkWidget *widget; - const gchar *search_text; - gboolean sensitive; - - 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. */ - - widget = shell_content->priv->search_entry; - shell_window = e_shell_view_get_shell_window (shell_view); - search_text = e_shell_content_get_search_text (shell_content); - - sensitive = - (search_text != NULL && *search_text != '\0') || - (e_shell_content_get_search_rule (shell_content) != NULL); - - if (sensitive) { - GtkStyle *style; - const GdkColor *fg_color, *bg_color; - - style = gtk_widget_get_style (widget); - fg_color = &style->text[(search_text != NULL && *search_text != '\0') ? GTK_STATE_SELECTED : GTK_STATE_INSENSITIVE]; - bg_color = &style->mid[GTK_STATE_SELECTED]; - - if (gdk_color_equal (fg_color, bg_color)) - bg_color = &style->base[GTK_STATE_SELECTED]; - - gtk_widget_modify_base (widget, GTK_STATE_NORMAL, bg_color); - gtk_widget_modify_text (widget, GTK_STATE_NORMAL, fg_color); - } else { - /* Text color will be updated when we move the focus. */ - gtk_widget_modify_base (widget, GTK_STATE_NORMAL, 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, 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. - * This will reset the entry to the appropriate visual state. */ - widget = gtk_bin_get_child (GTK_BIN (shell_content)); - if (GTK_IS_PANED (widget)) - widget = gtk_paned_get_child1 (GTK_PANED (widget)); - gtk_widget_grab_focus (widget); -} - -static void -shell_content_entry_activate_cb (EShellContent *shell_content, - GtkEntry *entry) -{ - EShellView *shell_view; - EShellWindow *shell_window; - GtkAction *action; - const gchar *text; - - shell_view = e_shell_content_get_shell_view (shell_content); - shell_window = e_shell_view_get_shell_window (shell_view); - - text = gtk_entry_get_text (entry); - if (text && *text) - action = E_SHELL_WINDOW_ACTION_SEARCH_QUICK (shell_window); - else - action = E_SHELL_WINDOW_ACTION_SEARCH_CLEAR (shell_window); - - gtk_action_activate (action); -} - -static void -shell_content_entry_changed_cb (EShellContent *shell_content, - GtkEntry *entry) -{ - EShellView *shell_view; - EShellWindow *shell_window; - GtkAction *action; - const gchar *text; - gboolean sensitive; - - shell_view = e_shell_content_get_shell_view (shell_content); - shell_window = e_shell_view_get_shell_window (shell_view); - - text = gtk_entry_get_text (entry); - sensitive = (text != NULL && *text != '\0' && !e_hinted_entry_get_hint_shown (E_HINTED_ENTRY (entry))); - - action = E_SHELL_WINDOW_ACTION_SEARCH_QUICK (shell_window); - gtk_action_set_sensitive (action, sensitive); -} - -static void -shell_content_entry_icon_press_cb (EShellContent *shell_content, - GtkEntryIconPosition icon_pos, - GdkEvent *event) -{ - EShellView *shell_view; - EShellWindow *shell_window; - GtkAction *action; - - /* Show the search options menu when the icon is pressed. */ - - if (icon_pos != GTK_ENTRY_ICON_PRIMARY) - return; - - 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); -} - -static void -shell_content_entry_icon_release_cb (EShellContent *shell_content, - GtkEntryIconPosition icon_pos, - GdkEvent *event) -{ - EShellView *shell_view; - EShellWindow *shell_window; - GtkAction *action; - - /* Clear the search when the icon is pressed and released. */ - - if (icon_pos != GTK_ENTRY_ICON_SECONDARY) - return; - - 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_CLEAR (shell_window); - gtk_action_activate (action); -} - -static gboolean -shell_content_entry_key_press_cb (EShellContent *shell_content, - GdkEventKey *key_event, - GtkWidget *entry) -{ - 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 -shell_content_init_search_context (EShellContent *shell_content) -{ - EShellContentClass *shell_content_class; - EShellView *shell_view; - EShellViewClass *shell_view_class; - EShellBackend *shell_backend; - ERuleContext *context; - EFilterRule *rule; - EFilterPart *part; - gchar *system_filename; - gchar *user_filename; - - shell_view = e_shell_content_get_shell_view (shell_content); - shell_backend = e_shell_view_get_shell_backend (shell_view); - shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); - g_return_if_fail (shell_view_class->search_rules != NULL); - - shell_content_class = E_SHELL_CONTENT_GET_CLASS (shell_content); - g_return_if_fail (shell_content_class->new_search_context != NULL); - - /* The basename for built-in searches is specified in the - * shell view class. All built-in search rules live in the - * same directory. */ - system_filename = g_build_filename ( - EVOLUTION_RULEDIR, shell_view_class->search_rules, NULL); - - /* The filename for custom saved searches is always of - * the form "$(shell_backend_data_dir)/searches.xml". */ - user_filename = g_build_filename ( - e_shell_backend_get_data_dir (shell_backend), - "searches.xml", NULL); - - context = shell_content_class->new_search_context (); - e_rule_context_add_part_set ( - context, "partset", E_TYPE_FILTER_PART, - e_rule_context_add_part, e_rule_context_next_part); - e_rule_context_add_rule_set ( - context, "ruleset", E_TYPE_FILTER_RULE, - e_rule_context_add_rule, e_rule_context_next_rule); - e_rule_context_load (context, system_filename, user_filename); - - /* XXX Not sure why this is necessary. */ - g_object_set_data_full ( - G_OBJECT (context), "system", - g_strdup (system_filename), g_free); - g_object_set_data_full ( - G_OBJECT (context), "user", - g_strdup (user_filename), g_free); - - rule = e_filter_rule_new (); - part = e_rule_context_next_part (context, NULL); - if (part == NULL) - g_warning ( - "Could not load %s search: no parts", - e_shell_view_get_name (shell_view)); - else - e_filter_rule_add_part (rule, e_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 -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) { @@ -380,72 +90,6 @@ shell_content_set_property (GObject *object, GParamSpec *pspec) { switch (property_id) { - case PROP_FILTER_ACTION: - e_shell_content_set_filter_action ( - E_SHELL_CONTENT (object), - g_value_get_object (value)); - return; - - case PROP_FILTER_VALUE: - e_shell_content_set_filter_value ( - E_SHELL_CONTENT (object), - g_value_get_int (value)); - return; - - case PROP_FILTER_VISIBLE: - e_shell_content_set_filter_visible ( - E_SHELL_CONTENT (object), - g_value_get_boolean (value)); - return; - - case PROP_SEARCH_HINT: - e_shell_content_set_search_hint ( - E_SHELL_CONTENT (object), - g_value_get_string (value)); - return; - - case PROP_SEARCH_RULE: - e_shell_content_set_search_rule ( - E_SHELL_CONTENT (object), - g_value_get_object (value)); - return; - - case PROP_SEARCH_TEXT: - e_shell_content_set_search_text ( - E_SHELL_CONTENT (object), - g_value_get_string (value)); - return; - - case PROP_SEARCH_VISIBLE: - e_shell_content_set_search_visible ( - E_SHELL_CONTENT (object), - g_value_get_boolean (value)); - return; - - case PROP_SCOPE_ACTION: - e_shell_content_set_scope_action ( - E_SHELL_CONTENT (object), - g_value_get_object (value)); - return; - - case PROP_SCOPE_VALUE: - e_shell_content_set_scope_value ( - E_SHELL_CONTENT (object), - g_value_get_int (value)); - return; - - case PROP_SCOPE_VISIBLE: - e_shell_content_set_scope_visible ( - E_SHELL_CONTENT (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), @@ -463,78 +107,6 @@ shell_content_get_property (GObject *object, GParamSpec *pspec) { switch (property_id) { - case PROP_FILTER_ACTION: - g_value_set_object ( - value, e_shell_content_get_filter_action ( - E_SHELL_CONTENT (object))); - return; - - case PROP_FILTER_VALUE: - g_value_set_int ( - value, e_shell_content_get_filter_value ( - E_SHELL_CONTENT (object))); - return; - - case PROP_FILTER_VISIBLE: - g_value_set_boolean ( - value, e_shell_content_get_filter_visible ( - E_SHELL_CONTENT (object))); - return; - - case PROP_SEARCH_CONTEXT: - g_value_set_object ( - value, e_shell_content_get_search_context ( - E_SHELL_CONTENT (object))); - return; - - case PROP_SEARCH_HINT: - g_value_set_string ( - value, e_shell_content_get_search_hint ( - E_SHELL_CONTENT (object))); - return; - - case PROP_SEARCH_RULE: - g_value_set_object ( - value, e_shell_content_get_search_rule ( - E_SHELL_CONTENT (object))); - return; - - case PROP_SEARCH_TEXT: - g_value_set_string ( - value, e_shell_content_get_search_text ( - E_SHELL_CONTENT (object))); - return; - - case PROP_SEARCH_VISIBLE: - g_value_set_boolean ( - value, e_shell_content_get_search_visible ( - E_SHELL_CONTENT (object))); - return; - - case PROP_SCOPE_ACTION: - g_value_set_object ( - value, e_shell_content_get_scope_action ( - E_SHELL_CONTENT (object))); - return; - - case PROP_SCOPE_VALUE: - g_value_set_int ( - value, e_shell_content_get_scope_value ( - E_SHELL_CONTENT (object))); - return; - - case PROP_SCOPE_VISIBLE: - g_value_set_boolean ( - value, e_shell_content_get_scope_visible ( - 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 ( @@ -558,85 +130,42 @@ shell_content_dispose (GObject *object) priv->shell_view = NULL; } - if (priv->search_context != NULL) { - g_object_unref (priv->search_context); - priv->search_context = NULL; - } - - if (priv->search_radio) { - g_signal_handlers_disconnect_matched ( - priv->search_radio, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, object); - g_object_unref (priv->search_radio); - priv->search_radio = 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; + EShellContentClass *class; EShellContent *shell_content; - GtkSizeGroup *size_group; - GtkAction *action; + EShellBackend *shell_backend; + EShellView *shell_view; GtkWidget *widget; + const gchar *data_dir; 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); - size_group = e_shell_view_get_size_group (shell_view); - - g_signal_connect_after ( - shell_view, "execute-search", - G_CALLBACK (shell_content_execute_search_cb), - shell_content); - - widget = shell_content->priv->search_entry; - - action = E_SHELL_WINDOW_ACTION_SEARCH_CLEAR (shell_window); - e_binding_new ( - action, "sensitive", - widget, "secondary-icon-sensitive"); - e_binding_new ( - action, "stock-id", - widget, "secondary-icon-stock"); - e_binding_new ( - action, "tooltip", - widget, "secondary-icon-tooltip-text"); - - action = E_SHELL_WINDOW_ACTION_SEARCH_OPTIONS (shell_window); - e_binding_new ( - action, "sensitive", - widget, "primary-icon-sensitive"); - e_binding_new ( - action, "stock-id", - widget, "primary-icon-stock"); - e_binding_new ( - action, "tooltip", - widget, "primary-icon-tooltip-text"); - - widget = shell_content->priv->search_bar; - gtk_size_group_add_widget (size_group, widget); - - shell_content_init_search_context (shell_content); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + /* XXX Regenerate the filename for custom saved search as done + * in shell_view_init_search_context(). ERuleContext ought + * to remember the filename when loading rules so you don't + * have to keep passing it in when saving rules. */ + data_dir = e_shell_backend_get_data_dir (shell_backend); + shell_content->priv->user_filename = + g_build_filename (data_dir, "searches.xml", NULL); + + class = E_SHELL_CONTENT_GET_CLASS (shell_content); + if (class->construct_searchbar != NULL) + widget = class->construct_searchbar (shell_content); + else + widget = NULL; + if (widget != NULL) { + gtk_widget_set_parent (widget, GTK_WIDGET (shell_content)); + shell_content->priv->searchbar = g_object_ref (widget); + gtk_widget_show (widget); + } } static void @@ -649,11 +178,11 @@ shell_content_destroy (GtkObject *gtk_object) /* Unparent the widget before destroying it to avoid * writing a custom GtkContainer::remove() method. */ - if (priv->search_bar != NULL) { - gtk_widget_unparent (priv->search_bar); - gtk_widget_destroy (priv->search_bar); - g_object_unref (priv->search_bar); - priv->search_bar = NULL; + if (priv->searchbar != NULL) { + gtk_widget_unparent (priv->searchbar); + gtk_widget_destroy (priv->searchbar); + g_object_unref (priv->searchbar); + priv->searchbar = NULL; } /* Chain up to parent's destroy() method. */ @@ -676,8 +205,10 @@ shell_content_size_request (GtkWidget *widget, child = gtk_bin_get_child (GTK_BIN (widget)); gtk_widget_size_request (child, requisition); - child = priv->search_bar; - gtk_widget_size_request (child, &child_requisition); + if (priv->searchbar == NULL) + return; + + gtk_widget_size_request (priv->searchbar, &child_requisition); requisition->width = MAX (requisition->width, child_requisition.width); requisition->height += child_requisition.height; } @@ -695,15 +226,20 @@ shell_content_size_allocate (GtkWidget *widget, widget->allocation = *allocation; - child = priv->search_bar; - gtk_widget_size_request (child, &child_requisition); + child = priv->searchbar; + + if (child == NULL) + child_requisition.height = 0; + else + gtk_widget_size_request (child, &child_requisition); child_allocation.x = allocation->x; child_allocation.y = allocation->y; child_allocation.width = allocation->width; child_allocation.height = child_requisition.height; - gtk_widget_size_allocate (child, &child_allocation); + if (child != NULL) + gtk_widget_size_allocate (child, &child_allocation); child_allocation.y += child_requisition.height; child_allocation.height = @@ -724,14 +260,46 @@ shell_content_forall (GtkContainer *container, priv = E_SHELL_CONTENT_GET_PRIVATE (container); - if (include_internals) - callback (priv->search_bar, callback_data); + if (include_internals && priv->searchbar != NULL) + callback (priv->searchbar, callback_data); /* Chain up to parent's forall() method. */ GTK_CONTAINER_CLASS (parent_class)->forall ( container, include_internals, callback, callback_data); } +static gchar * +shell_content_get_search_name (EShellContent *shell_content) +{ + EShellSearchbar *searchbar; + EShellView *shell_view; + EFilterRule *rule; + const gchar *search_text; + + shell_view = e_shell_content_get_shell_view (shell_content); + + rule = e_shell_view_get_search_rule (shell_view); + g_return_val_if_fail (E_IS_FILTER_RULE (rule), NULL); + + searchbar = E_SHELL_SEARCHBAR (shell_content->priv->searchbar); + search_text = e_shell_searchbar_get_search_text (searchbar); + + if (search_text == NULL || *search_text == '\0') + search_text = "''"; + + return g_strdup_printf ("%s %s", rule->name, search_text); +} + +static GtkWidget * +shell_content_construct_searchbar (EShellContent *shell_content) +{ + EShellView *shell_view; + + shell_view = e_shell_content_get_shell_view (shell_content); + + return e_shell_searchbar_new (shell_view); +} + static void shell_content_class_init (EShellContentClass *class) { @@ -747,7 +315,6 @@ 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; gtk_object_class = GTK_OBJECT_CLASS (class); @@ -760,134 +327,8 @@ shell_content_class_init (EShellContentClass *class) container_class = GTK_CONTAINER_CLASS (class); container_class->forall = shell_content_forall; - class->new_search_context = e_rule_context_new; - - g_object_class_install_property ( - object_class, - PROP_FILTER_ACTION, - g_param_spec_object ( - "filter-action", - NULL, - NULL, - GTK_TYPE_RADIO_ACTION, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_FILTER_VALUE, - g_param_spec_int ( - "filter-value", - NULL, - NULL, - G_MININT, - G_MAXINT, - 0, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_FILTER_VISIBLE, - g_param_spec_boolean ( - "filter-visible", - NULL, - NULL, - TRUE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property ( - object_class, - PROP_SEARCH_CONTEXT, - g_param_spec_object ( - "search-context", - NULL, - NULL, - E_TYPE_RULE_CONTEXT, - G_PARAM_READABLE)); - - g_object_class_install_property ( - object_class, - PROP_SEARCH_HINT, - g_param_spec_string ( - "search-hint", - NULL, - NULL, - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_SEARCH_RULE, - g_param_spec_object ( - "search-rule", - NULL, - NULL, - E_TYPE_FILTER_RULE, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_SEARCH_TEXT, - g_param_spec_string ( - "search-text", - NULL, - NULL, - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_SEARCH_VISIBLE, - g_param_spec_boolean ( - "search-visible", - NULL, - NULL, - TRUE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property ( - object_class, - PROP_SCOPE_ACTION, - g_param_spec_object ( - "scope-action", - NULL, - NULL, - GTK_TYPE_RADIO_ACTION, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_SCOPE_VALUE, - g_param_spec_int ( - "scope-value", - NULL, - NULL, - G_MININT, - G_MAXINT, - 0, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_SCOPE_VISIBLE, - g_param_spec_boolean ( - "scope-visible", - NULL, - NULL, - FALSE, - 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)); + class->get_search_name = shell_content_get_search_name; + class->construct_searchbar = shell_content_construct_searchbar; /** * EShellContent:shell-view @@ -909,128 +350,9 @@ shell_content_class_init (EShellContentClass *class) static void shell_content_init (EShellContent *shell_content) { - GtkBox *box; - GtkLabel *label; - GtkWidget *widget; - shell_content->priv = E_SHELL_CONTENT_GET_PRIVATE (shell_content); GTK_WIDGET_SET_FLAGS (shell_content, GTK_NO_WINDOW); - - /*** Build the Search Bar ***/ - - widget = gtk_hbox_new (FALSE, 24); - gtk_widget_set_parent (widget, GTK_WIDGET (shell_content)); - shell_content->priv->search_bar = g_object_ref (widget); - gtk_widget_show (widget); - - /* Filter Combo Widgets */ - - box = GTK_BOX (shell_content->priv->search_bar); - - widget = gtk_hbox_new (FALSE, 3); - gtk_box_pack_start (box, widget, FALSE, FALSE, 0); - - e_binding_new ( - shell_content, "filter-visible", - widget, "visible"); - - box = GTK_BOX (widget); - - /* Translators: The "Show:" label precedes a combo box that - * allows the user to filter the current view. Examples of - * items that appear in the combo box are "Unread Messages", - * "Important Messages", or "Active Appointments". */ - widget = gtk_label_new_with_mnemonic (_("Sho_w:")); - gtk_box_pack_start (box, widget, FALSE, FALSE, 0); - gtk_widget_show (widget); - - label = GTK_LABEL (widget); - - widget = e_action_combo_box_new (); - gtk_label_set_mnemonic_widget (label, widget); - gtk_box_pack_start (box, widget, FALSE, FALSE, 0); - shell_content->priv->filter_combo_box = widget; - gtk_widget_show (widget); - - /* Search Entry Widgets */ - - box = GTK_BOX (shell_content->priv->search_bar); - - widget = gtk_hbox_new (FALSE, 3); - gtk_box_pack_start (box, widget, TRUE, TRUE, 0); - - e_binding_new ( - shell_content, "search-visible", - widget, "visible"); - - box = GTK_BOX (widget); - - /* Translators: This is part of the quick search interface. - * example: Search: [_______________] in [ Current Folder ] */ - widget = gtk_label_new_with_mnemonic (_("Sear_ch:")); - gtk_box_pack_start (box, widget, FALSE, FALSE, 0); - gtk_widget_show (widget); - - label = GTK_LABEL (widget); - - widget = e_hinted_entry_new (); - gtk_label_set_mnemonic_widget (label, widget); - gtk_box_pack_start (box, widget, TRUE, TRUE, 0); - shell_content->priv->search_entry = widget; - gtk_widget_show (widget); - - g_signal_connect_swapped ( - widget, "activate", - G_CALLBACK (shell_content_entry_activate_cb), - shell_content); - - g_signal_connect_swapped ( - widget, "changed", - G_CALLBACK (shell_content_entry_changed_cb), - shell_content); - - g_signal_connect_swapped ( - widget, "icon-press", - G_CALLBACK (shell_content_entry_icon_press_cb), - shell_content); - - g_signal_connect_swapped ( - widget, "icon-release", - G_CALLBACK (shell_content_entry_icon_release_cb), - shell_content); - - g_signal_connect_swapped ( - widget, "key-press-event", - G_CALLBACK (shell_content_entry_key_press_cb), - shell_content); - - /* Scope Combo Widgets */ - - box = GTK_BOX (shell_content->priv->search_bar); - - widget = gtk_hbox_new (FALSE, 3); - gtk_box_pack_start (box, widget, FALSE, FALSE, 0); - - e_binding_new ( - shell_content, "scope-visible", - widget, "visible"); - - box = GTK_BOX (widget); - - /* Translators: This is part of the quick search interface. - * example: Search: [_______________] in [ Current Folder ] */ - widget = gtk_label_new_with_mnemonic (_("i_n")); - gtk_box_pack_start (box, widget, FALSE, FALSE, 0); - gtk_widget_show (widget); - - label = GTK_LABEL (widget); - - widget = e_action_combo_box_new (); - gtk_label_set_mnemonic_widget (label, widget); - gtk_box_pack_start (box, widget, FALSE, FALSE, 0); - shell_content->priv->scope_combo_box = widget; - gtk_widget_show (widget); } GType @@ -1077,6 +399,24 @@ e_shell_content_new (EShellView *shell_view) } /** + * e_shell_content_get_searchbar: + * @shell_view: an #EShellView + * + * Returns the search bar widget returned by the + * <structfield>construct_searchbar</structfield> method in + * #EShellContentClass. + * + * Returns: the search bar widget + **/ +GtkWidget * +e_shell_content_get_searchbar (EShellContent *shell_content) +{ + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); + + return shell_content->priv->searchbar; +} + +/** * e_shell_content_check_state: * @shell_content: an #EShellContent * @@ -1118,371 +458,27 @@ e_shell_content_get_shell_view (EShellContent *shell_content) return E_SHELL_VIEW (shell_content->priv->shell_view); } -GtkRadioAction * -e_shell_content_get_filter_action (EShellContent *shell_content) -{ - EActionComboBox *combo_box; - - g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); - - combo_box = E_ACTION_COMBO_BOX (shell_content->priv->filter_combo_box); - - return e_action_combo_box_get_action (combo_box); -} - -void -e_shell_content_set_filter_action (EShellContent *shell_content, - GtkRadioAction *filter_action) -{ - EActionComboBox *combo_box; - - g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); - - combo_box = E_ACTION_COMBO_BOX (shell_content->priv->filter_combo_box); - - e_action_combo_box_set_action (combo_box, filter_action); - - g_object_notify (G_OBJECT (shell_content), "filter-action"); -} - -gint -e_shell_content_get_filter_value (EShellContent *shell_content) -{ - EActionComboBox *combo_box; - - g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), 0); - - combo_box = E_ACTION_COMBO_BOX (shell_content->priv->filter_combo_box); - - return e_action_combo_box_get_current_value (combo_box); -} - -void -e_shell_content_set_filter_value (EShellContent *shell_content, - gint filter_value) -{ - EActionComboBox *combo_box; - - g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); - - combo_box = E_ACTION_COMBO_BOX (shell_content->priv->filter_combo_box); - - e_action_combo_box_set_current_value (combo_box, filter_value); - - g_object_notify (G_OBJECT (shell_content), "filter-value"); -} - -gboolean -e_shell_content_get_filter_visible (EShellContent *shell_content) -{ - g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), FALSE); - - return shell_content->priv->filter_visible; -} - -void -e_shell_content_set_filter_visible (EShellContent *shell_content, - gboolean filter_visible) -{ - g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); - - shell_content->priv->filter_visible = filter_visible; - - g_object_notify (G_OBJECT (shell_content), "filter-visible"); -} - -void -e_shell_content_add_filter_separator_before (EShellContent *shell_content, - gint action_value) -{ - EActionComboBox *combo_box; - - g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); - - combo_box = E_ACTION_COMBO_BOX (shell_content->priv->filter_combo_box); - - e_action_combo_box_add_separator_before (combo_box, action_value); -} - -void -e_shell_content_add_filter_separator_after (EShellContent *shell_content, - gint action_value) -{ - EActionComboBox *combo_box; - - g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); - - combo_box = E_ACTION_COMBO_BOX (shell_content->priv->filter_combo_box); - - e_action_combo_box_add_separator_after (combo_box, action_value); -} - -ERuleContext * -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; -} - -const gchar * -e_shell_content_get_search_hint (EShellContent *shell_content) -{ - EHintedEntry *entry; - - g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); - - entry = E_HINTED_ENTRY (shell_content->priv->search_entry); - - return e_hinted_entry_get_hint (entry); -} - -void -e_shell_content_set_search_hint (EShellContent *shell_content, - const gchar *search_hint) -{ - EHintedEntry *entry; - - g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); - - entry = E_HINTED_ENTRY (shell_content->priv->search_entry); - - e_hinted_entry_set_hint (entry, search_hint); - - g_object_notify (G_OBJECT (shell_content), "search-hint"); -} - -EFilterRule * -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_rule; -} - -void -e_shell_content_set_search_rule (EShellContent *shell_content, - EFilterRule *search_rule) -{ - g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); - - if (search_rule != NULL) { - g_return_if_fail (E_IS_FILTER_RULE (search_rule)); - g_object_ref (search_rule); - } - - if (shell_content->priv->search_rule != NULL) - g_object_unref (shell_content->priv->search_rule); - - 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 */ +/** + * e_shell_content_get_search_name: + * @shell_content: an #EShellContent + * + * Returns a newly-allocated string containing a suitable name for the + * current search criteria. This is used as the suggested name in the + * Save Search dialog. Free the returned string with g_free(). + * + * Returns: a name for the current search criteria + **/ gchar * -e_shell_content_get_search_rule_as_string (EShellContent *shell_content) +e_shell_content_get_search_name (EShellContent *shell_content) { - EFilterRule *rule; - GString *str; + EShellContentClass *class; 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); + class = E_SHELL_CONTENT_GET_CLASS (shell_content); + g_return_val_if_fail (class->get_search_name != NULL, NULL); - return g_string_free (str, FALSE); -} - -const gchar * -e_shell_content_get_search_text (EShellContent *shell_content) -{ - EHintedEntry *entry; - - g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); - - entry = E_HINTED_ENTRY (shell_content->priv->search_entry); - - return e_hinted_entry_get_text (entry); -} - -void -e_shell_content_set_search_text (EShellContent *shell_content, - const gchar *search_text) -{ - EHintedEntry *entry; - - g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); - - entry = E_HINTED_ENTRY (shell_content->priv->search_entry); - - e_hinted_entry_set_text (entry, search_text); - - shell_content_update_search_widgets (shell_content); - g_object_notify (G_OBJECT (shell_content), "search-text"); -} - -gboolean -e_shell_content_get_search_visible (EShellContent *shell_content) -{ - g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), FALSE); - - return shell_content->priv->search_visible; -} - -void -e_shell_content_set_search_visible (EShellContent *shell_content, - gboolean search_visible) -{ - g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); - - shell_content->priv->search_visible = search_visible; - - g_object_notify (G_OBJECT (shell_content), "search-visible"); -} - -GtkRadioAction * -e_shell_content_get_scope_action (EShellContent *shell_content) -{ - EActionComboBox *combo_box; - - g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); - - combo_box = E_ACTION_COMBO_BOX (shell_content->priv->scope_combo_box); - - return e_action_combo_box_get_action (combo_box); -} - -void -e_shell_content_set_scope_action (EShellContent *shell_content, - GtkRadioAction *scope_action) -{ - EActionComboBox *combo_box; - - g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); - - combo_box = E_ACTION_COMBO_BOX (shell_content->priv->scope_combo_box); - - e_action_combo_box_set_action (combo_box, scope_action); - - g_object_notify (G_OBJECT (shell_content), "scope-action"); -} - -gint -e_shell_content_get_scope_value (EShellContent *shell_content) -{ - EActionComboBox *combo_box; - - g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), 0); - - combo_box = E_ACTION_COMBO_BOX (shell_content->priv->scope_combo_box); - - return e_action_combo_box_get_current_value (combo_box); -} - -void -e_shell_content_set_scope_value (EShellContent *shell_content, - gint scope_value) -{ - EActionComboBox *combo_box; - - g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); - - combo_box = E_ACTION_COMBO_BOX (shell_content->priv->scope_combo_box); - - e_action_combo_box_set_current_value (combo_box, scope_value); - - g_object_notify (G_OBJECT (shell_content), "scope-value"); -} - -gboolean -e_shell_content_get_scope_visible (EShellContent *shell_content) -{ - g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), FALSE); - - return shell_content->priv->scope_visible; -} - -void -e_shell_content_set_scope_visible (EShellContent *shell_content, - gboolean scope_visible) -{ - g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); - - shell_content->priv->scope_visible = scope_visible; - - g_object_notify (G_OBJECT (shell_content), "scope-visible"); -} - -static void -search_radio_changed_cb (GtkRadioAction *action, - GtkRadioAction *current, - EShellContent *shell_content) -{ - EShellView *shell_view; - const gchar *search_text; - const gchar *label; - gint current_value; - - shell_view = e_shell_content_get_shell_view (shell_content); - - label = gtk_action_get_label (GTK_ACTION (current)); - e_shell_content_set_search_hint (shell_content, label); - - current_value = gtk_radio_action_get_current_value (current); - search_text = 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 != NULL && *search_text != '\0') - e_shell_view_execute_search (shell_view); - } else if (search_text != NULL) { - e_shell_content_set_search_text (shell_content, NULL); - } -} - -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 (search_action != NULL) { - g_return_if_fail (GTK_IS_RADIO_ACTION (search_action)); - g_object_ref (search_action); - } - - 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); - g_object_unref (shell_content->priv->search_radio); - } - - shell_content->priv->search_radio = search_action; - - if (shell_content->priv->search_radio != NULL) - 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; + return class->get_search_name (shell_content); } void @@ -1504,14 +500,14 @@ e_shell_content_run_advanced_search_dialog (EShellContent *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); + rule = e_shell_view_get_search_rule (shell_view); if (rule == NULL) rule = e_filter_rule_new (); else rule = e_filter_rule_clone (rule); - context = e_shell_content_get_search_context (shell_content); + context = E_SHELL_VIEW_GET_CLASS (shell_view)->search_context; widget = e_filter_rule_get_widget (rule, context); e_filter_rule_set_source (rule, E_FILTER_SOURCE_INCOMING); @@ -1548,10 +544,7 @@ run: goto run; } - e_shell_content_set_search_rule (shell_content, rule); - - shell_content_activate_advanced_search (shell_content); - e_shell_view_execute_search (shell_view); + e_shell_view_custom_search (shell_view, rule); if (response == GTK_RESPONSE_APPLY) { if (!e_rule_context_find_rule (context, rule->name, rule->source)) @@ -1568,13 +561,15 @@ exit: void e_shell_content_run_edit_searches_dialog (EShellContent *shell_content) { + EShellView *shell_view; ERuleContext *context; ERuleEditor *editor; const gchar *user_filename; g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); - context = e_shell_content_get_search_context (shell_content); + shell_view = e_shell_content_get_shell_view (shell_content); + context = E_SHELL_VIEW_GET_CLASS (shell_view)->search_context; user_filename = shell_content->priv->user_filename; editor = e_rule_editor_new ( @@ -1596,7 +591,6 @@ e_shell_content_run_save_search_dialog (EShellContent *shell_content) GtkWidget *widget; EFilterRule *rule; ERuleContext *context; - const gchar *search_text; const gchar *user_filename; gchar *search_name; gint response; @@ -1608,19 +602,15 @@ e_shell_content_run_save_search_dialog (EShellContent *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); + rule = e_shell_view_get_search_rule (shell_view); g_return_if_fail (E_IS_FILTER_RULE (rule)); rule = e_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); + search_name = e_shell_content_get_search_name (shell_content); e_filter_rule_set_name (rule, search_name); g_free (search_name); - context = e_shell_content_get_search_context (shell_content); + context = E_SHELL_VIEW_GET_CLASS (shell_view)->search_context; widget = e_filter_rule_get_widget (rule, context); e_filter_rule_set_source (rule, E_FILTER_SOURCE_INCOMING); @@ -1656,83 +646,13 @@ run: goto run; } - e_rule_context_add_rule (context, rule); + /* XXX This function steals the rule reference, so + * counteract that by referencing it again. */ + e_rule_context_add_rule (context, g_object_ref (rule)); + e_rule_context_save (context, user_filename); exit: g_object_unref (rule); gtk_widget_destroy (dialog); } - -void -e_shell_content_restore_state (EShellContent *shell_content, - const gchar *group_name) -{ - EShellView *shell_view; - EShellWindow *shell_window; - GKeyFile *key_file; - GtkAction *action; - GtkWidget *widget; - const gchar *search_text; - const gchar *key; - gchar *string; - - g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); - g_return_if_fail (group_name != NULL); - - shell_view = e_shell_content_get_shell_view (shell_content); - shell_window = e_shell_view_get_shell_window (shell_view); - key_file = e_shell_view_get_state_key_file (shell_view); - - /* Changing the combo boxes triggers searches, so block - * the search action until the state is fully restored. */ - action = E_SHELL_WINDOW_ACTION_SEARCH_QUICK (shell_window); - gtk_action_block_activate (action); - e_shell_view_block_execute_search (shell_view); - - key = STATE_KEY_SEARCH_FILTER; - string = g_key_file_get_string (key_file, group_name, key, NULL); - if (string != NULL && *string != '\0') - action = e_shell_window_get_action (shell_window, string); - else - action = NULL; - if (action != NULL) - gtk_action_activate (action); - else { - /* Pick the first combo box item. */ - widget = shell_content->priv->filter_combo_box; - gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0); - } - g_free (string); - - key = STATE_KEY_SEARCH_SCOPE; - string = g_key_file_get_string (key_file, group_name, key, NULL); - if (string != NULL && *string != '\0') - action = e_shell_window_get_action (shell_window, string); - else - action = NULL; - if (action != NULL) - gtk_action_activate (action); - else { - /* Pick the first combo box item. */ - widget = shell_content->priv->scope_combo_box; - gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0); - } - g_free (string); - - key = STATE_KEY_SEARCH_TEXT; - string = g_key_file_get_string (key_file, group_name, key, NULL); - search_text = e_shell_content_get_search_text (shell_content); - if (search_text != NULL && *search_text == '\0') - search_text = NULL; - if (g_strcmp0 (string, search_text) != 0) - e_shell_content_set_search_text (shell_content, string); - g_free (string); - - action = E_SHELL_WINDOW_ACTION_SEARCH_QUICK (shell_window); - gtk_action_unblock_activate (action); - e_shell_view_unblock_execute_search (shell_view); - - /* Now execute the search. */ - e_shell_view_execute_search (shell_view); -} |