diff options
Diffstat (limited to 'shell/e-shell-searchbar.c')
-rw-r--r-- | shell/e-shell-searchbar.c | 263 |
1 files changed, 233 insertions, 30 deletions
diff --git a/shell/e-shell-searchbar.c b/shell/e-shell-searchbar.c index a84e1eb1cb..f334e821e9 100644 --- a/shell/e-shell-searchbar.c +++ b/shell/e-shell-searchbar.c @@ -24,6 +24,7 @@ #include <config.h> #include <glib/gi18n-lib.h> +#include "e-util/e-util.h" #include "e-util/e-binding.h" #include "widgets/misc/e-action-combo-box.h" #include "widgets/misc/e-hinted-entry.h" @@ -36,7 +37,11 @@ #define SEARCH_OPTION_ADVANCED (-1) +/* Default "state key file" group: [Search Bar] */ +#define STATE_GROUP_DEFAULT "Search Bar" + #define STATE_KEY_SEARCH_FILTER "SearchFilter" +#define STATE_KEY_SEARCH_OPTION "SearchOption" #define STATE_KEY_SEARCH_SCOPE "SearchScope" #define STATE_KEY_SEARCH_TEXT "SearchText" @@ -52,16 +57,21 @@ struct _EShellSearchbarPrivate { GtkWidget *search_entry; GtkWidget *scope_combo_box; + /* State Key File */ + gchar *state_group; + guint filter_visible : 1; + guint label_visible : 1; guint search_visible : 1; guint scope_visible : 1; - guint label_visible : 1; + guint state_dirty : 1; }; enum { PROP_0, PROP_FILTER_COMBO_BOX, PROP_FILTER_VISIBLE, + PROP_LABEL_VISIBLE, PROP_SEARCH_HINT, PROP_SEARCH_OPTION, PROP_SEARCH_TEXT, @@ -69,7 +79,7 @@ enum { PROP_SCOPE_COMBO_BOX, PROP_SCOPE_VISIBLE, PROP_SHELL_VIEW, - PROP_LABEL_VISIBLE, + PROP_STATE_GROUP }; static gpointer parent_class; @@ -159,6 +169,8 @@ shell_searchbar_execute_search_cb (EShellView *shell_view, shell_searchbar_update_search_widgets (searchbar); + e_shell_searchbar_save_state (searchbar); + if (!e_shell_view_is_active (shell_view)) return; @@ -324,13 +336,14 @@ shell_searchbar_set_property (GObject *object, GParamSpec *pspec) { switch (property_id) { - case PROP_LABEL_VISIBLE: - e_shell_searchbar_set_label_visible ( + case PROP_FILTER_VISIBLE: + e_shell_searchbar_set_filter_visible ( E_SHELL_SEARCHBAR (object), g_value_get_boolean (value)); return; - case PROP_FILTER_VISIBLE: - e_shell_searchbar_set_filter_visible ( + + case PROP_LABEL_VISIBLE: + e_shell_searchbar_set_label_visible ( E_SHELL_SEARCHBAR (object), g_value_get_boolean (value)); return; @@ -370,6 +383,12 @@ shell_searchbar_set_property (GObject *object, E_SHELL_SEARCHBAR (object), g_value_get_object (value)); return; + + case PROP_STATE_GROUP: + e_shell_searchbar_set_state_group ( + E_SHELL_SEARCHBAR (object), + g_value_get_string (value)); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -441,6 +460,12 @@ shell_searchbar_get_property (GObject *object, value, e_shell_searchbar_get_shell_view ( E_SHELL_SEARCHBAR (object))); return; + + case PROP_STATE_GROUP: + g_value_set_string ( + value, e_shell_searchbar_get_state_group ( + E_SHELL_SEARCHBAR (object))); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -488,18 +513,25 @@ shell_searchbar_constructed (GObject *object) g_signal_connect ( shell_view, "clear-search", - G_CALLBACK (shell_searchbar_clear_search_cb), - searchbar); + G_CALLBACK (shell_searchbar_clear_search_cb), searchbar); g_signal_connect ( shell_view, "custom-search", - G_CALLBACK (shell_searchbar_custom_search_cb), - searchbar); + G_CALLBACK (shell_searchbar_custom_search_cb), searchbar); g_signal_connect_after ( shell_view, "execute-search", - G_CALLBACK (shell_searchbar_execute_search_cb), - searchbar); + G_CALLBACK (shell_searchbar_execute_search_cb), searchbar); + + widget = searchbar->priv->filter_combo_box; + + g_signal_connect_swapped ( + widget, "changed", + G_CALLBACK (e_shell_searchbar_set_state_dirty), searchbar); + + g_signal_connect_swapped ( + widget, "changed", + G_CALLBACK (e_shell_view_execute_search), shell_view); widget = searchbar->priv->search_entry; @@ -532,9 +564,22 @@ shell_searchbar_constructed (GObject *object) } static void +shell_searchbar_map (GtkWidget *widget) +{ + /* Chain up to parent's map() method. */ + GTK_WIDGET_CLASS (parent_class)->map (widget); + + /* Load state after constructed() so we don't derail + * subclass initialization. We wait until map() so we + * have usable style colors for the entry box. */ + e_shell_searchbar_load_state (E_SHELL_SEARCHBAR (widget)); +} + +static void shell_searchbar_class_init (EShellSearchbarClass *class) { GObjectClass *object_class; + GtkWidgetClass *widget_class; parent_class = g_type_class_peek_parent (class); g_type_class_add_private (class, sizeof (EShellSearchbarPrivate)); @@ -545,6 +590,9 @@ shell_searchbar_class_init (EShellSearchbarClass *class) object_class->dispose = shell_searchbar_dispose; object_class->constructed = shell_searchbar_constructed; + widget_class = GTK_WIDGET_CLASS (class); + widget_class->map = shell_searchbar_map; + g_object_class_install_property ( object_class, PROP_FILTER_COMBO_BOX, @@ -654,6 +702,22 @@ shell_searchbar_class_init (EShellSearchbarClass *class) E_TYPE_SHELL_VIEW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /** + * EShellContent:state-group + * + * Key file group name to read and write search bar state. + **/ + g_object_class_install_property ( + object_class, + PROP_STATE_GROUP, + g_param_spec_string ( + "state-group", + NULL, + NULL, + STATE_GROUP_DEFAULT, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); } static void @@ -737,6 +801,11 @@ shell_searchbar_init (EShellSearchbar *searchbar) searchbar); g_signal_connect_swapped ( + widget, "changed", + G_CALLBACK (e_shell_searchbar_set_state_dirty), + searchbar); + + g_signal_connect_swapped ( widget, "icon-press", G_CALLBACK (shell_searchbar_entry_icon_press_cb), searchbar); @@ -777,6 +846,11 @@ shell_searchbar_init (EShellSearchbar *searchbar) gtk_box_pack_start (box, widget, FALSE, FALSE, 0); searchbar->priv->scope_combo_box = widget; gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "changed", + G_CALLBACK (e_shell_searchbar_set_state_dirty), + searchbar); } GType @@ -856,7 +930,7 @@ e_shell_searchbar_get_label_visible (EShellSearchbar *searchbar) void e_shell_searchbar_set_label_visible (EShellSearchbar *searchbar, - gboolean label_visible) + gboolean label_visible) { g_return_if_fail (E_IS_SHELL_SEARCHBAR (searchbar)); @@ -1015,7 +1089,7 @@ e_shell_searchbar_get_scope_visible (EShellSearchbar *searchbar) void e_shell_searchbar_set_scope_visible (EShellSearchbar *searchbar, - gboolean scope_visible) + gboolean scope_visible) { g_return_if_fail (E_IS_SHELL_SEARCHBAR (searchbar)); @@ -1025,8 +1099,38 @@ e_shell_searchbar_set_scope_visible (EShellSearchbar *searchbar, } void -e_shell_searchbar_restore_state (EShellSearchbar *searchbar, - const gchar *group_name) +e_shell_searchbar_set_state_dirty (EShellSearchbar *searchbar) +{ + g_return_if_fail (E_IS_SHELL_SEARCHBAR (searchbar)); + + searchbar->priv->state_dirty = TRUE; +} + +const gchar * +e_shell_searchbar_get_state_group (EShellSearchbar *searchbar) +{ + g_return_val_if_fail (E_IS_SHELL_SEARCHBAR (searchbar), NULL); + + return searchbar->priv->state_group; +} + +void +e_shell_searchbar_set_state_group (EShellSearchbar *searchbar, + const gchar *state_group) +{ + g_return_if_fail (E_IS_SHELL_SEARCHBAR (searchbar)); + + if (state_group == NULL) + state_group = STATE_GROUP_DEFAULT; + + g_free (searchbar->priv->state_group); + searchbar->priv->state_group = g_strdup (state_group); + + g_object_notify (G_OBJECT (searchbar), "state-group"); +} + +void +e_shell_searchbar_load_state (EShellSearchbar *searchbar) { EShellView *shell_view; EShellWindow *shell_window; @@ -1034,15 +1138,19 @@ e_shell_searchbar_restore_state (EShellSearchbar *searchbar, GtkAction *action; GtkWidget *widget; const gchar *search_text; + const gchar *state_group; const gchar *key; gchar *string; + gint value = 0; g_return_if_fail (E_IS_SHELL_SEARCHBAR (searchbar)); - g_return_if_fail (group_name != NULL); shell_view = e_shell_searchbar_get_shell_view (searchbar); - shell_window = e_shell_view_get_shell_window (shell_view); + state_group = e_shell_searchbar_get_state_group (searchbar); + g_return_if_fail (state_group != NULL); + key_file = e_shell_view_get_state_key_file (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); /* Changing the combo boxes triggers searches, so block * the search action until the state is fully restored. */ @@ -1052,13 +1160,14 @@ e_shell_searchbar_restore_state (EShellSearchbar *searchbar, e_shell_view_block_execute_search (shell_view); e_shell_view_set_search_rule (shell_view, NULL); + key = STATE_KEY_SEARCH_FILTER; - string = g_key_file_get_string (key_file, group_name, key, NULL); + string = g_key_file_get_string (key_file, state_group, key, NULL); if (string != NULL && *string != '\0') action = e_shell_window_get_action (shell_window, string); else action = NULL; - if (action != NULL) + if (GTK_IS_RADIO_ACTION (action)) gtk_action_activate (action); else { /* Pick the first combo box item. */ @@ -1067,23 +1176,26 @@ e_shell_searchbar_restore_state (EShellSearchbar *searchbar, } g_free (string); - key = STATE_KEY_SEARCH_SCOPE; - string = g_key_file_get_string (key_file, group_name, key, NULL); + /* Avoid restoring to the "Advanced Search" option, since we + * don't currently save the search rule (TODO but we should). */ + key = STATE_KEY_SEARCH_OPTION; + string = g_key_file_get_string (key_file, state_group, key, NULL); if (string != NULL && *string != '\0') action = e_shell_window_get_action (shell_window, string); else action = NULL; - if (action != NULL) + if (GTK_IS_RADIO_ACTION (action)) + g_object_get (action, "value", &value, NULL); + else + value = SEARCH_OPTION_ADVANCED; + if (value != SEARCH_OPTION_ADVANCED) gtk_action_activate (action); - else { - /* Pick the first combo box item. */ - widget = searchbar->priv->scope_combo_box; - gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0); - } - g_free (string); + else if (searchbar->priv->search_option != NULL) + gtk_radio_action_set_current_value ( + searchbar->priv->search_option, 0); key = STATE_KEY_SEARCH_TEXT; - string = g_key_file_get_string (key_file, group_name, key, NULL); + string = g_key_file_get_string (key_file, state_group, key, NULL); search_text = e_shell_searchbar_get_search_text (searchbar); if (search_text != NULL && *search_text == '\0') search_text = NULL; @@ -1091,11 +1203,102 @@ e_shell_searchbar_restore_state (EShellSearchbar *searchbar, e_shell_searchbar_set_search_text (searchbar, string); g_free (string); + /* Search scope is hard-coded to the default state group. */ + state_group = STATE_GROUP_DEFAULT; + + key = STATE_KEY_SEARCH_SCOPE; + string = g_key_file_get_string (key_file, state_group, key, NULL); + if (string != NULL && *string != '\0') + action = e_shell_window_get_action (shell_window, string); + else + action = NULL; + if (GTK_IS_RADIO_ACTION (action)) + gtk_action_activate (action); + else { + /* Pick the first combo box item. */ + widget = searchbar->priv->scope_combo_box; + gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0); + } + g_free (string); + e_shell_view_unblock_execute_search (shell_view); action = E_SHELL_WINDOW_ACTION_SEARCH_QUICK (shell_window); gtk_action_unblock_activate (action); /* Now execute the search. */ + searchbar->priv->state_dirty = FALSE; e_shell_view_execute_search (shell_view); } + +void +e_shell_searchbar_save_state (EShellSearchbar *searchbar) +{ + EShellView *shell_view; + GKeyFile *key_file; + GtkRadioAction *radio_action; + EActionComboBox *action_combo_box; + const gchar *action_name; + const gchar *search_text; + const gchar *state_group; + const gchar *key; + + g_return_if_fail (E_IS_SHELL_SEARCHBAR (searchbar)); + + /* Skip saving state if it hasn't changed since it was loaded. */ + if (!searchbar->priv->state_dirty) + return; + + shell_view = e_shell_searchbar_get_shell_view (searchbar); + state_group = e_shell_searchbar_get_state_group (searchbar); + g_return_if_fail (state_group != NULL); + + key_file = e_shell_view_get_state_key_file (shell_view); + + key = STATE_KEY_SEARCH_FILTER; + action_combo_box = e_shell_searchbar_get_filter_combo_box (searchbar); + radio_action = e_action_combo_box_get_action (action_combo_box); + if (radio_action != NULL) + radio_action = e_radio_action_get_current_action (radio_action); + if (radio_action != NULL) { + action_name = gtk_action_get_name (GTK_ACTION (radio_action)); + g_key_file_set_string (key_file, state_group, key, action_name); + } else + g_key_file_remove_key (key_file, state_group, key, NULL); + + key = STATE_KEY_SEARCH_OPTION; + radio_action = e_shell_searchbar_get_search_option (searchbar); + if (radio_action != NULL) + radio_action = e_radio_action_get_current_action (radio_action); + if (radio_action != NULL) { + action_name = gtk_action_get_name (GTK_ACTION (radio_action)); + g_key_file_set_string (key_file, state_group, key, action_name); + } else + g_key_file_remove_key (key_file, state_group, key, NULL); + + key = STATE_KEY_SEARCH_TEXT; + search_text = e_shell_searchbar_get_search_text (searchbar); + if (search_text != NULL && *search_text == '\0') + search_text = NULL; + if (search_text != NULL) + g_key_file_set_string (key_file, state_group, key, search_text); + else + g_key_file_remove_key (key_file, state_group, key, NULL); + + /* Search scope is hard-coded to the default state group. */ + state_group = STATE_GROUP_DEFAULT; + + key = STATE_KEY_SEARCH_SCOPE; + action_combo_box = e_shell_searchbar_get_scope_combo_box (searchbar); + radio_action = e_action_combo_box_get_action (action_combo_box); + if (radio_action != NULL) + radio_action = e_radio_action_get_current_action (radio_action); + if (radio_action != NULL) { + action_name = gtk_action_get_name (GTK_ACTION (radio_action)); + g_key_file_set_string (key_file, state_group, key, action_name); + } else + g_key_file_remove_key (key_file, state_group, key, NULL); + + searchbar->priv->state_dirty = FALSE; + e_shell_view_set_state_dirty (shell_view); +} |