From 2ea8d8f1930bdc7f30e8556d6abeca33eb263af6 Mon Sep 17 00:00:00 2001 From: Srinivasa Ragavan Date: Fri, 22 May 2009 17:07:09 +0530 Subject: Filter/Search bar changes for Anjal. --- widgets/misc/e-search-bar.c | 395 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 337 insertions(+), 58 deletions(-) (limited to 'widgets/misc/e-search-bar.c') diff --git a/widgets/misc/e-search-bar.c b/widgets/misc/e-search-bar.c index a588b73b0c..2d1fd5eb5e 100644 --- a/widgets/misc/e-search-bar.c +++ b/widgets/misc/e-search-bar.c @@ -91,37 +91,69 @@ action_search_find_cb (GtkAction *action, } static void -action_search_type_cb (GtkAction *action, - ESearchBar *search_bar) +clear_button_state_changed (GtkWidget *clear_button, GtkStateType state, ESearchBar *search_bar) { - gtk_menu_popup ( - GTK_MENU (search_bar->priv->search_popup_menu), - NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ()); + g_return_if_fail (clear_button != NULL && search_bar != NULL); + + if (!search_bar->lite) + update_clear_menuitem_sensitive (search_bar); } -static GtkActionEntry search_entries[] = { - - { "search-clear", - GTK_STOCK_CLEAR, - NULL, - "q", - N_("Clear the most recent search"), - G_CALLBACK (action_search_clear_cb) }, - - { "search-find", - GTK_STOCK_FIND, - N_("_Find Now"), - NULL, - N_("Execute the search"), - G_CALLBACK (action_search_find_cb) }, - - { "search-type", - GTK_STOCK_FIND, - NULL, - NULL, - NULL, - G_CALLBACK (action_search_type_cb) } -}; +static char * +verb_name_from_id (int id) +{ + return g_strdup_printf ("ESearchBar:Activate:%d", id); +} + +/* This implements the "clear" action, i.e. clears the text and then emits + * ::search_activated. */ + +static void +clear_search (ESearchBar *esb) +{ + e_search_bar_set_text (esb, ""); + esb->block_search = TRUE; + if (esb->item_id < 0) + e_search_bar_set_item_id (esb, esb->last_search_option); + e_search_bar_set_viewitem_id (esb, 0); + esb->block_search = FALSE; + emit_search_activated (esb); +} + +static void +free_menu_items (ESearchBar *esb) +{ + GSList *p; + + if (esb->menu_items == NULL) + return; + + for (p = esb->menu_items; p != NULL; p = p->next) { + ESearchBarItem *item; + + item = (ESearchBarItem *) p->data; + + /* (No submitems for the menu_items, so no need to free that + member.) */ + + g_free (item->text); + g_free (item); + } + + g_slist_free (esb->menu_items); + esb->menu_items = NULL; +} + + +/* Signals. */ + +static void +emit_query_changed (ESearchBar *esb) +{ + g_signal_emit (esb, esb_signals [QUERY_CHANGED], 0); + if (!esb->lite) + update_clear_menuitem_sensitive (esb); +} static void search_bar_rule_changed (FilterRule *rule, @@ -131,10 +163,10 @@ search_bar_rule_changed (FilterRule *rule, sensitive = (rule != NULL && rule->parts != NULL); - gtk_dialog_set_response_sensitive ( - dialog, GTK_RESPONSE_OK, sensitive); - gtk_dialog_set_response_sensitive ( - dialog, GTK_RESPONSE_APPLY, sensitive); + if (!esb->lite) { + set_find_now_sensitive (esb, FALSE); + update_clear_menuitem_sensitive (esb); + } } static void @@ -221,8 +253,37 @@ paint_search_text (GtkWidget *widget, void e_search_bar_paint (ESearchBar *search_bar) { - EIconEntry *icon_entry; - GtkWidget *entry; + paint_search_text (search_bar->entry, search_bar); +} + +static gboolean +entry_focus_out_cb (GtkWidget *widget, + GdkEventFocus *event, + ESearchBar *esb) +{ + return paint_search_text (widget, esb); +} + +static void +entry_activated_cb (GtkWidget *widget, + ESearchBar *esb) +{ + const char *text = gtk_entry_get_text (GTK_ENTRY (esb->entry)); + GtkStyle *style = gtk_widget_get_default_style (); + + if (text && *text) { + gtk_widget_modify_base (esb->entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED])); + gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, &(style->text[GTK_STATE_SELECTED])); + gtk_widget_modify_base (esb->icon_entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED])); + if (!esb->lite) + gtk_widget_modify_base (esb->viewoption, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED])); + } else { + gtk_widget_modify_base (esb->entry, GTK_STATE_NORMAL, NULL); + gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, NULL); + gtk_widget_modify_base (esb->icon_entry, GTK_STATE_NORMAL, NULL); + if (!esb->lite) + gtk_widget_set_sensitive (esb->clear_button, FALSE); + } icon_entry = E_ICON_ENTRY (search_bar->priv->search_entry); entry = e_icon_entry_get_entry (icon_entry); @@ -539,10 +600,68 @@ search_bar_dispose (GObject *object) priv->filter_combo_box = NULL; } - if (priv->search_label != NULL) { - g_object_unref (priv->search_label); - priv->search_label = NULL; - } + if (!esb->lite && esb->ui_component != NULL) + update_bonobo_menus (esb); +} + +/* /\* Callback used when an option item is destroyed. We have to destroy its */ +/* * suboption items. */ +/* *\/ */ +/* static void */ +/* option_item_destroy_cb (GtkObject *object, gpointer data) */ +/* { */ +/* /\* ESearchBarSubitem *subitems; *\/ */ + +/* /\* subitems = data; *\/ */ + +/* /\* g_assert (subitems != NULL); *\/ */ +/* /\* free_subitems (subitems); *\/ */ +/* /\* g_object_set_data (G_OBJECT (object), "EsbChoiceSubitems", NULL); *\/ */ +/* } */ + +static void +set_option (ESearchBar *esb, ESearchBarItem *items) +{ + GtkWidget *menu; + GSList *group = NULL; + int i; + + if (esb->option_menu) + gtk_widget_destroy (esb->option_menu); + + esb->option_menu = menu = gtk_menu_new (); + for (i = 0; items[i].id != -1; i++) { + GtkWidget *item; + + /* Create a new group */ + if (items[i].id == 0) + group = NULL; + + if (items[i].text) { + char *str; + str = e_str_without_underscores (_(items[i].text)); + switch (items[i].type) { + case ESB_ITEMTYPE_NORMAL: + item = gtk_menu_item_new_with_label (str); + break; + case ESB_ITEMTYPE_CHECK: + item = gtk_check_menu_item_new_with_label (str); + break; + case ESB_ITEMTYPE_RADIO: + item = gtk_radio_menu_item_new_with_label (group, str); + group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM (item)); + break; + default: + /* Fixme : this should be a normal item */ + item = gtk_radio_menu_item_new_with_label (group, str); + group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM (item)); + break; + } + g_free (str); + } else { + item = gtk_menu_item_new (); + gtk_widget_set_sensitive (item, FALSE); + } if (priv->search_entry != NULL) { g_object_unref (priv->search_entry); @@ -816,19 +935,18 @@ e_search_bar_get_type (void) { static GType type = 0; - if (G_UNLIKELY (type == 0)) { - static const GTypeInfo type_info = { - sizeof (ESearchBarClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) search_bar_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (ESearchBar), - 0, /* n_preallocs */ - (GInstanceInitFunc) search_bar_init, - NULL /* value_table */ - }; + if (!esb->lite && esb->ui_component != NULL) { + bonobo_object_unref (BONOBO_OBJECT (esb->ui_component)); + esb->ui_component = NULL; + } +/* if (esb->entry) { */ +/* g_object_unref (esb->entry); */ +/* esb->entry = NULL; */ +/* } */ + if (esb->suboption) { + g_object_unref (esb->suboption); + esb->suboption = NULL; + } type = g_type_register_static ( GTK_TYPE_HBOX, "ESearchBar", &type_info, 0); @@ -869,8 +987,115 @@ e_search_bar_set_context (ESearchBar *search_bar, if (search_bar->priv->context != NULL) g_object_unref (search_bar->priv->context); - search_bar->priv->context = g_object_ref (context); - g_object_notify (G_OBJECT (search_bar), "context"); + bighbox = gtk_hbox_new (FALSE, 0); + search_bar->entry_box = gtk_hbox_new (0, FALSE); + search_bar->icon_entry = e_icon_entry_new (); + search_bar->entry = e_icon_entry_get_entry (E_ICON_ENTRY (search_bar->icon_entry)); + + g_signal_connect (search_bar->entry, "changed", + G_CALLBACK (entry_changed_cb), search_bar); + g_signal_connect (search_bar->entry, "activate", + G_CALLBACK (entry_activated_cb), search_bar); + g_signal_connect (search_bar->entry, "focus-in-event", + G_CALLBACK (entry_focus_in_cb), search_bar); + g_signal_connect (search_bar->entry, "focus-out-event", + G_CALLBACK (entry_focus_out_cb), search_bar); + g_signal_connect (search_bar->entry, "key-press-event", + G_CALLBACK (entry_key_press_cb), search_bar); + + search_bar->clear_button = e_icon_entry_create_button ("gtk-clear"); + g_signal_connect (G_OBJECT (search_bar->clear_button), "button-press-event", G_CALLBACK(clear_button_clicked_cb), search_bar); + e_icon_entry_pack_widget (E_ICON_ENTRY (search_bar->icon_entry), search_bar->clear_button, FALSE); + + search_bar->option_button = e_icon_entry_create_button ("gtk-find"); + g_signal_connect (G_OBJECT (search_bar->option_button), "button-press-event", G_CALLBACK(option_button_clicked_cb), search_bar); + e_icon_entry_pack_widget (E_ICON_ENTRY (search_bar->icon_entry), search_bar->option_button, TRUE); + + if (!search_bar->lite) + gtk_box_pack_start (GTK_BOX(search_bar->entry_box), search_bar->icon_entry, FALSE, FALSE, 0); + else + gtk_box_pack_start (GTK_BOX(search_bar->entry_box), search_bar->icon_entry, TRUE, TRUE, 0); + + + gtk_widget_show_all (search_bar->entry_box); + gtk_widget_set_sensitive (search_bar->clear_button, FALSE); + + if (!search_bar->lite) { + /* Current View filter */ + search_bar->viewoption_box = gtk_hbox_new (0, FALSE); + + /* To Translators: The "Show: " label is followed by the Quick Search Dropdown Menu where you can choose + to display "All Messages", "Unread Messages", "Message with 'Important' Label" and so on... */ + label = gtk_label_new_with_mnemonic (_("Sho_w: ")); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX(search_bar->viewoption_box), label, FALSE, FALSE, 0); + + search_bar->viewoption = gtk_option_menu_new (); + gtk_label_set_mnemonic_widget ((GtkLabel *)label, search_bar->viewoption); + gtk_box_pack_start (GTK_BOX(search_bar->viewoption_box), search_bar->viewoption, FALSE, TRUE, 0); + gtk_widget_show_all (search_bar->viewoption_box); + gtk_box_pack_start (GTK_BOX(search_bar), search_bar->viewoption_box, FALSE, FALSE, 0); + + hbox = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX(search_bar), hbox, FALSE, FALSE, 0); + } + + /* Search entry */ + hbox = gtk_hbox_new (FALSE, 0); + /* To Translators: The "Show: " label is followed by the Quick Search Text input field where one enters + the term to search for */ + if (!search_bar->lite) { + label = gtk_label_new_with_mnemonic (_("Sear_ch: ")); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX(hbox), search_bar->entry_box, FALSE, FALSE, 0); + gtk_label_set_mnemonic_widget ((GtkLabel *)label, search_bar->entry); + } else { + gtk_box_pack_start (GTK_BOX(hbox), search_bar->entry_box, TRUE, TRUE, 0); + } + gtk_widget_show (search_bar->entry_box); + + if (!search_bar->lite) { + /* Search Scope Widgets */ + search_bar->scopeoption_box = gtk_hbox_new (0, FALSE); + gtk_box_set_spacing (GTK_BOX (search_bar->scopeoption_box), 3); + /* To Translators: The " in " label is part of the Quick Search Bar, example: + Search: | | in | Current Folder/All Accounts/Current Account */ + label = gtk_label_new_with_mnemonic (_(" i_n ")); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX(search_bar->scopeoption_box), label, FALSE, FALSE, 0); + + search_bar->scopeoption = gtk_option_menu_new (); + /* g_signal_connect (GTK_OPTION_MENU (search_bar->scopeoption), "changed", scopeoption_changed_cb, search_bar); */ + gtk_box_pack_start (GTK_BOX(search_bar->scopeoption_box), search_bar->scopeoption, FALSE, FALSE, 0); + gtk_widget_show_all (search_bar->scopeoption_box); + gtk_widget_hide (hbox); + gtk_label_set_mnemonic_widget ((GtkLabel *)label, search_bar->scopeoption); + + gtk_box_pack_end (GTK_BOX(hbox), search_bar->scopeoption_box, FALSE, FALSE, 0); + gtk_widget_hide (search_bar->scopeoption_box); + + } + if (!search_bar->lite) + gtk_box_pack_end (GTK_BOX(search_bar), hbox, FALSE, FALSE, 0); + else + gtk_box_pack_end (GTK_BOX(search_bar), hbox, TRUE, TRUE, 0); + + gtk_widget_show (hbox); + + /* Set the menu */ + e_search_bar_set_menu (search_bar, menu_items); + e_search_bar_set_option (search_bar, option_items); + + /* + * If the default choice for the option menu has subitems, then we need to + * activate the search immediately. However, the developer won't have + * connected to the activated signal until after the object is constructed, + * so we can't emit here. Thus we launch a one-shot idle function that will + * emit the changed signal, so that the proper callback will get invoked. + */ + if (!search_bar->lite) + search_bar->pending_activate = g_idle_add (idle_activate_hack, search_bar); } GtkRadioAction * @@ -996,10 +1221,42 @@ e_search_bar_get_search_text (ESearchBar *search_bar) color1 = &style1->text[GTK_STATE_NORMAL]; color2 = &style2->text[GTK_STATE_INSENSITIVE]; - if (gdk_color_equal (color1, color2)) - return ""; +GtkWidget * +e_search_bar_lite_new (ESearchBarItem *menu_items, + ESearchBarItem *option_items) +{ + GtkWidget *widget; + + g_return_val_if_fail (option_items != NULL, NULL); + + widget = g_object_new (e_search_bar_get_type (), NULL); + E_SEARCH_BAR(widget)->lite = TRUE; - return gtk_entry_get_text (GTK_ENTRY (entry)); + e_search_bar_construct (E_SEARCH_BAR (widget), menu_items, option_items); + + return widget; +} + +void +e_search_bar_set_ui_component (ESearchBar *search_bar, + BonoboUIComponent *ui_component) +{ + g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); + + if (search_bar->lite) + return; + + if (search_bar->ui_component != NULL) { + remove_bonobo_menus (search_bar); + bonobo_object_unref (BONOBO_OBJECT (search_bar->ui_component)); + } + + search_bar->ui_component = ui_component; + if (ui_component != NULL) { + bonobo_object_ref (BONOBO_OBJECT (ui_component)); + setup_standard_verbs (search_bar); + setup_bonobo_menus (search_bar); + } } void @@ -1009,7 +1266,12 @@ e_search_bar_set_search_text (ESearchBar *search_bar, EIconEntry *icon_entry; GtkWidget *entry; - g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); + if (search_bar->lite) + return; + + verb_name = verb_name_from_id (id); + path = g_strconcat ("/commands/", verb_name, NULL); + g_free (verb_name); icon_entry = E_ICON_ENTRY (search_bar->priv->search_entry); entry = e_icon_entry_get_entry (icon_entry); @@ -1033,6 +1295,8 @@ e_search_bar_set_search_value (ESearchBar *search_bar, gint value) { g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); + if (!search_bar->viewoption_menu) + return; /* FIXME */ @@ -1044,7 +1308,22 @@ e_search_bar_get_search_visible (ESearchBar *search_bar) { g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), FALSE); - return GTK_WIDGET_VISIBLE (search_bar->priv->search_entry); + if (!search_bar->option_menu) + return; + row = find_id (search_bar->option_menu, id, "EsbItemId", NULL); + if (row == -1) + return; + + if (id>=0) + search_bar->last_search_option = id; + search_bar->item_id = id; + gtk_menu_set_active ((GtkMenu *)search_bar->option_menu, row); + + if (!search_bar->block_search) + emit_query_changed (search_bar); + + if (!search_bar->lite) + update_clear_menuitem_sensitive (search_bar); } void -- cgit v1.2.3