diff options
-rw-r--r-- | addressbook/gui/component/e-book-shell-view-actions.c | 77 | ||||
-rw-r--r-- | addressbook/gui/component/e-book-shell-view-private.h | 6 | ||||
-rw-r--r-- | calendar/modules/e-cal-shell-view-private.c | 6 | ||||
-rw-r--r-- | calendar/modules/e-cal-shell-view-private.h | 2 | ||||
-rw-r--r-- | calendar/modules/e-memo-shell-content.c | 1 | ||||
-rw-r--r-- | calendar/modules/e-memo-shell-sidebar.c | 95 | ||||
-rw-r--r-- | calendar/modules/e-memo-shell-view-actions.c | 131 | ||||
-rw-r--r-- | calendar/modules/e-memo-shell-view-actions.h | 10 | ||||
-rw-r--r-- | calendar/modules/e-memo-shell-view-private.c | 129 | ||||
-rw-r--r-- | calendar/modules/e-memo-shell-view-private.h | 16 | ||||
-rw-r--r-- | calendar/modules/e-task-shell-view-private.c | 12 | ||||
-rw-r--r-- | calendar/modules/e-task-shell-view-private.h | 2 | ||||
-rw-r--r-- | e-util/e-util.c | 26 | ||||
-rw-r--r-- | e-util/e-util.h | 2 | ||||
-rw-r--r-- | shell/e-shell-content.c | 13 | ||||
-rw-r--r-- | shell/e-shell-content.h | 3 | ||||
-rw-r--r-- | shell/e-shell-window-actions.c | 10 | ||||
-rw-r--r-- | widgets/misc/e-action-combo-box.c | 52 | ||||
-rw-r--r-- | widgets/misc/e-action-combo-box.h | 3 |
19 files changed, 533 insertions, 63 deletions
diff --git a/addressbook/gui/component/e-book-shell-view-actions.c b/addressbook/gui/component/e-book-shell-view-actions.c index f0acab8138..211487ca01 100644 --- a/addressbook/gui/component/e-book-shell-view-actions.c +++ b/addressbook/gui/component/e-book-shell-view-actions.c @@ -518,7 +518,7 @@ action_search_execute_cb (GtkAction *action, /* Filter by category. */ value = e_shell_content_get_filter_value (shell_content); - if (value >= 0) { + if (value >= CONTACT_FILTER_ANY_CATEGORY) { GList *categories; const gchar *category_name; gchar *temp; @@ -551,6 +551,15 @@ action_search_execute_cb (GtkAction *action, e_book_shell_content_set_preview_contact (book_shell_content, NULL); } +static void +action_search_filter_cb (GtkRadioAction *action, + GtkRadioAction *current, + EBookShellView *book_shell_view) +{ + g_debug ("Contacts filter changed"); + action_search_execute_cb (GTK_ACTION (current), book_shell_view); +} + static GtkActionEntry contact_entries[] = { { "address-book-copy", @@ -751,6 +760,16 @@ static GtkToggleActionEntry contact_toggle_entries[] = { TRUE } }; +static GtkRadioActionEntry contact_filter_entries[] = { + + { "contact-filter-any-category", + NULL, + N_("Any Category"), + NULL, + NULL, + CONTACT_FILTER_ANY_CATEGORY } +}; + static GtkRadioActionEntry contact_search_entries[] = { { "contact-search-any-field-contains", @@ -934,6 +953,10 @@ e_book_shell_view_actions_update (EBookShellView *book_shell_view) action = ACTION (CONTACT_SEND_MESSAGE); sensitive = (n_selected > 0); gtk_action_set_sensitive (action, sensitive); + label = ngettext ( + "_Send Message to Contact", + "_Send Message to Contacts", n_selected); + g_object_set (action, "label", label, NULL); /* TODO Add some context sensitivity to SEND_MESSAGE: * Send Message to Contact (n_selected == 1) @@ -958,53 +981,55 @@ e_book_shell_view_update_search_filter (EBookShellView *book_shell_view) EShellContent *shell_content; EShellView *shell_view; GtkActionGroup *action_group; - GtkRadioAction *action; + GtkRadioAction *radio_action; GList *list, *iter; - GSList *group = NULL; + GSList *group; gint ii; shell_view = E_SHELL_VIEW (book_shell_view); shell_content = e_shell_view_get_shell_content (shell_view); action_group = book_shell_view->priv->filter_actions; - /* 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); + e_action_group_remove_all_actions (action_group); - action = gtk_radio_action_new ( - "category-any", _("Any Category"), NULL, NULL, -1); + /* Add the standard filter actions. */ + gtk_action_group_add_radio_actions ( + action_group, contact_filter_entries, + G_N_ELEMENTS (contact_filter_entries), + CONTACT_FILTER_ANY_CATEGORY, + G_CALLBACK (action_search_filter_cb), + book_shell_view); - /* Activating the action executes a new search. */ - g_signal_connect ( - action, "activate", - G_CALLBACK (action_search_execute_cb), book_shell_view); + /* Retrieve the radio group from an action we just added. */ + list = gtk_action_group_list_actions (action_group); + radio_action = GTK_RADIO_ACTION (list->data); + group = gtk_radio_action_get_group (radio_action); + g_list_free (list); - gtk_radio_action_set_group (action, group); - group = gtk_radio_action_get_group (action); + /* Build the category actions. */ list = e_categories_get_list (); for (iter = list, ii = 0; iter != NULL; iter = iter->next, ii++) { const gchar *category_name = iter->data; + GtkAction *action; gchar *action_name; - action_name = g_strdup_printf ("category-%d", ii); - action = gtk_radio_action_new ( + action_name = g_strdup_printf ( + "contact-filter-category-%d", ii); + radio_action = gtk_radio_action_new ( action_name, category_name, NULL, NULL, ii); g_free (action_name); - /* Activating the action executes a new search. */ - g_signal_connect ( - action, "activate", G_CALLBACK ( - action_search_execute_cb), book_shell_view); + gtk_radio_action_set_group (radio_action, group); + group = gtk_radio_action_get_group (radio_action); - gtk_radio_action_set_group (action, group); - group = gtk_radio_action_get_group (action); + /* The action group takes ownership of the action. */ + action = GTK_ACTION (radio_action); + gtk_action_group_add_action (action_group, action); + g_object_unref (radio_action); } g_list_free (list); /* Use any action in the group; doesn't matter which. */ - e_shell_content_set_filter_action (shell_content, action); + e_shell_content_set_filter_action (shell_content, radio_action); } diff --git a/addressbook/gui/component/e-book-shell-view-private.h b/addressbook/gui/component/e-book-shell-view-private.h index 00a9249c2d..63ce28cc10 100644 --- a/addressbook/gui/component/e-book-shell-view-private.h +++ b/addressbook/gui/component/e-book-shell-view-private.h @@ -71,6 +71,12 @@ struct _EditorUidClosure { EBookShellView *view; }; +/* List these in the order to be displayed. + * Positive values are reserved for categories. */ +enum { + CONTACT_FILTER_ANY_CATEGORY +}; + /* List these in the order to be displayed. */ enum { CONTACT_SEARCH_NAME_CONTAINS, diff --git a/calendar/modules/e-cal-shell-view-private.c b/calendar/modules/e-cal-shell-view-private.c index 97aada4a89..75d0e0e8db 100644 --- a/calendar/modules/e-cal-shell-view-private.c +++ b/calendar/modules/e-cal-shell-view-private.c @@ -133,11 +133,11 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) g_signal_connect_swapped ( calendar, "dates-shown-changed", - G_CALLBACK (e_cal_shell_view_sidebar_update), + G_CALLBACK (e_cal_shell_view_update_sidebar), cal_shell_view); e_shell_view_update_actions (shell_view); - e_cal_shell_view_sidebar_update (cal_shell_view); + e_cal_shell_view_update_sidebar (cal_shell_view); } void @@ -196,7 +196,7 @@ e_cal_shell_view_set_status_message (ECalShellView *cal_shell_view, } void -e_cal_shell_view_sidebar_update (ECalShellView *cal_shell_view) +e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view) { EShellView *shell_view; EShellSidebar *shell_sidebar; diff --git a/calendar/modules/e-cal-shell-view-private.h b/calendar/modules/e-cal-shell-view-private.h index 645b514bf4..6960187508 100644 --- a/calendar/modules/e-cal-shell-view-private.h +++ b/calendar/modules/e-cal-shell-view-private.h @@ -93,7 +93,7 @@ void e_cal_shell_view_actions_init void e_cal_shell_view_set_status_message (ECalShellView *cal_shell_view, const gchar *status_message); -void e_cal_shell_view_sidebar_update +void e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view); G_END_DECLS diff --git a/calendar/modules/e-memo-shell-content.c b/calendar/modules/e-memo-shell-content.c index 52055f5146..95a86ad5a9 100644 --- a/calendar/modules/e-memo-shell-content.c +++ b/calendar/modules/e-memo-shell-content.c @@ -336,6 +336,7 @@ memo_shell_content_constructed (GObject *object) gtk_scrolled_window_set_shadow_type ( GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); gtk_paned_add2 (GTK_PANED (container), widget); + gtk_widget_show (widget); container = widget; diff --git a/calendar/modules/e-memo-shell-sidebar.c b/calendar/modules/e-memo-shell-sidebar.c index 21948b87ed..5fed456f53 100644 --- a/calendar/modules/e-memo-shell-sidebar.c +++ b/calendar/modules/e-memo-shell-sidebar.c @@ -88,7 +88,28 @@ memo_shell_sidebar_emit_status_message (EMemoShellSidebar *memo_shell_sidebar, static void memo_shell_sidebar_update_timezone (EMemoShellSidebar *memo_shell_sidebar) { - /* FIXME */ + GHashTable *client_table; + icaltimezone *zone; + GList *keys; + + zone = calendar_config_get_icaltimezone (); + client_table = memo_shell_sidebar->priv->client_table; + keys = g_hash_table_get_values (client_table); + + while (keys != NULL) { + ECal *client = keys->data; + + if (e_cal_get_load_state (client) == E_CAL_LOAD_LOADED) + e_cal_set_default_timezone (client, zone, NULL); + + keys = g_list_delete_link (keys, keys); + } + + /* XXX Need to call e_memo_preview_set_default_timezone() here + * but the sidebar is not really supposed to access content + * stuff. I guess we could emit an "update-timezone" signal + * here, but that feels wrong. Maybe this whole thing should + * be in EMemoShellView instead. */ } static void @@ -171,6 +192,8 @@ memo_shell_sidebar_client_opened_cb (EMemoShellSidebar *memo_shell_sidebar, shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); shell_window = e_shell_view_get_shell_window (shell_view); + g_debug ("%s (status = %d)", G_STRFUNC, status); + switch (status) { case E_CALENDAR_STATUS_OK: g_signal_handlers_disconnect_matched ( @@ -203,10 +226,60 @@ memo_shell_sidebar_client_opened_cb (EMemoShellSidebar *memo_shell_sidebar, } static void +memo_shell_sidebar_row_changed_cb (EMemoShellSidebar *memo_shell_sidebar, + GtkTreePath *tree_path, + GtkTreeIter *tree_iter, + GtkTreeModel *tree_model) +{ + ESourceSelector *selector; + ESource *source; + + /* XXX ESourceSelector's underlying tree store has only one + * column: ESource objects. While we're not supposed to + * know this, listening for "row-changed" signals from + * the model is easier to deal with than the selector's + * "selection-changed" signal, which doesn't tell you + * _which_ row changed. */ + + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + gtk_tree_model_get (tree_model, tree_iter, 0, &source, -1); + + /* XXX This signal gets emitted a lot while the model is being + * rebuilt, during which time we won't get a valid ESource. + * ESourceSelector should probably block this signal while + * rebuilding the model, but we'll be forgiving and not + * emit a warning. */ + if (!E_IS_SOURCE (source)) + return; + + if (e_source_selector_source_is_selected (selector, source)) + e_memo_shell_sidebar_add_source (memo_shell_sidebar, source); + else + e_memo_shell_sidebar_remove_source (memo_shell_sidebar, source); +} + +static void memo_shell_sidebar_selection_changed_cb (EMemoShellSidebar *memo_shell_sidebar, ESourceSelector *selector) { - /* FIXME */ + GSList *list, *iter; + + /* This signal is emitted less frequently than "row-changed", + * especially when the model is being rebuilt. So we'll take + * it easy on poor GConf. */ + + list = e_source_selector_get_selection (selector); + + for (iter = list; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + + iter->data = (gpointer) e_source_peek_uid (source); + g_object_unref (source); + } + + calendar_config_set_memos_selected (list); + + g_slist_free (list); } static void @@ -216,6 +289,9 @@ memo_shell_sidebar_primary_selection_changed_cb (EMemoShellSidebar *memo_shell_s ESource *source; const gchar *uid; + /* XXX ESourceSelector needs a "primary-selection-uid" property + * so we can just bind the property with GConfBridge. */ + source = e_source_selector_peek_primary_selection (selector); if (source == NULL) return; @@ -283,6 +359,7 @@ memo_shell_sidebar_constructed (GObject *object) ESourceList *source_list; ESource *source; GtkContainer *container; + GtkTreeModel *model; GtkWidget *widget; GSList *list, *iter; gchar *uid; @@ -316,6 +393,13 @@ memo_shell_sidebar_constructed (GObject *object) priv->selector = g_object_ref (widget); gtk_widget_show (widget); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); + + g_signal_connect_swapped ( + model, "row-changed", + G_CALLBACK (memo_shell_sidebar_row_changed_cb), + object); + g_signal_connect_swapped ( widget, "selection-changed", G_CALLBACK (memo_shell_sidebar_selection_changed_cb), @@ -352,8 +436,7 @@ memo_shell_sidebar_constructed (GObject *object) if (source == NULL) continue; - e_source_selector_select_source ( - E_SOURCE_SELECTOR (priv->selector), source); + e_source_selector_select_source (selector, source); } g_slist_free (list); } @@ -532,6 +615,8 @@ e_memo_shell_sidebar_add_source (EMemoShellSidebar *memo_shell_sidebar, uid = e_source_peek_uid (source); client = g_hash_table_lookup (client_table, uid); + g_debug ("%s (%s): %s", G_STRFUNC, e_source_peek_relative_uri (source), client != NULL ? "Already added" : "Added"); + if (client != NULL) return; @@ -582,6 +667,8 @@ e_memo_shell_sidebar_remove_source (EMemoShellSidebar *memo_shell_sidebar, uid = e_source_peek_uid (source); client = g_hash_table_lookup (client_table, uid); + g_debug ("%s (%s): %s", G_STRFUNC, e_source_peek_relative_uri (source), client == NULL ? "Already removed" : "Removed"); + if (client == NULL) return; diff --git a/calendar/modules/e-memo-shell-view-actions.c b/calendar/modules/e-memo-shell-view-actions.c index 6b6bac4fab..7c63447cc2 100644 --- a/calendar/modules/e-memo-shell-view-actions.c +++ b/calendar/modules/e-memo-shell-view-actions.c @@ -21,6 +21,23 @@ #include "e-memo-shell-view-private.h" static void +action_gal_save_custom_view_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EShellView *shell_view; + GalViewInstance *view_instance; + + shell_view = E_SHELL_VIEW (memo_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + view_instance = e_memo_shell_content_get_view_instance (memo_shell_content); + gal_view_instance_save_as (view_instance); +} + +static void action_memo_clipboard_copy_cb (GtkAction *action, EMemoShellView *memo_shell_view) { @@ -122,7 +139,7 @@ action_memo_list_copy_cb (GtkAction *action, memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); source = e_source_selector_peek_primary_selection (selector); - g_return_if_fail (source == NULL); + g_return_if_fail (E_IS_SOURCE (source)); copy_source_dialog ( GTK_WINDOW (shell_window), @@ -158,7 +175,7 @@ action_memo_list_delete_cb (GtkAction *action, memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); source = e_source_selector_peek_primary_selection (selector); - g_return_if_fail (source == NULL); + g_return_if_fail (E_IS_SOURCE (source)); /* Ask for confirmation. */ response = e_error_run ( @@ -260,7 +277,7 @@ action_memo_list_properties_cb (GtkAction *action, memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); source = e_source_selector_peek_primary_selection (selector); - g_return_if_fail (source != NULL); + g_return_if_fail (E_IS_SOURCE (source)); calendar_setup_edit_memo_list (GTK_WINDOW (shell_window), source); } @@ -405,6 +422,27 @@ action_memo_save_as_cb (GtkAction *action, g_free (string); } +static void +action_search_execute_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EShellView *shell_view; + + shell_view = E_SHELL_VIEW (memo_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + e_memo_shell_view_execute_search (memo_shell_view); +} + +static void +action_search_filter_cb (GtkRadioAction *action, + GtkRadioAction *current, + EMemoShellView *memo_shell_view) +{ + e_memo_shell_view_execute_search (memo_shell_view); +} + static GtkActionEntry memo_entries[] = { { "memo-clipboard-copy", @@ -531,6 +569,23 @@ static GtkToggleActionEntry memo_toggle_entries[] = { TRUE } }; +static GtkRadioActionEntry memo_filter_entries[] = { + + { "memo-filter-any-category", + NULL, + N_("Any Category"), + NULL, + NULL, + MEMO_FILTER_ANY_CATEGORY }, + + { "memo-filter-unmatched", + NULL, + N_("Unmatched"), + NULL, + NULL, + MEMO_FILTER_UNMATCHED } +}; + static GtkRadioActionEntry memo_search_entries[] = { { "memo-search-any-field-contains", @@ -600,4 +655,74 @@ e_memo_shell_view_actions_init (EMemoShellView *memo_shell_view) action = ACTION (MEMO_DELETE); g_object_set (action, "short-label", _("Delete"), NULL); + + g_signal_connect ( + ACTION (GAL_SAVE_CUSTOM_VIEW), "activate", + G_CALLBACK (action_gal_save_custom_view_cb), memo_shell_view); + + g_signal_connect ( + ACTION (SEARCH_EXECUTE), "activate", + G_CALLBACK (action_search_execute_cb), memo_shell_view); +} + +void +e_memo_shell_view_update_search_filter (EMemoShellView *memo_shell_view) +{ + EShellContent *shell_content; + EShellView *shell_view; + GtkActionGroup *action_group; + GtkRadioAction *radio_action; + GList *list, *iter; + GSList *group; + gint ii; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + action_group = memo_shell_view->priv->filter_actions; + + e_action_group_remove_all_actions (action_group); + + /* Add the standard filter actions. */ + gtk_action_group_add_radio_actions ( + action_group, memo_filter_entries, + G_N_ELEMENTS (memo_filter_entries), + MEMO_FILTER_ANY_CATEGORY, + G_CALLBACK (action_search_filter_cb), + memo_shell_view); + + /* Retrieve the radio group from an action we just added. */ + list = gtk_action_group_list_actions (action_group); + radio_action = GTK_RADIO_ACTION (list->data); + group = gtk_radio_action_get_group (radio_action); + g_list_free (list); + + /* Build the category actions. */ + + list = e_categories_get_list (); + for (iter = list, ii = 0; iter != NULL; iter = iter->next, ii++) { + const gchar *category_name = iter->data; + GtkAction *action; + gchar *action_name; + + action_name = g_strdup_printf ( + "memo-filter-category-%d", ii); + radio_action = gtk_radio_action_new ( + action_name, category_name, NULL, NULL, ii); + g_free (action_name); + + gtk_radio_action_set_group (radio_action, group); + group = gtk_radio_action_get_group (radio_action); + + /* The action group takes ownership of the action. */ + action = GTK_ACTION (radio_action); + gtk_action_group_add_action (action_group, action); + g_object_unref (radio_action); + } + g_list_free (list); + + /* Use any action in the group; doesn't matter which. */ + e_shell_content_set_filter_action (shell_content, radio_action); + + e_shell_content_add_filter_separator_after ( + shell_content, MEMO_FILTER_UNMATCHED); } diff --git a/calendar/modules/e-memo-shell-view-actions.h b/calendar/modules/e-memo-shell-view-actions.h index 4ac71c2083..abaf9a9c2a 100644 --- a/calendar/modules/e-memo-shell-view-actions.h +++ b/calendar/modules/e-memo-shell-view-actions.h @@ -32,6 +32,10 @@ E_SHELL_WINDOW_ACTION ((window), "memo-clipboard-paste") #define E_SHELL_WINDOW_ACTION_MEMO_DELETE(window) \ E_SHELL_WINDOW_ACTION ((window), "memo-delete") +#define E_SHELL_WINDOW_ACTION_MEMO_FILTER_ANY_CATEGORY(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-filter-any-category") +#define E_SHELL_WINDOW_ACTION_MEMO_FILTER_UNMATCHED(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-filter-unmatched") #define E_SHELL_WINDOW_ACTION_MEMO_OPEN(window) \ E_SHELL_WINDOW_ACTION ((window), "memo-open") #define E_SHELL_WINDOW_ACTION_MEMO_PREVIEW(window) \ @@ -40,6 +44,12 @@ E_SHELL_WINDOW_ACTION ((window), "memo-print") #define E_SHELL_WINDOW_ACTION_MEMO_PRINT_PREVIEW(window) \ E_SHELL_WINDOW_ACTION ((window), "memo-print-preview") +#define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_ANY_FIELD_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-search-any-field-contains") +#define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_DESCRIPTION_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-search-description-contains") +#define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_SUMMARY_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-search-summary-contains") /* Action Groups */ #define E_SHELL_WINDOW_ACTION_GROUP_MEMOS(window) \ diff --git a/calendar/modules/e-memo-shell-view-private.c b/calendar/modules/e-memo-shell-view-private.c index 8d8a8e110d..0a95c998ec 100644 --- a/calendar/modules/e-memo-shell-view-private.c +++ b/calendar/modules/e-memo-shell-view-private.c @@ -49,6 +49,8 @@ memo_shell_view_table_user_created_cb (EMemoShellView *memo_shell_view, memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; e_memo_shell_sidebar_add_source (memo_shell_sidebar, source); + + e_cal_model_add_client (model, client); } static void @@ -158,6 +160,7 @@ e_memo_shell_view_private_init (EMemoShellView *memo_shell_view, priv->source_list = g_object_ref (source_list); priv->memo_actions = gtk_action_group_new ("memos"); + priv->filter_actions = gtk_action_group_new ("memos-filter"); if (!gal_view_collection_loaded (shell_view_class->view_collection)) memo_shell_view_load_view_collection (shell_view_class); @@ -173,15 +176,17 @@ e_memo_shell_view_private_constructed (EMemoShellView *memo_shell_view) EMemoShellViewPrivate *priv = memo_shell_view->priv; EMemoShellContent *memo_shell_content; EMemoShellSidebar *memo_shell_sidebar; + EShellView *shell_view; + EShellWindow *shell_window; EShellContent *shell_content; EShellSidebar *shell_sidebar; - EShellView *shell_view; EMemoTable *memo_table; ECalModel *model; ETable *table; ESourceSelector *selector; shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); shell_content = e_shell_view_get_shell_content (shell_view); shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); @@ -224,22 +229,22 @@ e_memo_shell_view_private_constructed (EMemoShellView *memo_shell_view) g_signal_connect_swapped ( model, "model-changed", - G_CALLBACK (e_memo_shell_view_sidebar_update), + G_CALLBACK (e_memo_shell_view_update_sidebar), memo_shell_view); g_signal_connect_swapped ( model, "model-rows-deleted", - G_CALLBACK (e_memo_shell_view_sidebar_update), + G_CALLBACK (e_memo_shell_view_update_sidebar), memo_shell_view); g_signal_connect_swapped ( model, "model-rows-inserted", - G_CALLBACK (e_memo_shell_view_sidebar_update), + G_CALLBACK (e_memo_shell_view_update_sidebar), memo_shell_view); g_signal_connect_swapped ( table, "selection-change", - G_CALLBACK (e_memo_shell_view_sidebar_update), + G_CALLBACK (e_memo_shell_view_update_sidebar), memo_shell_view); g_signal_connect_swapped ( @@ -262,8 +267,15 @@ e_memo_shell_view_private_constructed (EMemoShellView *memo_shell_view) G_CALLBACK (e_shell_view_update_actions), memo_shell_view); + e_categories_register_change_listener ( + G_CALLBACK (e_memo_shell_view_update_search_filter), + memo_shell_view); + e_memo_shell_view_actions_init (memo_shell_view); - e_memo_shell_view_sidebar_update (memo_shell_view); + e_memo_shell_view_update_sidebar (memo_shell_view); + e_memo_shell_view_update_search_filter (memo_shell_view); + + e_memo_shell_view_execute_search (memo_shell_view); } void @@ -274,6 +286,7 @@ e_memo_shell_view_private_dispose (EMemoShellView *memo_shell_view) DISPOSE (priv->source_list); DISPOSE (priv->memo_actions); + DISPOSE (priv->filter_actions); DISPOSE (priv->memo_shell_content); DISPOSE (priv->memo_shell_sidebar); @@ -293,6 +306,105 @@ e_memo_shell_view_private_finalize (EMemoShellView *memo_shell_view) } void +e_memo_shell_view_execute_search (EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EShellView *shell_view; + EShellWindow *shell_window; + EShellContent *shell_content; + GtkAction *action; + GString *string; + EMemoPreview *memo_preview; + EMemoTable *memo_table; + ECalModel *model; + FilterRule *rule; + const gchar *format; + const gchar *text; + gchar *query; + gint value; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + text = e_shell_content_get_search_text (shell_content); + + shell_window = e_shell_view_get_shell_window (shell_view); + action = ACTION (MEMO_SEARCH_ANY_FIELD_CONTAINS); + value = gtk_radio_action_get_current_value ( + GTK_RADIO_ACTION (action)); + + if (text == NULL || *text == '\0') { + text = ""; + value = MEMO_SEARCH_SUMMARY_CONTAINS; + } + + switch (value) { + default: + text = ""; + /* fall through */ + + case MEMO_SEARCH_SUMMARY_CONTAINS: + format = "(contains? \"summary\" %s)"; + break; + + case MEMO_SEARCH_DESCRIPTION_CONTAINS: + format = "(contains? \"description\" %s)"; + break; + + case MEMO_SEARCH_ANY_FIELD_CONTAINS: + format = "(contains? \"any\" %s)"; + break; + } + + /* Build the query. */ + string = g_string_new (""); + e_sexp_encode_string (string, text); + query = g_strdup_printf (format, string->str); + g_string_free (string, TRUE); + + /* Filter by category. */ + value = e_shell_content_get_filter_value (shell_content); + if (value == MEMO_FILTER_UNMATCHED) { + gchar *temp; + + temp = g_strdup_printf ( + "(and (has-categories? #f) %s", query); + g_free (query); + query = temp; + } else if (value != MEMO_FILTER_ANY_CATEGORY) { + GList *categories; + const gchar *category_name; + gchar *temp; + + categories = e_categories_get_list (); + category_name = g_list_nth_data (categories, value); + g_list_free (categories); + + temp = g_strdup_printf ( + "(and (has-categories? \"%s\") %s)", + category_name, query); + g_free (query); + query = temp; + } + + /* XXX This is wrong. We need to programmatically construct a + * FilterRule, tell it to build code, and pass the resulting + * expression string to ECalModel. */ + rule = filter_rule_new (); + e_shell_content_set_search_rule (shell_content, rule); + g_object_unref (rule); + + /* Submit the query. */ + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + model = e_memo_table_get_model (memo_table); + e_cal_model_set_search_query (model, query); + g_free (query); + + memo_preview = e_memo_shell_content_get_memo_preview (memo_shell_content); + e_memo_preview_clear (memo_preview); +} + +void e_memo_shell_view_open_memo (EMemoShellView *memo_shell_view, ECalModelComponent *comp_data) { @@ -356,11 +468,14 @@ e_memo_shell_view_set_status_message (EMemoShellView *memo_shell_view, } else e_activity_set_primary_text (activity, status_message); + if (status_message != NULL && *status_message != '\0') + g_debug ("Memos: %s", status_message); + memo_shell_view->priv->activity = activity; } void -e_memo_shell_view_sidebar_update (EMemoShellView *memo_shell_view) +e_memo_shell_view_update_sidebar (EMemoShellView *memo_shell_view) { EMemoShellContent *memo_shell_content; EShellView *shell_view; diff --git a/calendar/modules/e-memo-shell-view-private.h b/calendar/modules/e-memo-shell-view-private.h index fd30a14898..b3e6404f26 100644 --- a/calendar/modules/e-memo-shell-view-private.h +++ b/calendar/modules/e-memo-shell-view-private.h @@ -25,6 +25,8 @@ #include <string.h> #include <glib/gi18n.h> +#include <libedataserver/e-categories.h> +#include <libedataserver/e-sexp.h> #include "e-util/e-dialog-utils.h" #include "e-util/e-error.h" @@ -63,6 +65,13 @@ G_BEGIN_DECLS +/* List these in the order to be displayed. + * Positive values are reserved for categories. */ +enum { + MEMO_FILTER_ANY_CATEGORY = -2, + MEMO_FILTER_UNMATCHED = -1 +}; + /* List these in the order to be displayed. */ enum { MEMO_SEARCH_SUMMARY_CONTAINS, @@ -79,6 +88,7 @@ struct _EMemoShellViewPrivate { /*** UI Management ***/ GtkActionGroup *memo_actions; + GtkActionGroup *filter_actions; /*** Other Stuff ***/ @@ -103,13 +113,17 @@ void e_memo_shell_view_private_finalize void e_memo_shell_view_actions_init (EMemoShellView *memo_shell_view); +void e_memo_shell_view_execute_search + (EMemoShellView *memo_shell_view); void e_memo_shell_view_open_memo (EMemoShellView *memo_shell_view, ECalModelComponent *comp_data); void e_memo_shell_view_set_status_message (EMemoShellView *memo_shell_view, const gchar *status_message); -void e_memo_shell_view_sidebar_update +void e_memo_shell_view_update_sidebar + (EMemoShellView *memo_shell_view); +void e_memo_shell_view_update_search_filter (EMemoShellView *memo_shell_view); G_END_DECLS diff --git a/calendar/modules/e-task-shell-view-private.c b/calendar/modules/e-task-shell-view-private.c index 8e573f538d..0b81de1186 100644 --- a/calendar/modules/e-task-shell-view-private.c +++ b/calendar/modules/e-task-shell-view-private.c @@ -321,26 +321,26 @@ e_task_shell_view_private_constructed (ETaskShellView *task_shell_view) g_signal_connect_swapped ( model, "model-changed", - G_CALLBACK (e_task_shell_view_sidebar_update), + G_CALLBACK (e_task_shell_view_update_sidebar), task_shell_view); g_signal_connect_swapped ( model, "model-rows-deleted", - G_CALLBACK (e_task_shell_view_sidebar_update), + G_CALLBACK (e_task_shell_view_update_sidebar), task_shell_view); g_signal_connect_swapped ( model, "model-rows-inserted", - G_CALLBACK (e_task_shell_view_sidebar_update), + G_CALLBACK (e_task_shell_view_update_sidebar), task_shell_view); g_signal_connect_swapped ( table, "selection-change", - G_CALLBACK (e_task_shell_view_sidebar_update), + G_CALLBACK (e_task_shell_view_update_sidebar), task_shell_view); e_task_shell_view_actions_init (task_shell_view); - e_task_shell_view_sidebar_update (task_shell_view); + e_task_shell_view_update_sidebar (task_shell_view); } void @@ -451,7 +451,7 @@ e_task_shell_view_set_status_message (ETaskShellView *task_shell_view, } void -e_task_shell_view_sidebar_update (ETaskShellView *task_shell_view) +e_task_shell_view_update_sidebar (ETaskShellView *task_shell_view) { ETaskShellContent *task_shell_content; EShellView *shell_view; diff --git a/calendar/modules/e-task-shell-view-private.h b/calendar/modules/e-task-shell-view-private.h index bad511ca20..2627545e3d 100644 --- a/calendar/modules/e-task-shell-view-private.h +++ b/calendar/modules/e-task-shell-view-private.h @@ -107,7 +107,7 @@ void e_task_shell_view_open_task void e_task_shell_view_set_status_message (ETaskShellView *task_shell_view, const gchar *status_message); -void e_task_shell_view_sidebar_update +void e_task_shell_view_update_sidebar (ETaskShellView *task_shell_view); G_END_DECLS diff --git a/e-util/e-util.c b/e-util/e-util.c index 0055407068..0c737d08a3 100644 --- a/e-util/e-util.c +++ b/e-util/e-util.c @@ -140,6 +140,32 @@ e_load_ui_definition (GtkUIManager *ui_manager, } /** + * e_action_group_remove_all_actions: + * @action_group: a #GtkActionGroup + * + * Removes all actions from the action group. + **/ +void +e_action_group_remove_all_actions (GtkActionGroup *action_group) +{ + GList *list, *iter; + + /* XXX I've proposed this function for inclusion in GTK+. + * GtkActionGroup stores actions in an internal hash + * table and can do this more efficiently by calling + * g_hash_table_remove_all(). + * + * http://bugzilla.gnome.org/show_bug.cgi?id=550485 */ + + g_return_if_fail (GTK_IS_ACTION_GROUP (action_group)); + + 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); +} + +/** * e_str_without_underscores: * @s: the string to strip underscores from. * diff --git a/e-util/e-util.h b/e-util/e-util.h index a6aaa19a99..63cdafe058 100644 --- a/e-util/e-util.h +++ b/e-util/e-util.h @@ -46,6 +46,8 @@ void e_display_help (GtkWindow *parent, const gchar *link_id); guint e_load_ui_definition (GtkUIManager *ui_manager, const gchar *basename); +void e_action_group_remove_all_actions + (GtkActionGroup *action_group); char * e_str_without_underscores (const char *s); gint e_str_compare (gconstpointer x, diff --git a/shell/e-shell-content.c b/shell/e-shell-content.c index efa3b663f0..f3685793b7 100644 --- a/shell/e-shell-content.c +++ b/shell/e-shell-content.c @@ -1013,6 +1013,19 @@ e_shell_content_set_filter_visible (EShellContent *shell_content, } } +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); +} + RuleContext * e_shell_content_get_search_context (EShellContent *shell_content) { diff --git a/shell/e-shell-content.h b/shell/e-shell-content.h index defeb0a403..ae9d0446ab 100644 --- a/shell/e-shell-content.h +++ b/shell/e-shell-content.h @@ -82,6 +82,9 @@ gboolean e_shell_content_get_filter_visible void e_shell_content_set_filter_visible (EShellContent *shell_content, gboolean filter_visible); +void e_shell_content_add_filter_separator_after + (EShellContent *shell_content, + gint action_value); RuleContext * e_shell_content_get_search_context (EShellContent *shell_content); FilterRule * e_shell_content_get_search_rule (EShellContent *shell_content); diff --git a/shell/e-shell-window-actions.c b/shell/e-shell-window-actions.c index 28920a7eb7..ab403c31dc 100644 --- a/shell/e-shell-window-actions.c +++ b/shell/e-shell-window-actions.c @@ -1727,7 +1727,6 @@ e_shell_window_create_switcher_actions (EShellWindow *shell_window) gtk_action_group_add_action_with_accel ( action_group, GTK_ACTION (action), accelerator); - g_debug ("Adding action '%s'", action_name); e_shell_switcher_add_action (switcher, GTK_ACTION (action)); gtk_ui_manager_add_ui ( @@ -1767,7 +1766,6 @@ e_shell_window_update_view_menu (EShellWindow *shell_window) GalViewCollection *view_collection; GtkRadioAction *radio_action; GtkAction *action; - GList *list, *iter; GSList *radio_group; gboolean visible; const gchar *path; @@ -1789,13 +1787,7 @@ e_shell_window_update_view_menu (EShellWindow *shell_window) /* 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); + e_action_group_remove_all_actions (action_group); /* We have a view ID, so forge ahead. */ count = gal_view_collection_get_count (view_collection); diff --git a/widgets/misc/e-action-combo-box.c b/widgets/misc/e-action-combo-box.c index 5e32268431..e826fb2a54 100644 --- a/widgets/misc/e-action-combo-box.c +++ b/widgets/misc/e-action-combo-box.c @@ -98,6 +98,10 @@ action_combo_box_render_pixbuf (GtkCellLayout *layout, gtk_tree_model_get (model, iter, COLUMN_ACTION, &action, -1); + /* A NULL action means the row is a separator. */ + if (action == NULL) + return; + g_object_get ( G_OBJECT (action), "icon-name", &icon_name, @@ -134,6 +138,10 @@ action_combo_box_render_text (GtkCellLayout *layout, gtk_tree_model_get (model, iter, COLUMN_ACTION, &action, -1); + /* A NULL action means the row is a separator. */ + if (action == NULL) + return; + g_object_get ( G_OBJECT (action), "label", &label, @@ -157,6 +165,22 @@ action_combo_box_render_text (GtkCellLayout *layout, g_free (label); } +static gboolean +action_combo_box_is_row_separator (GtkTreeModel *model, + GtkTreeIter *iter) +{ + GtkAction *action; + gboolean separator; + + /* NULL actions are rendered as separators. */ + gtk_tree_model_get (model, iter, COLUMN_ACTION, &action, -1); + separator = (action == NULL); + if (action != NULL) + g_object_unref (action); + + return separator; +} + static void action_combo_box_update_model (EActionComboBox *combo_box) { @@ -170,8 +194,11 @@ action_combo_box_update_model (EActionComboBox *combo_box) return; } + /* We store values in the sort column as floats so that we can + * insert separators in between consecutive integer values and + * still maintain the proper ordering. */ list_store = gtk_list_store_new ( - 2, GTK_TYPE_RADIO_ACTION, G_TYPE_INT); + 2, GTK_TYPE_RADIO_ACTION, G_TYPE_FLOAT); list = gtk_radio_action_get_group (combo_box->priv->action); @@ -186,7 +213,7 @@ action_combo_box_update_model (EActionComboBox *combo_box) g_object_get (G_OBJECT (action), "value", &value, NULL); gtk_list_store_set ( list_store, &iter, COLUMN_ACTION, - list->data, COLUMN_SORT, value, -1); + list->data, COLUMN_SORT, (gfloat) value, -1); path = gtk_tree_model_get_path ( GTK_TREE_MODEL (list_store), &iter); @@ -349,6 +376,10 @@ action_combo_box_init (EActionComboBox *combo_box) (GtkCellLayoutDataFunc) action_combo_box_render_text, combo_box, NULL); + gtk_combo_box_set_row_separator_func ( + GTK_COMBO_BOX (combo_box), (GtkTreeViewRowSeparatorFunc) + action_combo_box_is_row_separator, NULL, NULL); + combo_box->priv->index = g_hash_table_new_full ( g_direct_hash, g_direct_equal, (GDestroyNotify) NULL, @@ -477,3 +508,20 @@ e_action_combo_box_set_current_value (EActionComboBox *combo_box, gtk_radio_action_set_current_value ( combo_box->priv->action, current_value); } + +void +e_action_combo_box_add_separator_after (EActionComboBox *combo_box, + gint action_value) +{ + GtkTreeModel *model; + GtkTreeIter iter; + + g_return_if_fail (E_ACTION_IS_COMBO_BOX (combo_box)); + + /* NULL actions are rendered as separators. */ + model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box)); + gtk_list_store_append (GTK_LIST_STORE (model), &iter); + gtk_list_store_set ( + GTK_LIST_STORE (model), &iter, COLUMN_ACTION, + NULL, COLUMN_SORT, (gfloat) action_value + 0.5, -1); +} diff --git a/widgets/misc/e-action-combo-box.h b/widgets/misc/e-action-combo-box.h index 452c3fa265..7327c4723b 100644 --- a/widgets/misc/e-action-combo-box.h +++ b/widgets/misc/e-action-combo-box.h @@ -73,6 +73,9 @@ gint e_action_combo_box_get_current_value void e_action_combo_box_set_current_value (EActionComboBox *combo_box, gint current_value); +void e_action_combo_box_add_separator_after + (EActionComboBox *combo_box, + gint action_value); G_END_DECLS |