From ddcc505dbf7893735bb02d971a6df1a411cdb646 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Wed, 1 Aug 2001 23:33:40 +0000 Subject: The calendar search bar widget now includes a drop-down menu of available 2001-08-01 Federico Mena Quintero The calendar search bar widget now includes a drop-down menu of available categories. * pcs/query.c (func_has_categories): Handle one and only one #f value as meaning "unfiled", for components that have no categories at all. * pcs/cal-backend-file.c (open_cal): Duh, do not notify here about changed categories since at this point we don't have any clients bound to us yet. (create_cal): Likewise. (cal_backend_file_add_cal): Notify here. * gui/cal-search-bar.h (CalSearchBarClass): New signal "category_changed". * gui/cal-search-bar.c (cal_search_bar_construct): Add a drop-down menu for the list of categories. (search_option_items): Removed the "Has category" option, since we now have the drop-down menu instad and it would be confusing to have both options. (regen_query): Likewise. Also, this function is now the old cal_search_bar_query_changed() and is shared by that very function and by the callback from the drop-down menu. (notify_query_contains): Include the sub-sexp for the categories. (cal_search_bar_set_categories): New function. (cal_search_bar_get_category): New function. (categories_selection_done_cb): Emit the "category_changed" signal. * gui/e-tasks.c (obj_updated_cb): Removed function since it did not do anything; all updates are handled by the CalendarModel. (obj_removed_cb): Likewise. (ETasksPrivate): Removed the fields for the categories option menu, since now it is in the ESearchBar. (search_bar_sexp_changed_cb): Use calendar_model_set_query() directly here, as we do not need to frob the sexp anymore. (update_query): Removed. (client_categories_changed_cb): New callback. (search_bar_category_changed_cb): New callback. (e_tasks_new_task): Set the default category on the component to the one that is selected in the search bar. (e_tasks_on_filter_selected): Removed. (e_tasks_on_categories_changed): Removed. (e_tasks_rebuild_categories_menu): Removed. (e_tasks_add_menu_item): Removed. (e_tasks_setup_view_menus): Sanitized not to sink objects wildly. (e_tasks_discard_view_menus): New function. * gui/calendar-model.h (CalendarModelClass): Removed the "categories_changed" signal since this is handled in the Wombat now. * gui/calendar-model.c (calendar_model_get_categories): Removed. (calendar_model_set_value_at): Do not collect the categories. (query_obj_updated_cb): Likewise. (calendar_model_collect_categories): Removed. (calendar_model_set_default_category): Constify. * gui/tasks-control.c (tasks_control_deactivate): Call e_tasks_discard_view_menus(). * gui/gnome-cal.c (search_bar_category_changed_cb): Set the default category for the task pad's model. svn path=/trunk/; revision=11559 --- calendar/gui/cal-search-bar.c | 280 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 260 insertions(+), 20 deletions(-) (limited to 'calendar/gui/cal-search-bar.c') diff --git a/calendar/gui/cal-search-bar.c b/calendar/gui/cal-search-bar.c index 351f65c5e6..e5cfcf95e9 100644 --- a/calendar/gui/cal-search-bar.c +++ b/calendar/gui/cal-search-bar.c @@ -24,9 +24,13 @@ #endif #include +#include +#include +#include #include #include #include +#include #include "cal-search-bar.h" @@ -42,8 +46,7 @@ enum { SEARCH_ANY_FIELD_CONTAINS, SEARCH_SUMMARY_CONTAINS, SEARCH_DESCRIPTION_CONTAINS, - SEARCH_COMMENT_CONTAINS, - SEARCH_HAS_CATEGORY + SEARCH_COMMENT_CONTAINS }; static ESearchBarItem search_option_items[] = { @@ -51,13 +54,19 @@ static ESearchBarItem search_option_items[] = { { N_("Summary contains"), SEARCH_SUMMARY_CONTAINS }, { N_("Description contains"), SEARCH_DESCRIPTION_CONTAINS }, { N_("Comment contains"), SEARCH_COMMENT_CONTAINS }, - { N_("Has category"), SEARCH_HAS_CATEGORY }, { NULL, -1 } }; +/* Private part of the CalSearchBar structure */ +struct CalSearchBarPrivate { + /* Option menu for the categories drop-down */ + GtkOptionMenu *categories_omenu; +}; + static void cal_search_bar_class_init (CalSearchBarClass *class); +static void cal_search_bar_init (CalSearchBar *cal_search); static void cal_search_bar_query_changed (ESearchBar *search); static void cal_search_bar_menu_activated (ESearchBar *search, int item); @@ -65,6 +74,7 @@ static void cal_search_bar_menu_activated (ESearchBar *search, int item); /* Signal IDs */ enum { SEXP_CHANGED, + CATEGORY_CHANGED, LAST_SIGNAL }; @@ -91,7 +101,7 @@ cal_search_bar_get_type (void) sizeof (CalSearchBar), sizeof (CalSearchBarClass), (GtkClassInitFunc) cal_search_bar_class_init, - (GtkObjectInitFunc) NULL, + (GtkObjectInitFunc) cal_search_bar_init, NULL, /* reserved_1 */ NULL, /* reserved_2 */ (GtkClassInitFunc) NULL @@ -122,14 +132,36 @@ cal_search_bar_class_init (CalSearchBarClass *class) GTK_TYPE_NONE, 1, GTK_TYPE_STRING); + cal_search_bar_signals[CATEGORY_CHANGED] = + gtk_signal_new ("category_changed", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (CalSearchBarClass, category_changed), + gtk_marshal_NONE__STRING, + GTK_TYPE_NONE, 1, + GTK_TYPE_STRING); + gtk_object_class_add_signals (object_class, cal_search_bar_signals, LAST_SIGNAL); class->sexp_changed = NULL; + class->category_changed = NULL; e_search_bar_class->query_changed = cal_search_bar_query_changed; e_search_bar_class->menu_activated = cal_search_bar_menu_activated; } +/* Object initialization function for the calendar search bar */ +static void +cal_search_bar_init (CalSearchBar *cal_search) +{ + CalSearchBarPrivate *priv; + + priv = g_new (CalSearchBarPrivate, 1); + cal_search->priv = priv; + + priv->categories_omenu = NULL; +} + /* Emits the "sexp_changed" signal for the calendar search bar */ @@ -140,33 +172,93 @@ notify_sexp_changed (CalSearchBar *cal_search, const char *sexp) sexp); } +/* Returns the string of the currently selected category, NULL for "Unmatched", + * or (const char *) 1 for "All". + */ +static const char * +get_current_category (CalSearchBar *cal_search) +{ + CalSearchBarPrivate *priv; + GtkMenu *menu; + GtkWidget *active; + const char *category; + + priv = cal_search->priv; + + menu = GTK_MENU (gtk_option_menu_get_menu (priv->categories_omenu)); + + active = gtk_menu_get_active (menu); + g_assert (active != NULL); + + category = gtk_object_get_user_data (GTK_OBJECT (active)); + return category; +} + +/* Returns a sexp for the selected category in the drop-down menu. The "All" + * option is returned as (const char *) 1, and the "Unfiled" option is returned + * as NULL. + */ +static char * +get_category_sexp (CalSearchBar *cal_search) +{ + const char *category; + + category = get_current_category (cal_search); + + if (category == NULL) + return g_strdup ("(has-categories? #f)"); /* Unfiled items */ + else if (category == (const char *) 1) + return NULL; /* All items */ + else + return g_strdup_printf ("(has-categories? \"%s\")", category); /* Specific category */ +} + /* Sets the query string to be (contains? "field" "text") */ static void notify_query_contains (CalSearchBar *cal_search, const char *field, const char *text) { char *sexp; + char *category_sexp; + + category_sexp = get_category_sexp (cal_search); + + if (category_sexp) + /* "Contains" sexp plus a sexp for a category or for unfiled items */ + sexp = g_strdup_printf ("(and (contains? \"%s\" \"%s\")" + " %s)", + field, text, category_sexp); + else + /* "Contains" sexp; matches any category */ + sexp = g_strdup_printf ("(contains? \"%s\" \"%s\")", field, text); - sexp = g_strdup_printf ("(contains? \"%s\" \"%s\")", field, text); notify_sexp_changed (cal_search, sexp); + + if (category_sexp) + g_free (category_sexp); + g_free (sexp); } -/* query_changed handler for the calendar search bar */ +/* Creates a new query from the values in the widgets and notifies upstream */ static void -cal_search_bar_query_changed (ESearchBar *search) +regen_query (CalSearchBar *cal_search) { - CalSearchBar *cal_search; + CalSearchBarPrivate *priv; int item; char *text; - cal_search = CAL_SEARCH_BAR (search); + priv = cal_search->priv; - item = e_search_bar_get_option_choice (search); - text = e_search_bar_get_text (search); + /* Fetch the data from the ESearchBar's entry widgets */ + + item = e_search_bar_get_option_choice (E_SEARCH_BAR (cal_search)); + text = e_search_bar_get_text (E_SEARCH_BAR (cal_search)); if (!text) return; /* This is an error in the UTF8 conversion, not an empty string! */ + /* Generate the different types of queries */ + switch (item) { case SEARCH_ANY_FIELD_CONTAINS: notify_query_contains (cal_search, "any", text); @@ -184,15 +276,6 @@ cal_search_bar_query_changed (ESearchBar *search) notify_query_contains (cal_search, "comment", text); break; - case SEARCH_HAS_CATEGORY: { - char *sexp; - - sexp = g_strdup_printf ("(has-categories? \"%s\")", text); - notify_sexp_changed (cal_search, sexp); - g_free (sexp); - break; - } - default: g_assert_not_reached (); } @@ -200,6 +283,16 @@ cal_search_bar_query_changed (ESearchBar *search) g_free (text); } +/* query_changed handler for the calendar search bar */ +static void +cal_search_bar_query_changed (ESearchBar *search) +{ + CalSearchBar *cal_search; + + cal_search = CAL_SEARCH_BAR (search); + regen_query (cal_search); +} + /* menu_activated handler for the calendar search bar */ static void cal_search_bar_menu_activated (ESearchBar *search, int item) @@ -224,6 +317,39 @@ cal_search_bar_menu_activated (ESearchBar *search, int item) +/* Callback used when an item is selected in the categories option menu */ +static void +categories_selection_done_cb (GtkMenuShell *menu_shell, gpointer data) +{ + CalSearchBar *cal_search; + const char *category; + + cal_search = CAL_SEARCH_BAR (data); + regen_query (cal_search); + + category = cal_search_bar_get_category (cal_search); + gtk_signal_emit (GTK_OBJECT (cal_search), cal_search_bar_signals[CATEGORY_CHANGED], + category); +} + +/* Creates the option menu of categories */ +static void +setup_categories_omenu (CalSearchBar *cal_search) +{ + CalSearchBarPrivate *priv; + GtkWidget *label; + + priv = cal_search->priv; + + priv->categories_omenu = GTK_OPTION_MENU (gtk_option_menu_new ()); + gtk_box_pack_end (GTK_BOX (cal_search), GTK_WIDGET (priv->categories_omenu), FALSE, FALSE, 0); + gtk_widget_show (GTK_WIDGET (priv->categories_omenu)); + + label = gtk_label_new (_("Category:")); + gtk_box_pack_end (GTK_BOX (cal_search), label, FALSE, FALSE, 4); + gtk_widget_show (label); +} + /** * cal_search_bar_construct: * @cal_search: A calendar search bar. @@ -239,6 +365,8 @@ cal_search_bar_construct (CalSearchBar *cal_search) g_return_val_if_fail (IS_CAL_SEARCH_BAR (cal_search), NULL); e_search_bar_construct (E_SEARCH_BAR (cal_search), search_menu_items, search_option_items); + setup_categories_omenu (cal_search); + return cal_search; } @@ -258,3 +386,115 @@ cal_search_bar_new (void) cal_search = gtk_type_new (TYPE_CAL_SEARCH_BAR); return GTK_WIDGET (cal_search_bar_construct (cal_search)); } + +/* Callback used when a categories menu item is destroyed. We free its user + * data, which is the category string. + */ +static void +item_destroyed_cb (GtkObject *object, gpointer data) +{ + char *category; + + category = gtk_object_get_user_data (object); + g_assert (category != NULL); + + g_free (category); +} + +/** + * cal_search_bar_set_categories: + * @cal_search: A calendar search bar. + * @categories: Array of pointers to strings for the category names. + * + * Sets the list of categories that are to be shown in the drop-down list + * of a calendar search bar. The search bar will automatically add an item + * for "unfiled" components, that is, those that have no categories assigned + * to them. + **/ +void +cal_search_bar_set_categories (CalSearchBar *cal_search, GPtrArray *categories) +{ + CalSearchBarPrivate *priv; + GtkMenu *menu; + GtkWidget *item; + int i; + + g_return_if_fail (cal_search != NULL); + g_return_if_fail (IS_CAL_SEARCH_BAR (cal_search)); + g_return_if_fail (categories != NULL); + + priv = cal_search->priv; + + menu = GTK_MENU (gtk_menu_new ()); + gtk_signal_connect (GTK_OBJECT (menu), "selection_done", + GTK_SIGNAL_FUNC (categories_selection_done_cb), cal_search); + + /* All, Unmatched, separator items */ + + item = gtk_menu_item_new_with_label (_("All")); + gtk_object_set_user_data (GTK_OBJECT (item), (char *) 1); + gtk_menu_append (menu, item); + gtk_widget_show (item); + + item = gtk_menu_item_new_with_label (_("Unfiled")); + gtk_object_set_user_data (GTK_OBJECT (item), NULL); + gtk_menu_append (menu, item); + gtk_widget_show (item); + + if (categories->len > 0) { + item = gtk_menu_item_new (); + gtk_widget_set_sensitive (item, FALSE); + gtk_menu_append (menu, item); + gtk_widget_show (item); + } + + /* Categories items */ + + for (i = 0; i < categories->len; i++) { + char *str; + + /* FIXME: Put the category icons here */ + + str = e_utf8_to_gtk_string (GTK_WIDGET (menu), categories->pdata[i]); + if (!str) + continue; + + item = gtk_menu_item_new_with_label (str); + g_free (str); + + gtk_object_set_user_data (GTK_OBJECT (item), g_strdup (categories->pdata[i])); + gtk_signal_connect (GTK_OBJECT (item), "destroy", + GTK_SIGNAL_FUNC (item_destroyed_cb), + NULL); + + gtk_menu_append (menu, item); + gtk_widget_show (item); + } + + /* Set the new menu; the old one will be destroyed automatically */ + + gtk_option_menu_set_menu (priv->categories_omenu, GTK_WIDGET (menu)); +} + +/** + * cal_search_bar_get_category: + * @cal_search: A calendar search bar. + * + * Queries the currently selected category name in a calendar search bar. + * If "All" or "Unfiled" are selected, this function will return NULL. + * + * Return value: Name of the selected category, or NULL if there is no + * selected category. + **/ +const char * +cal_search_bar_get_category (CalSearchBar *cal_search) +{ + const char *category; + + category = get_current_category (cal_search); + + if (!category || category == (const char *) 1) + return NULL; + else + return category; +} -- cgit v1.2.3