diff options
29 files changed, 3106 insertions, 4135 deletions
diff --git a/libnautilus-private/nautilus-clipboard.c b/libnautilus-private/nautilus-clipboard.c index dd6f9c040..d194cf346 100644 --- a/libnautilus-private/nautilus-clipboard.c +++ b/libnautilus-private/nautilus-clipboard.c @@ -33,428 +33,6 @@ #include <gtk/gtk.h> #include <string.h> -typedef struct _TargetCallbackData TargetCallbackData; - -typedef void (* SelectAllCallback) (gpointer target); -typedef void (* ConnectCallbacksFunc) (GObject *object, - TargetCallbackData *target_data); - -static void selection_changed_callback (GtkWidget *widget, - gpointer callback_data); -static void owner_change_callback (GtkClipboard *clipboard, - GdkEventOwnerChange *event, - gpointer callback_data); -struct _TargetCallbackData { - GtkUIManager *ui_manager; - GtkActionGroup *action_group; - gboolean shares_selection_changes; - - SelectAllCallback select_all_callback; - - ConnectCallbacksFunc connect_callbacks; - ConnectCallbacksFunc disconnect_callbacks; -}; - -static void -cut_callback (gpointer target) -{ - g_assert (target != NULL); - - g_signal_emit_by_name (target, "cut-clipboard"); -} - -static void -copy_callback (gpointer target) -{ - g_assert (target != NULL); - - g_signal_emit_by_name (target, "copy-clipboard"); -} - -static void -paste_callback (gpointer target) -{ - g_assert (target != NULL); - - g_signal_emit_by_name (target, "paste-clipboard"); -} - -static void -editable_select_all_callback (gpointer target) -{ - GtkEditable *editable; - - editable = GTK_EDITABLE (target); - g_assert (editable != NULL); - - gtk_editable_set_position (editable, -1); - gtk_editable_select_region (editable, 0, -1); -} - -static void -action_cut_callback (GtkAction *action, - gpointer callback_data) -{ - cut_callback (callback_data); -} - -static void -action_copy_callback (GtkAction *action, - gpointer callback_data) -{ - copy_callback (callback_data); -} - -static void -action_paste_callback (GtkAction *action, - gpointer callback_data) -{ - paste_callback (callback_data); -} - -static void -action_select_all_callback (GtkAction *action, - gpointer callback_data) -{ - TargetCallbackData *target_data; - - g_assert (callback_data != NULL); - - target_data = g_object_get_data (callback_data, "Nautilus:clipboard_target_data"); - g_assert (target_data != NULL); - - target_data->select_all_callback (callback_data); -} - -static void -received_clipboard_contents (GtkClipboard *clipboard, - GtkSelectionData *selection_data, - gpointer data) -{ - GtkActionGroup *action_group; - GtkAction *action; - - action_group = data; - - action = gtk_action_group_get_action (action_group, - "Paste"); - if (action != NULL) { - gtk_action_set_sensitive (action, - gtk_selection_data_targets_include_text (selection_data)); - } - - g_object_unref (action_group); -} - - -static void -set_paste_sensitive_if_clipboard_contains_data (GtkActionGroup *action_group) -{ - GtkAction *action; - if (gdk_display_supports_selection_notification (gdk_display_get_default ())) { - gtk_clipboard_request_contents (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), - gdk_atom_intern ("TARGETS", FALSE), - received_clipboard_contents, - g_object_ref (action_group)); - } else { - /* If selection notification isn't supported, always activate Paste */ - action = gtk_action_group_get_action (action_group, - "Paste"); - gtk_action_set_sensitive (action, TRUE); - } -} - -static void -set_clipboard_menu_items_sensitive (GtkActionGroup *action_group) -{ - GtkAction *action; - - action = gtk_action_group_get_action (action_group, - "Cut"); - gtk_action_set_sensitive (action, TRUE); - action = gtk_action_group_get_action (action_group, - "Copy"); - gtk_action_set_sensitive (action, TRUE); -} - -static void -set_clipboard_menu_items_insensitive (GtkActionGroup *action_group) -{ - GtkAction *action; - - action = gtk_action_group_get_action (action_group, - "Cut"); - gtk_action_set_sensitive (action, FALSE); - action = gtk_action_group_get_action (action_group, - "Copy"); - gtk_action_set_sensitive (action, FALSE); -} - -static gboolean -clipboard_items_are_merged_in (GtkWidget *widget) -{ - return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), - "Nautilus:clipboard_menu_items_merged")); -} - -static void -set_clipboard_items_are_merged_in (GObject *widget_as_object, - gboolean merged_in) -{ - g_object_set_data (widget_as_object, - "Nautilus:clipboard_menu_items_merged", - GINT_TO_POINTER (merged_in)); -} - -static void -editable_connect_callbacks (GObject *object, - TargetCallbackData *target_data) -{ - g_signal_connect_after (object, "selection-changed", - G_CALLBACK (selection_changed_callback), target_data); - selection_changed_callback (GTK_WIDGET (object), - target_data); -} - -static void -editable_disconnect_callbacks (GObject *object, - TargetCallbackData *target_data) -{ - g_signal_handlers_disconnect_matched (object, - G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, - 0, 0, NULL, - G_CALLBACK (selection_changed_callback), - target_data); -} - -static void -merge_in_clipboard_menu_items (GObject *widget_as_object, - TargetCallbackData *target_data) -{ - gboolean add_selection_callback; - - g_assert (target_data != NULL); - - add_selection_callback = target_data->shares_selection_changes; - - gtk_ui_manager_insert_action_group (target_data->ui_manager, - target_data->action_group, 0); - - set_paste_sensitive_if_clipboard_contains_data (target_data->action_group); - - g_signal_connect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), "owner-change", - G_CALLBACK (owner_change_callback), target_data); - - if (add_selection_callback) { - target_data->connect_callbacks (widget_as_object, target_data); - } else { - /* If we don't use sensitivity, everything should be on */ - set_clipboard_menu_items_sensitive (target_data->action_group); - } - set_clipboard_items_are_merged_in (widget_as_object, TRUE); -} - -static void -merge_out_clipboard_menu_items (GObject *widget_as_object, - TargetCallbackData *target_data) - -{ - gboolean selection_callback_was_added; - - g_assert (target_data != NULL); - - gtk_ui_manager_remove_action_group (target_data->ui_manager, - target_data->action_group); - - g_signal_handlers_disconnect_matched (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), - G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, - 0, 0, NULL, - G_CALLBACK (owner_change_callback), - target_data); - - selection_callback_was_added = target_data->shares_selection_changes; - - if (selection_callback_was_added) { - target_data->disconnect_callbacks (widget_as_object, target_data); - } - set_clipboard_items_are_merged_in (widget_as_object, FALSE); -} - -static gboolean -focus_changed_callback (GtkWidget *widget, - GdkEventAny *event, - gpointer callback_data) -{ - /* Connect the component to the container if the widget has focus. */ - if (gtk_widget_has_focus (widget)) { - if (!clipboard_items_are_merged_in (widget)) { - merge_in_clipboard_menu_items (G_OBJECT (widget), callback_data); - } - } else { - if (clipboard_items_are_merged_in (widget)) { - merge_out_clipboard_menu_items (G_OBJECT (widget), callback_data); - } - } - - return FALSE; -} - -static void -selection_changed_callback (GtkWidget *widget, - gpointer callback_data) -{ - TargetCallbackData *target_data; - GtkEditable *editable; - int start, end; - - target_data = (TargetCallbackData *) callback_data; - g_assert (target_data != NULL); - - editable = GTK_EDITABLE (widget); - g_assert (editable != NULL); - - if (gtk_editable_get_selection_bounds (editable, &start, &end) && start != end) { - set_clipboard_menu_items_sensitive (target_data->action_group); - } else { - set_clipboard_menu_items_insensitive (target_data->action_group); - } -} - -static void -owner_change_callback (GtkClipboard *clipboard, - GdkEventOwnerChange *event, - gpointer callback_data) -{ - TargetCallbackData *target_data; - - g_assert (callback_data != NULL); - target_data = callback_data; - - set_paste_sensitive_if_clipboard_contains_data (target_data->action_group); -} - -static void -target_destroy_callback (GtkWidget *object, - gpointer callback_data) -{ - g_assert (callback_data != NULL); - - if (clipboard_items_are_merged_in (object)) { - merge_out_clipboard_menu_items (G_OBJECT (object), callback_data); - } -} - -static void -target_data_free (TargetCallbackData *target_data) -{ - g_object_unref (target_data->action_group); - g_free (target_data); -} - -static const GtkActionEntry clipboard_entries[] = { - /* name, stock id */ { "Cut", NULL, - /* label, accelerator */ N_("Cu_t"), "<control>X", - /* tooltip */ N_("Cut the selected text to the clipboard"), - G_CALLBACK (action_cut_callback) }, - /* name, stock id */ { "Copy", NULL, - /* label, accelerator */ N_("_Copy"), "<control>C", - /* tooltip */ N_("Copy the selected text to the clipboard"), - G_CALLBACK (action_copy_callback) }, - /* name, stock id */ { "Paste", NULL, - /* label, accelerator */ N_("_Paste"), "<control>V", - /* tooltip */ N_("Paste the text stored on the clipboard"), - G_CALLBACK (action_paste_callback) }, - /* name, stock id */ { "Select All", NULL, - /* label, accelerator */ N_("Select _All"), "<control>A", - /* tooltip */ N_("Select all the text in a text field"), - G_CALLBACK (action_select_all_callback) }, -}; - -static TargetCallbackData * -initialize_clipboard_component_with_callback_data (GtkEditable *target, - GtkUIManager *ui_manager, - gboolean shares_selection_changes, - SelectAllCallback select_all_callback, - ConnectCallbacksFunc connect_callbacks, - ConnectCallbacksFunc disconnect_callbacks) -{ - GtkActionGroup *action_group; - TargetCallbackData *target_data; - - action_group = gtk_action_group_new ("ClipboardActions"); - gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions (action_group, - clipboard_entries, G_N_ELEMENTS (clipboard_entries), - target); - - /* Do the actual connection of the UI to the container at - * focus time, and disconnect at both focus and destroy - * time. - */ - target_data = g_new (TargetCallbackData, 1); - target_data->ui_manager = ui_manager; - target_data->action_group = action_group; - target_data->shares_selection_changes = shares_selection_changes; - target_data->select_all_callback = select_all_callback; - target_data->connect_callbacks = connect_callbacks; - target_data->disconnect_callbacks = disconnect_callbacks; - - return target_data; -} - -static void -nautilus_clipboard_real_set_up (gpointer target, - GtkUIManager *ui_manager, - gboolean shares_selection_changes, - SelectAllCallback select_all_callback, - ConnectCallbacksFunc connect_callbacks, - ConnectCallbacksFunc disconnect_callbacks) -{ - TargetCallbackData *target_data; - - if (g_object_get_data (G_OBJECT (target), "Nautilus:clipboard_target_data") != NULL) { - return; - } - - target_data = initialize_clipboard_component_with_callback_data - (target, - ui_manager, - shares_selection_changes, - select_all_callback, - connect_callbacks, - disconnect_callbacks); - - g_signal_connect (target, "focus-in-event", - G_CALLBACK (focus_changed_callback), target_data); - g_signal_connect (target, "focus-out-event", - G_CALLBACK (focus_changed_callback), target_data); - g_signal_connect (target, "destroy", - G_CALLBACK (target_destroy_callback), target_data); - - g_object_set_data_full (G_OBJECT (target), "Nautilus:clipboard_target_data", - target_data, (GDestroyNotify) target_data_free); - - /* Call the focus changed callback once to merge if the window is - * already in focus. - */ - focus_changed_callback (GTK_WIDGET (target), NULL, target_data); -} - -void -nautilus_clipboard_set_up_editable (GtkEditable *target, - GtkUIManager *ui_manager, - gboolean shares_selection_changes) -{ - g_return_if_fail (GTK_IS_EDITABLE (target)); - g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager)); - - nautilus_clipboard_real_set_up (target, ui_manager, - shares_selection_changes, - editable_select_all_callback, - editable_connect_callbacks, - editable_disconnect_callbacks); -} - static GList * convert_lines_to_str_list (char **lines, gboolean *cut) { diff --git a/libnautilus-private/nautilus-clipboard.h b/libnautilus-private/nautilus-clipboard.h index 26d976230..eee64ef97 100644 --- a/libnautilus-private/nautilus-clipboard.h +++ b/libnautilus-private/nautilus-clipboard.h @@ -26,18 +26,6 @@ #include <gtk/gtk.h> -/* This makes this editable or text view put clipboard commands into - * the passed UI manager when the editable/text view is in focus. - * Callers in Nautilus normally get the UI manager from - * nautilus_window_get_ui_manager. */ -/* The shares selection changes argument should be set to true if the - * widget uses the signal "selection-changed" to tell others about - * text selection changes. The NautilusEntry widget - * is currently the only editable in nautilus that shares selection - * changes. */ -void nautilus_clipboard_set_up_editable (GtkEditable *target, - GtkUIManager *ui_manager, - gboolean shares_selection_changes); void nautilus_clipboard_clear_if_colliding_uris (GtkWidget *widget, const GList *item_uris, GdkAtom copied_files_atom); diff --git a/libnautilus-private/nautilus-ui-utilities.c b/libnautilus-private/nautilus-ui-utilities.c index 6fcc3a419..f766b6fd6 100644 --- a/libnautilus-private/nautilus-ui-utilities.c +++ b/libnautilus-private/nautilus-ui-utilities.c @@ -29,87 +29,146 @@ #include <gio/gio.h> #include <gtk/gtk.h> +#include <string.h> -void -nautilus_ui_unmerge_ui (GtkUIManager *ui_manager, - guint *merge_id, - GtkActionGroup **action_group) +static GMenuModel * +find_gmenu_model (GMenuModel *model, + const gchar *model_id) { - if (*merge_id != 0) { - gtk_ui_manager_remove_ui (ui_manager, - *merge_id); - *merge_id = 0; - } - if (*action_group != NULL) { - gtk_ui_manager_remove_action_group (ui_manager, - *action_group); - *action_group = NULL; + gint i, n_items; + GMenuModel *insertion_model = NULL; + + n_items = g_menu_model_get_n_items (model); + + for (i = 0; i < n_items && !insertion_model; i++) { + gchar *id = NULL; + if (g_menu_model_get_item_attribute (model, i, "id", "s", &id) && + g_strcmp0 (id, model_id) == 0) { + insertion_model = g_menu_model_get_item_link (model, i, G_MENU_LINK_SECTION); + if (!insertion_model) + insertion_model = g_menu_model_get_item_link (model, i, G_MENU_LINK_SUBMENU); + } else { + GMenuModel *submodel; + GMenuModel *submenu; + gint j, j_items; + + submodel = g_menu_model_get_item_link (model, i, G_MENU_LINK_SECTION); + + if (!submodel) { + submodel = g_menu_model_get_item_link (model, i, G_MENU_LINK_SUBMENU); + if (!submodel) + continue; + } + + j_items = g_menu_model_get_n_items (submodel); + for (j = 0; j < j_items && !insertion_model; j++) { + submenu = g_menu_model_get_item_link (submodel, j, G_MENU_LINK_SUBMENU); + if (submenu) + insertion_model = find_gmenu_model (submenu, model_id); + } + } + + g_free (id); } + + return insertion_model; } - + +/* + * The original GMenu is modified adding to the section @submodel_name + * the items in @gmenu_to_merge. + * @gmenu_to_merge should be a list of menu items. + */ void -nautilus_ui_prepare_merge_ui (GtkUIManager *ui_manager, - const char *name, - guint *merge_id, - GtkActionGroup **action_group) +nautilus_gmenu_merge (GMenu *original, + GMenu *gmenu_to_merge, + const gchar *submodel_name, + gboolean prepend) { - *merge_id = gtk_ui_manager_new_merge_id (ui_manager); - *action_group = gtk_action_group_new (name); - gtk_action_group_set_translation_domain (*action_group, GETTEXT_PACKAGE); - gtk_ui_manager_insert_action_group (ui_manager, *action_group, 0); - g_object_unref (*action_group); /* owned by ui manager */ -} + gint i, n_items; + GMenuModel *submodel; + GMenuItem *item; -static void -extension_action_callback (GtkAction *action, - gpointer callback_data) -{ - nautilus_menu_item_activate (NAUTILUS_MENU_ITEM (callback_data)); + g_return_if_fail (G_IS_MENU (original)); + g_return_if_fail (G_IS_MENU (gmenu_to_merge)); + + submodel = find_gmenu_model (G_MENU_MODEL (original), submodel_name); + + g_return_if_fail (submodel != NULL); + + n_items = g_menu_model_get_n_items (G_MENU_MODEL (gmenu_to_merge)); + + for (i = 0; i < n_items; i++) { + item = g_menu_item_new_from_model (G_MENU_MODEL (gmenu_to_merge), i); + if (prepend) + g_menu_prepend_item (G_MENU (submodel), item); + else + g_menu_append_item (G_MENU (submodel), item); + g_object_unref (item); + } } -GtkAction * -nautilus_action_from_menu_item (NautilusMenuItem *item, - GtkWidget *parent_widget) +/* + * The GMenu @menu is modified adding to the section @submodel_name + * the item @item. + */ +void +nautilus_gmenu_add_item_in_submodel (GMenu *menu, + GMenuItem *item, + const gchar *submodel_name, + gboolean prepend) { - char *name, *label, *tip, *icon_name; - gboolean sensitive, priority; - GtkAction *action; - GdkPixbuf *pixbuf; + GMenuModel *submodel; - g_object_get (G_OBJECT (item), - "name", &name, "label", &label, - "tip", &tip, "icon", &icon_name, - "sensitive", &sensitive, - "priority", &priority, - NULL); - - action = gtk_action_new (name, - label, - tip, - NULL); - - if (icon_name != NULL) { - pixbuf = nautilus_ui_get_menu_icon (icon_name, parent_widget); - if (pixbuf != NULL) { - gtk_action_set_gicon (action, G_ICON (pixbuf)); - g_object_unref (pixbuf); - } - } + g_return_if_fail (G_IS_MENU (menu)); + g_return_if_fail (G_IS_MENU_ITEM (item)); - gtk_action_set_sensitive (action, sensitive); - g_object_set (action, "is-important", priority, NULL); + submodel = find_gmenu_model (G_MENU_MODEL (menu), submodel_name); - g_signal_connect_data (action, "activate", - G_CALLBACK (extension_action_callback), - g_object_ref (item), - (GClosureNotify)g_object_unref, 0); + g_return_if_fail (submodel != NULL); + if (prepend) + g_menu_prepend_item (G_MENU (submodel), item); + else + g_menu_append_item (G_MENU (submodel), item); +} + +void +nautilus_pop_up_context_menu (GtkWidget *parent, + GMenu *menu, + GdkEventButton *event) +{ + GtkWidget *gtk_menu; + + int button; + + g_return_if_fail (G_IS_MENU (menu)); + g_return_if_fail (GTK_IS_WIDGET (parent)); + + gtk_menu = gtk_menu_new_from_model (G_MENU_MODEL (menu)); + gtk_menu_attach_to_widget (GTK_MENU (gtk_menu), parent, NULL); + /* The event button needs to be 0 if we're popping up this menu from + * a button release, else a 2nd click outside the menu with any button + * other than the one that invoked the menu will be ignored (instead + * of dismissing the menu). This is a subtle fragility of the GTK menu code. + */ + if (event) { + button = event->type == GDK_BUTTON_RELEASE + ? 0 + : event->button; + } else { + button = 0; + } - g_free (name); - g_free (label); - g_free (tip); - g_free (icon_name); + gtk_menu_popup (GTK_MENU (gtk_menu), /* menu */ + NULL, /* parent_menu_shell */ + NULL, /* parent_menu_item */ + NULL, /* popup_position_func */ + NULL, /* popup_position_data */ + button, /* button */ + event ? event->time : gtk_get_current_event_time ()); /* activate_time */ - return action; + g_object_ref_sink (gtk_menu); + g_object_unref (gtk_menu); } GdkPixbuf * @@ -161,6 +220,18 @@ nautilus_escape_action_name (const char *action_name, case '"': g_string_append (s, "\\q"); break; + case ' ': + g_string_append (s, "+"); + break; + case '(': + g_string_append (s, "#"); + break; + case ')': + g_string_append (s, "^"); + break; + case ':': + g_string_append (s, "\\\\"); + break; default: g_string_append_c (s, *action_name); } diff --git a/libnautilus-private/nautilus-ui-utilities.h b/libnautilus-private/nautilus-ui-utilities.h index 0341478ac..18b3d78a4 100644 --- a/libnautilus-private/nautilus-ui-utilities.h +++ b/libnautilus-private/nautilus-ui-utilities.h @@ -26,15 +26,18 @@ #include <gtk/gtk.h> #include <libnautilus-extension/nautilus-menu-item.h> -void nautilus_ui_unmerge_ui (GtkUIManager *ui_manager, - guint *merge_id, - GtkActionGroup **action_group); -void nautilus_ui_prepare_merge_ui (GtkUIManager *ui_manager, - const char *name, - guint *merge_id, - GtkActionGroup **action_group); -GtkAction * nautilus_action_from_menu_item (NautilusMenuItem *item, - GtkWidget *parent_widget); + +void nautilus_gmenu_add_item_in_submodel (GMenu *menu, + GMenuItem *item, + const gchar *section_name, + gboolean prepend); +void nautilus_gmenu_merge (GMenu *original, + GMenu *gmenu_to_merge, + const gchar *submodel_name, + gboolean prepend); +void nautilus_pop_up_context_menu (GtkWidget *parent, + GMenu *menu, + GdkEventButton *event); GdkPixbuf * nautilus_ui_get_menu_icon (const char *icon_name, GtkWidget *parent_widget); diff --git a/src/Makefile.am b/src/Makefile.am index 6f0d6a848..d3c88dd73 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -137,7 +137,6 @@ nautilus_built_sources = \ $(NULL) nautilus_SOURCES = \ - nautilus-actions.h \ nautilus-application.c \ nautilus-application.h \ nautilus-application-actions.c \ @@ -208,7 +207,6 @@ nautilus_SOURCES = \ nautilus-view.h \ nautilus-view-dnd.c \ nautilus-view-dnd.h \ - nautilus-window-menus.c \ nautilus-window-private.h \ nautilus-window-slot.c \ nautilus-window-slot.h \ diff --git a/src/nautilus-app-menu.ui b/src/nautilus-app-menu.ui index c534cbd19..514dc5d33 100644 --- a/src/nautilus-app-menu.ui +++ b/src/nautilus-app-menu.ui @@ -9,13 +9,14 @@ </section> <section> <item> - <attribute name="action">app.connect-to-server</attribute> - <attribute name="label" translatable="yes">Connect to _Server…</attribute> + <attribute name="action">app.show-hide-sidebar</attribute> + <attribute name="label" translatable="yes">Sidebar</attribute> </item> + </section> + <section> <item> - <attribute name="action">app.bookmarks</attribute> - <attribute name="label" translatable="yes">_Bookmarks</attribute> - <attribute name="accel"><Primary>b</attribute> + <attribute name="action">app.connect-to-server</attribute> + <attribute name="label" translatable="yes">Connect to _Server…</attribute> </item> </section> <section> diff --git a/src/nautilus-application-actions.c b/src/nautilus-application-actions.c index a69de747d..b37c38559 100644 --- a/src/nautilus-application-actions.c +++ b/src/nautilus-application-actions.c @@ -28,6 +28,8 @@ #define DEBUG_FLAG NAUTILUS_DEBUG_APPLICATION #include <libnautilus-private/nautilus-debug.h> +#include <libnautilus-private/nautilus-ui-utilities.h> +#include <libnautilus-private/nautilus-global-preferences.h> static void action_new_window (GSimpleAction *action, @@ -240,12 +242,33 @@ action_show_file_transfers (GSimpleAction *action, nautilus_progress_ui_handler_ensure_window (progress_handler); } +static void +action_show_hide_sidebar (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + GList *window, *windows; + + windows = gtk_application_get_windows (GTK_APPLICATION (user_data)); + + for (window = windows; window != NULL; window = window->next) { + if (g_variant_get_boolean (state)) { + nautilus_window_show_sidebar (window->data); + } else { + nautilus_window_hide_sidebar (window->data); + } + } + + g_simple_action_set_state (action, state); +} + static GActionEntry app_entries[] = { { "new-window", action_new_window, NULL, NULL, NULL }, { "connect-to-server", action_connect_to_server, NULL, NULL, NULL }, { "enter-location", action_enter_location, NULL, NULL, NULL }, { "bookmarks", action_bookmarks, NULL, NULL, NULL }, { "preferences", action_preferences, NULL, NULL, NULL }, + { "show-hide-sidebar", NULL, NULL, "true", action_show_hide_sidebar }, { "search", action_search, "(ss)", NULL, NULL }, { "about", action_about, NULL, NULL, NULL }, { "help", action_help, NULL, NULL, NULL }, @@ -261,12 +284,12 @@ nautilus_init_application_actions (NautilusApplication *app) { GtkBuilder *builder; GError *error = NULL; + gboolean show_sidebar; const gchar *debug_no_app_menu; g_action_map_add_action_entries (G_ACTION_MAP (app), app_entries, G_N_ELEMENTS (app_entries), app); - gtk_application_add_accelerator (GTK_APPLICATION (app), "F10", "win.gear-menu", NULL); builder = gtk_builder_new (); gtk_builder_add_from_resource (builder, "/org/gnome/nautilus/nautilus-app-menu.ui", &error); @@ -288,4 +311,14 @@ nautilus_init_application_actions (NautilusApplication *app) "gtk-shell-shows-app-menu", FALSE, NULL); } + + show_sidebar = g_settings_get_boolean (nautilus_window_state, + NAUTILUS_WINDOW_STATE_START_WITH_SIDEBAR); + + g_action_group_change_action_state (G_ACTION_GROUP (app), + "show-hide-sidebar", + g_variant_new_boolean (show_sidebar)); + + nautilus_application_add_accelerator (G_APPLICATION (app), "app.show-hide-sidebar", "F9"); + nautilus_application_add_accelerator (G_APPLICATION (app), "app.bookmarks", "<control>b"); } diff --git a/src/nautilus-application.c b/src/nautilus-application.c index 8c3488c2c..197dd28a0 100644 --- a/src/nautilus-application.c +++ b/src/nautilus-application.c @@ -86,6 +86,19 @@ struct _NautilusApplicationPriv { GList *windows; }; +void +nautilus_application_add_accelerator (GApplication *app, + const gchar *action_name, + const gchar *accel) +{ + const gchar *vaccels[] = { + accel, + NULL + }; + + gtk_application_set_accels_for_action (GTK_APPLICATION (app), action_name, vaccels); +} + GList * nautilus_application_get_windows (NautilusApplication *application) { diff --git a/src/nautilus-application.h b/src/nautilus-application.h index 540d8b48b..3dd4af598 100644 --- a/src/nautilus-application.h +++ b/src/nautilus-application.h @@ -63,6 +63,10 @@ NautilusApplication * nautilus_application_new (void); NautilusWindow * nautilus_application_create_window (NautilusApplication *application, GdkScreen *screen); +void nautilus_application_add_accelerator (GApplication *app, + const gchar *action_name, + const gchar *accel); + GList * nautilus_application_get_windows (NautilusApplication *application); void nautilus_application_open_location (NautilusApplication *application, diff --git a/src/nautilus-canvas-view-ui.xml b/src/nautilus-canvas-view-ui.xml deleted file mode 100644 index 4ead416bb..000000000 --- a/src/nautilus-canvas-view-ui.xml +++ /dev/null @@ -1,22 +0,0 @@ -<ui> - <popup name="ViewMenu" accelerators="true"> - <placeholder name="Layout Options"> - <menuitem name="Manual Layout" action="Manual Layout"/> - <placeholder name="Auto Layout"> - <menuitem name="Sort by Name" action="Sort by Name"/> - <menuitem name="Sort by Size" action="Sort by Size"/> - <menuitem name="Sort by Type" action="Sort by Type"/> - <menuitem name="Sort by Modification Date" action="Sort by Modification Date"/> - <menuitem name="Sort by Access Date" action="Sort by Access Date"/> - <menuitem name="Sort by Trash Time" action="Sort by Trash Time"/> - <menuitem name="Sort by Search Relevance" action="Sort by Search Relevance"/> - </placeholder> - <separator name="Layout separator"/> - <menuitem name="Reversed Order" action="Reversed Order"/> - <menuitem name="Keep Aligned" action="Keep Aligned"/> - </placeholder> - <separator/> - <placeholder name="View Details"> - </placeholder> - </popup> -</ui> diff --git a/src/nautilus-canvas-view.c b/src/nautilus-canvas-view.c index e6761995b..c56f0210a 100644 --- a/src/nautilus-canvas-view.c +++ b/src/nautilus-canvas-view.c @@ -25,11 +25,11 @@ #include "nautilus-canvas-view.h" -#include "nautilus-actions.h" #include "nautilus-canvas-view-container.h" #include "nautilus-desktop-canvas-view.h" #include "nautilus-error-reporting.h" #include "nautilus-view-dnd.h" +#include "nautilus-toolbar.h" #include <stdlib.h> #include <errno.h> @@ -75,7 +75,7 @@ static GParamSpec *properties[NUM_PROPERTIES] = { NULL, }; typedef struct { const NautilusFileSortType sort_type; const char *metadata_text; - const char *action; + const char *action_target_name; } SortCriterion; typedef enum { @@ -94,9 +94,6 @@ struct NautilusCanvasViewDetails const SortCriterion *sort; gboolean sort_reversed; - GtkActionGroup *canvas_action_group; - guint canvas_merge_id; - gulong clipboard_handler_id; GtkWidget *canvas_container; @@ -107,7 +104,6 @@ struct NautilusCanvasViewDetails gboolean supports_keep_aligned; }; - /* Note that the first item in this list is the default sort, * and that the items show up in the menu in the order they * appear in this list. @@ -116,37 +112,37 @@ static const SortCriterion sort_criteria[] = { { NAUTILUS_FILE_SORT_BY_DISPLAY_NAME, "name", - "Sort by Name" + "name" }, { NAUTILUS_FILE_SORT_BY_SIZE, "size", - "Sort by Size" + "size" }, { NAUTILUS_FILE_SORT_BY_TYPE, "type", - "Sort by Type" + "type" }, { NAUTILUS_FILE_SORT_BY_MTIME, "modification date", - "Sort by Modification Date" + "modification-date" }, { NAUTILUS_FILE_SORT_BY_ATIME, "access date", - "Sort by Access Date" + "access-date" }, { NAUTILUS_FILE_SORT_BY_TRASHED_TIME, "trashed", - NAUTILUS_ACTION_SORT_TRASH_TIME + "trash-time" }, { NAUTILUS_FILE_SORT_BY_SEARCH_RELEVANCE, NULL, - NAUTILUS_ACTION_SORT_SEARCH_RELEVANCE, + "search-relevance", } }; @@ -154,19 +150,15 @@ static void nautilus_canvas_view_set_directory_sort_by (N NautilusFile *file, const char *sort_by); static void nautilus_canvas_view_set_zoom_level (NautilusCanvasView *view, - NautilusCanvasZoomLevel new_level, - gboolean always_emit); + NautilusCanvasZoomLevel new_level); static void nautilus_canvas_view_update_click_mode (NautilusCanvasView *canvas_view); static gboolean nautilus_canvas_view_supports_scaling (NautilusCanvasView *canvas_view); static void nautilus_canvas_view_reveal_selection (NautilusView *view); static const SortCriterion *get_sort_criterion_by_sort_type (NautilusFileSortType sort_type); -static void set_sort_criterion_by_sort_type (NautilusCanvasView *canvas_view, - NautilusFileSortType sort_type); static gboolean set_sort_reversed (NautilusCanvasView *canvas_view, gboolean new_value, gboolean set_metadata); static void switch_to_manual_layout (NautilusCanvasView *view); -static void update_layout_menus (NautilusCanvasView *view); static NautilusFileSortType get_default_sort_order (NautilusFile *file, gboolean *reversed); static void nautilus_canvas_view_clear (NautilusView *view); @@ -292,9 +284,6 @@ real_set_sort_criterion (NautilusCanvasView *canvas_view, file, sort->metadata_text); } - - /* Update the layout menus to match the new sort setting. */ - update_layout_menus (canvas_view); } static void @@ -312,12 +301,6 @@ set_sort_criterion (NautilusCanvasView *canvas_view, real_set_sort_criterion (canvas_view, sort, FALSE, set_metadata); } -static void -clear_sort_criterion (NautilusCanvasView *canvas_view) -{ - real_set_sort_criterion (canvas_view, NULL, TRUE, TRUE); -} - void nautilus_canvas_view_clean_up_by_name (NautilusCanvasView *canvas_view) { @@ -346,25 +329,6 @@ nautilus_canvas_view_using_auto_layout (NautilusCanvasView *canvas_view) } static void -action_sort_radio_callback (GtkAction *action, - GtkRadioAction *current, - NautilusCanvasView *view) -{ - NautilusFileSortType sort_type; - - sort_type = gtk_radio_action_get_current_value (current); - - /* Note that id might be a toggle item. - * Ignore non-sort ids so that they don't cause sorting. - */ - if (sort_type == NAUTILUS_FILE_SORT_NONE) { - switch_to_manual_layout (view); - } else { - set_sort_criterion_by_sort_type (view, sort_type); - } -} - -static void list_covers (NautilusCanvasIconData *data, gpointer callback_data) { GSList **file_list; @@ -495,68 +459,6 @@ nautilus_canvas_view_supports_keep_aligned (NautilusCanvasView *view) return view->details->supports_keep_aligned; } -static void -update_layout_menus (NautilusCanvasView *view) -{ - gboolean is_auto_layout; - GtkAction *action; - const char *action_name; - NautilusFile *file; - - if (view->details->canvas_action_group == NULL) { - return; - } - - is_auto_layout = nautilus_canvas_view_using_auto_layout (view); - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (view)); - - if (nautilus_canvas_view_supports_auto_layout (view)) { - /* Mark sort criterion. */ - action_name = is_auto_layout ? view->details->sort->action : NAUTILUS_ACTION_MANUAL_LAYOUT; - action = gtk_action_group_get_action (view->details->canvas_action_group, - action_name); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); - - action = gtk_action_group_get_action (view->details->canvas_action_group, - NAUTILUS_ACTION_REVERSED_ORDER); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), - view->details->sort_reversed); - gtk_action_set_sensitive (action, is_auto_layout); - - action = gtk_action_group_get_action (view->details->canvas_action_group, - NAUTILUS_ACTION_SORT_TRASH_TIME); - - if (file != NULL && nautilus_file_is_in_trash (file)) { - gtk_action_set_visible (action, TRUE); - } else { - gtk_action_set_visible (action, FALSE); - } - - action = gtk_action_group_get_action (view->details->canvas_action_group, - NAUTILUS_ACTION_SORT_SEARCH_RELEVANCE); - - if (file != NULL && nautilus_file_is_in_search (file)) { - gtk_action_set_visible (action, TRUE); - } else { - gtk_action_set_visible (action, FALSE); - } - } - - action = gtk_action_group_get_action (view->details->canvas_action_group, - NAUTILUS_ACTION_MANUAL_LAYOUT); - gtk_action_set_visible (action, - nautilus_canvas_view_supports_manual_layout (view)); - - action = gtk_action_group_get_action (view->details->canvas_action_group, - NAUTILUS_ACTION_KEEP_ALIGNED); - gtk_action_set_visible (action, - nautilus_canvas_view_supports_keep_aligned (view)); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), - nautilus_canvas_container_is_keep_aligned (get_canvas_container (view))); - gtk_action_set_sensitive (action, !is_auto_layout); -} - - static char * nautilus_canvas_view_get_directory_sort_by (NautilusCanvasView *canvas_view, NautilusFile *file) @@ -737,9 +639,6 @@ set_sort_reversed (NautilusCanvasView *canvas_view, /* Store the new sort setting. */ nautilus_canvas_view_set_directory_sort_reversed (canvas_view, nautilus_view_get_directory_as_file (NAUTILUS_VIEW (canvas_view)), new_value); } - - /* Update the layout menus to match the new sort-order setting. */ - update_layout_menus (canvas_view); return TRUE; } @@ -759,6 +658,19 @@ get_sort_criterion_by_metadata_text (const char *metadata_text) } static const SortCriterion * +get_sort_criterion_by_action_target_name (const char *action_target_name) +{ + guint i; + /* Figure out what the new sort setting should be. */ + for (i = 0; i < G_N_ELEMENTS (sort_criteria); i++) { + if (g_strcmp0 (sort_criteria[i].action_target_name, action_target_name) == 0) { + return &sort_criteria[i]; + } + } + return NULL; +} + +static const SortCriterion * get_sort_criterion_by_sort_type (NautilusFileSortType sort_type) { guint i; @@ -828,8 +740,10 @@ nautilus_canvas_view_begin_loading (NautilusView *view) (get_canvas_container (canvas_view), nautilus_canvas_view_get_directory_auto_layout (canvas_view, file)); - /* e.g. keep aligned may have changed */ - update_layout_menus (canvas_view); + /* We could changed to the trash directory or to searching, and then we + * need to update the menus */ + nautilus_view_update_context_menus(view); + nautilus_view_update_toolbar_menus(view); } static void @@ -878,8 +792,7 @@ nautilus_canvas_view_get_zoom_level (NautilusView *view) static void nautilus_canvas_view_set_zoom_level (NautilusCanvasView *view, - NautilusCanvasZoomLevel new_level, - gboolean always_emit) + NautilusCanvasZoomLevel new_level) { NautilusCanvasContainer *canvas_container; @@ -888,20 +801,10 @@ nautilus_canvas_view_set_zoom_level (NautilusCanvasView *view, new_level <= NAUTILUS_CANVAS_ZOOM_LEVEL_LARGE); canvas_container = get_canvas_container (view); - if (nautilus_canvas_container_get_zoom_level (canvas_container) == new_level) { - if (always_emit) { - g_signal_emit_by_name (view, "zoom-level-changed"); - } + if (nautilus_canvas_container_get_zoom_level (canvas_container) == new_level) return; - } nautilus_canvas_container_set_zoom_level (canvas_container, new_level); - - g_signal_emit_by_name (view, "zoom-level-changed"); - - if (nautilus_view_get_active (NAUTILUS_VIEW (view))) { - nautilus_view_update_menus (NAUTILUS_VIEW (view)); - } } static void @@ -913,7 +816,10 @@ nautilus_canvas_view_zoom_to_level (NautilusView *view, g_assert (NAUTILUS_IS_CANVAS_VIEW (view)); canvas_view = NAUTILUS_CANVAS_VIEW (view); - nautilus_canvas_view_set_zoom_level (canvas_view, zoom_level, FALSE); + nautilus_canvas_view_set_zoom_level (canvas_view, zoom_level); + + /* Chain up to the parent to update menus */ + NAUTILUS_VIEW_CLASS (nautilus_canvas_view_parent_class)->zoom_to_level (view, zoom_level); } static void @@ -926,13 +832,14 @@ nautilus_canvas_view_bump_zoom_level (NautilusView *view, int zoom_increment) return; } - new_level = nautilus_canvas_view_get_zoom_level (view) + zoom_increment; if (new_level >= NAUTILUS_CANVAS_ZOOM_LEVEL_SMALL && new_level <= NAUTILUS_CANVAS_ZOOM_LEVEL_LARGE) { nautilus_canvas_view_zoom_to_level (view, new_level); } + + nautilus_view_update_toolbar_menus (view); } static void @@ -988,68 +895,79 @@ nautilus_canvas_view_get_selection (NautilusView *view) } static void -set_sort_criterion_by_sort_type (NautilusCanvasView *canvas_view, - NautilusFileSortType sort_type) +action_reversed_order (GSimpleAction *action, + GVariant *state, + gpointer user_data) { - const SortCriterion *sort; + gboolean reversed_order; - g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view)); + g_assert (NAUTILUS_IS_CANVAS_VIEW (user_data)); - sort = get_sort_criterion_by_sort_type (sort_type); - g_return_if_fail (sort != NULL); - - if (sort == canvas_view->details->sort - && nautilus_canvas_view_using_auto_layout (canvas_view)) { - return; + reversed_order = g_variant_get_boolean (state); + if (set_sort_reversed (user_data, reversed_order, TRUE)) { + nautilus_canvas_container_sort (get_canvas_container (user_data)); + nautilus_canvas_view_reveal_selection (NAUTILUS_VIEW (user_data)); } - set_sort_criterion (canvas_view, sort, TRUE); - nautilus_canvas_container_sort (get_canvas_container (canvas_view)); - nautilus_canvas_view_reveal_selection (NAUTILUS_VIEW (canvas_view)); + g_simple_action_set_state (action, state); } - static void -action_reversed_order_callback (GtkAction *action, - gpointer user_data) +action_keep_aligned (GSimpleAction *action, + GVariant *state, + gpointer user_data) { + NautilusFile *file; NautilusCanvasView *canvas_view; + gboolean keep_aligned; canvas_view = NAUTILUS_CANVAS_VIEW (user_data); + file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (canvas_view)); + keep_aligned = g_variant_get_boolean (state); - if (set_sort_reversed (canvas_view, - gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)), - TRUE)) { - nautilus_canvas_container_sort (get_canvas_container (canvas_view)); - nautilus_canvas_view_reveal_selection (NAUTILUS_VIEW (canvas_view)); - } + nautilus_canvas_view_set_directory_keep_aligned (canvas_view, + file, + keep_aligned); + nautilus_canvas_container_set_keep_aligned (get_canvas_container (canvas_view), + keep_aligned); + + g_simple_action_set_state (action, state); } static void -action_keep_aligned_callback (GtkAction *action, - gpointer user_data) +action_sort_order_changed (GSimpleAction *action, + GVariant *value, + gpointer user_data) { - NautilusCanvasView *canvas_view; - NautilusFile *file; - gboolean keep_aligned; + const gchar *target_name; + const SortCriterion *sort_criterion; - canvas_view = NAUTILUS_CANVAS_VIEW (user_data); + g_assert (NAUTILUS_IS_CANVAS_VIEW (user_data)); - keep_aligned = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + target_name = g_variant_get_string (value, NULL); + sort_criterion = get_sort_criterion_by_action_target_name (target_name); - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (canvas_view)); - nautilus_canvas_view_set_directory_keep_aligned (canvas_view, - file, - keep_aligned); - - nautilus_canvas_container_set_keep_aligned (get_canvas_container (canvas_view), - keep_aligned); + g_assert (sort_criterion != NULL); + /* Note that id might be a toggle item. + * Ignore non-sort ids so that they don't cause sorting. + */ + if (sort_criterion->sort_type == NAUTILUS_FILE_SORT_NONE) { + switch_to_manual_layout (user_data); + } else { + set_sort_criterion (user_data, sort_criterion, TRUE); + + nautilus_canvas_container_sort (get_canvas_container (user_data)); + nautilus_canvas_view_reveal_selection (NAUTILUS_VIEW (user_data)); + } + + g_simple_action_set_state (action, value); } static void switch_to_manual_layout (NautilusCanvasView *canvas_view) { - if (!nautilus_canvas_view_using_auto_layout (canvas_view)) { + if (!nautilus_canvas_view_using_auto_layout (canvas_view) || + !nautilus_view_is_editable (NAUTILUS_VIEW (canvas_view))) { return; } @@ -1076,8 +994,6 @@ layout_changed_callback (NautilusCanvasContainer *container, file, nautilus_canvas_view_using_auto_layout (canvas_view)); } - - update_layout_menus (canvas_view); } static gboolean @@ -1099,124 +1015,72 @@ nautilus_canvas_view_start_renaming_file (NautilusView *view, (get_canvas_container (NAUTILUS_CANVAS_VIEW (view)), select_all); } -static const GtkToggleActionEntry canvas_view_toggle_entries[] = { - /* name, stock id */ { "Reversed Order", NULL, - /* label, accelerator */ N_("Re_versed Order"), NULL, - /* tooltip */ N_("Display icons in the opposite order"), - G_CALLBACK (action_reversed_order_callback), - 0 }, - /* name, stock id */ { "Keep Aligned", NULL, - /* label, accelerator */ N_("_Keep Aligned"), NULL, - /* tooltip */ N_("Keep icons lined up on a grid"), - G_CALLBACK (action_keep_aligned_callback), - 0 }, -}; - -static const GtkRadioActionEntry arrange_radio_entries[] = { - { NAUTILUS_ACTION_MANUAL_LAYOUT, NULL, - N_("_Manually"), NULL, - N_("Leave icons wherever they are dropped"), - NAUTILUS_FILE_SORT_NONE }, - { "Sort by Name", NULL, - N_("By _Name"), NULL, - N_("Keep icons sorted by name in rows"), - NAUTILUS_FILE_SORT_BY_DISPLAY_NAME }, - { "Sort by Size", NULL, - N_("By _Size"), NULL, - N_("Keep icons sorted by size in rows"), - NAUTILUS_FILE_SORT_BY_SIZE }, - { "Sort by Type", NULL, - N_("By _Type"), NULL, - N_("Keep icons sorted by type in rows"), - NAUTILUS_FILE_SORT_BY_TYPE }, - { "Sort by Modification Date", NULL, - N_("By Modification _Date"), NULL, - N_("Keep icons sorted by modification date in rows"), - NAUTILUS_FILE_SORT_BY_MTIME }, - { "Sort by Access Date", NULL, - N_("By _Access Date"), NULL, - N_("Keep icons sorted by access date in rows"), - NAUTILUS_FILE_SORT_BY_ATIME }, - { NAUTILUS_ACTION_SORT_TRASH_TIME, NULL, - N_("By T_rash Time"), NULL, - N_("Keep icons sorted by trash time in rows"), - NAUTILUS_FILE_SORT_BY_TRASHED_TIME }, - { NAUTILUS_ACTION_SORT_SEARCH_RELEVANCE, NULL, - N_("By Search Relevance"), NULL, - N_("Keep icons sorted by search relevance in rows"), - NAUTILUS_FILE_SORT_BY_SEARCH_RELEVANCE }, +const GActionEntry canvas_view_entries[] = { + { "keep-aligned", NULL, NULL, "true", action_keep_aligned }, + { "reversed-order", NULL, NULL, "false", action_reversed_order }, + { "sort", NULL, "s", "'name'", action_sort_order_changed }, }; static void -nautilus_canvas_view_merge_menus (NautilusView *view) +nautilus_canvas_view_update_actions_state (NautilusView *view) { + GActionGroup *view_action_group; + GAction *action; + gboolean keep_aligned; NautilusCanvasView *canvas_view; - GtkUIManager *ui_manager; - GtkActionGroup *action_group; - - g_assert (NAUTILUS_IS_CANVAS_VIEW (view)); - - NAUTILUS_VIEW_CLASS (nautilus_canvas_view_parent_class)->merge_menus (view); canvas_view = NAUTILUS_CANVAS_VIEW (view); - ui_manager = nautilus_view_get_ui_manager (NAUTILUS_VIEW (canvas_view)); + NAUTILUS_VIEW_CLASS (nautilus_canvas_view_parent_class)->update_actions_state (view); - action_group = gtk_action_group_new ("CanvasViewActions"); - gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE); - canvas_view->details->canvas_action_group = action_group; - gtk_action_group_add_toggle_actions (action_group, - canvas_view_toggle_entries, G_N_ELEMENTS (canvas_view_toggle_entries), - canvas_view); - gtk_action_group_add_radio_actions (action_group, - arrange_radio_entries, - G_N_ELEMENTS (arrange_radio_entries), - -1, - G_CALLBACK (action_sort_radio_callback), - canvas_view); - - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - g_object_unref (action_group); /* owned by ui manager */ + view_action_group = nautilus_view_get_action_group (view); + if (nautilus_canvas_view_supports_auto_layout (canvas_view)) { + g_action_group_change_action_state (view_action_group, + "reversed-order", + g_variant_new_boolean (NAUTILUS_CANVAS_VIEW (view)->details->sort_reversed)); - canvas_view->details->canvas_merge_id = - gtk_ui_manager_add_ui_from_resource (ui_manager, "/org/gnome/nautilus/nautilus-canvas-view-ui.xml", NULL); + g_action_group_change_action_state (view_action_group, + "sort", + g_variant_new_string (NAUTILUS_CANVAS_VIEW (view)->details->sort->action_target_name)); + } - update_layout_menus (canvas_view); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), "keep-aligned"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + canvas_view->details->supports_keep_aligned); + if (canvas_view->details->supports_keep_aligned) { + keep_aligned = nautilus_canvas_container_is_keep_aligned (get_canvas_container (canvas_view)); + g_action_change_state (action, g_variant_new_boolean (keep_aligned)); + } } static void -nautilus_canvas_view_unmerge_menus (NautilusView *view) +nautilus_canvas_view_update_toolbar_menus (NautilusView *view) { - NautilusCanvasView *canvas_view; - GtkUIManager *ui_manager; + NautilusFile *file; + NautilusToolbar *toolbar; + NautilusCanvasContainer *canvas_container; + gint zoom_level; - canvas_view = NAUTILUS_CANVAS_VIEW (view); + NAUTILUS_VIEW_CLASS (nautilus_canvas_view_parent_class)->update_toolbar_menus (view); - NAUTILUS_VIEW_CLASS (nautilus_canvas_view_parent_class)->unmerge_menus (view); + toolbar = NAUTILUS_TOOLBAR (nautilus_window_get_toolbar (nautilus_view_get_window (view))); - ui_manager = nautilus_view_get_ui_manager (view); - if (ui_manager != NULL) { - nautilus_ui_unmerge_ui (ui_manager, - &canvas_view->details->canvas_merge_id, - &canvas_view->details->canvas_action_group); - } -} -static void -nautilus_canvas_view_update_menus (NautilusView *view) -{ - NautilusCanvasView *canvas_view; - GtkAction *action; - gboolean editable; - canvas_view = NAUTILUS_CANVAS_VIEW (view); + nautilus_toolbar_show_sort_menu (toolbar); - NAUTILUS_VIEW_CLASS (nautilus_canvas_view_parent_class)->update_menus(view); + file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (view)); + if (file != NULL && nautilus_file_is_in_trash (file)) + nautilus_toolbar_show_sort_trash_time (toolbar); + + if (file != NULL && nautilus_file_is_in_search (file)) + nautilus_toolbar_show_sort_search_relevance (toolbar); + + canvas_container = get_canvas_container (NAUTILUS_CANVAS_VIEW (view)); + zoom_level = nautilus_canvas_container_get_zoom_level (canvas_container); - editable = nautilus_view_is_editable (view); - action = gtk_action_group_get_action (canvas_view->details->canvas_action_group, - NAUTILUS_ACTION_MANUAL_LAYOUT); - gtk_action_set_sensitive (action, editable); + nautilus_toolbar_view_menu_widget_set_zoom_level (toolbar, + (gdouble) (zoom_level)); } static void @@ -1457,8 +1321,7 @@ canvas_container_context_click_selection_callback (NautilusCanvasContainer *cont g_assert (NAUTILUS_IS_CANVAS_CONTAINER (container)); g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view)); - nautilus_view_pop_up_selection_context_menu - (NAUTILUS_VIEW (canvas_view), event); + nautilus_view_pop_up_selection_context_menu (NAUTILUS_VIEW (canvas_view), event); } static void @@ -1469,27 +1332,7 @@ canvas_container_context_click_background_callback (NautilusCanvasContainer *con g_assert (NAUTILUS_IS_CANVAS_CONTAINER (container)); g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view)); - nautilus_view_pop_up_background_context_menu - (NAUTILUS_VIEW (canvas_view), event); -} - -static gboolean -nautilus_canvas_view_react_to_canvas_change_idle_callback (gpointer data) -{ - NautilusCanvasView *canvas_view; - - g_assert (NAUTILUS_IS_CANVAS_VIEW (data)); - - canvas_view = NAUTILUS_CANVAS_VIEW (data); - canvas_view->details->react_to_canvas_change_idle_id = 0; - - /* Rebuild the menus since some of them (e.g. Restore Stretched Icons) - * may be different now. - */ - nautilus_view_update_menus (NAUTILUS_VIEW (canvas_view)); - - /* Don't call this again (unless rescheduled) */ - return FALSE; + nautilus_view_pop_up_background_context_menu (NAUTILUS_VIEW (canvas_view), event); } static void @@ -1505,20 +1348,6 @@ icon_position_changed_callback (NautilusCanvasContainer *container, g_assert (container == get_canvas_container (canvas_view)); g_assert (NAUTILUS_IS_FILE (file)); - /* Schedule updating menus for the next idle. Doing it directly here - * noticeably slows down canvas stretching. The other work here to - * store the canvas position and scale does not seem to noticeably - * slow down canvas stretching. It would be trickier to move to an - * idle call, because we'd have to keep track of potentially multiple - * sets of file/geometry info. - */ - if (nautilus_view_get_active (NAUTILUS_VIEW (canvas_view)) && - canvas_view->details->react_to_canvas_change_idle_id == 0) { - canvas_view->details->react_to_canvas_change_idle_id - = g_idle_add (nautilus_canvas_view_react_to_canvas_change_idle_callback, - canvas_view); - } - /* Store the new position of the canvas in the metadata. */ if (!nautilus_canvas_view_using_auto_layout (canvas_view)) { position_string = g_strdup_printf @@ -1557,20 +1386,6 @@ icon_rename_ended_cb (NautilusCanvasContainer *container, nautilus_rename_file (file, new_name, NULL, NULL); } -static void -icon_rename_started_cb (NautilusCanvasContainer *container, - GtkWidget *widget, - gpointer callback_data) -{ - NautilusView *directory_view; - - directory_view = NAUTILUS_VIEW (callback_data); - nautilus_clipboard_set_up_editable - (GTK_EDITABLE (widget), - nautilus_view_get_ui_manager (directory_view), - FALSE); -} - static char * get_icon_uri_callback (NautilusCanvasContainer *container, NautilusFile *file, @@ -1841,15 +1656,13 @@ create_canvas_container (NautilusCanvasView *canvas_view) G_CALLBACK (get_stored_icon_position_callback), canvas_view, 0); g_signal_connect_object (canvas_container, "layout-changed", G_CALLBACK (layout_changed_callback), canvas_view, 0); - g_signal_connect_object (canvas_container, "icon-rename-started", - G_CALLBACK (icon_rename_started_cb), canvas_view, 0); g_signal_connect_object (canvas_container, "icon-rename-ended", G_CALLBACK (icon_rename_ended_cb), canvas_view, 0); g_signal_connect_object (canvas_container, "icon-stretch-started", - G_CALLBACK (nautilus_view_update_menus), canvas_view, + G_CALLBACK (nautilus_view_update_context_menus), canvas_view, G_CONNECT_SWAPPED); g_signal_connect_object (canvas_container, "icon-stretch-ended", - G_CALLBACK (nautilus_view_update_menus), canvas_view, + G_CALLBACK (nautilus_view_update_context_menus), canvas_view, G_CONNECT_SWAPPED); g_signal_connect_object (canvas_container, "get-stored-layout-timestamp", @@ -2030,6 +1843,7 @@ nautilus_canvas_view_class_init (NautilusCanvasViewClass *klass) nautilus_view_class->add_file = nautilus_canvas_view_add_file; nautilus_view_class->begin_loading = nautilus_canvas_view_begin_loading; nautilus_view_class->bump_zoom_level = nautilus_canvas_view_bump_zoom_level; + nautilus_view_class->zoom_to_level = nautilus_canvas_view_zoom_to_level; nautilus_view_class->can_rename_file = nautilus_canvas_view_can_rename_file; nautilus_view_class->can_zoom_in = nautilus_canvas_view_can_zoom_in; nautilus_view_class->can_zoom_out = nautilus_canvas_view_can_zoom_out; @@ -2050,11 +1864,10 @@ nautilus_canvas_view_class_init (NautilusCanvasViewClass *klass) nautilus_view_class->compare_files = compare_files; nautilus_view_class->zoom_to_level = nautilus_canvas_view_zoom_to_level; nautilus_view_class->click_policy_changed = nautilus_canvas_view_click_policy_changed; - nautilus_view_class->merge_menus = nautilus_canvas_view_merge_menus; - nautilus_view_class->unmerge_menus = nautilus_canvas_view_unmerge_menus; + nautilus_view_class->update_toolbar_menus = nautilus_canvas_view_update_toolbar_menus; + nautilus_view_class->update_actions_state = nautilus_canvas_view_update_actions_state; nautilus_view_class->sort_directories_first_changed = nautilus_canvas_view_sort_directories_first_changed; nautilus_view_class->start_renaming_file = nautilus_canvas_view_start_renaming_file; - nautilus_view_class->update_menus = nautilus_canvas_view_update_menus; nautilus_view_class->using_manual_layout = nautilus_canvas_view_using_manual_layout; nautilus_view_class->widget_to_file_operation_position = nautilus_canvas_view_widget_to_file_operation_position; nautilus_view_class->get_view_id = nautilus_canvas_view_get_id; @@ -2097,6 +1910,7 @@ static void nautilus_canvas_view_init (NautilusCanvasView *canvas_view) { NautilusCanvasContainer *canvas_container; + GActionGroup *view_action_group; g_return_if_fail (gtk_bin_get_child (GTK_BIN (canvas_view)) == NULL); @@ -2138,6 +1952,12 @@ nautilus_canvas_view_init (NautilusCanvasView *canvas_view) g_signal_connect (nautilus_clipboard_monitor_get (), "clipboard-info", G_CALLBACK (canvas_view_notify_clipboard_info), canvas_view); + + view_action_group = nautilus_view_get_action_group (NAUTILUS_VIEW (canvas_view)); + g_action_map_add_action_entries (G_ACTION_MAP (view_action_group), + canvas_view_entries, + G_N_ELEMENTS (canvas_view_entries), + canvas_view); } NautilusView * diff --git a/src/nautilus-desktop-canvas-view.c b/src/nautilus-desktop-canvas-view.c index 946748abc..757a98f90 100644 --- a/src/nautilus-desktop-canvas-view.c +++ b/src/nautilus-desktop-canvas-view.c @@ -27,7 +27,6 @@ #include "nautilus-desktop-canvas-view.h" -#include "nautilus-actions.h" #include "nautilus-canvas-view-container.h" #include "nautilus-view.h" @@ -65,8 +64,6 @@ struct NautilusDesktopCanvasViewDetails { GdkWindow *root_window; - GtkActionGroup *desktop_action_group; - guint desktop_merge_id; /* For the desktop rescanning */ @@ -76,8 +73,7 @@ struct NautilusDesktopCanvasViewDetails }; static void default_zoom_level_changed (gpointer user_data); -static void real_merge_menus (NautilusView *view); -static void real_update_menus (NautilusView *view); +static void real_update_context_menus (NautilusView *view); static void nautilus_desktop_canvas_view_update_canvas_container_fonts (NautilusDesktopCanvasView *view); static void font_changed_callback (gpointer callback_data); @@ -239,7 +235,6 @@ static void nautilus_desktop_canvas_view_dispose (GObject *object) { NautilusDesktopCanvasView *canvas_view; - GtkUIManager *ui_manager; canvas_view = NAUTILUS_DESKTOP_CANVAS_VIEW (object); @@ -249,13 +244,6 @@ nautilus_desktop_canvas_view_dispose (GObject *object) canvas_view->details->reload_desktop_timeout = 0; } - ui_manager = nautilus_view_get_ui_manager (NAUTILUS_VIEW (canvas_view)); - if (ui_manager != NULL) { - nautilus_ui_unmerge_ui (ui_manager, - &canvas_view->details->desktop_merge_id, - &canvas_view->details->desktop_action_group); - } - g_signal_handlers_disconnect_by_func (nautilus_icon_view_preferences, default_zoom_level_changed, canvas_view); @@ -263,7 +251,7 @@ nautilus_desktop_canvas_view_dispose (GObject *object) font_changed_callback, canvas_view); g_signal_handlers_disconnect_by_func (gnome_lockdown_preferences, - nautilus_view_update_menus, + nautilus_view_update_context_menus, canvas_view); G_OBJECT_CLASS (nautilus_desktop_canvas_view_parent_class)->dispose (object); @@ -278,8 +266,7 @@ nautilus_desktop_canvas_view_class_init (NautilusDesktopCanvasViewClass *class) G_OBJECT_CLASS (class)->dispose = nautilus_desktop_canvas_view_dispose; - vclass->merge_menus = real_merge_menus; - vclass->update_menus = real_update_menus; + vclass->update_context_menus = real_update_context_menus; vclass->get_view_id = real_get_id; g_type_class_add_private (class, sizeof (NautilusDesktopCanvasViewDetails)); @@ -517,7 +504,7 @@ nautilus_desktop_canvas_view_init (NautilusDesktopCanvasView *desktop_canvas_vie g_signal_connect_swapped (gnome_lockdown_preferences, "changed::" NAUTILUS_PREFERENCES_LOCKDOWN_COMMAND_LINE, - G_CALLBACK (nautilus_view_update_menus), + G_CALLBACK (nautilus_view_update_context_menus), desktop_canvas_view); } @@ -559,53 +546,58 @@ get_control_center_command (const gchar ** params_out) } static void -action_change_background_callback (GtkAction *action, - gpointer data) +action_change_background (GSimpleAction *action, + GVariant *state, + gpointer user_data) { const gchar *control_center_cmd, *params; - g_assert (NAUTILUS_VIEW (data)); + g_assert (NAUTILUS_VIEW (user_data)); control_center_cmd = get_control_center_command (¶ms); if (control_center_cmd == NULL) { return; } - nautilus_launch_application_from_command (gtk_widget_get_screen (GTK_WIDGET (data)), + nautilus_launch_application_from_command (gtk_widget_get_screen (GTK_WIDGET (user_data)), control_center_cmd, FALSE, params, NULL); } static void -action_empty_trash_conditional_callback (GtkAction *action, - gpointer data) +action_empty_trash (GSimpleAction *action, + GVariant *state, + gpointer user_data) { - g_assert (NAUTILUS_IS_VIEW (data)); + g_assert (NAUTILUS_IS_VIEW (user_data)); - nautilus_file_operations_empty_trash (GTK_WIDGET (data)); + nautilus_file_operations_empty_trash (GTK_WIDGET (user_data)); } static void -action_stretch_callback (GtkAction *action, - gpointer callback_data) +action_stretch (GSimpleAction *action, + GVariant *state, + gpointer user_data) { nautilus_canvas_container_show_stretch_handles - (get_canvas_container (callback_data)); + (get_canvas_container (user_data)); } static void -action_unstretch_callback (GtkAction *action, - gpointer callback_data) +action_unstretch (GSimpleAction *action, + GVariant *state, + gpointer user_data) { - nautilus_canvas_container_unstretch (get_canvas_container (callback_data)); + nautilus_canvas_container_unstretch (get_canvas_container (user_data)); } static void -action_clean_up_callback (GtkAction *action, - gpointer callback_data) +action_organize_desktop_by_name (GSimpleAction *action, + GVariant *state, + gpointer user_data) { - nautilus_canvas_view_clean_up_by_name (NAUTILUS_CANVAS_VIEW (callback_data)); + nautilus_canvas_view_clean_up_by_name (NAUTILUS_CANVAS_VIEW (user_data)); } static gboolean @@ -637,146 +629,59 @@ trash_link_is_selection (NautilusView *view) return result; } +const GActionEntry desktop_view_entries[] = { + { "change-background", action_change_background }, + { "organize-desktop-by-name", action_organize_desktop_by_name }, + { "empty-trash", action_empty_trash }, + { "stretch", action_stretch }, + { "unstretch", action_unstretch }, +}; + static void -real_update_menus (NautilusView *view) +real_update_context_menus (NautilusView *view) { + NautilusCanvasContainer *canvas_container; NautilusDesktopCanvasView *desktop_view; - NautilusCanvasContainer *canvas_container; - gboolean include_empty_trash; - char *label; - GtkAction *action; - int selection_count; + GAction *action; + GActionGroup *view_action_group; + int selection_count; g_assert (NAUTILUS_IS_DESKTOP_CANVAS_VIEW (view)); - NAUTILUS_VIEW_CLASS (nautilus_desktop_canvas_view_parent_class)->update_menus (view); + NAUTILUS_VIEW_CLASS (nautilus_desktop_canvas_view_parent_class)->update_context_menus (view); + view_action_group = nautilus_view_get_action_group (view); desktop_view = NAUTILUS_DESKTOP_CANVAS_VIEW (view); - /* Empty Trash */ - include_empty_trash = trash_link_is_selection (view); - action = gtk_action_group_get_action (desktop_view->details->desktop_action_group, - NAUTILUS_ACTION_EMPTY_TRASH_CONDITIONAL); - gtk_action_set_visible (action, - include_empty_trash); - if (include_empty_trash) { - label = g_strdup (_("E_mpty Trash")); - g_object_set (action , "label", label, NULL); - gtk_action_set_sensitive (action, - !nautilus_trash_monitor_is_empty ()); - g_free (label); - } - - /* Stretch */ - selection_count = nautilus_view_get_selection_count (view); - canvas_container = get_canvas_container (desktop_view); - - action = gtk_action_group_get_action (desktop_view->details->desktop_action_group, - NAUTILUS_ACTION_STRETCH); - gtk_action_set_sensitive (action, - selection_count == 1 - && canvas_container != NULL - && !nautilus_canvas_container_has_stretch_handles (canvas_container)); - gtk_action_set_visible (action, TRUE); + g_action_map_add_action_entries (G_ACTION_MAP (view_action_group), + desktop_view_entries, + G_N_ELEMENTS (desktop_view_entries), + view); - /* Unstretch */ - action = gtk_action_group_get_action (desktop_view->details->desktop_action_group, - NAUTILUS_ACTION_UNSTRETCH); - g_object_set (action, "label", - (selection_count > 1) - ? _("Restore Icons' Original Si_zes") - : _("Restore Icon's Original Si_ze"), - NULL); - gtk_action_set_sensitive (action, - canvas_container != NULL - && nautilus_canvas_container_is_stretched (canvas_container)); - gtk_action_set_visible (action, TRUE); -} + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), "empty-trash"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), trash_link_is_selection (view)); -static const GtkActionEntry desktop_view_entries[] = { - /* name, stock id */ - { NAUTILUS_ACTION_CHANGE_BACKGROUND, NULL, - /* label, accelerator */ - N_("Change Desktop _Background"), NULL, - /* tooltip */ - N_("Show a window that lets you set your desktop background's pattern or color"), - G_CALLBACK (action_change_background_callback) }, - /* name, stock id */ - { "Empty Trash Conditional", NULL, - /* label, accelerator */ - N_("Empty Trash"), NULL, - /* tooltip */ - N_("Delete all items in the Trash"), - G_CALLBACK (action_empty_trash_conditional_callback) }, - /* name, stock id */ - { NAUTILUS_ACTION_CLEAN_UP, NULL, - /* label, accelerator */ - N_("_Organize Desktop by Name"), NULL, - /* tooltip */ - N_("Reposition icons to better fit in the window and avoid overlapping"), - G_CALLBACK (action_clean_up_callback) }, - /* name, stock id */ - { "Stretch", NULL, - /* label, accelerator */ - N_("Resize Icon…"), NULL, - /* tooltip */ - N_("Make the selected icons resizable"), - G_CALLBACK (action_stretch_callback) }, - /* name, stock id */ - { "Unstretch", NULL, - /* label, accelerator */ - N_("Restore Icons' Original Si_zes"), NULL, - /* tooltip */ - N_("Restore each selected icon to its original size"), - G_CALLBACK (action_unstretch_callback) }, -}; + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), "keep-aligned"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), TRUE); -static void -real_merge_menus (NautilusView *view) -{ - NautilusDesktopCanvasView *desktop_view; - GtkUIManager *ui_manager; - GtkActionGroup *action_group; - GtkAction *action; + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), "organize-desktop-by-name"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), TRUE); - NAUTILUS_VIEW_CLASS (nautilus_desktop_canvas_view_parent_class)->merge_menus (view); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), "change-background"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), TRUE); - desktop_view = NAUTILUS_DESKTOP_CANVAS_VIEW (view); + /* Stretch */ + selection_count = nautilus_view_get_selection_count (view); + canvas_container = get_canvas_container (desktop_view); - ui_manager = nautilus_view_get_ui_manager (view); - - action_group = gtk_action_group_new ("DesktopViewActions"); - gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE); - desktop_view->details->desktop_action_group = action_group; - gtk_action_group_add_actions (action_group, - desktop_view_entries, G_N_ELEMENTS (desktop_view_entries), - view); - - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - g_object_unref (action_group); /* owned by ui manager */ - - desktop_view->details->desktop_merge_id = - gtk_ui_manager_add_ui_from_resource (ui_manager, "/org/gnome/nautilus/nautilus-desktop-canvas-view-ui.xml", NULL); - - gtk_ui_manager_add_ui (ui_manager, - desktop_view->details->desktop_merge_id, - POPUP_PATH_CANVAS_APPEARANCE, - NAUTILUS_ACTION_STRETCH, - NAUTILUS_ACTION_STRETCH, - GTK_UI_MANAGER_MENUITEM, - FALSE); - gtk_ui_manager_add_ui (ui_manager, - desktop_view->details->desktop_merge_id, - POPUP_PATH_CANVAS_APPEARANCE, - NAUTILUS_ACTION_UNSTRETCH, - NAUTILUS_ACTION_UNSTRETCH, - GTK_UI_MANAGER_MENUITEM, - FALSE); - - if (get_control_center_command (NULL) == NULL) { - action = gtk_action_group_get_action (action_group, NAUTILUS_ACTION_CHANGE_BACKGROUND); - gtk_action_set_visible (action, FALSE); - } + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), "stretch"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), selection_count == 1 && + canvas_container != NULL && + !nautilus_canvas_container_has_stretch_handles (canvas_container)); + /* Unstretch */ + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), "unstretch"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), canvas_container != NULL && + nautilus_canvas_container_is_stretched (canvas_container)); } NautilusView * diff --git a/src/nautilus-desktop-window.c b/src/nautilus-desktop-window.c index 399fb9f92..862f5db37 100644 --- a/src/nautilus-desktop-window.c +++ b/src/nautilus-desktop-window.c @@ -24,7 +24,6 @@ #include <config.h> #include "nautilus-desktop-window.h" #include "nautilus-window-private.h" -#include "nautilus-actions.h" #include <X11/Xatom.h> #include <gdk/gdkx.h> @@ -75,25 +74,22 @@ nautilus_desktop_window_finalize (GObject *obj) static void nautilus_desktop_window_init_actions (NautilusDesktopWindow *window) { - GtkAction *action; - GtkActionGroup *action_group; - - action_group = nautilus_window_get_main_action_group (NAUTILUS_WINDOW (window)); + GAction *action; /* Don't allow close action on desktop */ - action = gtk_action_group_get_action (action_group, - NAUTILUS_ACTION_CLOSE); - gtk_action_set_sensitive (action, FALSE); + action = g_action_map_lookup_action (G_ACTION_MAP (window), + "close-current-view"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE); /* Don't allow new tab on desktop */ - action = gtk_action_group_get_action (action_group, - NAUTILUS_ACTION_NEW_TAB); - gtk_action_set_sensitive (action, FALSE); + action = g_action_map_lookup_action (G_ACTION_MAP (window), + "new-tab"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE); /* Don't allow search on desktop */ - action = gtk_action_group_get_action (action_group, - NAUTILUS_ACTION_SEARCH); - gtk_action_set_sensitive (action, FALSE); + action = g_action_map_lookup_action (G_ACTION_MAP (window), + "toggle-search"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE); } static void diff --git a/src/nautilus-list-view-ui.xml b/src/nautilus-list-view-ui.xml deleted file mode 100644 index 20f336d3c..000000000 --- a/src/nautilus-list-view-ui.xml +++ /dev/null @@ -1,7 +0,0 @@ -<ui> - <popup name="ViewMenu" accelerators="true"> - <placeholder name="View Details"> - <menuitem name="Visible Columns" action="Visible Columns"/> - </placeholder> - </popup> -</ui> diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c index 835e069d0..ea409d475 100644 --- a/src/nautilus-list-view.c +++ b/src/nautilus-list-view.c @@ -30,6 +30,7 @@ #include "nautilus-list-model.h" #include "nautilus-error-reporting.h" #include "nautilus-view-dnd.h" +#include "nautilus-toolbar.h" #include <string.h> #include <eel/eel-vfs-extensions.h> @@ -60,8 +61,6 @@ struct NautilusListViewDetails { GtkTreeView *tree_view; NautilusListModel *model; - GtkActionGroup *list_action_group; - guint list_merge_id; GtkTreeViewColumn *file_name_column; int file_name_column_num; @@ -88,7 +87,6 @@ struct NautilusListViewDetails { gboolean drag_started; gboolean ignore_button_release; gboolean row_selected_on_button_down; - gboolean menus_ready; gboolean active; GHashTable *columns; @@ -129,9 +127,8 @@ static GtkTargetList * source_target_list = NULL; static GList *nautilus_list_view_get_selection (NautilusView *view); static GList *nautilus_list_view_get_selection_for_file_transfer (NautilusView *view); -static void nautilus_list_view_set_zoom_level (NautilusListView *view, - NautilusListZoomLevel new_level, - gboolean always_set_level); +static void nautilus_list_view_set_zoom_level (NautilusListView *view, + NautilusListZoomLevel new_level); static void nautilus_list_view_scroll_to_file (NautilusListView *view, NautilusFile *file); static void nautilus_list_view_rename_callback (NautilusFile *file, @@ -1290,11 +1287,6 @@ cell_renderer_editing_started_cb (GtkCellRenderer *renderer, g_signal_connect (entry, "focus-out-event", G_CALLBACK (editable_focus_out_cb), list_view); - - nautilus_clipboard_set_up_editable - (GTK_EDITABLE (entry), - nautilus_view_get_ui_manager (NAUTILUS_VIEW (list_view)), - FALSE); } static void @@ -3005,12 +2997,13 @@ create_column_editor (NautilusListView *view) } static void -action_visible_columns_callback (GtkAction *action, - gpointer callback_data) +action_visible_columns (GSimpleAction *action, + GVariant *state, + gpointer user_data) { NautilusListView *list_view; - list_view = NAUTILUS_LIST_VIEW (callback_data); + list_view = NAUTILUS_LIST_VIEW (user_data); if (list_view->details->column_editor) { gtk_window_present (GTK_WINDOW (list_view->details->column_editor)); @@ -3023,79 +3016,30 @@ action_visible_columns_callback (GtkAction *action, } } -static const GtkActionEntry list_view_entries[] = { - /* name, stock id */ { "Visible Columns", NULL, - /* label, accelerator */ N_("Visible _Columns…"), NULL, - /* tooltip */ N_("Select the columns visible in this folder"), - G_CALLBACK (action_visible_columns_callback) }, +const GActionEntry list_view_entries[] = { + { "visible-columns", action_visible_columns }, }; static void -nautilus_list_view_merge_menus (NautilusView *view) -{ - NautilusListView *list_view; - GtkUIManager *ui_manager; - GtkActionGroup *action_group; - - list_view = NAUTILUS_LIST_VIEW (view); - - NAUTILUS_VIEW_CLASS (nautilus_list_view_parent_class)->merge_menus (view); - - ui_manager = nautilus_view_get_ui_manager (view); - - action_group = gtk_action_group_new ("ListViewActions"); - gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE); - list_view->details->list_action_group = action_group; - gtk_action_group_add_actions (action_group, - list_view_entries, G_N_ELEMENTS (list_view_entries), - list_view); - - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - g_object_unref (action_group); /* owned by ui manager */ - - list_view->details->list_merge_id = - gtk_ui_manager_add_ui_from_resource (ui_manager, "/org/gnome/nautilus/nautilus-list-view-ui.xml", NULL); - - list_view->details->menus_ready = TRUE; -} - -static void -nautilus_list_view_unmerge_menus (NautilusView *view) -{ - NautilusListView *list_view; - GtkUIManager *ui_manager; - - list_view = NAUTILUS_LIST_VIEW (view); - - NAUTILUS_VIEW_CLASS (nautilus_list_view_parent_class)->unmerge_menus (view); - - ui_manager = nautilus_view_get_ui_manager (view); - if (ui_manager != NULL) { - nautilus_ui_unmerge_ui (ui_manager, - &list_view->details->list_merge_id, - &list_view->details->list_action_group); - } -} - -static void -nautilus_list_view_update_menus (NautilusView *view) +nautilus_list_view_update_toolbar_menus (NautilusView *view) { NautilusListView *list_view; + NautilusToolbar *toolbar; list_view = NAUTILUS_LIST_VIEW (view); - /* don't update if the menus aren't ready */ - if (!list_view->details->menus_ready) { - return; - } + NAUTILUS_VIEW_CLASS (nautilus_list_view_parent_class)->update_toolbar_menus (view); + + toolbar = NAUTILUS_TOOLBAR (nautilus_window_get_toolbar (nautilus_view_get_window (view))); + nautilus_toolbar_view_menu_widget_set_zoom_level (toolbar, + (gdouble) list_view->details->zoom_level); - NAUTILUS_VIEW_CLASS (nautilus_list_view_parent_class)->update_menus (view); + nautilus_toolbar_show_visible_columns (toolbar); } static void nautilus_list_view_set_zoom_level (NautilusListView *view, - NautilusListZoomLevel new_level, - gboolean always_emit) + NautilusListZoomLevel new_level) { int column; @@ -3104,14 +3048,10 @@ nautilus_list_view_set_zoom_level (NautilusListView *view, new_level <= NAUTILUS_LIST_ZOOM_LEVEL_LARGE); if (view->details->zoom_level == new_level) { - if (always_emit) { - g_signal_emit_by_name (NAUTILUS_VIEW(view), "zoom-level-changed"); - } return; } view->details->zoom_level = new_level; - g_signal_emit_by_name (NAUTILUS_VIEW(view), "zoom-level-changed"); /* Select correctly scaled icons. */ column = nautilus_list_model_get_column_id_from_zoom_level (new_level); @@ -3119,51 +3059,47 @@ nautilus_list_view_set_zoom_level (NautilusListView *view, GTK_CELL_RENDERER (view->details->pixbuf_cell), "surface", column, NULL); - - nautilus_view_update_menus (NAUTILUS_VIEW (view)); - set_up_pixbuf_size (view); } static void -nautilus_list_view_bump_zoom_level (NautilusView *view, int zoom_increment) +nautilus_list_view_zoom_to_level (NautilusView *view, + gint zoom_level) { NautilusListView *list_view; - gint new_level; g_return_if_fail (NAUTILUS_IS_LIST_VIEW (view)); list_view = NAUTILUS_LIST_VIEW (view); - new_level = list_view->details->zoom_level + zoom_increment; - if (new_level >= NAUTILUS_LIST_ZOOM_LEVEL_SMALL && - new_level <= NAUTILUS_LIST_ZOOM_LEVEL_LARGE) { - nautilus_list_view_set_zoom_level (list_view, new_level, FALSE); - } + nautilus_list_view_set_zoom_level (list_view, zoom_level); + + NAUTILUS_VIEW_CLASS (nautilus_list_view_parent_class)->zoom_to_level (view, zoom_level); } + static void -nautilus_list_view_zoom_to_level (NautilusView *view, - gint zoom_level) +nautilus_list_view_bump_zoom_level (NautilusView *view, int zoom_increment) { NautilusListView *list_view; + gint new_level; g_return_if_fail (NAUTILUS_IS_LIST_VIEW (view)); list_view = NAUTILUS_LIST_VIEW (view); + new_level = list_view->details->zoom_level + zoom_increment; - nautilus_list_view_set_zoom_level (list_view, zoom_level, FALSE); + if (new_level >= NAUTILUS_LIST_ZOOM_LEVEL_SMALL && + new_level <= NAUTILUS_LIST_ZOOM_LEVEL_LARGE) { + nautilus_list_view_zoom_to_level (view, new_level); + } } static void nautilus_list_view_restore_default_zoom_level (NautilusView *view) { - NautilusListView *list_view; - g_return_if_fail (NAUTILUS_IS_LIST_VIEW (view)); - list_view = NAUTILUS_LIST_VIEW (view); - - nautilus_list_view_set_zoom_level (list_view, get_default_zoom_level (), FALSE); + nautilus_list_view_zoom_to_level (view, get_default_zoom_level ()); } static gboolean @@ -3559,10 +3495,8 @@ nautilus_list_view_class_init (NautilusListViewClass *class) nautilus_view_class->get_selection_for_file_transfer = nautilus_list_view_get_selection_for_file_transfer; nautilus_view_class->is_empty = nautilus_list_view_is_empty; nautilus_view_class->remove_file = nautilus_list_view_remove_file; - nautilus_view_class->merge_menus = nautilus_list_view_merge_menus; - nautilus_view_class->unmerge_menus = nautilus_list_view_unmerge_menus; - nautilus_view_class->update_menus = nautilus_list_view_update_menus; nautilus_view_class->restore_default_zoom_level = nautilus_list_view_restore_default_zoom_level; + nautilus_view_class->update_toolbar_menus = nautilus_list_view_update_toolbar_menus; nautilus_view_class->reveal_selection = nautilus_list_view_reveal_selection; nautilus_view_class->select_all = nautilus_list_view_select_all; nautilus_view_class->select_first = nautilus_list_view_select_first; @@ -3582,6 +3516,7 @@ nautilus_list_view_class_init (NautilusListViewClass *class) static void nautilus_list_view_init (NautilusListView *list_view) { + GActionGroup *view_action_group; list_view->details = g_new0 (NautilusListViewDetails, 1); /* ensure that the zoom level is always set before settings up the tree view columns */ @@ -3609,13 +3544,19 @@ nautilus_list_view_init (NautilusListView *list_view) nautilus_list_view_click_policy_changed (NAUTILUS_VIEW (list_view)); nautilus_list_view_sort_directories_first_changed (NAUTILUS_VIEW (list_view)); - nautilus_list_view_set_zoom_level (list_view, get_default_zoom_level (), TRUE); + nautilus_list_view_set_zoom_level (list_view, get_default_zoom_level ()); list_view->details->hover_path = NULL; list_view->details->clipboard_handler_id = g_signal_connect (nautilus_clipboard_monitor_get (), "clipboard-info", G_CALLBACK (list_view_notify_clipboard_info), list_view); + + view_action_group = nautilus_view_get_action_group (NAUTILUS_VIEW (list_view)); + g_action_map_add_action_entries (G_ACTION_MAP (view_action_group), + list_view_entries, + G_N_ELEMENTS (list_view_entries), + list_view); } NautilusView * diff --git a/src/nautilus-toolbar-action-menu.xml b/src/nautilus-toolbar-action-menu.xml new file mode 100644 index 000000000..a0eefd658 --- /dev/null +++ b/src/nautilus-toolbar-action-menu.xml @@ -0,0 +1,35 @@ +<?xml version="1.0"?> +<interface> + <!-- interface-requires gtk+ 3.0 --> + <menu id="action-menu"> + <section> + <item> + <attribute name="label" translatable="yes">New _Folder</attribute> + <attribute name="action">view.new-folder</attribute> + </item> + <item> + <attribute name="label" translatable="yes">New _Tab</attribute> + <attribute name="action">win.new-tab</attribute> + </item> + </section> + <section> + <attribute name="id">undo-redo-section</attribute> + </section> + <section> + <item> + <attribute name="label" translatable="yes">Select _All</attribute> + <attribute name="action">view.select-all</attribute> + </item> + <item> + <attribute name="label" translatable="yes">Enter _Location</attribute> + <attribute name="action">win.enter-location</attribute> + </item> + </section> + <section> + <item> + <attribute name="label" translatable="yes">_Bookmark this Location</attribute> + <attribute name="action">win.bookmark-current-location</attribute> + </item> + </section> + </menu> +</interface>
\ No newline at end of file diff --git a/src/nautilus-toolbar-ui.xml b/src/nautilus-toolbar-ui.xml new file mode 100644 index 000000000..4ecd63669 --- /dev/null +++ b/src/nautilus-toolbar-ui.xml @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <!-- interface-requires gtk+ 3.8 --> + <template class="NautilusToolbar" parent="GtkHeaderBar"> + <property name="visible">True</property> + <property name="show-close-button">True</property> + <child> + <object class="GtkBox" id="navigation_box"> + <property name="visible">True</property> + <property name="orientation">horizontal</property> + <style> + <class name="linked"/> + <class name="raised"/> + </style> + <child> + <object class="GtkButton" id="back_button"> + <property name="visible">True</property> + <property name="sensitive">True</property> + <property name="action_name">win.back</property> + <style> + <class name="image-button"/> + </style> + <child> + <object class="GtkImage" id="back_icon"> + <property name="visible">True</property> + <property name="icon-name">go-previous-symbolic</property> + <property name="icon-size">1</property> + </object> + </child> + </object> + <packing> + <property name="pack-type">start</property> + </packing> + </child> + <child> + <object class="GtkButton" id="forward_button"> + <property name="visible">True</property> + <property name="sensitive">True</property> + <property name="action_name">win.forward</property> + <style> + <class name="image-button"/> + </style> + <child> + <object class="GtkImage" id="forward_icon"> + <property name="visible">True</property> + <property name="icon-name">go-next-symbolic</property> + <property name="icon-size">1</property> + </object> + </child> + </object> + <packing> + <property name="pack-type">start</property> + </packing> + </child> + </object> + <packing> + <property name="pack-type">start</property> + </packing> + </child> + <child> + <object class="GtkBox" id="path_bar_container"> + </object> + <packing> + <property name="pack-type">start</property> + </packing> + </child> + <child> + <object class="GtkBox" id="location_entry_container"> + </object> + <packing> + <property name="pack-type">start</property> + </packing> + </child> + <child> + <object class="GtkMenuButton" id="action_button"> + <property name="visible">True</property> + <property name="sensitive">True</property> + <property name="action_name">win.action-menu</property> + <style> + <class name="image-button"/> + </style> + <child> + <object class="GtkImage" id="action_icon"> + <property name="visible">True</property> + <property name="icon-name">open-menu-symbolic</property> + <property name="icon-size">1</property> + </object> + </child> + </object> + <packing> + <property name="pack-type">end</property> + </packing> + </child> + <child> + <object class="GtkMenuButton" id="view_button"> + <property name="visible">True</property> + <property name="sensitive">True</property> + <style> + <class name="image-button"/> + </style> + </object> + <packing> + <property name="pack-type">end</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="search_button"> + <property name="visible">True</property> + <property name="sensitive">True</property> + <property name="action_name">win.toggle-search</property> + <style> + <class name="image-button"/> + </style> + <child> + <object class="GtkImage" id="search_icon"> + <property name="visible">True</property> + <property name="icon-name">edit-find-symbolic</property> + <property name="icon-size">1</property> + </object> + </child> + </object> + <packing> + <property name="pack-type">end</property> + </packing> + </child> + </template> +</interface> diff --git a/src/nautilus-toolbar-view-menu.xml b/src/nautilus-toolbar-view-menu.xml new file mode 100644 index 000000000..42249aa42 --- /dev/null +++ b/src/nautilus-toolbar-view-menu.xml @@ -0,0 +1,227 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <object class ="GtkPopoverMenu" id="view_menu_widget"> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="border_width">9</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <property name="width_request">160</property> + <child> + <object class="GtkBox" id="views_box"> + <property name="visible">True</property> + <property name="orientation">horizontal</property> + <style> + <class name="linked"/> + </style> + <child> + <object class="GtkModelButton" id="grid_button"> + <property name="visible">True</property> + <property name="text">Grid</property> + <property name="action-name">win.view-mode</property> + <property name="action-target">'grid'</property> + <property name="iconic">True</property> + <property name="centered">True</property> + <property name="icon">icon_grid</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkModelButton" id="list_button"> + <property name="visible">True</property> + <property name="text">List</property> + <property name="action-name">win.view-mode</property> + <property name="action-target">'list'</property> + <property name="iconic">True</property> + <property name="centered">True</property> + <property name="icon">icon_list</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + <child> + <object class="GtkScale" id="zoom_level_scale"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="draw_value">False</property> + <property name="has_origin">False</property> + <property name="adjustment">zoom_adjustment_grid</property> + <property name="round_digits">0</property> + <property name="restrict_to_fill_level">False</property> + <marks> + <mark value="0" position="bottom"/> + <mark value="1" position="bottom"/> + <mark value="2" position="bottom"/> + </marks> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + <child> + <object class="GtkBox" id="sort_menu"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="orientation">horizontal</property> + </object> + </child> + <child> + <object class="GtkLabel" id="sort_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">start</property> + <property name="label" translatable="yes">Sort</property> + <property name="margin-start">12</property> + <style> + <class name="separator"/> + </style> + </object> + </child> + <child> + <object class="GtkModelButton" id="sort_name"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="text" translatable="yes">_Name</property> + <property name="action-name">view.sort</property> + <property name="action-target">'name'</property> + </object> + </child> + <child> + <object class="GtkModelButton" id="sort_size"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="text" translatable="yes">_Size</property> + <property name="action-name">view.sort</property> + <property name="action-target">'size'</property> + </object> + </child> + <child> + <object class="GtkModelButton" id="sort_type"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="text" translatable="yes">_Type</property> + <property name="action-name">view.sort</property> + <property name="action-target">'type'</property> + </object> + </child> + <child> + <object class="GtkModelButton" id="sort_access_date"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="text" translatable="yes">Last _Opened</property> + <property name="action-name">view.sort</property> + <property name="action-target">'access-date'</property> + </object> + </child> + <child> + <object class="GtkModelButton" id="sort_trash_time"> + <property name="visible">False</property> + <property name="can_focus">True</property> + <property name="text" translatable="yes">Last _Trashed</property> + <property name="action-name">view.sort</property> + <property name="action-target">'trash-time'</property> + </object> + </child> + <child> + <object class="GtkModelButton" id="sort_search_relevance"> + <property name="visible">False</property> + <property name="can_focus">True</property> + <property name="text" translatable="yes">Search _Relevance</property> + <property name="action-name">view.sort</property> + <property name="action-target">'search-relevance'</property> + </object> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="orientation">horizontal</property> + </object> + </child> + <child> + <object class="GtkModelButton" id="reversed_order"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="text" translatable="yes">Re_verse order</property> + <property name="action-name">view.reversed-order</property> + </object> + </child> + </object> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="orientation">horizontal</property> + </object> + </child> + <child> + <object class="GtkModelButton" id="visible_columns"> + <property name="visible">False</property> + <property name="can_focus">True</property> + <property name="text" translatable="yes">_Visible Columns…</property> + <property name="action-name">view.visible-columns</property> + </object> + </child> + <child> + <object class="GtkModelButton" id="show_hidden_files"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="text" translatable="yes">Show _Hidden Files</property> + <property name="action-name">view.show-hidden-files</property> + </object> + </child> + <child> + <object class="GtkModelButton" id="reload"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="text" translatable="yes">_Reload</property> + <property name="action-name">win.reload</property> + </object> + </child> + <child> + <object class="GtkModelButton" id="stop"> + <property name="visible">False</property> + <property name="can_focus">True</property> + <property name="text" translatable="yes">St_op</property> + <property name="action-name">win.stop</property> + </object> + </child> + </object> + </child> + </object> + <object class="GThemedIcon" id="icon_grid"> + <property name="name">view-grid-symbolic</property> + </object> + <object class="GThemedIcon" id="icon_list"> + <property name="name">view-list-symbolic</property> + </object> + <object class="GtkAdjustment" id="zoom_adjustment_list"> + <property name="lower">0</property> + <property name="upper">2</property> + <property name="step_increment">1</property> + <property name="page_increment">1</property> + <property name="value">1</property> + </object> + <object class="GtkAdjustment" id="zoom_adjustment_grid"> + <property name="lower">0</property> + <property name="upper">2</property> + <property name="step_increment">1</property> + <property name="page_increment">1</property> + <property name="value">1</property> + </object> +</interface>
\ No newline at end of file diff --git a/src/nautilus-toolbar.c b/src/nautilus-toolbar.c index 642f524bc..ce86ebfdf 100644 --- a/src/nautilus-toolbar.c +++ b/src/nautilus-toolbar.c @@ -28,7 +28,6 @@ #include "nautilus-location-entry.h" #include "nautilus-pathbar.h" -#include "nautilus-actions.h" #include <libnautilus-private/nautilus-global-preferences.h> #include <libnautilus-private/nautilus-ui-utilities.h> @@ -42,15 +41,38 @@ typedef enum { NAUTILUS_NAVIGATION_DIRECTION_FORWARD } NautilusNavigationDirection; -struct _NautilusToolbarPriv { +struct _NautilusToolbarPrivate { NautilusWindow *window; + GtkWidget *path_bar_container; + GtkWidget *location_entry_container; GtkWidget *path_bar; GtkWidget *location_entry; gboolean show_location_entry; guint popup_timeout_id; + + gdouble scale_zoom_level; + + GtkWidget *view_button; + GtkWidget *action_button; + + GtkWidget *view_menu_widget; + GtkWidget *sort_menu; + GtkWidget *sort_trash_time; + GtkWidget *sort_search_relevance; + GtkWidget *visible_columns; + GtkWidget *stop; + GtkWidget *reload; + GtkAdjustment *zoom_adjustment_grid; + GtkAdjustment *zoom_adjustment_list; + GtkAdjustment *active_zoom_adjustment; + GtkWidget *zoom_level_scale; + GMenu *action_menu; + + GtkWidget *forward_button; + GtkWidget *back_button; }; enum { @@ -61,10 +83,36 @@ enum { static GParamSpec *properties[NUM_PROPERTIES] = { NULL, }; -G_DEFINE_TYPE (NautilusToolbar, nautilus_toolbar, GTK_TYPE_HEADER_BAR); +G_DEFINE_TYPE_WITH_PRIVATE(NautilusToolbar, nautilus_toolbar, GTK_TYPE_HEADER_BAR); static void unschedule_menu_popup_timeout (NautilusToolbar *self); +void +nautilus_toolbar_update_view_mode (NautilusToolbar *self, + const gchar *view_mode) +{ + gchar *name; + GtkWidget *image; + + if (g_strcmp0 (view_mode, "list") == 0) { + name = "view-list-symbolic"; + self->priv->active_zoom_adjustment = self->priv->zoom_adjustment_list; + } else if (g_strcmp0 (view_mode, "grid") == 0) { + name = "view-grid-symbolic"; + self->priv->active_zoom_adjustment = self->priv->zoom_adjustment_grid; + } else { + g_assert_not_reached (); + } + + gtk_range_set_adjustment (GTK_RANGE (self->priv->zoom_level_scale), + self->priv->active_zoom_adjustment); + + image = gtk_image_new (); + gtk_button_set_image (GTK_BUTTON (self->priv->view_button), image); + gtk_image_set_from_icon_name (GTK_IMAGE (image), name, + GTK_ICON_SIZE_MENU); +} + static void toolbar_update_appearance (NautilusToolbar *self) { @@ -79,45 +127,6 @@ toolbar_update_appearance (NautilusToolbar *self) !show_location_entry); } -static GtkWidget * -toolbar_create_toolbutton (NautilusToolbar *self, - gboolean create_menu, - gboolean create_toggle, - const gchar *name, - const gchar *tooltip) -{ - GtkWidget *button, *image; - GtkActionGroup *action_group; - GtkAction *action; - - action_group = nautilus_window_get_main_action_group (self->priv->window); - - if (create_menu) { - button = gtk_menu_button_new (); - } else if (create_toggle) { - button = gtk_toggle_button_new (); - } else { - button = gtk_button_new (); - } - - image = gtk_image_new (); - - gtk_button_set_image (GTK_BUTTON (button), image); - - if (create_menu) { - gtk_image_set_from_icon_name (GTK_IMAGE (image), name, - GTK_ICON_SIZE_MENU); - gtk_widget_set_tooltip_text (button, tooltip); - } else { - action = gtk_action_group_get_action (action_group, name); - gtk_activatable_set_related_action (GTK_ACTIVATABLE (button), action); - gtk_button_set_label (GTK_BUTTON (button), NULL); - gtk_widget_set_tooltip_text (button, gtk_action_get_tooltip (action)); - } - - return button; -} - static void activate_back_or_forward_menu_item (GtkMenuItem *menu_item, NautilusWindow *window, @@ -145,6 +154,25 @@ activate_forward_menu_item_callback (GtkMenuItem *menu_item, NautilusWindow *win activate_back_or_forward_menu_item (menu_item, window, FALSE); } +void +nautilus_toolbar_sync_navigation_buttons (NautilusToolbar *self) +{ + NautilusWindowSlot *active_slot; + GAction *action; + gboolean enabled; + + /* Check if the back and forward buttons need enabling or disabling. */ + active_slot = nautilus_window_get_active_slot (self->priv->window); + + action = g_action_map_lookup_action (G_ACTION_MAP (self->priv->window), "back"); + enabled = nautilus_window_slot_get_back_history (active_slot) != NULL; + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), enabled); + + action = g_action_map_lookup_action (G_ACTION_MAP (self->priv->window), "forward"); + enabled = nautilus_window_slot_get_forward_history (active_slot) != NULL; + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), enabled); +} + static void fill_menu (NautilusWindow *window, GtkWidget *menu, @@ -316,11 +344,10 @@ schedule_menu_popup_timeout (NautilusToolbar *self, popup_menu_timeout_cb, data, (GDestroyNotify) schedule_menu_data_free); } - static gboolean -tool_button_press_cb (GtkButton *button, - GdkEventButton *event, - gpointer user_data) +navigation_button_press_cb (GtkButton *button, + GdkEventButton *event, + gpointer user_data) { NautilusToolbar *self = user_data; @@ -338,9 +365,9 @@ tool_button_press_cb (GtkButton *button, } static gboolean -tool_button_release_cb (GtkButton *button, - GdkEventButton *event, - gpointer user_data) +navigation_button_release_cb (GtkButton *button, + GdkEventButton *event, + gpointer user_data) { NautilusToolbar *self = user_data; @@ -350,137 +377,83 @@ tool_button_release_cb (GtkButton *button, } static void -navigation_button_setup_menu (NautilusToolbar *self, - GtkWidget *button, - NautilusNavigationDirection direction) +zoom_level_changed (GtkRange *range, + NautilusToolbar *self) { - g_object_set_data (G_OBJECT (button), "nav-direction", GUINT_TO_POINTER (direction)); - - g_signal_connect (button, "button-press-event", - G_CALLBACK (tool_button_press_cb), self); - g_signal_connect (button, "button-release-event", - G_CALLBACK (tool_button_release_cb), self); -} + NautilusWindowSlot *slot; + NautilusView *view; + gdouble zoom_level; -static gboolean -gear_menu_key_press (GtkWidget *widget, - GdkEventKey *event, - gpointer user_data) -{ - GdkModifierType mask = gtk_accelerator_get_default_mod_mask (); + zoom_level = gtk_range_get_value (range); + slot = nautilus_window_get_active_slot (self->priv->window); + view = nautilus_window_slot_get_current_view (slot); - if ((event->state & mask) == 0 && (event->keyval == GDK_KEY_F10)) { - gtk_menu_shell_deactivate (GTK_MENU_SHELL (widget)); - return TRUE; - } - - return FALSE; + g_action_group_change_action_state (nautilus_view_get_action_group (view), + "zoom-to-level", + g_variant_new_int32 ((gint) zoom_level)); } static void -nautilus_toolbar_constructed (GObject *obj) +nautilus_toolbar_init (NautilusToolbar *self) { - NautilusToolbar *self = NAUTILUS_TOOLBAR (obj); - GtkWidget *toolbar; - GtkWidget *button; - GtkWidget *menu; - GtkWidget *box; - GtkUIManager *ui_manager; - - G_OBJECT_CLASS (nautilus_toolbar_parent_class)->constructed (obj); - - toolbar = GTK_WIDGET (obj); - - ui_manager = nautilus_window_get_ui_manager (self->priv->window); - - /* Back and Forward */ - box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); - - /* Back */ - button = toolbar_create_toolbutton (self, FALSE, FALSE, NAUTILUS_ACTION_BACK, NULL); - gtk_widget_set_valign (button, GTK_ALIGN_CENTER); - gtk_action_set_icon_name (gtk_activatable_get_related_action (GTK_ACTIVATABLE (button)), - "go-previous-symbolic"); - navigation_button_setup_menu (self, button, NAUTILUS_NAVIGATION_DIRECTION_BACK); - gtk_container_add (GTK_CONTAINER (box), button); - - /* Forward */ - button = toolbar_create_toolbutton (self, FALSE, FALSE, NAUTILUS_ACTION_FORWARD, NULL); - gtk_widget_set_valign (button, GTK_ALIGN_CENTER); - gtk_action_set_icon_name (gtk_activatable_get_related_action (GTK_ACTIVATABLE (button)), - "go-next-symbolic"); - navigation_button_setup_menu (self, button, NAUTILUS_NAVIGATION_DIRECTION_FORWARD); - gtk_container_add (GTK_CONTAINER (box), button); - - gtk_style_context_add_class (gtk_widget_get_style_context (box), - GTK_STYLE_CLASS_RAISED); - gtk_style_context_add_class (gtk_widget_get_style_context (box), - GTK_STYLE_CLASS_LINKED); + GtkBuilder *builder; - gtk_header_bar_pack_start (GTK_HEADER_BAR (toolbar), box); + self->priv = nautilus_toolbar_get_instance_private (self); + gtk_widget_init_template (GTK_WIDGET (self)); self->priv->path_bar = g_object_new (NAUTILUS_TYPE_PATH_BAR, NULL); - gtk_header_bar_pack_start (GTK_HEADER_BAR (toolbar), self->priv->path_bar); + gtk_container_add (GTK_CONTAINER (self->priv->path_bar_container), + self->priv->path_bar); - /* entry-like location bar */ self->priv->location_entry = nautilus_location_entry_new (); - gtk_header_bar_pack_start (GTK_HEADER_BAR (toolbar), self->priv->location_entry); - - /* Action Menu */ - button = toolbar_create_toolbutton (self, TRUE, FALSE, "open-menu-symbolic", _("Location options")); - gtk_widget_set_valign (button, GTK_ALIGN_CENTER); - menu = gtk_ui_manager_get_widget (ui_manager, "/ActionMenu"); - gtk_widget_set_halign (menu, GTK_ALIGN_END); - gtk_menu_button_set_popup (GTK_MENU_BUTTON (button), menu); - gtk_actionable_set_action_name (GTK_ACTIONABLE (button), "win.gear-menu"); - g_signal_connect (menu, "key-press-event", G_CALLBACK (gear_menu_key_press), self); - - gtk_header_bar_pack_end (GTK_HEADER_BAR (toolbar), button); - - /* View buttons */ - box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); - - button = toolbar_create_toolbutton (self, FALSE, TRUE, NAUTILUS_ACTION_VIEW_LIST, NULL); - gtk_widget_set_valign (button, GTK_ALIGN_CENTER); - gtk_container_add (GTK_CONTAINER (box), button); - button = toolbar_create_toolbutton (self, FALSE, TRUE, NAUTILUS_ACTION_VIEW_GRID, NULL); - gtk_widget_set_valign (button, GTK_ALIGN_CENTER); - gtk_container_add (GTK_CONTAINER (box), button); - button = toolbar_create_toolbutton (self, TRUE, FALSE, "go-down-symbolic", _("View options")); - gtk_widget_set_valign (button, GTK_ALIGN_CENTER); - gtk_container_add (GTK_CONTAINER (box), button); - menu = gtk_ui_manager_get_widget (ui_manager, "/ViewMenu"); - gtk_menu_button_set_popup (GTK_MENU_BUTTON (button), menu); - - gtk_style_context_add_class (gtk_widget_get_style_context (box), - GTK_STYLE_CLASS_RAISED); - gtk_style_context_add_class (gtk_widget_get_style_context (box), - GTK_STYLE_CLASS_LINKED); - - gtk_header_bar_pack_end (GTK_HEADER_BAR (toolbar), box); - - /* search */ - button = toolbar_create_toolbutton (self, FALSE, TRUE, NAUTILUS_ACTION_SEARCH, NULL); - gtk_widget_set_valign (button, GTK_ALIGN_CENTER); - gtk_widget_set_margin_start (button, 76); - gtk_header_bar_pack_end (GTK_HEADER_BAR (toolbar), button); - - g_signal_connect_swapped (nautilus_preferences, - "changed::" NAUTILUS_PREFERENCES_ALWAYS_USE_LOCATION_ENTRY, - G_CALLBACK (toolbar_update_appearance), self); - - gtk_widget_show_all (toolbar); + gtk_container_add (GTK_CONTAINER (self->priv->location_entry_container), + self->priv->location_entry); + + builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-toolbar-view-menu.xml"); + self->priv->view_menu_widget = GTK_WIDGET (gtk_builder_get_object (builder, "view_menu_widget")); + self->priv->zoom_level_scale = GTK_WIDGET (gtk_builder_get_object (builder, "zoom_level_scale")); + self->priv->zoom_adjustment_grid = g_object_ref (GTK_ADJUSTMENT (gtk_builder_get_object (builder, "zoom_adjustment_grid"))); + self->priv->zoom_adjustment_list = g_object_ref (GTK_ADJUSTMENT (gtk_builder_get_object (builder, "zoom_adjustment_list"))); + + self->priv->sort_menu = GTK_WIDGET (gtk_builder_get_object (builder, "sort_menu")); + self->priv->sort_trash_time = GTK_WIDGET (gtk_builder_get_object (builder, "sort_trash_time")); + self->priv->sort_search_relevance = GTK_WIDGET (gtk_builder_get_object (builder, "sort_search_relevance")); + self->priv->visible_columns = GTK_WIDGET (gtk_builder_get_object (builder, "visible_columns")); + self->priv->reload = GTK_WIDGET (gtk_builder_get_object (builder, "reload")); + self->priv->stop = GTK_WIDGET (gtk_builder_get_object (builder, "stop")); + + gtk_menu_button_set_popover (GTK_MENU_BUTTON (self->priv->view_button), + self->priv->view_menu_widget); + g_object_unref (builder); + + builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-toolbar-action-menu.xml"); + self->priv->action_menu = G_MENU (gtk_builder_get_object (builder, "action-menu")); + gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (self->priv->action_button), + G_MENU_MODEL (self->priv->action_menu)); + g_object_unref (builder); + + g_signal_connect(self->priv->zoom_level_scale, "value-changed", + G_CALLBACK(zoom_level_changed), + self); + + g_object_set_data (G_OBJECT (self->priv->back_button), "nav-direction", + GUINT_TO_POINTER (NAUTILUS_NAVIGATION_DIRECTION_BACK)); + g_object_set_data (G_OBJECT (self->priv->forward_button), "nav-direction", + GUINT_TO_POINTER (NAUTILUS_NAVIGATION_DIRECTION_FORWARD)); + g_signal_connect (self->priv->back_button, "button-press-event", + G_CALLBACK (navigation_button_press_cb), self); + g_signal_connect (self->priv->back_button, "button-release-event", + G_CALLBACK (navigation_button_release_cb), self); + g_signal_connect (self->priv->forward_button, "button-press-event", + G_CALLBACK (navigation_button_press_cb), self); + g_signal_connect (self->priv->forward_button, "button-release-event", + G_CALLBACK (navigation_button_release_cb), self); + + gtk_widget_show_all (GTK_WIDGET (self)); toolbar_update_appearance (self); } static void -nautilus_toolbar_init (NautilusToolbar *self) -{ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NAUTILUS_TYPE_TOOLBAR, - NautilusToolbarPriv); -} - -static void nautilus_toolbar_get_property (GObject *object, guint property_id, GValue *value, @@ -535,11 +508,12 @@ static void nautilus_toolbar_class_init (NautilusToolbarClass *klass) { GObjectClass *oclass; + GtkWidgetClass *widget_class; + widget_class = GTK_WIDGET_CLASS (klass); oclass = G_OBJECT_CLASS (klass); oclass->get_property = nautilus_toolbar_get_property; oclass->set_property = nautilus_toolbar_set_property; - oclass->constructed = nautilus_toolbar_constructed; oclass->dispose = nautilus_toolbar_dispose; properties[PROP_WINDOW] = @@ -556,8 +530,124 @@ nautilus_toolbar_class_init (NautilusToolbarClass *klass) FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_type_class_add_private (klass, sizeof (NautilusToolbarClass)); g_object_class_install_properties (oclass, NUM_PROPERTIES, properties); + + gtk_widget_class_set_template_from_resource (widget_class, + "/org/gnome/nautilus/nautilus-toolbar-ui.xml"); + + gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, view_button); + gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, action_button); + gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, path_bar_container); + gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, location_entry_container); + gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, back_button); + gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, forward_button); +} + +void +nautilus_toolbar_action_menu_add_item (NautilusToolbar *self, + GMenuItem *item, + const gchar *section_name) +{ + nautilus_gmenu_add_item_in_submodel (self->priv->action_menu, + item, + section_name, + FALSE); +} + +void +nautilus_toolbar_reset_menus (NautilusToolbar *self) +{ + NautilusWindowSlot *slot; + NautilusView *view; + GActionGroup *view_action_group; + GtkBuilder *builder; + + gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (self->priv->action_button), NULL); + + builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-toolbar-action-menu.xml"); + self->priv->action_menu = G_MENU (gtk_builder_get_object (builder, "action-menu")); + gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (self->priv->action_button), + G_MENU_MODEL (self->priv->action_menu)); + g_object_unref (builder); + + /* Allow actions from the current view to be activated through + * the view menu and action menu of the toolbar */ + slot = nautilus_window_get_active_slot (self->priv->window); + view = nautilus_window_slot_get_current_view (slot); + view_action_group = nautilus_view_get_action_group (view); + gtk_widget_insert_action_group (GTK_WIDGET (self), + "view", + G_ACTION_GROUP (view_action_group)); + + gtk_widget_hide (self->priv->sort_menu); + gtk_widget_hide (self->priv->sort_trash_time); + gtk_widget_hide (self->priv->sort_search_relevance); + gtk_widget_hide (self->priv->visible_columns); +} + +void +nautilus_toolbar_show_sort_menu (NautilusToolbar *self) +{ + gtk_widget_show (self->priv->sort_menu); +} + +void +nautilus_toolbar_show_sort_trash_time (NautilusToolbar *self) +{ + gtk_widget_show (self->priv->sort_trash_time); +} + +void +nautilus_toolbar_show_sort_search_relevance (NautilusToolbar *self) +{ + gtk_widget_show (self->priv->sort_search_relevance); +} + +void +nautilus_toolbar_show_visible_columns (NautilusToolbar *self) +{ + gtk_widget_show (self->priv->visible_columns); +} + +void +nautilus_toolbar_show_stop (NautilusToolbar *self) +{ + gtk_widget_show (self->priv->stop); +} + +void +nautilus_toolbar_show_reload (NautilusToolbar *self) +{ + gtk_widget_show (self->priv->reload); +} + +void +nautilus_toolbar_hide_stop (NautilusToolbar *self) +{ + gtk_widget_hide (self->priv->stop); +} + +void +nautilus_toolbar_hide_reload (NautilusToolbar *self) +{ + gtk_widget_hide (self->priv->reload); +} + +void nautilus_toolbar_view_menu_widget_set_zoom_level (NautilusToolbar *self, + gdouble level) +{ + g_return_if_fail (NAUTILUS_IS_TOOLBAR (self)); + + /* We only want to change the level when there's and actual view + * mode set, so skip all other calls to here. Those calls came from + * update_toolbar_menus in the natuilus-view after a parent is set, etc. + * We will receive eventually a mode change and another update here by nautilus view + * update_toolbar_menus */ + if (self->priv->active_zoom_adjustment == NULL) + return; + + gtk_adjustment_set_value (GTK_ADJUSTMENT (self->priv->active_zoom_adjustment), + level); } GtkWidget * diff --git a/src/nautilus-toolbar.h b/src/nautilus-toolbar.h index 2a8d2ddb3..9b0444313 100644 --- a/src/nautilus-toolbar.h +++ b/src/nautilus-toolbar.h @@ -42,7 +42,7 @@ (G_TYPE_INSTANCE_GET_CLASS ((obj), NAUTILUS_TYPE_TOOLBAR, NautilusToolbarClass)) typedef struct _NautilusToolbar NautilusToolbar; -typedef struct _NautilusToolbarPriv NautilusToolbarPriv; +typedef struct _NautilusToolbarPrivate NautilusToolbarPrivate; typedef struct _NautilusToolbarClass NautilusToolbarClass; typedef enum { @@ -54,7 +54,7 @@ struct _NautilusToolbar { GtkHeaderBar parent; /* private */ - NautilusToolbarPriv *priv; + NautilusToolbarPrivate *priv; }; struct _NautilusToolbarClass { @@ -72,5 +72,24 @@ void nautilus_toolbar_set_show_main_bar (NautilusToolbar *self, gboolean show_main_bar); void nautilus_toolbar_set_show_location_entry (NautilusToolbar *self, gboolean show_location_entry); +void nautilus_toolbar_action_menu_add_item (NautilusToolbar *self, + GMenuItem *item, + const gchar *section_name); +void nautilus_toolbar_reset_menus (NautilusToolbar *self); + +void nautilus_toolbar_sync_navigation_buttons (NautilusToolbar *self); +void nautilus_toolbar_view_menu_widget_set_zoom_level (NautilusToolbar *self, + gdouble level); +void nautilus_toolbar_update_view_mode (NautilusToolbar *self, + const gchar *view_mode); + +void nautilus_toolbar_show_sort_menu (NautilusToolbar *self); +void nautilus_toolbar_show_sort_trash_time (NautilusToolbar *self); +void nautilus_toolbar_show_sort_search_relevance (NautilusToolbar *self); +void nautilus_toolbar_show_visible_columns (NautilusToolbar *self); +void nautilus_toolbar_show_stop (NautilusToolbar *self); +void nautilus_toolbar_show_reload (NautilusToolbar *self); +void nautilus_toolbar_hide_stop (NautilusToolbar *self); +void nautilus_toolbar_hide_reload (NautilusToolbar *self); #endif /* __NAUTILUS_TOOLBAR_H__ */ diff --git a/src/nautilus-view-context-menus.xml b/src/nautilus-view-context-menus.xml new file mode 100644 index 000000000..6aa89a31d --- /dev/null +++ b/src/nautilus-view-context-menus.xml @@ -0,0 +1,228 @@ +<?xml version="1.0"?> +<interface> + <menu id="background-menu"> + <item> + <attribute name="label" translatable="yes">New _Folder</attribute> + <attribute name="action">view.new-folder</attribute> + </item> + <submenu> + <attribute name="id">templates-submenu</attribute> + <attribute name="label" translatable="yes">New _Document</attribute> + <attribute name="action">view.new-document</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </submenu> + <section> + <item> + <attribute name="label" translatable="yes">_Paste</attribute> + <attribute name="action">view.paste</attribute> + </item> + </section> + <section> + <item> + <attribute name="label" translatable="yes">Select _All</attribute> + <attribute name="action">view.select-all</attribute> + </item> + </section> + <section> + <item> + <attribute name="label" translatable="yes">P_roperties</attribute> + <attribute name="action">view.properties</attribute> + </item> + </section> + <section> + <item> + <attribute name="label" translatable="yes">_Keep aligned</attribute> + <attribute name="action">view.keep-aligned</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + <item> + <attribute name="label" translatable="yes">Organize _Desktop by Name</attribute> + <attribute name="action">view.organize-desktop-by-name</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + </section> + <section> + <item> + <attribute name="label" translatable="yes">Change _Background</attribute> + <attribute name="action">view.change-background</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + </section> + </menu> + <menu id="selection-menu"> + <section> + <attribute name="id">new-folder-with-selection-section</attribute> + </section> + <section> + <attribute name="id">open-with-default-application-section</attribute> + </section> + <submenu> + <attribute name="id">scripts-submenu</attribute> + <attribute name="label" translatable="yes">_Scripts</attribute> + <attribute name="action">view.scripts</attribute> + <attribute name="hidden-when">action-disabled</attribute> + <section> + <item> + <attribute name="label" translatable="yes">_Open Scripts Folder</attribute> + <attribute name="action">view.open-scripts-folder</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + </section> + </submenu> + <section> + <item> + <attribute name="label" translatable="yes">_Open Item Location</attribute> + <attribute name="action">view.open-item-location</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + <item> + <attribute name="label" translatable="yes">Open In New _Window</attribute> + <attribute name="action">view.open-item-new-window</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + <item> + <attribute name="label" translatable="yes">Open In New _Tab</attribute> + <attribute name="action">view.open-item-new-tab</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + </section> + <section> + <item> + <attribute name="label" translatable="yes">Open With Other _Application</attribute> + <attribute name="action">view.open-with-other-application</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + </section> + <section> + <attribute name="id">drive-section</attribute> + <item> + <attribute name="label" translatable="yes">_Mount</attribute> + <attribute name="action">view.mount-volume</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + <item> + <attribute name="label" translatable="yes">_Unmount</attribute> + <attribute name="action">view.unmount-volume</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + <item> + <attribute name="label" translatable="yes">_Eject</attribute> + <attribute name="action">view.eject-volume</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + <item> + <attribute name="label" translatable="yes">_Start</attribute> + <attribute name="action">view.start-volume</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + <item> + <attribute name="label" translatable="yes">_Stop</attribute> + <attribute name="action">view.stop-volume</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + <item> + <attribute name="label" translatable="yes">_Detect Media</attribute> + <attribute name="action">view.detect-media</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + </section> + <section> + <item> + <attribute name="label" translatable="yes">Cu_t</attribute> + <attribute name="action">view.cut</attribute> + </item> + <item> + <attribute name="label" translatable="yes">_Copy</attribute> + <attribute name="action">view.copy</attribute> + </item> + <item> + <attribute name="label" translatable="yes">_Paste Into Folder</attribute> + <attribute name="action">view.paste-into</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + </section> + <section> + <item> + <attribute name="label" translatable="yes">Move to…</attribute> + <attribute name="action">view.move-to</attribute> + </item> + <item> + <attribute name="label" translatable="yes">Copy to…</attribute> + <attribute name="action">view.copy-to</attribute> + </item> + </section> + <section> + <item> + <attribute name="label" translatable="yes">Mo_ve to Trash</attribute> + <attribute name="action">view.move-to-trash</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + <item> + <attribute name="label" translatable="yes">_Delete Permanently</attribute> + <attribute name="action">view.delete</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + <item> + <attribute name="label" translatable="yes">Empty Trash</attribute> + <attribute name="action">view.empty-trash</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + <item> + <attribute name="label" translatable="yes">_Restore From Trash</attribute> + <attribute name="action">view.restore-from-trash</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + </section> + <section> + <item> + <attribute name="label" translatable="yes">Resize Icon…</attribute> + <attribute name="action">view.stretch</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + <item> + <attribute name="label" translatable="yes">Restore Icon's Original Size</attribute> + <attribute name="action">view.unstretch</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + </section> + <section> + <item> + <attribute name="label" translatable="yes">Rena_me</attribute> + <attribute name="action">view.rename</attribute> + </item> + </section> + <section> + <item> + <attribute name="label" translatable="yes">Set As Wallpaper</attribute> + <attribute name="action">view.set-as-wallpaper</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + </section> + <section> + <item> + <attribute name="label" translatable="yes">P_roperties</attribute> + <attribute name="action">view.properties</attribute> + </item> + </section> + </menu> + <menu id="pathbar-menu"> + <section> + <item> + <attribute name="label" translatable="yes">Open In New _Window</attribute> + <attribute name="action">view.pathbar-open-item-new-window</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + <item> + <attribute name="label" translatable="yes">Open In New _Tab</attribute> + <attribute name="action">view.pathbar-open-item-new-tab</attribute> + <attribute name="hidden-when">action-disabled</attribute> + </item> + </section> + <section> + <item> + <attribute name="label" translatable="yes">P_roperties</attribute> + <attribute name="action">view.pathbar-properties</attribute> + </item> + </section> + </menu> +</interface> diff --git a/src/nautilus-view.c b/src/nautilus-view.c index e378e71ec..b502644d5 100644 --- a/src/nautilus-view.c +++ b/src/nautilus-view.c @@ -29,7 +29,6 @@ #include "nautilus-view.h" -#include "nautilus-actions.h" #include "nautilus-application.h" #include "nautilus-desktop-canvas-view.h" #include "nautilus-error-reporting.h" @@ -37,6 +36,8 @@ #include "nautilus-mime-actions.h" #include "nautilus-previewer.h" #include "nautilus-properties-window.h" +#include "nautilus-window.h" +#include "nautilus-toolbar.h" #if ENABLE_EMPTY_VIEW #include "nautilus-empty-view.h" @@ -111,26 +112,6 @@ #define MAX_QUEUED_UPDATES 500 -#define NAUTILUS_VIEW_MENU_PATH_APPLICATIONS_SUBMENU_PLACEHOLDER "/ActionMenu/Open Placeholder/Open With/Applications Placeholder" -#define NAUTILUS_VIEW_MENU_PATH_APPLICATIONS_PLACEHOLDER "/ActionMenu/Open Placeholder/Applications Placeholder" -#define NAUTILUS_VIEW_MENU_PATH_SCRIPTS_PLACEHOLDER "/ActionMenu/Open Placeholder/Scripts/Scripts Placeholder" -#define NAUTILUS_VIEW_MENU_PATH_EXTENSION_ACTIONS_PLACEHOLDER "/ActionMenu/Edit/Extension Actions" -#define NAUTILUS_VIEW_MENU_PATH_NEW_DOCUMENTS_PLACEHOLDER "/ActionMenu/New Items Placeholder/New Documents/New Documents Placeholder" -#define NAUTILUS_VIEW_MENU_PATH_OPEN "/ActionMenu/Open Placeholder/Open" - -#define NAUTILUS_VIEW_POPUP_PATH_SELECTION "/selection" -#define NAUTILUS_VIEW_POPUP_PATH_APPLICATIONS_SUBMENU_PLACEHOLDER "/selection/Open Placeholder/Open With/Applications Placeholder" -#define NAUTILUS_VIEW_POPUP_PATH_APPLICATIONS_PLACEHOLDER "/selection/Open Placeholder/Applications Placeholder" -#define NAUTILUS_VIEW_POPUP_PATH_SCRIPTS_PLACEHOLDER "/selection/Open Placeholder/Scripts/Scripts Placeholder" -#define NAUTILUS_VIEW_POPUP_PATH_EXTENSION_ACTIONS "/selection/Extension Actions" -#define NAUTILUS_VIEW_POPUP_PATH_OPEN "/selection/Open Placeholder/Open" - -#define NAUTILUS_VIEW_POPUP_PATH_BACKGROUND "/background" -#define NAUTILUS_VIEW_POPUP_PATH_BACKGROUND_SCRIPTS_PLACEHOLDER "/background/Before Zoom Items/New Object Items/Scripts/Scripts Placeholder" -#define NAUTILUS_VIEW_POPUP_PATH_BACKGROUND_NEW_DOCUMENTS_PLACEHOLDER "/background/Before Zoom Items/New Object Items/New Documents/New Documents Placeholder" - -#define NAUTILUS_VIEW_POPUP_PATH_LOCATION "/location" - #define MAX_MENU_LEVELS 5 #define TEMPLATE_LIMIT 30 @@ -144,7 +125,6 @@ enum { FILE_CHANGED, MOVE_COPY_ITEMS, REMOVE_FILE, - ZOOM_LEVEL_CHANGED, SELECTION_CHANGED, TRASH, DELETE, @@ -170,7 +150,6 @@ struct NautilusViewDetails NautilusWindowSlot *slot; NautilusDirectory *model; NautilusFile *directory_as_file; - GtkActionGroup *dir_action_group; NautilusFile *pathbar_popup_directory_as_file; GdkEventButton *pathbar_popup_event; guint dir_merge_id; @@ -178,18 +157,10 @@ struct NautilusViewDetails gboolean supports_zooming; GList *scripts_directory_list; - GtkActionGroup *scripts_action_group; - guint scripts_merge_id; - GList *templates_directory_list; - GtkActionGroup *templates_action_group; - guint templates_merge_id; - - GtkActionGroup *extensions_menu_action_group; - guint extensions_menu_merge_id; guint display_selection_idle_id; - guint update_menus_timeout_id; + guint update_context_menus_timeout_id; guint update_status_idle_id; guint reveal_selection_idle_id; @@ -226,9 +197,8 @@ struct NautilusViewDetails * after it finishes loading the directory and its view. */ gboolean loading; - gboolean scripts_invalid; - gboolean templates_invalid; gboolean templates_present; + gboolean scripts_present; /* flag to indicate that no file updates should be dispatched to subclasses. * This is a workaround for bug #87701 that prevents the list view from @@ -254,12 +224,15 @@ struct NautilusViewDetails gboolean metadata_for_directory_as_file_pending; gboolean metadata_for_files_in_directory_pending; - GtkActionGroup *open_with_action_group; - guint open_with_merge_id; - GList *subdirectory_list; GdkPoint context_menu_position; + + GMenu *selection_menu; + GMenu *background_menu; + GMenu *pathbar_menu; + + GActionGroup *view_action_group; }; typedef struct { @@ -275,16 +248,12 @@ static void trash_or_delete_files (GtkWindow NautilusView *view); static void load_directory (NautilusView *view, NautilusDirectory *directory); -static void nautilus_view_merge_menus (NautilusView *view); -static void nautilus_view_unmerge_menus (NautilusView *view); -static void nautilus_view_set_show_hidden_files (NautilusView *view, - gboolean show_hidden); static void clipboard_changed_callback (NautilusClipboardMonitor *monitor, NautilusView *view); static void open_one_in_new_window (gpointer data, gpointer callback_data); -static void schedule_update_menus (NautilusView *view); -static void remove_update_menus_timeout_callback (NautilusView *view); +static void schedule_update_context_menus (NautilusView *view); +static void remove_update_context_menus_timeout_callback (NautilusView *view); static void schedule_update_status (NautilusView *view); static void remove_update_status_idle_callback (NautilusView *view); static void reset_update_interval (NautilusView *view); @@ -304,35 +273,13 @@ static void nautilus_view_select_file (NautilusView static void update_templates_directory (NautilusView *view); -static gboolean file_list_all_are_folders (GList *file_list); static void unschedule_pop_up_pathbar_context_menu (NautilusView *view); +static void real_zoom_to_level (NautilusView *view, + gint zoom_level); G_DEFINE_TYPE (NautilusView, nautilus_view, GTK_TYPE_SCROLLED_WINDOW); -/* virtual methods (public and non-public) */ - -/** - * nautilus_view_merge_menus: - * - * Add this view's menus to the window's menu bar. - * @view: NautilusView in question. - */ -static void -nautilus_view_merge_menus (NautilusView *view) -{ - g_return_if_fail (NAUTILUS_IS_VIEW (view)); - - NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->merge_menus (view); -} - -static void -nautilus_view_unmerge_menus (NautilusView *view) -{ - g_return_if_fail (NAUTILUS_IS_VIEW (view)); - - NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->unmerge_menus (view);} - static char * real_get_backing_uri (NautilusView *view) { @@ -539,6 +486,20 @@ nautilus_view_bump_zoom_level (NautilusView *view, NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->bump_zoom_level (view, zoom_increment); } +/* We want to keep the logic of which menus and when to update them in + * this class, so children need to chain to the parent when they set the zoom + * level through this function. + * The chain up should be done after the child updated the zoom level, so the + * menus are updated acordingly + * + */ +static void +real_zoom_to_level (NautilusView *view, + gint zoom_level) +{ + nautilus_view_update_toolbar_menus (view); +} + /** * nautilus_view_zoom_to_level: * @@ -665,30 +626,6 @@ nautilus_view_get_selection (NautilusView *view) return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_selection (view); } -/** - * nautilus_view_update_menus: - * - * Update the sensitivity and wording of dynamic menu items. - * @view: NautilusView in question. - */ -void -nautilus_view_update_menus (NautilusView *view) -{ - g_return_if_fail (NAUTILUS_IS_VIEW (view)); - - if (!view->details->active) { - return; - } - - NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->update_menus (view); -} - -typedef struct { - GAppInfo *application; - GList *files; - NautilusView *directory_view; -} ApplicationLaunchParameters; - typedef struct { NautilusFile *file; NautilusView *directory_view; @@ -699,38 +636,6 @@ typedef struct { NautilusView *directory_view; } CreateTemplateParameters; -static ApplicationLaunchParameters * -application_launch_parameters_new (GAppInfo *application, - GList *files, - NautilusView *directory_view) -{ - ApplicationLaunchParameters *result; - - result = g_new0 (ApplicationLaunchParameters, 1); - result->application = g_object_ref (application); - result->files = nautilus_file_list_copy (files); - - if (directory_view != NULL) { - g_object_ref (directory_view); - result->directory_view = directory_view; - } - - return result; -} - -static void -application_launch_parameters_free (ApplicationLaunchParameters *parameters) -{ - g_object_unref (parameters->application); - nautilus_file_list_free (parameters->files); - - if (parameters->directory_view != NULL) { - g_object_unref (parameters->directory_view); - } - - g_free (parameters); -} - static GList * file_and_directory_list_to_files (GList *fad_list) { @@ -853,7 +758,7 @@ create_templates_parameters_free (CreateTemplateParameters *parameters) g_free (parameters); } -static NautilusWindow * +NautilusWindow * nautilus_view_get_window (NautilusView *view) { return nautilus_window_slot_get_window (view->details->slot); @@ -1027,23 +932,24 @@ nautilus_view_activate_file (NautilusView *view, } static void -action_open_callback (GtkAction *action, - gpointer callback_data) +action_open_with_default_application (GSimpleAction *action, + GVariant *state, + gpointer user_data) { NautilusView *view; - view = NAUTILUS_VIEW (callback_data); + view = NAUTILUS_VIEW (user_data); nautilus_view_activate_selection (view); } - static void -action_open_close_parent_callback (GtkAction *action, - gpointer callback_data) +action_open_file_and_close_window (GSimpleAction *action, + GVariant *state, + gpointer user_data) { GList *selection; NautilusView *view; - view = NAUTILUS_VIEW (callback_data); + view = NAUTILUS_VIEW (user_data); selection = nautilus_view_get_selection (view); nautilus_view_activate_files (view, @@ -1054,9 +960,9 @@ action_open_close_parent_callback (GtkAction *action, } static void - -action_open_item_location_callback (GtkAction *action, - gpointer callback_data) +action_open_item_location (GSimpleAction *action, + GVariant *state, + gpointer user_data) { NautilusView *view; GList *selection; @@ -1065,7 +971,7 @@ action_open_item_location_callback (GtkAction *action, NautilusFile *activation_file; NautilusFile *location; - view = NAUTILUS_VIEW (callback_data); + view = NAUTILUS_VIEW (user_data); selection = nautilus_view_get_selection (view); if (!selection) @@ -1084,36 +990,16 @@ action_open_item_location_callback (GtkAction *action, nautilus_file_list_free (selection); } - static void -action_open_alternate_callback (GtkAction *action, - gpointer callback_data) +action_open_item_new_tab (GSimpleAction *action, + GVariant *state, + gpointer user_data) { NautilusView *view; GList *selection; GtkWindow *window; - view = NAUTILUS_VIEW (callback_data); - selection = nautilus_view_get_selection (view); - - window = nautilus_view_get_containing_window (view); - - if (nautilus_view_confirm_multiple (window, g_list_length (selection), FALSE)) { - g_list_foreach (selection, open_one_in_new_window, view); - } - - nautilus_file_list_free (selection); -} - -static void -action_open_new_tab_callback (GtkAction *action, - gpointer callback_data) -{ - NautilusView *view; - GList *selection; - GtkWindow *window; - - view = NAUTILUS_VIEW (callback_data); + view = NAUTILUS_VIEW (user_data); selection = nautilus_view_get_selection (view); window = nautilus_view_get_containing_window (view); @@ -1129,31 +1015,14 @@ action_open_new_tab_callback (GtkAction *action, } static void -action_location_open_alternate_callback (GtkAction *action, - gpointer callback_data) -{ - NautilusView *view; - NautilusFile *file; - - view = NAUTILUS_VIEW (callback_data); - - file = view->details->pathbar_popup_directory_as_file; - if (file == NULL) { - return; - } - nautilus_view_activate_file (view, - file, - NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW); -} - -static void -action_location_open_in_new_tab_callback (GtkAction *action, - gpointer callback_data) +action_pathbar_open_item_new_tab (GSimpleAction *action, + GVariant *state, + gpointer user_data) { NautilusView *view; NautilusFile *file; - view = NAUTILUS_VIEW (callback_data); + view = NAUTILUS_VIEW (user_data); file = view->details->pathbar_popup_directory_as_file; if (file == NULL) { @@ -1245,12 +1114,13 @@ open_with_other_program (NautilusView *view) } static void -action_other_application_callback (GtkAction *action, - gpointer callback_data) +action_open_with_other_application (GSimpleAction *action, + GVariant *state, + gpointer user_data) { - g_assert (NAUTILUS_IS_VIEW (callback_data)); + g_assert (NAUTILUS_IS_VIEW (user_data)); - open_with_other_program (NAUTILUS_VIEW (callback_data)); + open_with_other_program (NAUTILUS_VIEW (user_data)); } static void @@ -1272,26 +1142,12 @@ trash_or_delete_selected_files (NautilusView *view) } } -static gboolean -real_trash (NautilusView *view) -{ - GtkAction *action; - - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_TRASH); - if (gtk_action_get_sensitive (action) && - gtk_action_get_visible (action)) { - trash_or_delete_selected_files (view); - return TRUE; - } - return FALSE; -} - static void -action_trash_callback (GtkAction *action, - gpointer callback_data) +action_move_to_trash (GSimpleAction *action, + GVariant *state, + gpointer user_data) { - trash_or_delete_selected_files (NAUTILUS_VIEW (callback_data)); + trash_or_delete_selected_files (NAUTILUS_VIEW (user_data)); } static void @@ -1320,20 +1176,22 @@ delete_selected_files (NautilusView *view) } static void -action_delete_callback (GtkAction *action, - gpointer callback_data) +action_delete (GSimpleAction *action, + GVariant *state, + gpointer user_data) { - delete_selected_files (NAUTILUS_VIEW (callback_data)); + delete_selected_files (NAUTILUS_VIEW (user_data)); } static void -action_restore_from_trash_callback (GtkAction *action, - gpointer callback_data) +action_restore_from_trash (GSimpleAction *action, + GVariant *state, + gpointer user_data) { NautilusView *view; GList *selection; - view = NAUTILUS_VIEW (callback_data); + view = NAUTILUS_VIEW (user_data); selection = nautilus_view_get_selection_for_file_transfer (view); nautilus_restore_files_from_trash (selection, @@ -1343,37 +1201,28 @@ action_restore_from_trash_callback (GtkAction *action, } -static gboolean -real_delete (NautilusView *view) +static void +action_select_all (GSimpleAction *action, + GVariant *state, + gpointer user_data) { - GtkAction *action; + NautilusView *view; - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_DELETE); - if (gtk_action_get_sensitive (action) && - gtk_action_get_visible (action)) { - delete_selected_files (view); - return TRUE; - } - return FALSE; -} + g_assert (NAUTILUS_IS_VIEW (user_data)); -static void -action_select_all_callback (GtkAction *action, - gpointer callback_data) -{ - g_assert (NAUTILUS_IS_VIEW (callback_data)); + view = NAUTILUS_VIEW (user_data); - nautilus_view_select_all (callback_data); + nautilus_view_select_all (view); } static void -action_invert_selection_callback (GtkAction *action, - gpointer callback_data) +action_invert_selection (GSimpleAction *action, + GVariant *state, + gpointer user_data) { - g_assert (NAUTILUS_IS_VIEW (callback_data)); + g_assert (NAUTILUS_IS_VIEW (user_data)); - nautilus_view_invert_selection (callback_data); + nautilus_view_invert_selection (user_data); } static void @@ -1473,12 +1322,13 @@ select_pattern (NautilusView *view) } static void -action_select_pattern_callback (GtkAction *action, - gpointer callback_data) +action_select_pattern (GSimpleAction *action, + GVariant *state, + gpointer user_data) { - g_assert (NAUTILUS_IS_VIEW (callback_data)); + g_assert (NAUTILUS_IS_VIEW (user_data)); - select_pattern(callback_data); + select_pattern(user_data); } typedef struct { @@ -1886,34 +1736,37 @@ nautilus_view_new_file (NautilusView *directory_view, } static void -action_new_folder_callback (GtkAction *action, - gpointer callback_data) -{ - g_assert (NAUTILUS_IS_VIEW (callback_data)); +action_new_folder (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + g_assert (NAUTILUS_IS_VIEW (user_data)); - nautilus_view_new_folder (NAUTILUS_VIEW (callback_data), FALSE); + nautilus_view_new_folder (NAUTILUS_VIEW (user_data), FALSE); } static void -action_new_folder_with_selection_callback (GtkAction *action, - gpointer callback_data) +action_new_folder_with_selection (GSimpleAction *action, + GVariant *state, + gpointer user_data) { - g_assert (NAUTILUS_IS_VIEW (callback_data)); + g_assert (NAUTILUS_IS_VIEW (user_data)); - nautilus_view_new_folder (NAUTILUS_VIEW (callback_data), TRUE); + nautilus_view_new_folder (NAUTILUS_VIEW (user_data), TRUE); } static void -action_properties_callback (GtkAction *action, - gpointer callback_data) +action_properties (GSimpleAction *action, + GVariant *state, + gpointer user_data) { NautilusView *view; GList *selection; GList *files; - g_assert (NAUTILUS_IS_VIEW (callback_data)); + g_assert (NAUTILUS_IS_VIEW (user_data)); - view = NAUTILUS_VIEW (callback_data); + view = NAUTILUS_VIEW (user_data); selection = nautilus_view_get_selection (view); if (g_list_length (selection) == 0) { if (view->details->directory_as_file != NULL) { @@ -1929,46 +1782,245 @@ action_properties_callback (GtkAction *action, nautilus_file_list_free (selection); } -static gboolean -all_files_in_trash (GList *files) +static void +action_pathbar_properties (GSimpleAction *action, + GVariant *state, + gpointer user_data) { - GList *node; + NautilusView *view; + GList *files; - /* Result is ambiguous if called on NULL, so disallow. */ - g_return_val_if_fail (files != NULL, FALSE); + g_assert (NAUTILUS_IS_VIEW (user_data)); - for (node = files; node != NULL; node = node->next) { - if (!nautilus_file_is_in_trash (NAUTILUS_FILE (node->data))) { - return FALSE; + view = NAUTILUS_VIEW (user_data); + g_assert (NAUTILUS_IS_FILE (view->details->pathbar_popup_directory_as_file)); + + files = g_list_append (NULL, nautilus_file_ref (view->details->pathbar_popup_directory_as_file)); + + nautilus_properties_window_present (files, GTK_WIDGET (view), NULL); + + nautilus_file_list_free (files); +} + +static void +nautilus_view_set_show_hidden_files (NautilusView *view, + gboolean show_hidden) +{ + if (view->details->ignore_hidden_file_preferences) { + return; + } + + if (show_hidden != view->details->show_hidden_files) { + view->details->show_hidden_files = show_hidden; + if (view->details->model != NULL) { + load_directory (view, view->details->model); } } +} - return TRUE; +static void +action_show_hidden_files (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + gboolean show_hidden; + NautilusView *view; + + g_assert (NAUTILUS_IS_VIEW (user_data)); + + view = NAUTILUS_VIEW (user_data); + show_hidden = g_variant_get_boolean (state); + + nautilus_view_set_show_hidden_files (view, show_hidden); + + g_simple_action_set_state (action, state); } -static gboolean -all_selected_items_in_trash (GList *selection) +static void +action_undo (GSimpleAction *action, + GVariant *state, + gpointer user_data) { - gboolean result; + GtkWidget *toplevel; + NautilusView *view; - /* If the contents share a parent directory, we need only - * check that parent directory. Otherwise we have to inspect - * each selected item. - */ - result = (selection == NULL) ? FALSE : all_files_in_trash (selection); - return result; + g_assert (NAUTILUS_IS_VIEW (user_data)); + + view = NAUTILUS_VIEW (user_data); + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view)); + nautilus_file_undo_manager_undo (GTK_WINDOW (toplevel)); } static void -action_show_hidden_files_callback (GtkAction *action, - gpointer callback_data) +action_redo (GSimpleAction *action, + GVariant *state, + gpointer user_data) { + GtkWidget *toplevel; NautilusView *view; - view = NAUTILUS_VIEW (callback_data); + g_assert (NAUTILUS_IS_VIEW (user_data)); + + view = NAUTILUS_VIEW (user_data); + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view)); + nautilus_file_undo_manager_redo (GTK_WINDOW (toplevel)); +} + +static void +action_zoom_in (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusView *view; + + g_assert (NAUTILUS_IS_VIEW (user_data)); + + view = NAUTILUS_VIEW (user_data); + + nautilus_view_bump_zoom_level (view, 1); +} + +static void +action_zoom_out (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusView *view; + + g_assert (NAUTILUS_IS_VIEW (user_data)); + + view = NAUTILUS_VIEW (user_data); + + nautilus_view_bump_zoom_level (view, -1); +} - nautilus_view_set_show_hidden_files - (view, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))); +static void +action_zoom_default (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + nautilus_view_restore_default_zoom_level (user_data); +} + +static void +action_zoom_to_level (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusView *view; + gdouble zoom_value; + + g_assert (NAUTILUS_IS_VIEW (user_data)); + + view = NAUTILUS_VIEW (user_data); + zoom_value = g_variant_get_int32 (state); + + nautilus_view_zoom_to_level (view, zoom_value); +} + +static void +action_open_item_new_window (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusView *view; + GtkWindow *window; + GList *selection; + + view = NAUTILUS_VIEW (user_data); + selection = nautilus_view_get_selection (view); + window = GTK_WINDOW (nautilus_view_get_containing_window (view)); + + if (nautilus_view_confirm_multiple (window, g_list_length (selection), TRUE)) { + g_list_foreach (selection, open_one_in_new_window, view); + } + + nautilus_file_list_free (selection); +} + +static void +action_pathbar_open_item_new_window (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusView *view; + NautilusFile *file; + + view = NAUTILUS_VIEW (user_data); + + file = view->details->pathbar_popup_directory_as_file; + if (file == NULL) { + return; + } + + nautilus_view_activate_file (view, + file, + NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW); +} + +static void +paste_clipboard_data (NautilusView *view, + GtkSelectionData *selection_data, + char *destination_uri) +{ + gboolean cut; + GList *item_uris; + + cut = FALSE; + item_uris = nautilus_clipboard_get_uri_list_from_selection_data (selection_data, &cut, + copied_files_atom); + + if (item_uris != NULL && destination_uri != NULL) { + nautilus_view_move_copy_items (view, item_uris, NULL, destination_uri, + cut ? GDK_ACTION_MOVE : GDK_ACTION_COPY, + 0, 0); + + /* If items are cut then remove from clipboard */ + if (cut) { + gtk_clipboard_clear (nautilus_clipboard_get (GTK_WIDGET (view))); + } + + g_list_free_full (item_uris, g_free); + } +} + +static void +paste_clipboard_received_callback (GtkClipboard *clipboard, + GtkSelectionData *selection_data, + gpointer data) +{ + NautilusView *view; + char *view_uri; + + view = NAUTILUS_VIEW (data); + + view_uri = nautilus_view_get_backing_uri (view); + + if (view->details->slot != NULL) { + paste_clipboard_data (view, selection_data, view_uri); + } + + g_free (view_uri); + + g_object_unref (view); +} + +static void +action_paste_files (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusView *view; + + g_assert (NAUTILUS_IS_VIEW (user_data)); + + view = NAUTILUS_VIEW (user_data); + + g_object_ref (view); + gtk_clipboard_request_contents (nautilus_clipboard_get (GTK_WIDGET (view)), + copied_files_atom, + paste_clipboard_received_callback, + view); } static void @@ -2098,9 +2150,8 @@ scripts_added_or_changed_callback (NautilusDirectory *directory, view = NAUTILUS_VIEW (callback_data); - view->details->scripts_invalid = TRUE; if (view->details->active) { - schedule_update_menus (view); + schedule_update_context_menus (view); } } @@ -2113,9 +2164,8 @@ templates_added_or_changed_callback (NautilusDirectory *directory, view = NAUTILUS_VIEW (callback_data); - view->details->templates_invalid = TRUE; if (view->details->active) { - schedule_update_menus (view); + schedule_update_context_menus (view); } } @@ -2212,8 +2262,15 @@ slot_active (NautilusWindowSlot *slot, view->details->active = TRUE; - nautilus_view_merge_menus (view); - schedule_update_menus (view); + /* Avoid updating the toolbar withouth making sure the toolbar + * zoom slider has the correct adjustment that changes when the + * view mode changes + */ + nautilus_window_slot_sync_view_mode (slot); + nautilus_view_update_context_menus(view); + nautilus_view_update_toolbar_menus (view); + + schedule_update_context_menus (view); } static void @@ -2226,8 +2283,7 @@ slot_inactive (NautilusWindowSlot *slot, view->details->active = FALSE; - nautilus_view_unmerge_menus (view); - remove_update_menus_timeout_callback (view); + remove_update_context_menus_timeout_callback (view); } void @@ -2256,92 +2312,14 @@ nautilus_view_get_selection_count (NautilusView *view) } static void -update_undo_actions (NautilusView *view) -{ - NautilusFileUndoInfo *info; - NautilusFileUndoManagerState undo_state; - GtkAction *action; - const gchar *label, *tooltip; - gboolean available, is_undo; - gboolean undo_active, redo_active; - gchar *undo_label, *undo_description, *redo_label, *redo_description; - - undo_label = undo_description = redo_label = redo_description = NULL; - - undo_active = FALSE; - redo_active = FALSE; - - info = nautilus_file_undo_manager_get_action (); - undo_state = nautilus_file_undo_manager_get_state (); - - if (info != NULL && - (undo_state > NAUTILUS_FILE_UNDO_MANAGER_STATE_NONE)) { - is_undo = (undo_state == NAUTILUS_FILE_UNDO_MANAGER_STATE_UNDO); - - if (is_undo) { - undo_active = TRUE; - } else { - redo_active = TRUE; - } - - nautilus_file_undo_info_get_strings (info, - &undo_label, &undo_description, - &redo_label, &redo_description); - } - - /* Update undo entry */ - action = gtk_action_group_get_action (view->details->dir_action_group, - "Undo"); - available = undo_active; - if (available) { - label = undo_label; - tooltip = undo_description; - } else { - /* Reset to default info */ - label = _("Undo"); - tooltip = _("Undo last action"); - } - - g_object_set (action, - "label", label, - "tooltip", tooltip, - NULL); - gtk_action_set_sensitive (action, available); - - /* Update redo entry */ - action = gtk_action_group_get_action (view->details->dir_action_group, - "Redo"); - available = redo_active; - if (available) { - label = redo_label; - tooltip = redo_description; - } else { - /* Reset to default info */ - label = _("Redo"); - tooltip = _("Redo last undone action"); - } - - g_object_set (action, - "label", label, - "tooltip", tooltip, - NULL); - gtk_action_set_sensitive (action, available); - - g_free (undo_label); - g_free (undo_description); - g_free (redo_label); - g_free (redo_description); -} - -static void -undo_manager_changed_cb (NautilusFileUndoManager* manager, - NautilusView *view) +undo_manager_changed (NautilusFileUndoManager* manager, + NautilusView *view) { if (!view->details->active) { return; } - update_undo_actions (view); + nautilus_view_update_toolbar_menus (view); } void @@ -2389,127 +2367,6 @@ have_bulk_rename_tool () } static void -nautilus_view_init (NautilusView *view) -{ - AtkObject *atk_object; - NautilusDirectory *scripts_directory; - NautilusDirectory *templates_directory; - char *templates_uri; - - nautilus_profile_start (NULL); - - view->details = G_TYPE_INSTANCE_GET_PRIVATE (view, NAUTILUS_TYPE_VIEW, - NautilusViewDetails); - - /* Default to true; desktop-icon-view sets to false */ - view->details->show_foreign_files = TRUE; - - view->details->non_ready_files = - g_hash_table_new_full (file_and_directory_hash, - file_and_directory_equal, - (GDestroyNotify)file_and_directory_free, - NULL); - - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (view), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (view), NULL); - gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (view), NULL); - - gtk_style_context_set_junction_sides (gtk_widget_get_style_context (GTK_WIDGET (view)), - GTK_JUNCTION_TOP | GTK_JUNCTION_LEFT); - - if (set_up_scripts_directory_global ()) { - scripts_directory = nautilus_directory_get_by_uri (scripts_directory_uri); - add_directory_to_scripts_directory_list (view, scripts_directory); - nautilus_directory_unref (scripts_directory); - } else { - g_warning ("Ignoring scripts directory, it may be a broken link\n"); - } - - if (nautilus_should_use_templates_directory ()) { - templates_uri = nautilus_get_templates_directory_uri (); - templates_directory = nautilus_directory_get_by_uri (templates_uri); - g_free (templates_uri); - add_directory_to_templates_directory_list (view, templates_directory); - nautilus_directory_unref (templates_directory); - } - update_templates_directory (view); - - view->details->sort_directories_first = - g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_SORT_DIRECTORIES_FIRST); - view->details->show_hidden_files = - g_settings_get_boolean (gtk_filechooser_preferences, NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES); - - g_signal_connect_object (nautilus_trash_monitor_get (), "trash-state-changed", - G_CALLBACK (nautilus_view_trash_state_changed_callback), view, 0); - - /* React to clipboard changes */ - g_signal_connect_object (nautilus_clipboard_monitor_get (), "clipboard-changed", - G_CALLBACK (clipboard_changed_callback), view, 0); - - /* Register to menu provider extension signal managing menu updates */ - g_signal_connect_object (nautilus_signaller_get_current (), "popup-menu-changed", - G_CALLBACK (schedule_update_menus), view, G_CONNECT_SWAPPED); - - gtk_widget_show (GTK_WIDGET (view)); - - g_signal_connect_swapped (nautilus_preferences, - "changed::" NAUTILUS_PREFERENCES_ENABLE_DELETE, - G_CALLBACK (schedule_update_menus), view); - g_signal_connect_swapped (nautilus_preferences, - "changed::" NAUTILUS_PREFERENCES_CLICK_POLICY, - G_CALLBACK (click_policy_changed_callback), - view); - g_signal_connect_swapped (nautilus_preferences, - "changed::" NAUTILUS_PREFERENCES_SORT_DIRECTORIES_FIRST, - G_CALLBACK (sort_directories_first_changed_callback), view); - g_signal_connect_swapped (gtk_filechooser_preferences, - "changed::" NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES, - G_CALLBACK (show_hidden_files_changed_callback), view); - g_signal_connect_swapped (gnome_lockdown_preferences, - "changed::" NAUTILUS_PREFERENCES_LOCKDOWN_COMMAND_LINE, - G_CALLBACK (schedule_update_menus), view); - - g_signal_connect_object (nautilus_file_undo_manager_get (), "undo-changed", - G_CALLBACK (undo_manager_changed_cb), view, 0); - - /* Accessibility */ - atk_object = gtk_widget_get_accessible (GTK_WIDGET (view)); - atk_object_set_name (atk_object, _("Content View")); - atk_object_set_description (atk_object, _("View of the current folder")); - - nautilus_profile_end (NULL); -} - -static void -real_unmerge_menus (NautilusView *view) -{ - GtkUIManager *ui_manager; - - ui_manager = nautilus_view_get_ui_manager (view); - if (ui_manager == NULL) { - return; - } - - nautilus_ui_unmerge_ui (ui_manager, - &view->details->dir_merge_id, - &view->details->dir_action_group); - nautilus_ui_unmerge_ui (ui_manager, - &view->details->extensions_menu_merge_id, - &view->details->extensions_menu_action_group); - nautilus_ui_unmerge_ui (ui_manager, - &view->details->open_with_merge_id, - &view->details->open_with_action_group); - nautilus_ui_unmerge_ui (ui_manager, - &view->details->scripts_merge_id, - &view->details->scripts_action_group); - nautilus_ui_unmerge_ui (ui_manager, - &view->details->templates_merge_id, - &view->details->templates_action_group); -} - -static void nautilus_view_destroy (GtkWidget *object) { NautilusView *view; @@ -2519,7 +2376,6 @@ nautilus_view_destroy (GtkWidget *object) disconnect_model_handlers (view); - nautilus_view_unmerge_menus (view); nautilus_view_stop_loading (view); for (node = view->details->scripts_directory_list; node != NULL; node = next) { @@ -2537,7 +2393,7 @@ nautilus_view_destroy (GtkWidget *object) view->details->subdirectory_list->data); } - remove_update_menus_timeout_callback (view); + remove_update_context_menus_timeout_callback (view); remove_update_status_idle_callback (view); if (view->details->display_selection_idle_id != 0) { @@ -2579,7 +2435,7 @@ nautilus_view_finalize (GObject *object) view = NAUTILUS_VIEW (object); g_signal_handlers_disconnect_by_func (nautilus_preferences, - schedule_update_menus, view); + schedule_update_context_menus, view); g_signal_handlers_disconnect_by_func (nautilus_preferences, click_policy_changed_callback, view); g_signal_handlers_disconnect_by_func (nautilus_preferences, @@ -2590,7 +2446,7 @@ nautilus_view_finalize (GObject *object) nautilus_view_display_selection_info, view); g_signal_handlers_disconnect_by_func (gnome_lockdown_preferences, - schedule_update_menus, view); + schedule_update_context_menus, view); unschedule_pop_up_pathbar_context_menu (view); if (view->details->pathbar_popup_event != NULL) { @@ -2832,7 +2688,8 @@ done_loading (NautilusView *view, * is no NautilusWindow any more. */ if (window != NULL) { - schedule_update_menus (view); + nautilus_view_update_toolbar_menus (view); + schedule_update_context_menus (view); schedule_update_status (view); reset_update_interval (view); @@ -3084,7 +2941,7 @@ copy_move_done_callback (GHashTable *debuting_files, G_CONNECT_AFTER); } /* Schedule menu update for undo items */ - schedule_update_menus (directory_view); + schedule_update_context_menus (directory_view); } copy_move_done_data_free (copy_move_done_data); @@ -3345,27 +3202,24 @@ display_selection_info_idle_callback (gpointer data) } static void -remove_update_menus_timeout_callback (NautilusView *view) +remove_update_context_menus_timeout_callback (NautilusView *view) { - if (view->details->update_menus_timeout_id != 0) { - g_source_remove (view->details->update_menus_timeout_id); - view->details->update_menus_timeout_id = 0; + if (view->details->update_context_menus_timeout_id != 0) { + g_source_remove (view->details->update_context_menus_timeout_id); + view->details->update_context_menus_timeout_id = 0; } } static void -update_menus_if_pending (NautilusView *view) +update_context_menus_if_pending (NautilusView *view) { - if (view->details->update_menus_timeout_id == 0) { - return; - } + remove_update_context_menus_timeout_callback (view); - remove_update_menus_timeout_callback (view); - nautilus_view_update_menus (view); + nautilus_view_update_context_menus(view); } static gboolean -update_menus_timeout_callback (gpointer data) +update_context_menus_timeout_callback (gpointer data) { NautilusView *view; @@ -3373,8 +3227,8 @@ update_menus_timeout_callback (gpointer data) g_object_ref (G_OBJECT (view)); - view->details->update_menus_timeout_id = 0; - nautilus_view_update_menus (view); + view->details->update_context_menus_timeout_id = 0; + nautilus_view_update_context_menus(view); g_object_unref (G_OBJECT (view)); @@ -3596,7 +3450,7 @@ files_changed_callback (NautilusDirectory *directory, /* A change in MIME type could affect the Open with menu, for * one thing, so we need to update menus when files change. */ - schedule_update_menus (view); + schedule_update_context_menus (view); } static void @@ -3711,19 +3565,6 @@ nautilus_view_get_loading (NautilusView *view) return view->details->loading; } -GtkUIManager * -nautilus_view_get_ui_manager (NautilusView *view) -{ - NautilusWindow *window; - - if (view->details->slot == NULL) { - return NULL; - } - - window = nautilus_window_slot_get_window (view->details->slot); - return nautilus_window_get_ui_manager (window); -} - /** * nautilus_view_get_model: * @@ -3888,6 +3729,17 @@ start_renaming_file (NautilusView *view, } static void +open_one_in_new_window (gpointer data, gpointer callback_data) +{ + g_assert (NAUTILUS_IS_FILE (data)); + g_assert (NAUTILUS_IS_VIEW (callback_data)); + + nautilus_view_activate_file (NAUTILUS_VIEW (callback_data), + NAUTILUS_FILE (data), + NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW); +} + +static void update_context_menu_position_from_event (NautilusView *view, GdkEventButton *event) { @@ -3902,19 +3754,6 @@ update_context_menu_position_from_event (NautilusView *view, } } -/* handle the open command */ - -static void -open_one_in_new_window (gpointer data, gpointer callback_data) -{ - g_assert (NAUTILUS_IS_FILE (data)); - g_assert (NAUTILUS_IS_VIEW (callback_data)); - - nautilus_view_activate_file (NAUTILUS_VIEW (callback_data), - NAUTILUS_FILE (data), - NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW); -} - NautilusFile * nautilus_view_get_directory_as_file (NautilusView *view) { @@ -3923,470 +3762,6 @@ nautilus_view_get_directory_as_file (NautilusView *view) return view->details->directory_as_file; } -static void -open_with_launch_application_callback (GtkAction *action, - gpointer callback_data) -{ - ApplicationLaunchParameters *launch_parameters; - - launch_parameters = (ApplicationLaunchParameters *) callback_data; - nautilus_launch_application - (launch_parameters->application, - launch_parameters->files, - nautilus_view_get_containing_window (launch_parameters->directory_view)); -} - -static char * -escape_action_path (const char *action_path) -{ - GString *s; - - if (action_path == NULL) { - return NULL; - } - - s = g_string_sized_new (strlen (action_path) + 2); - - while (*action_path != 0) { - switch (*action_path) { - case '\\': - g_string_append (s, "\\\\"); - break; - case '&': - g_string_append (s, "\\a"); - break; - case '"': - g_string_append (s, "\\q"); - break; - default: - g_string_append_c (s, *action_path); - } - - action_path ++; - } - return g_string_free (s, FALSE); -} - - -static void -add_submenu (GtkUIManager *ui_manager, - GtkActionGroup *action_group, - guint merge_id, - const char *parent_path, - const char *uri, - const char *label, - GdkPixbuf *pixbuf, - gboolean add_action) -{ - char *escaped_label; - char *action_name; - char *submenu_name; - char *escaped_submenu_name; - GtkAction *action; - - if (parent_path != NULL) { - action_name = nautilus_escape_action_name (uri, "submenu_"); - submenu_name = g_path_get_basename (uri); - escaped_submenu_name = escape_action_path (submenu_name); - escaped_label = eel_str_double_underscores (label); - - if (add_action) { - action = gtk_action_new (action_name, - escaped_label, - NULL, - NULL); - if (pixbuf != NULL) { - gtk_action_set_gicon (action, G_ICON (pixbuf)); - } - - g_object_set (action, "hide-if-empty", FALSE, NULL); - - gtk_action_group_add_action (action_group, - action); - g_object_unref (action); - } - - gtk_ui_manager_add_ui (ui_manager, - merge_id, - parent_path, - escaped_submenu_name, - action_name, - GTK_UI_MANAGER_MENU, - FALSE); - g_free (action_name); - g_free (escaped_label); - g_free (submenu_name); - g_free (escaped_submenu_name); - } -} - -static void -menu_item_show_image (GtkUIManager *ui_manager, - const char *parent_path, - const char *action_name) -{ - char *path; - GtkWidget *menuitem; - - path = g_strdup_printf ("%s/%s", parent_path, action_name); - menuitem = gtk_ui_manager_get_widget (ui_manager, - path); - if (menuitem != NULL) { - gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), - TRUE); - } - g_free (path); -} - -static void -add_application_to_open_with_menu (NautilusView *view, - GAppInfo *application, - GList *files, - int index, - const char *menu_placeholder, - const char *popup_placeholder, - const gboolean submenu) -{ - ApplicationLaunchParameters *launch_parameters; - char *tip; - char *label; - char *action_name; - char *escaped_app; - GtkAction *action; - GIcon *app_icon; - GtkUIManager *ui_manager; - - launch_parameters = application_launch_parameters_new - (application, files, view); - escaped_app = eel_str_double_underscores (g_app_info_get_name (application)); - if (submenu) - label = g_strdup_printf ("%s", escaped_app); - else - label = g_strdup_printf (_("Open With %s"), escaped_app); - - tip = g_strdup_printf (ngettext ("Use “%s” to open the selected item", - "Use “%s” to open the selected items", - g_list_length (files)), - escaped_app); - g_free (escaped_app); - - action_name = g_strdup_printf ("open_with_%d", index); - - action = gtk_action_new (action_name, - label, - tip, - NULL); - - app_icon = g_app_info_get_icon (application); - if (app_icon != NULL) { - g_object_ref (app_icon); - } else { - app_icon = g_themed_icon_new ("application-x-executable"); - } - - gtk_action_set_gicon (action, app_icon); - g_object_unref (app_icon); - - g_signal_connect_data (action, "activate", - G_CALLBACK (open_with_launch_application_callback), - launch_parameters, - (GClosureNotify)application_launch_parameters_free, 0); - - gtk_action_group_add_action (view->details->open_with_action_group, - action); - g_object_unref (action); - - ui_manager = nautilus_view_get_ui_manager (view); - gtk_ui_manager_add_ui (ui_manager, - view->details->open_with_merge_id, - popup_placeholder, - action_name, - action_name, - GTK_UI_MANAGER_MENUITEM, - FALSE); - - menu_item_show_image (ui_manager, popup_placeholder, action_name); - - g_free (action_name); - g_free (label); - g_free (tip); -} - -static void -get_x_content_async_callback (const char **content, - gpointer user_data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (user_data); - - if (view->details->slot != NULL) { - schedule_update_menus (view); - } - g_object_unref (view); -} - -static void -add_x_content_apps (NautilusView *view, NautilusFile *file, GList **applications) -{ - GMount *mount; - char **x_content_types; - unsigned int n; - - g_return_if_fail (applications != NULL); - - mount = nautilus_file_get_mount (file); - - if (mount == NULL) { - return; - } - - x_content_types = nautilus_get_cached_x_content_types_for_mount (mount); - if (x_content_types != NULL) { - for (n = 0; x_content_types[n] != NULL; n++) { - char *x_content_type = x_content_types[n]; - GList *app_info_for_x_content_type; - - app_info_for_x_content_type = g_app_info_get_all_for_type (x_content_type); - *applications = g_list_concat (*applications, app_info_for_x_content_type); - } - g_strfreev (x_content_types); - } else { - nautilus_get_x_content_types_for_mount_async (mount, - get_x_content_async_callback, - NULL, - g_object_ref (view)); - - } - - g_object_unref (mount); -} - -static void -reset_open_with_menu (NautilusView *view, GList *selection) -{ - GList *applications, *node; - NautilusFile *file; - gboolean submenu_visible, filter_default; - int num_applications; - int index; - gboolean other_applications_visible; - gboolean open_with_chooser_visible; - GtkUIManager *ui_manager; - GtkAction *action; - GAppInfo *default_app; - - /* Clear any previous inserted items in the applications and viewers placeholders */ - - ui_manager = nautilus_view_get_ui_manager (view); - nautilus_ui_unmerge_ui (ui_manager, - &view->details->open_with_merge_id, - &view->details->open_with_action_group); - - nautilus_ui_prepare_merge_ui (ui_manager, - "OpenWithGroup", - &view->details->open_with_merge_id, - &view->details->open_with_action_group); - - other_applications_visible = (selection != NULL); - filter_default = (selection != NULL); - - for (node = selection; node != NULL; node = node->next) { - - file = NAUTILUS_FILE (node->data); - - other_applications_visible &= (!nautilus_mime_file_opens_in_view (file) && - !nautilus_file_is_nautilus_link (file)); - } - - default_app = NULL; - if (filter_default) { - default_app = nautilus_mime_get_default_application_for_files (selection); - } - - applications = NULL; - if (other_applications_visible) { - applications = nautilus_mime_get_applications_for_files (selection); - } - - if (g_list_length (selection) == 1) { - add_x_content_apps (view, NAUTILUS_FILE (selection->data), &applications); - } - - - num_applications = g_list_length (applications); - - submenu_visible = (num_applications > 1); - - for (node = applications, index = 0; node != NULL; node = node->next, index++) { - GAppInfo *application; - char *menu_path; - char *popup_path; - - application = node->data; - - if (default_app != NULL && g_app_info_equal (default_app, application)) { - continue; - } - - if (submenu_visible) { - menu_path = NAUTILUS_VIEW_MENU_PATH_APPLICATIONS_SUBMENU_PLACEHOLDER; - popup_path = NAUTILUS_VIEW_POPUP_PATH_APPLICATIONS_SUBMENU_PLACEHOLDER; - } else { - menu_path = NAUTILUS_VIEW_MENU_PATH_APPLICATIONS_PLACEHOLDER; - popup_path = NAUTILUS_VIEW_POPUP_PATH_APPLICATIONS_PLACEHOLDER; - } - - gtk_ui_manager_add_ui (nautilus_view_get_ui_manager (view), - view->details->open_with_merge_id, - menu_path, - "separator", - NULL, - GTK_UI_MANAGER_SEPARATOR, - FALSE); - - add_application_to_open_with_menu (view, - node->data, - selection, - index, - menu_path, popup_path, submenu_visible); - } - g_list_free_full (applications, g_object_unref); - if (default_app != NULL) { - g_object_unref (default_app); - } - - open_with_chooser_visible = other_applications_visible && - g_list_length (selection) == 1; - - if (submenu_visible) { - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_OTHER_APPLICATION1); - gtk_action_set_visible (action, open_with_chooser_visible); - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_OTHER_APPLICATION2); - gtk_action_set_visible (action, FALSE); - } else { - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_OTHER_APPLICATION1); - gtk_action_set_visible (action, FALSE); - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_OTHER_APPLICATION2); - gtk_action_set_visible (action, open_with_chooser_visible); - } -} - -static GList * -get_all_extension_menu_items (GtkWidget *window, - GList *selection) -{ - GList *items; - GList *providers; - GList *l; - - providers = nautilus_module_get_extensions_for_type (NAUTILUS_TYPE_MENU_PROVIDER); - items = NULL; - - for (l = providers; l != NULL; l = l->next) { - NautilusMenuProvider *provider; - GList *file_items; - - provider = NAUTILUS_MENU_PROVIDER (l->data); - file_items = nautilus_menu_provider_get_file_items (provider, - window, - selection); - items = g_list_concat (items, file_items); - } - - nautilus_module_extension_list_free (providers); - - return items; -} - -typedef struct -{ - NautilusMenuItem *item; - NautilusView *view; - GList *selection; - GtkAction *action; -} ExtensionActionCallbackData; - - -static void -extension_action_callback_data_free (ExtensionActionCallbackData *data) -{ - g_object_unref (data->item); - nautilus_file_list_free (data->selection); - - g_free (data); -} - -static gboolean -search_in_menu_items (GList* items, const char *item_name) -{ - GList* list; - - for (list = items; list != NULL; list = list->next) { - NautilusMenu* menu; - char *name; - - g_object_get (list->data, "name", &name, NULL); - if (strcmp (name, item_name) == 0) { - g_free (name); - return TRUE; - } - g_free (name); - - menu = NULL; - g_object_get (list->data, "menu", &menu, NULL); - if (menu != NULL) { - gboolean ret; - GList* submenus; - - submenus = nautilus_menu_get_items (menu); - ret = search_in_menu_items (submenus, item_name); - nautilus_menu_item_list_free (submenus); - g_object_unref (menu); - if (ret) { - return TRUE; - } - } - } - return FALSE; -} - -static void -extension_action_callback (GtkAction *action, - gpointer callback_data) -{ - ExtensionActionCallbackData *data; - char *item_name; - gboolean is_valid; - GList *l; - GList *items; - - data = callback_data; - - /* Make sure the selected menu item is valid for the final sniffed - * mime type */ - g_object_get (data->item, "name", &item_name, NULL); - items = get_all_extension_menu_items (gtk_widget_get_toplevel (GTK_WIDGET (data->view)), - data->selection); - - is_valid = search_in_menu_items (items, item_name); - - for (l = items; l != NULL; l = l->next) { - g_object_unref (l->data); - } - g_list_free (items); - - g_free (item_name); - - if (is_valid) { - nautilus_menu_item_activate (data->item); - } -} - static GdkPixbuf * get_menu_icon_for_file (NautilusFile *file, GtkWidget *widget) @@ -4405,153 +3780,6 @@ get_menu_icon_for_file (NautilusFile *file, return pixbuf; } -static GtkAction * -add_extension_action_for_files (NautilusView *view, - NautilusMenuItem *item, - GList *files) -{ - char *name, *label, *tip, *icon; - gboolean sensitive, priority; - GtkAction *action; - GdkPixbuf *pixbuf; - ExtensionActionCallbackData *data; - - g_object_get (G_OBJECT (item), - "name", &name, "label", &label, - "tip", &tip, "icon", &icon, - "sensitive", &sensitive, - "priority", &priority, - NULL); - - action = gtk_action_new (name, - label, - tip, - NULL); - - if (icon != NULL) { - pixbuf = nautilus_ui_get_menu_icon (icon, GTK_WIDGET (view)); - if (pixbuf != NULL) { - gtk_action_set_gicon (action, G_ICON (pixbuf)); - g_object_unref (pixbuf); - } - } - - gtk_action_set_sensitive (action, sensitive); - g_object_set (action, "is-important", priority, NULL); - - data = g_new0 (ExtensionActionCallbackData, 1); - data->item = g_object_ref (item); - data->view = view; - data->selection = nautilus_file_list_copy (files); - data->action = action; - - g_signal_connect_data (action, "activate", - G_CALLBACK (extension_action_callback), - data, - (GClosureNotify)extension_action_callback_data_free, 0); - - gtk_action_group_add_action (view->details->extensions_menu_action_group, - GTK_ACTION (action)); - g_object_unref (action); - - g_free (name); - g_free (label); - g_free (tip); - g_free (icon); - - return action; -} - -static void -add_extension_menu_items (NautilusView *view, - GList *files, - GList *menu_items, - const char *subdirectory) -{ - GtkUIManager *ui_manager; - GList *l; - - ui_manager = nautilus_view_get_ui_manager (view); - - for (l = menu_items; l; l = l->next) { - NautilusMenuItem *item; - NautilusMenu *menu; - GtkAction *action; - char *path; - - item = NAUTILUS_MENU_ITEM (l->data); - - g_object_get (item, "menu", &menu, NULL); - - action = add_extension_action_for_files (view, item, files); - - path = g_build_path ("/", NAUTILUS_VIEW_POPUP_PATH_EXTENSION_ACTIONS, subdirectory, NULL); - gtk_ui_manager_add_ui (ui_manager, - view->details->extensions_menu_merge_id, - path, - gtk_action_get_name (action), - gtk_action_get_name (action), - (menu != NULL) ? GTK_UI_MANAGER_MENU : GTK_UI_MANAGER_MENUITEM, - FALSE); - g_free (path); - - path = g_build_path ("/", NAUTILUS_VIEW_MENU_PATH_EXTENSION_ACTIONS_PLACEHOLDER, subdirectory, NULL); - gtk_ui_manager_add_ui (ui_manager, - view->details->extensions_menu_merge_id, - path, - gtk_action_get_name (action), - gtk_action_get_name (action), - (menu != NULL) ? GTK_UI_MANAGER_MENU : GTK_UI_MANAGER_MENUITEM, - FALSE); - g_free (path); - - /* recursively fill the menu */ - if (menu != NULL) { - char *subdir; - GList *children; - - children = nautilus_menu_get_items (menu); - - subdir = g_build_path ("/", subdirectory, gtk_action_get_name (action), NULL); - add_extension_menu_items (view, - files, - children, - subdir); - - nautilus_menu_item_list_free (children); - g_free (subdir); - } - } -} - -static void -reset_extension_actions_menu (NautilusView *view, GList *selection) -{ - GList *items; - GtkUIManager *ui_manager; - - /* Clear any previous inserted items in the extension actions placeholder */ - ui_manager = nautilus_view_get_ui_manager (view); - - nautilus_ui_unmerge_ui (ui_manager, - &view->details->extensions_menu_merge_id, - &view->details->extensions_menu_action_group); - - nautilus_ui_prepare_merge_ui (ui_manager, - "DirExtensionsMenuGroup", - &view->details->extensions_menu_merge_id, - &view->details->extensions_menu_action_group); - - items = get_all_extension_menu_items (gtk_widget_get_toplevel (GTK_WIDGET (view)), - selection); - if (items != NULL) { - add_extension_menu_items (view, selection, items, ""); - - g_list_foreach (items, (GFunc) g_object_unref, NULL); - g_list_free (items); - } -} - static char * change_to_view_directory (NautilusView *view) { @@ -4745,7 +3973,9 @@ unset_script_environment_variables (void) } static void -run_script_callback (GtkAction *action, gpointer callback_data) +run_script (GSimpleAction *action, + GVariant *state, + gpointer user_data) { ScriptLaunchParameters *launch_parameters; GdkScreen *screen; @@ -4756,7 +3986,7 @@ run_script_callback (GtkAction *action, gpointer callback_data) char *old_working_dir; char **parameters; - launch_parameters = (ScriptLaunchParameters *) callback_data; + launch_parameters = (ScriptLaunchParameters *) user_data; file_uri = nautilus_file_get_uri (launch_parameters->file); local_file_path = g_filename_from_uri (file_uri, NULL, NULL); @@ -4776,7 +4006,7 @@ run_script_callback (GtkAction *action, gpointer callback_data) screen = gtk_widget_get_screen (GTK_WIDGET (launch_parameters->directory_view)); - DEBUG ("run_script_callback, script_path=“%s” (omitting script parameters)", + DEBUG ("run_script, script_path=“%s” (omitting script parameters)", local_file_path); nautilus_launch_application_from_command_array (screen, quoted_path, FALSE, @@ -4791,112 +4021,48 @@ run_script_callback (GtkAction *action, gpointer callback_data) } static void -add_script_to_scripts_menus (NautilusView *directory_view, +add_script_to_scripts_menus (NautilusView *view, NautilusFile *file, - const char *menu_path, - const char *popup_path, - const char *popup_bg_path) + GMenu *menu) { + gchar *name; + GdkPixbuf *mimetype_icon; + gchar *action_name, *detailed_action_name; ScriptLaunchParameters *launch_parameters; - char *tip; - char *name; - char *uri; - char *action_name; - char *escaped_label; - GdkPixbuf *pixbuf; - GtkUIManager *ui_manager; - GtkAction *action; + GAction *action; + GMenuItem *menu_item; - name = nautilus_file_get_display_name (file); - uri = nautilus_file_get_uri (file); - tip = g_strdup_printf (_("Run “%s” on any selected items"), name); - - launch_parameters = script_launch_parameters_new (file, directory_view); - - action_name = nautilus_escape_action_name (uri, "script_"); - escaped_label = eel_str_double_underscores (name); - - action = gtk_action_new (action_name, - escaped_label, - tip, - NULL); + launch_parameters = script_launch_parameters_new (file, view); - pixbuf = get_menu_icon_for_file (file, GTK_WIDGET (directory_view)); - if (pixbuf != NULL) { - gtk_action_set_gicon (action, G_ICON (pixbuf)); - g_object_unref (pixbuf); - } + name = nautilus_file_get_display_name (file); + action_name = nautilus_escape_action_name (name, "script_"); + action = G_ACTION (g_simple_action_new (action_name, NULL)); + g_signal_connect_data (action, "activate", - G_CALLBACK (run_script_callback), + G_CALLBACK (run_script), launch_parameters, (GClosureNotify)script_launch_parameters_free, 0); - gtk_action_group_add_action_with_accel (directory_view->details->scripts_action_group, - action, NULL); + g_action_map_add_action (G_ACTION_MAP (view->details->view_action_group), action); + g_object_unref (action); + + detailed_action_name = g_strconcat ("view.", action_name, NULL); + menu_item = g_menu_item_new (name, detailed_action_name); - ui_manager = nautilus_view_get_ui_manager (directory_view); - - gtk_ui_manager_add_ui (ui_manager, - directory_view->details->scripts_merge_id, - menu_path, - action_name, - action_name, - GTK_UI_MANAGER_MENUITEM, - FALSE); - gtk_ui_manager_add_ui (ui_manager, - directory_view->details->scripts_merge_id, - popup_path, - action_name, - action_name, - GTK_UI_MANAGER_MENUITEM, - FALSE); - gtk_ui_manager_add_ui (ui_manager, - directory_view->details->scripts_merge_id, - popup_bg_path, - action_name, - action_name, - GTK_UI_MANAGER_MENUITEM, - FALSE); - - menu_item_show_image (ui_manager, menu_path, action_name); - menu_item_show_image (ui_manager, popup_path, action_name); - menu_item_show_image (ui_manager, popup_bg_path, action_name); - - g_free (name); - g_free (uri); - g_free (tip); - g_free (action_name); - g_free (escaped_label); -} + mimetype_icon = get_menu_icon_for_file (file, GTK_WIDGET (view)); + if (mimetype_icon != NULL) { + g_menu_item_set_icon (menu_item, G_ICON (mimetype_icon)); + g_object_unref (mimetype_icon); + } -static void -add_submenu_to_directory_menus (NautilusView *directory_view, - GtkActionGroup *action_group, - guint merge_id, - NautilusFile *file, - const char *menu_path, - const char *popup_path, - const char *popup_bg_path) -{ - char *name; - GdkPixbuf *pixbuf; - char *uri; - GtkUIManager *ui_manager; + g_menu_append_item (menu, menu_item); - ui_manager = nautilus_view_get_ui_manager (directory_view); - uri = nautilus_file_get_uri (file); - name = nautilus_file_get_display_name (file); - pixbuf = get_menu_icon_for_file (file, GTK_WIDGET (directory_view)); - add_submenu (ui_manager, action_group, merge_id, menu_path, uri, name, pixbuf, TRUE); - add_submenu (ui_manager, action_group, merge_id, popup_path, uri, name, pixbuf, FALSE); - add_submenu (ui_manager, action_group, merge_id, popup_bg_path, uri, name, pixbuf, FALSE); - if (pixbuf) { - g_object_unref (pixbuf); - } g_free (name); - g_free (uri); + g_free (action_name); + g_free (detailed_action_name); + g_object_unref (menu_item); } static gboolean @@ -4923,199 +4089,169 @@ directory_belongs_in_scripts_menu (const char *uri) return TRUE; } -static gboolean -update_directory_in_scripts_menu (NautilusView *view, NautilusDirectory *directory) +static GMenu * +update_directory_in_scripts_menu (NautilusView *view, + NautilusDirectory *directory) { - char *menu_path, *popup_path, *popup_bg_path; GList *file_list, *filtered, *node; + GMenu *menu, *children_menu; + GMenuItem *menu_item; gboolean any_scripts; NautilusFile *file; NautilusDirectory *dir; char *uri; - char *escaped_path; - - uri = nautilus_directory_get_uri (directory); - escaped_path = escape_action_path (uri + scripts_directory_uri_length); - g_free (uri); - menu_path = g_strconcat (NAUTILUS_VIEW_MENU_PATH_SCRIPTS_PLACEHOLDER, - escaped_path, - NULL); - popup_path = g_strconcat (NAUTILUS_VIEW_POPUP_PATH_SCRIPTS_PLACEHOLDER, - escaped_path, - NULL); - popup_bg_path = g_strconcat (NAUTILUS_VIEW_POPUP_PATH_BACKGROUND_SCRIPTS_PLACEHOLDER, - escaped_path, - NULL); - g_free (escaped_path); + int num; + + g_return_if_fail (NAUTILUS_IS_VIEW (view)); + g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); file_list = nautilus_directory_get_file_list (directory); filtered = nautilus_file_list_filter_hidden (file_list, FALSE); nautilus_file_list_free (file_list); + menu = g_menu_new (); file_list = nautilus_file_list_sort_by_display_name (filtered); + num = 0; any_scripts = FALSE; - for (node = file_list; node != NULL; node = node->next) { + for (node = file_list; num < TEMPLATE_LIMIT && node != NULL; node = node->next, num++) { file = node->data; - - if (nautilus_file_is_launchable (file)) { - add_script_to_scripts_menus (view, file, menu_path, popup_path, popup_bg_path); - any_scripts = TRUE; - } else if (nautilus_file_is_directory (file)) { + if (nautilus_file_is_directory (file)) { uri = nautilus_file_get_uri (file); if (directory_belongs_in_scripts_menu (uri)) { dir = nautilus_directory_get_by_uri (uri); add_directory_to_scripts_directory_list (view, dir); - nautilus_directory_unref (dir); - add_submenu_to_directory_menus (view, - view->details->scripts_action_group, - view->details->scripts_merge_id, - file, menu_path, popup_path, popup_bg_path); + children_menu = update_directory_in_scripts_menu (view, dir); - any_scripts = TRUE; + if (children_menu != NULL) { + menu_item = g_menu_item_new_submenu (nautilus_file_get_display_name (file), + G_MENU_MODEL (children_menu)); + g_menu_append_item (menu, menu_item); + any_scripts = TRUE; + g_object_unref (menu_item); + g_object_unref (children_menu); + } + + nautilus_directory_unref (dir); } g_free (uri); + } else if (nautilus_file_is_launchable (file)) { + add_script_to_scripts_menus (view, file, menu); + any_scripts = TRUE; } } nautilus_file_list_free (file_list); - g_free (popup_path); - g_free (popup_bg_path); - g_free (menu_path); + if (!any_scripts) { + g_object_unref (menu); + menu = NULL; + } - return any_scripts; + return menu; } + + static void update_scripts_menu (NautilusView *view) { - gboolean any_scripts; GList *sorted_copy, *node; NautilusDirectory *directory; + GMenu *submenu; char *uri; - GtkUIManager *ui_manager; - GtkAction *action; - - /* There is a race condition here. If we don't mark the scripts menu as - valid before we begin our task then we can lose script menu updates that - occur before we finish. */ - view->details->scripts_invalid = FALSE; - - ui_manager = nautilus_view_get_ui_manager (view); - nautilus_ui_unmerge_ui (ui_manager, - &view->details->scripts_merge_id, - &view->details->scripts_action_group); - - nautilus_ui_prepare_merge_ui (ui_manager, - "ScriptsGroup", - &view->details->scripts_merge_id, - &view->details->scripts_action_group); - /* As we walk through the directories, remove any that no longer belong. */ - any_scripts = FALSE; sorted_copy = nautilus_directory_list_sort_by_uri (nautilus_directory_list_copy (view->details->scripts_directory_list)); + for (node = sorted_copy; node != NULL; node = node->next) { directory = node->data; uri = nautilus_directory_get_uri (directory); if (!directory_belongs_in_scripts_menu (uri)) { remove_directory_from_scripts_directory_list (view, directory); - } else if (update_directory_in_scripts_menu (view, directory)) { - any_scripts = TRUE; } g_free (uri); } nautilus_directory_list_free (sorted_copy); - action = gtk_action_group_get_action (view->details->dir_action_group, NAUTILUS_ACTION_SCRIPTS); - gtk_action_set_visible (action, any_scripts); + directory = nautilus_directory_get_by_uri (scripts_directory_uri); + submenu = update_directory_in_scripts_menu (view, directory); + if (submenu != NULL) { + nautilus_gmenu_merge (view->details->selection_menu, + submenu, + "scripts-submenu", + TRUE); + } + + view->details->scripts_present = submenu != NULL; } static void -create_template_callback (GtkAction *action, gpointer callback_data) +create_template (GSimpleAction *action, + GVariant *state, + gpointer user_data) { + CreateTemplateParameters *parameters; - parameters = callback_data; + parameters = user_data; nautilus_view_new_file (parameters->directory_view, NULL, parameters->file); } static void -add_template_to_templates_menus (NautilusView *directory_view, +add_template_to_templates_menus (NautilusView *view, NautilusFile *file, - const char *menu_path, - const char *popup_bg_path) + GMenu *menu) { - char *tmp, *tip, *uri, *name; + char *tmp, *uri, *name; char *escaped_label; - GdkPixbuf *pixbuf; - char *action_name; + GdkPixbuf *mimetype_icon; + char *action_name, *detailed_action_name; CreateTemplateParameters *parameters; - GtkUIManager *ui_manager; - GtkAction *action; + GAction *action; + GMenuItem *menu_item; tmp = nautilus_file_get_display_name (file); name = eel_filename_strip_extension (tmp); g_free (tmp); uri = nautilus_file_get_uri (file); - tip = g_strdup_printf (_("Create a new document from template “%s”"), name); action_name = nautilus_escape_action_name (uri, "template_"); escaped_label = eel_str_double_underscores (name); - parameters = create_template_parameters_new (file, directory_view); + parameters = create_template_parameters_new (file, view); - action = gtk_action_new (action_name, - escaped_label, - tip, - NULL); + action = G_ACTION (g_simple_action_new (action_name, NULL)); - pixbuf = get_menu_icon_for_file (file, GTK_WIDGET (directory_view)); - if (pixbuf != NULL) { - gtk_action_set_gicon (action, G_ICON (pixbuf)); - g_object_unref (pixbuf); - } - g_signal_connect_data (action, "activate", - G_CALLBACK (create_template_callback), + G_CALLBACK (create_template), parameters, (GClosureNotify)create_templates_parameters_free, 0); + + g_action_map_add_action (G_ACTION_MAP (view->details->view_action_group), action); - gtk_action_group_add_action (directory_view->details->templates_action_group, - action); g_object_unref (action); - - ui_manager = nautilus_view_get_ui_manager (directory_view); - - gtk_ui_manager_add_ui (ui_manager, - directory_view->details->templates_merge_id, - menu_path, - action_name, - action_name, - GTK_UI_MANAGER_MENUITEM, - FALSE); - gtk_ui_manager_add_ui (ui_manager, - directory_view->details->templates_merge_id, - popup_bg_path, - action_name, - action_name, - GTK_UI_MANAGER_MENUITEM, - FALSE); + detailed_action_name = g_strconcat ("view.", action_name, NULL); + menu_item = g_menu_item_new (name, detailed_action_name); + + mimetype_icon = get_menu_icon_for_file (file, GTK_WIDGET (view)); + if (mimetype_icon != NULL) { + g_menu_item_set_icon (menu_item, G_ICON (mimetype_icon)); + g_object_unref (mimetype_icon); + } - menu_item_show_image (ui_manager, menu_path, action_name); - menu_item_show_image (ui_manager, popup_bg_path, action_name); + g_menu_append_item (menu, menu_item); g_free (escaped_label); g_free (name); - g_free (tip); g_free (uri); g_free (action_name); + g_free (detailed_action_name); } static void @@ -5168,37 +4304,28 @@ directory_belongs_in_templates_menu (const char *templates_directory_uri, return TRUE; } -static gboolean +static GMenu * update_directory_in_templates_menu (NautilusView *view, - const char *templates_directory_uri, NautilusDirectory *directory) { - char *menu_path, *popup_bg_path; GList *file_list, *filtered, *node; + GMenu *menu, *children_menu; + GMenuItem *menu_item; gboolean any_templates; NautilusFile *file; NautilusDirectory *dir; - char *escaped_path; char *uri; + char *templates_directory_uri; int num; - /* We know this directory belongs to the template dir, so it must exist */ - g_assert (templates_directory_uri); - - uri = nautilus_directory_get_uri (directory); - escaped_path = escape_action_path (uri + strlen (templates_directory_uri)); - g_free (uri); - menu_path = g_strconcat (NAUTILUS_VIEW_MENU_PATH_NEW_DOCUMENTS_PLACEHOLDER, - escaped_path, - NULL); - popup_bg_path = g_strconcat (NAUTILUS_VIEW_POPUP_PATH_BACKGROUND_NEW_DOCUMENTS_PLACEHOLDER, - escaped_path, - NULL); - g_free (escaped_path); + g_return_if_fail (NAUTILUS_IS_VIEW (view)); + g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); file_list = nautilus_directory_get_file_list (directory); filtered = nautilus_file_list_filter_hidden (file_list, FALSE); nautilus_file_list_free (file_list); + templates_directory_uri = nautilus_get_templates_directory_uri (); + menu = g_menu_new (); file_list = nautilus_file_list_sort_by_display_name (filtered); @@ -5206,34 +4333,41 @@ update_directory_in_templates_menu (NautilusView *view, any_templates = FALSE; for (node = file_list; num < TEMPLATE_LIMIT && node != NULL; node = node->next, num++) { file = node->data; - if (nautilus_file_is_directory (file)) { uri = nautilus_file_get_uri (file); if (directory_belongs_in_templates_menu (templates_directory_uri, uri)) { dir = nautilus_directory_get_by_uri (uri); add_directory_to_templates_directory_list (view, dir); - nautilus_directory_unref (dir); - add_submenu_to_directory_menus (view, - view->details->templates_action_group, - view->details->templates_merge_id, - file, menu_path, NULL, popup_bg_path); + children_menu = update_directory_in_templates_menu (view, dir); + + if (children_menu != NULL) { + menu_item = g_menu_item_new_submenu (nautilus_file_get_display_name (file), + G_MENU_MODEL (children_menu)); + g_menu_append_item (menu, menu_item); + any_templates = TRUE; + g_object_unref (menu_item); + g_object_unref (children_menu); + } - any_templates = TRUE; + nautilus_directory_unref (dir); } g_free (uri); } else if (nautilus_file_can_read (file)) { - add_template_to_templates_menus (view, file, menu_path, popup_bg_path); + add_template_to_templates_menus (view, file, menu); any_templates = TRUE; } } nautilus_file_list_free (file_list); + g_free (templates_directory_uri); - g_free (popup_bg_path); - g_free (menu_path); + if (!any_templates) { + g_object_unref (menu); + menu = NULL; + } - return any_templates; + return menu; } @@ -5241,63 +4375,54 @@ update_directory_in_templates_menu (NautilusView *view, static void update_templates_menu (NautilusView *view) { - gboolean any_templates; GList *sorted_copy, *node; NautilusDirectory *directory; - GtkUIManager *ui_manager; + GMenu *submenu; char *uri; char *templates_directory_uri; if (nautilus_should_use_templates_directory ()) { templates_directory_uri = nautilus_get_templates_directory_uri (); } else { - templates_directory_uri = NULL; + view->details->templates_present = FALSE; + return; } - /* There is a race condition here. If we don't mark the scripts menu as - valid before we begin our task then we can lose template menu updates that - occur before we finish. */ - view->details->templates_invalid = FALSE; - ui_manager = nautilus_view_get_ui_manager (view); - nautilus_ui_unmerge_ui (ui_manager, - &view->details->templates_merge_id, - &view->details->templates_action_group); - - nautilus_ui_prepare_merge_ui (ui_manager, - "TemplatesGroup", - &view->details->templates_merge_id, - &view->details->templates_action_group); - - /* As we walk through the directories, remove any that no longer belong. */ - any_templates = FALSE; sorted_copy = nautilus_directory_list_sort_by_uri (nautilus_directory_list_copy (view->details->templates_directory_list)); + for (node = sorted_copy; node != NULL; node = node->next) { directory = node->data; uri = nautilus_directory_get_uri (directory); if (!directory_belongs_in_templates_menu (templates_directory_uri, uri)) { remove_directory_from_templates_directory_list (view, directory); - } else if (update_directory_in_templates_menu (view, - templates_directory_uri, - directory)) { - any_templates = TRUE; } g_free (uri); } nautilus_directory_list_free (sorted_copy); - view->details->templates_present = any_templates; + directory = nautilus_directory_get_by_uri (templates_directory_uri); + submenu = update_directory_in_templates_menu (view, directory); + if (submenu != NULL) { + nautilus_gmenu_merge (view->details->background_menu, + submenu, + "templates-submenu", + FALSE); + } + + view->details->templates_present = submenu != NULL; g_free (templates_directory_uri); } static void -action_open_scripts_folder_callback (GtkAction *action, - gpointer callback_data) -{ +action_open_scripts_folder (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ NautilusView *view; static GFile *location = NULL; @@ -5305,24 +4430,10 @@ action_open_scripts_folder_callback (GtkAction *action, location = g_file_new_for_uri (scripts_directory_uri); } - view = NAUTILUS_VIEW (callback_data); + view = NAUTILUS_VIEW (user_data); nautilus_window_slot_open_location (view->details->slot, location, 0); } -static GtkMenu * -create_popup_menu (NautilusView *view, const char *popup_path) -{ - GtkWidget *menu; - - menu = gtk_ui_manager_get_widget (nautilus_view_get_ui_manager (view), - popup_path); - gtk_menu_set_screen (GTK_MENU (menu), - gtk_widget_get_screen (GTK_WIDGET (view))); - gtk_widget_show (GTK_WIDGET (menu)); - - return GTK_MENU (menu); -} - typedef struct _CopyCallbackData { NautilusView *view; GtkFileChooser *chooser; @@ -5739,13 +4850,14 @@ copy_or_cut_files (NautilusView *view, } static void -action_copy_files_callback (GtkAction *action, - gpointer callback_data) +action_copy (GSimpleAction *action, + GVariant *state, + gpointer user_data) { NautilusView *view; GList *selection; - view = NAUTILUS_VIEW (callback_data); + view = NAUTILUS_VIEW (user_data); selection = nautilus_view_get_selection_for_file_transfer (view); copy_or_cut_files (view, selection, FALSE); @@ -5753,13 +4865,14 @@ action_copy_files_callback (GtkAction *action, } static void -action_cut_files_callback (GtkAction *action, - gpointer callback_data) +action_cut (GSimpleAction *action, + GVariant *state, + gpointer user_data) { NautilusView *view; GList *selection; - view = NAUTILUS_VIEW (callback_data); + view = NAUTILUS_VIEW (user_data); selection = nautilus_view_get_selection_for_file_transfer (view); copy_or_cut_files (view, selection, TRUE); @@ -5767,72 +4880,27 @@ action_cut_files_callback (GtkAction *action, } static void -action_copy_to_callback (GtkAction *action, - gpointer callback_data) +action_copy_to (GSimpleAction *action, + GVariant *state, + gpointer user_data) { NautilusView *view; - view = NAUTILUS_VIEW (callback_data); + view = NAUTILUS_VIEW (user_data); copy_or_move_selection (view, FALSE); } static void -action_move_to_callback (GtkAction *action, - gpointer callback_data) +action_move_to (GSimpleAction *action, + GVariant *state, + gpointer user_data) { NautilusView *view; - view = NAUTILUS_VIEW (callback_data); + view = NAUTILUS_VIEW (user_data); copy_or_move_selection (view, TRUE); } -static void -paste_clipboard_data (NautilusView *view, - GtkSelectionData *selection_data, - char *destination_uri) -{ - gboolean cut; - GList *item_uris; - - cut = FALSE; - item_uris = nautilus_clipboard_get_uri_list_from_selection_data (selection_data, &cut, - copied_files_atom); - - if (item_uris != NULL && destination_uri != NULL) { - nautilus_view_move_copy_items (view, item_uris, NULL, destination_uri, - cut ? GDK_ACTION_MOVE : GDK_ACTION_COPY, - 0, 0); - - /* If items are cut then remove from clipboard */ - if (cut) { - gtk_clipboard_clear (nautilus_clipboard_get (GTK_WIDGET (view))); - } - - g_list_free_full (item_uris, g_free); - } -} - -static void -paste_clipboard_received_callback (GtkClipboard *clipboard, - GtkSelectionData *selection_data, - gpointer data) -{ - NautilusView *view; - char *view_uri; - - view = NAUTILUS_VIEW (data); - - view_uri = nautilus_view_get_backing_uri (view); - - if (view->details->slot != NULL) { - paste_clipboard_data (view, selection_data, view_uri); - } - - g_free (view_uri); - - g_object_unref (view); -} - typedef struct { NautilusView *view; NautilusFile *target; @@ -5865,21 +4933,6 @@ paste_into_clipboard_received_callback (GtkClipboard *clipboard, } static void -action_paste_files_callback (GtkAction *action, - gpointer callback_data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (callback_data); - - g_object_ref (view); - gtk_clipboard_request_contents (nautilus_clipboard_get (GTK_WIDGET (view)), - copied_files_atom, - paste_clipboard_received_callback, - view); -} - -static void paste_into (NautilusView *view, NautilusFile *target) { @@ -5900,13 +4953,14 @@ paste_into (NautilusView *view, } static void -action_paste_files_into_callback (GtkAction *action, - gpointer callback_data) +action_paste_files_into (GSimpleAction *action, + GVariant *state, + gpointer user_data) { NautilusView *view; GList *selection; - view = NAUTILUS_VIEW (callback_data); + view = NAUTILUS_VIEW (user_data); selection = nautilus_view_get_selection (view); if (selection != NULL) { paste_into (view, NAUTILUS_FILE (selection->data)); @@ -5947,38 +5001,6 @@ invoke_external_bulk_rename_utility (NautilusView *view, } static void -real_action_undo (NautilusView *view) -{ - GtkWidget *toplevel; - - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view)); - nautilus_file_undo_manager_undo (GTK_WINDOW (toplevel)); -} - -static void -real_action_redo (NautilusView *view) -{ - GtkWidget *toplevel; - - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view)); - nautilus_file_undo_manager_redo (GTK_WINDOW (toplevel)); -} - -static void -action_undo_callback (GtkAction *action, - gpointer callback_data) -{ - real_action_undo (NAUTILUS_VIEW (callback_data)); -} - -static void -action_redo_callback (GtkAction *action, - gpointer callback_data) -{ - real_action_redo (NAUTILUS_VIEW (callback_data)); -} - -static void real_action_rename (NautilusView *view, gboolean select_all) { @@ -6010,17 +5032,11 @@ real_action_rename (NautilusView *view, } static void -action_rename_callback (GtkAction *action, - gpointer callback_data) -{ - real_action_rename (NAUTILUS_VIEW (callback_data), FALSE); -} - -static void -action_rename_select_all_callback (GtkAction *action, - gpointer callback_data) +action_rename (GSimpleAction *action, + GVariant *state, + gpointer user_data) { - real_action_rename (NAUTILUS_VIEW (callback_data), TRUE); + real_action_rename (NAUTILUS_VIEW (user_data), TRUE); } #define BG_KEY_PRIMARY_COLOR "primary-color" @@ -6089,20 +5105,21 @@ can_set_wallpaper (GList *selection) } static void -action_set_as_wallpaper_callback (GtkAction *action, - NautilusView *view) +action_set_as_wallpaper (GSimpleAction *action, + GVariant *state, + gpointer user_data) { GList *selection; /* Copy the item to Pictures/Wallpaper since it may be remote. Then set it as the current wallpaper. */ - g_assert (NAUTILUS_IS_VIEW (view)); + g_assert (NAUTILUS_IS_VIEW (user_data)); - selection = nautilus_view_get_selection (view); + selection = nautilus_view_get_selection (user_data); if (can_set_wallpaper (selection) - && selection_not_empty_in_menu_callback (view, selection)) { + && selection_not_empty_in_menu_callback (user_data, selection)) { NautilusFile *file; char *target_uri; GList *uris; @@ -6122,7 +5139,7 @@ action_set_as_wallpaper_callback (GtkAction *action, NULL, target_uri, GDK_ACTION_COPY, - GTK_WIDGET (view), + GTK_WIDGET (user_data), wallpaper_copy_done_callback, NULL); g_free (target_uri); @@ -6234,15 +5251,16 @@ file_stop_callback (NautilusFile *file, } static void -action_mount_volume_callback (GtkAction *action, - gpointer data) +action_mount_volume (GSimpleAction *action, + GVariant *state, + gpointer user_data) { NautilusFile *file; GList *selection, *l; NautilusView *view; GMountOperation *mount_op; - view = NAUTILUS_VIEW (data); + view = NAUTILUS_VIEW (user_data); selection = nautilus_view_get_selection (view); for (l = selection; l != NULL; l = l->next) { @@ -6261,14 +5279,15 @@ action_mount_volume_callback (GtkAction *action, } static void -action_unmount_volume_callback (GtkAction *action, - gpointer data) +action_unmount_volume (GSimpleAction *action, + GVariant *state, + gpointer user_data) { NautilusFile *file; GList *selection, *l; NautilusView *view; - view = NAUTILUS_VIEW (data); + view = NAUTILUS_VIEW (user_data); selection = nautilus_view_get_selection (view); @@ -6286,14 +5305,15 @@ action_unmount_volume_callback (GtkAction *action, } static void -action_eject_volume_callback (GtkAction *action, - gpointer data) +action_eject_volume (GSimpleAction *action, + GVariant *state, + gpointer user_data) { NautilusFile *file; GList *selection, *l; NautilusView *view; - view = NAUTILUS_VIEW (data); + view = NAUTILUS_VIEW (user_data); selection = nautilus_view_get_selection (view); for (l = selection; l != NULL; l = l->next) { @@ -6338,15 +5358,16 @@ file_start_callback (NautilusFile *file, } static void -action_start_volume_callback (GtkAction *action, - gpointer data) +action_start_volume (GSimpleAction *action, + GVariant *state, + gpointer user_data) { NautilusFile *file; GList *selection, *l; NautilusView *view; GMountOperation *mount_op; - view = NAUTILUS_VIEW (data); + view = NAUTILUS_VIEW (user_data); selection = nautilus_view_get_selection (view); for (l = selection; l != NULL; l = l->next) { @@ -6363,14 +5384,15 @@ action_start_volume_callback (GtkAction *action, } static void -action_stop_volume_callback (GtkAction *action, - gpointer data) +action_stop_volume (GSimpleAction *action, + GVariant *state, + gpointer user_data) { NautilusFile *file; GList *selection, *l; NautilusView *view; - view = NAUTILUS_VIEW (data); + view = NAUTILUS_VIEW (user_data); selection = nautilus_view_get_selection (view); for (l = selection; l != NULL; l = l->next) { @@ -6388,14 +5410,15 @@ action_stop_volume_callback (GtkAction *action, } static void -action_detect_media_callback (GtkAction *action, - gpointer data) +action_detect_media (GSimpleAction *action, + GVariant *state, + gpointer user_data) { NautilusFile *file; GList *selection, *l; NautilusView *view; - view = NAUTILUS_VIEW (data); + view = NAUTILUS_VIEW (user_data); selection = nautilus_view_get_selection (view); for (l = selection; l != NULL; l = l->next) { @@ -6414,268 +5437,56 @@ nautilus_view_get_show_hidden_files (NautilusView *view) return view->details->show_hidden_files; } -static void -nautilus_view_set_show_hidden_files (NautilusView *view, - gboolean show_hidden) -{ - if (view->details->ignore_hidden_file_preferences) { - return; - } - - if (show_hidden != view->details->show_hidden_files) { - view->details->show_hidden_files = show_hidden; - if (view->details->model != NULL) { - load_directory (view, view->details->model); - } - } -} - -static const GtkActionEntry directory_view_entries[] = { - /* name, stock id, label */ { NAUTILUS_ACTION_NEW_DOCUMENTS, "document-new", N_("New _Document") }, - /* name, stock id, label */ { NAUTILUS_ACTION_OPEN_WITH, NULL, N_("Open Wit_h"), - NULL, N_("Choose a program with which to open the selected item") }, - /* name, stock id */ { NAUTILUS_ACTION_PROPERTIES, NULL, - /* label, accelerator */ N_("P_roperties"), "<alt>Return", - /* tooltip */ N_("View or modify the properties of each selected item"), - G_CALLBACK (action_properties_callback) }, - /* name, stock id */ { "PropertiesAccel", NULL, - /* label, accelerator */ "PropertiesAccel", "<control>I", - /* tooltip */ NULL, - G_CALLBACK (action_properties_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_NEW_FOLDER, "folder-new", - /* label, accelerator */ N_("New _Folder"), "<control><shift>N", - /* tooltip */ N_("Create a new empty folder inside this folder"), - G_CALLBACK (action_new_folder_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_NEW_FOLDER_WITH_SELECTION, NULL, - /* label, accelerator */ N_("New Folder with Selection"), NULL, - /* tooltip */ N_("Create a new folder containing the selected items"), - G_CALLBACK (action_new_folder_with_selection_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_OPEN, NULL, - /* label, accelerator */ N_("_Open"), "<control>o", - /* tooltip */ N_("Open the selected item in this window"), - G_CALLBACK (action_open_callback) }, - /* name, stock id */ { "OpenAccel", NULL, - /* label, accelerator */ "OpenAccel", "<alt>Down", - /* tooltip */ NULL, - G_CALLBACK (action_open_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_OPEN_ITEM_LOCATION, NULL, - /* label, accelerator */ N_("Open _Item Location"), "<control><alt>o", - /* tooltip */ N_("Open the selected item's location in this window"), - G_CALLBACK (action_open_item_location_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_OPEN_ALTERNATE, NULL, - /* label, accelerator */ N_("Open in Navigation Window"), "<control><shift>o", - /* tooltip */ N_("Open each selected item in a navigation window"), - G_CALLBACK (action_open_alternate_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_OPEN_IN_NEW_TAB, NULL, - /* label, accelerator */ N_("Open in New _Tab"), "<control><shift>t", - /* tooltip */ N_("Open each selected item in a new tab"), - G_CALLBACK (action_open_new_tab_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_OTHER_APPLICATION1, NULL, - /* label, accelerator */ N_("Other _Application…"), NULL, - /* tooltip */ N_("Choose another application with which to open the selected item"), - G_CALLBACK (action_other_application_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_OTHER_APPLICATION2, NULL, - /* label, accelerator */ N_("Open With Other _Application…"), NULL, - /* tooltip */ N_("Choose another application with which to open the selected item"), - G_CALLBACK (action_other_application_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_OPEN_SCRIPTS_FOLDER, NULL, - /* label, accelerator */ N_("_Open Scripts Folder"), NULL, - /* tooltip */ N_("Show the folder containing the scripts that appear in this menu"), - G_CALLBACK (action_open_scripts_folder_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_CUT, NULL, - /* label, accelerator */ N_("Cu_t"), "<control>X", - /* tooltip */ N_("Prepare the selected files to be moved with a Paste command"), - G_CALLBACK (action_cut_files_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_COPY, NULL, - /* label, accelerator */ N_("_Copy"), "<control>C", - /* tooltip */ N_("Prepare the selected files to be copied with a Paste command"), - G_CALLBACK (action_copy_files_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_PASTE, NULL, - /* label, accelerator */ N_("_Paste"), "<control>V", - /* tooltip */ N_("Move or copy files previously selected by a Cut or Copy command"), - G_CALLBACK (action_paste_files_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_PASTE_FILES_INTO, NULL, - /* label, accelerator */ N_("_Paste Into Folder"), NULL, - /* tooltip */ N_("Move or copy files previously selected by a Cut or Copy command into the selected folder"), - G_CALLBACK (action_paste_files_into_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_COPY_TO, NULL, - /* label, accelerator */ N_("Copy To…"), NULL, - /* tooltip */ N_("Copy selected files to another location"), - G_CALLBACK (action_copy_to_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_MOVE_TO, NULL, - /* label, accelerator */ N_("Move To…"), NULL, - /* tooltip */ N_("Move selected files to another location"), - G_CALLBACK (action_move_to_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_SELECT_ALL, NULL, - /* label, accelerator */ N_("Select _All"), "<control>A", - /* tooltip */ N_("Select all items in this window"), - G_CALLBACK (action_select_all_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_SELECT_PATTERN, NULL, - /* label, accelerator */ N_("Select I_tems Matching…"), "<control>S", - /* tooltip */ N_("Select items in this window matching a given pattern"), - G_CALLBACK (action_select_pattern_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_INVERT_SELECTION, NULL, - /* label, accelerator */ N_("_Invert Selection"), "<control><shift>I", - /* tooltip */ N_("Select all and only the items that are not currently selected"), - G_CALLBACK (action_invert_selection_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_RENAME, NULL, - /* label, accelerator */ N_("Rena_me…"), "F2", - /* tooltip */ N_("Rename selected item"), - G_CALLBACK (action_rename_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_SET_AS_WALLPAPER, NULL, - /* label, accelerator */ N_("Set as Wallpaper"), NULL, - /* tooltip */ N_("Make item the wallpaper"), - G_CALLBACK (action_set_as_wallpaper_callback) }, - /* name, stock id */ { "RenameSelectAll", NULL, - /* label, accelerator */ "RenameSelectAll", "<shift>F2", - /* tooltip */ NULL, - G_CALLBACK (action_rename_select_all_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_TRASH, NULL, - /* label, accelerator */ N_("Mo_ve to Trash"), "<control>Delete", - /* tooltip */ N_("Move each selected item to the Trash"), - G_CALLBACK (action_trash_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_DELETE, NULL, - /* label, accelerator */ N_("_Delete"), "<shift>Delete", - /* tooltip */ N_("Delete each selected item, without moving to the Trash"), - G_CALLBACK (action_delete_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_RESTORE_FROM_TRASH, NULL, - /* label, accelerator */ N_("_Restore"), NULL, - NULL, - G_CALLBACK (action_restore_from_trash_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_UNDO, NULL, - /* label, accelerator */ N_("_Undo"), "<control>Z", - /* tooltip */ N_("Undo the last action"), - G_CALLBACK (action_undo_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_REDO, NULL, - /* label, accelerator */ N_("_Redo"), "<shift><control>Z", - /* tooltip */ N_("Redo the last undone action"), - G_CALLBACK (action_redo_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_MOUNT_VOLUME, NULL, - /* label, accelerator */ N_("_Mount"), NULL, - /* tooltip */ N_("Mount the selected volume"), - G_CALLBACK (action_mount_volume_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_UNMOUNT_VOLUME, NULL, - /* label, accelerator */ N_("_Unmount"), NULL, - /* tooltip */ N_("Unmount the selected volume"), - G_CALLBACK (action_unmount_volume_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_EJECT_VOLUME, NULL, - /* label, accelerator */ N_("_Eject"), NULL, - /* tooltip */ N_("Eject the selected volume"), - G_CALLBACK (action_eject_volume_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_START_VOLUME, NULL, - /* label, accelerator */ N_("_Start"), NULL, - /* tooltip */ N_("Start the selected volume"), - G_CALLBACK (action_start_volume_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_STOP_VOLUME, NULL, - /* label, accelerator */ N_("_Stop"), NULL, - /* tooltip */ N_("Stop the selected volume"), - G_CALLBACK (action_stop_volume_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_POLL, NULL, - /* label, accelerator */ N_("_Detect Media"), NULL, - /* tooltip */ N_("Detect media in the selected drive"), - G_CALLBACK (action_detect_media_callback) }, - /* name, stock id */ { "OpenCloseParent", NULL, - /* label, accelerator */ N_("Open File and Close window"), "<alt><shift>Down", - /* tooltip */ NULL, - G_CALLBACK (action_open_close_parent_callback) }, - - /* Location-specific actions */ - /* name, stock id */ { NAUTILUS_ACTION_LOCATION_OPEN_ALTERNATE, NULL, - /* label, accelerator */ N_("Open in Navigation Window"), NULL, - /* tooltip */ N_("Open this folder in a navigation window"), - G_CALLBACK (action_location_open_alternate_callback) }, - /* name, stock id */ { NAUTILUS_ACTION_LOCATION_OPEN_IN_NEW_TAB, NULL, - /* label, accelerator */ N_("Open in New _Tab"), NULL, - /* tooltip */ N_("Open this folder in a new tab"), - G_CALLBACK (action_location_open_in_new_tab_callback) }, -}; - -static const GtkToggleActionEntry directory_view_toggle_entries[] = { - /* name, stock id */ { NAUTILUS_ACTION_SHOW_HIDDEN_FILES, NULL, - /* label, accelerator */ N_("Show _Hidden Files"), "<control>H", - /* tooltip */ N_("Toggle the display of hidden files in the current window"), - G_CALLBACK (action_show_hidden_files_callback), - TRUE }, +const GActionEntry view_entries[] = { + /* Toolbar menu */ + { "zoom-in", action_zoom_in }, + { "zoom-out", action_zoom_out }, + { "zoom-default", action_zoom_default }, + { "zoom-to-level", NULL, NULL, "1", action_zoom_to_level }, + { "undo", action_undo }, + { "redo", action_redo }, + { "show-hidden-files", NULL, NULL, "true", action_show_hidden_files }, + /* Background menu */ + { "new-folder", action_new_folder }, + { "select-all", action_select_all }, + { "paste", action_paste_files }, + { "new-document" }, + /* Selection menu */ + { "scripts" }, + { "new-folder-with-selection", action_new_folder_with_selection }, + { "open-scripts-folder", action_open_scripts_folder }, + { "open-item-location", action_open_item_location }, + { "open-with-default-application", action_open_with_default_application }, + { "open-with-other-application", action_open_with_other_application }, + { "open-item-new-window", action_open_item_new_window }, + { "open-item-new-tab", action_open_item_new_tab }, + { "cut", action_cut}, + { "copy", action_copy}, + { "move-to", action_move_to}, + { "copy-to", action_copy_to}, + { "move-to-trash", action_move_to_trash}, + { "delete", action_delete}, + { "restore-from-trash", action_restore_from_trash}, + { "paste-into", action_paste_files_into }, + { "rename", action_rename}, + { "properties", action_properties}, + { "set-as-wallpaper", action_set_as_wallpaper }, + { "mount-volume", action_mount_volume }, + { "unmount-volume", action_unmount_volume }, + { "eject-volume", action_eject_volume }, + { "start-volume", action_start_volume }, + { "stop-volume", action_stop_volume }, + { "detect-media", action_detect_media }, + /* Pathbar menu */ + { "pathbar-open-item-new-window", action_pathbar_open_item_new_window }, + { "pathbar-open-item-new-tab", action_pathbar_open_item_new_tab }, + { "pathbar-properties", action_pathbar_properties}, + /* Only accesible by shorcuts */ + { "select-pattern", action_select_pattern }, + { "invert-selection", action_invert_selection }, + { "open-file-and-close-window", action_open_file_and_close_window } }; -static void -pre_activate (NautilusView *view, - GtkAction *action, - GtkActionGroup *action_group) -{ - GdkEvent *event; - GtkWidget *proxy; - gboolean activated_from_popup; - - /* check whether action was activated through a popup menu. - * If not, unset the last stored context menu popup position */ - activated_from_popup = FALSE; - - event = gtk_get_current_event (); - proxy = gtk_get_event_widget (event); - - if (proxy != NULL) { - GtkWidget *toplevel; - GdkWindowTypeHint hint; - - toplevel = gtk_widget_get_toplevel (proxy); - - if (GTK_IS_WINDOW (toplevel)) { - hint = gtk_window_get_type_hint (GTK_WINDOW (toplevel)); - - if (hint == GDK_WINDOW_TYPE_HINT_POPUP_MENU) { - activated_from_popup = TRUE; - } - } - } - - if (!activated_from_popup) { - update_context_menu_position_from_event (view, NULL); - } -} - -static void -real_merge_menus (NautilusView *view) -{ - GtkActionGroup *action_group; - GtkUIManager *ui_manager; - GtkAction *action; - char *tooltip; - - ui_manager = nautilus_view_get_ui_manager (view); - - action_group = gtk_action_group_new ("DirViewActions"); - gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE); - view->details->dir_action_group = action_group; - gtk_action_group_add_actions (action_group, - directory_view_entries, G_N_ELEMENTS (directory_view_entries), - view); - gtk_action_group_add_toggle_actions (action_group, - directory_view_toggle_entries, G_N_ELEMENTS (directory_view_toggle_entries), - view); - - tooltip = g_strdup (_("Run or manage scripts")); - /* Create a script action here specially because its tooltip is dynamic */ - action = gtk_action_new ("Scripts", _("_Scripts"), tooltip, NULL); - gtk_action_group_add_action (action_group, action); - g_object_unref (action); - g_free (tooltip); - - g_signal_connect_object (action_group, "pre-activate", - G_CALLBACK (pre_activate), G_OBJECT (view), - G_CONNECT_SWAPPED); - - /* Insert action group at end so clipboard action group ends up before it */ - gtk_ui_manager_insert_action_group (ui_manager, action_group, -1); - g_object_unref (action_group); /* owned by ui manager */ - - view->details->dir_merge_id = gtk_ui_manager_add_ui_from_resource (ui_manager, "/org/gnome/nautilus/nautilus-directory-view-ui.xml", NULL); - - view->details->scripts_invalid = TRUE; - view->details->templates_invalid = TRUE; -} - - static gboolean can_paste_into_file (NautilusFile *file) { @@ -6716,9 +5527,7 @@ clipboard_targets_received (GtkClipboard *clipboard, NautilusView *view; gboolean can_paste; int i; - GList *selection; - int count; - GtkAction *action; + GAction *action; view = NAUTILUS_VIEW (user_data); can_paste = FALSE; @@ -6731,82 +5540,27 @@ clipboard_targets_received (GtkClipboard *clipboard, } if (targets) { - for (i=0; i < n_targets; i++) { + for (i = 0; i < n_targets; i++) { if (targets[i] == copied_files_atom) { can_paste = TRUE; } } } - - - selection = nautilus_view_get_selection (view); - count = g_list_length (selection); - - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_PASTE); - gtk_action_set_sensitive (action, - can_paste && !nautilus_view_is_read_only (view)); - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_PASTE_FILES_INTO); - gtk_action_set_sensitive (action, - can_paste && count == 1 && - can_paste_into_file (NAUTILUS_FILE (selection->data))); + action = g_action_map_lookup_action (G_ACTION_MAP (view->details->view_action_group), + "paste"); + /* Take into account if the action was previously disabled for other reasons, + * like the directory not being writabble */ + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + can_paste && g_action_get_enabled (action)); - nautilus_file_list_free (selection); - - g_object_unref (view); -} + action = g_action_map_lookup_action (G_ACTION_MAP (view->details->view_action_group), + "paste-into"); -static gboolean -file_list_all_are_folders (GList *file_list) -{ - GList *l; - NautilusFile *file, *linked_file; - char *activation_uri; - gboolean is_dir; + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + can_paste && g_action_get_enabled (action)); - for (l = file_list; l != NULL; l = l->next) { - file = NAUTILUS_FILE (l->data); - if (nautilus_file_is_nautilus_link (file) && - !NAUTILUS_IS_DESKTOP_ICON_FILE (file)) { - if (nautilus_file_is_launcher (file)) { - return FALSE; - } - - activation_uri = nautilus_file_get_activation_uri (file); - - if (activation_uri == NULL) { - g_free (activation_uri); - return FALSE; - } - - linked_file = nautilus_file_get_existing_by_uri (activation_uri); - - /* We might not actually know the type of the linked file yet, - * however we don't want to schedule a read, since that might do things - * like ask for password etc. This is a bit unfortunate, but I don't - * know any way around it, so we do various heuristics here - * to get things mostly right - */ - is_dir = - (linked_file != NULL && - nautilus_file_is_directory (linked_file)) || - (activation_uri != NULL && - activation_uri[strlen (activation_uri) - 1] == '/'); - - nautilus_file_unref (linked_file); - g_free (activation_uri); - - if (!is_dir) { - return FALSE; - } - } else if (!(nautilus_file_is_directory (file) || - NAUTILUS_IS_DESKTOP_ICON_FILE (file))) { - return FALSE; - } - } - return TRUE; + g_object_unref (view); } static void @@ -6856,57 +5610,18 @@ file_should_show_foreach (NautilusFile *file, } static gboolean -files_are_all_directories (GList *files) -{ - NautilusFile *file; - GList *l; - gboolean all_directories; - - all_directories = TRUE; - - for (l = files; l != NULL; l = l->next) { - file = NAUTILUS_FILE (l->data); - all_directories &= nautilus_file_is_directory (file); - } - - return all_directories; -} - -static gboolean -files_is_none_directory (GList *files) -{ - NautilusFile *file; - GList *l; - gboolean no_directory; - - no_directory = TRUE; - - for (l = files; l != NULL; l = l->next) { - file = NAUTILUS_FILE (l->data); - no_directory &= !nautilus_file_is_directory (file); - } - - return no_directory; -} - -static void -update_restore_from_trash_action (GtkAction *action, - GList *files, - gboolean is_self) +can_restore_from_trash (GList *files) { NautilusFile *original_file; NautilusFile *original_dir; GHashTable *original_dirs_hash; GList *original_dirs; - GFile *original_location; - char *tooltip, *original_name; + gboolean can_restore; original_file = NULL; original_dir = NULL; original_dirs = NULL; original_dirs_hash = NULL; - original_location = NULL; - original_name = NULL; if (files != NULL) { if (g_list_length (files) == 1) { @@ -6922,83 +5637,7 @@ update_restore_from_trash_action (GtkAction *action, } } - if (original_file != NULL || original_dirs != NULL) { - gtk_action_set_visible (action, TRUE); - - if (original_file != NULL) { - original_location = nautilus_file_get_location (original_file); - } else if (original_dir != NULL) { - original_location = nautilus_file_get_location (original_dir); - } - - if (original_location != NULL) { - original_name = g_file_get_parse_name (original_location); - } - - if (is_self) { - g_assert (g_list_length (files) == 1); - g_assert (original_location != NULL); - tooltip = g_strdup_printf (_("Move the open folder out of the trash to “%s”"), original_name); - } else if (files_are_all_directories (files)) { - if (original_name != NULL) { - if (g_list_length (files) == 1) { - tooltip = g_strdup_printf (_("Move the selected folder out of the trash to “%s”"), - original_name); - } else { - tooltip = g_strdup_printf (_("Move the selected folders out of the trash to “%s”"), - original_name); - } - } else { - if (g_list_length (files) == 1) { - tooltip = g_strdup (_("Move the selected folder out of the trash")); - } else { - tooltip = g_strdup (_("Move the selected folders out of the trash")); - } - } - } else if (files_is_none_directory (files)) { - if (original_name != NULL) { - if (g_list_length (files) == 1) { - tooltip = g_strdup_printf (_("Move the selected file out of the trash to “%s”"), - original_name); - } else { - tooltip = g_strdup_printf (_("Move the selected files out of the trash to “%s”"), - original_name); - } - } else { - if (g_list_length (files) == 1) { - tooltip = g_strdup (_("Move the selected file out of the trash")); - } else { - tooltip = g_strdup (_("Move the selected files out of the trash")); - } - } - } else { - if (original_name != NULL) { - if (g_list_length (files) == 1) { - tooltip = g_strdup_printf (_("Move the selected item out of the trash to “%s”"), - original_name); - } else { - tooltip = g_strdup_printf (_("Move the selected items out of the trash to “%s”"), - original_name); - } - } else { - if (g_list_length (files) == 1) { - tooltip = g_strdup (_("Move the selected item out of the trash")); - } else { - tooltip = g_strdup (_("Move the selected items out of the trash")); - } - } - } - g_free (original_name); - - g_object_set (action, "tooltip", tooltip, NULL); - g_free (tooltip); - - if (original_location != NULL) { - g_object_unref (original_location); - } - } else { - gtk_action_set_visible (action, FALSE); - } + can_restore = original_file != NULL || original_dirs != NULL; nautilus_file_unref (original_file); nautilus_file_unref (original_dir); @@ -7007,220 +5646,14 @@ update_restore_from_trash_action (GtkAction *action, if (original_dirs_hash != NULL) { g_hash_table_destroy (original_dirs_hash); } -} - -static void -real_update_menus_volumes (NautilusView *view, - GList *selection, - gint selection_count) -{ - GList *l; - NautilusFile *file; - gboolean show_mount; - gboolean show_unmount; - gboolean show_eject; - gboolean show_start; - gboolean show_stop; - gboolean show_poll; - GDriveStartStopType start_stop_type; - GtkAction *action; - - show_mount = (selection != NULL); - show_unmount = (selection != NULL); - show_eject = (selection != NULL); - show_start = (selection != NULL && selection_count == 1); - show_stop = (selection != NULL && selection_count == 1); - show_poll = (selection != NULL && selection_count == 1); - start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN; - - for (l = selection; l != NULL && (show_mount || show_unmount - || show_eject - || show_start || show_stop - || show_poll); - l = l->next) { - gboolean show_mount_one; - gboolean show_unmount_one; - gboolean show_eject_one; - gboolean show_start_one; - gboolean show_stop_one; - gboolean show_poll_one; - - file = NAUTILUS_FILE (l->data); - file_should_show_foreach (file, - &show_mount_one, - &show_unmount_one, - &show_eject_one, - &show_start_one, - &show_stop_one, - &show_poll_one, - &start_stop_type); - - show_mount &= show_mount_one; - show_unmount &= show_unmount_one; - show_eject &= show_eject_one; - show_start &= show_start_one; - show_stop &= show_stop_one; - show_poll &= show_poll_one; - } - - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_MOUNT_VOLUME); - gtk_action_set_visible (action, show_mount); - - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_UNMOUNT_VOLUME); - gtk_action_set_visible (action, show_unmount); - - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_EJECT_VOLUME); - gtk_action_set_visible (action, show_eject); - - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_START_VOLUME); - gtk_action_set_visible (action, show_start); - if (show_start) { - switch (start_stop_type) { - default: - case G_DRIVE_START_STOP_TYPE_UNKNOWN: - gtk_action_set_label (action, _("_Start")); - gtk_action_set_tooltip (action, _("Start the selected drive")); - break; - case G_DRIVE_START_STOP_TYPE_SHUTDOWN: - gtk_action_set_label (action, _("_Start")); - gtk_action_set_tooltip (action, _("Start the selected drive")); - break; - case G_DRIVE_START_STOP_TYPE_NETWORK: - gtk_action_set_label (action, _("_Connect")); - gtk_action_set_tooltip (action, _("Connect to the selected drive")); - break; - case G_DRIVE_START_STOP_TYPE_MULTIDISK: - gtk_action_set_label (action, _("_Start Multi-disk Drive")); - gtk_action_set_tooltip (action, _("Start the selected multi-disk drive")); - break; - case G_DRIVE_START_STOP_TYPE_PASSWORD: - gtk_action_set_label (action, _("U_nlock Drive")); - gtk_action_set_tooltip (action, _("Unlock the selected drive")); - break; - } - } - - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_STOP_VOLUME); - gtk_action_set_visible (action, show_stop); - if (show_stop) { - switch (start_stop_type) { - default: - case G_DRIVE_START_STOP_TYPE_UNKNOWN: - gtk_action_set_label (action, _("_Stop")); - gtk_action_set_tooltip (action, _("Stop the selected drive")); - break; - case G_DRIVE_START_STOP_TYPE_SHUTDOWN: - gtk_action_set_label (action, _("_Safely Remove Drive")); - gtk_action_set_tooltip (action, _("Safely remove the selected drive")); - break; - case G_DRIVE_START_STOP_TYPE_NETWORK: - gtk_action_set_label (action, _("_Disconnect")); - gtk_action_set_tooltip (action, _("Disconnect the selected drive")); - break; - case G_DRIVE_START_STOP_TYPE_MULTIDISK: - gtk_action_set_label (action, _("_Stop Multi-disk Drive")); - gtk_action_set_tooltip (action, _("Stop the selected multi-disk drive")); - break; - case G_DRIVE_START_STOP_TYPE_PASSWORD: - gtk_action_set_label (action, _("_Lock Drive")); - gtk_action_set_tooltip (action, _("Lock the selected drive")); - break; - } - } - - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_POLL); - gtk_action_set_visible (action, show_poll); -} - -/* TODO: we should split out this routine into two functions: - * Update on clipboard changes - * Update on selection changes - */ -static void -real_update_paste_menu (NautilusView *view, - GList *selection, - gint selection_count) -{ - gboolean can_paste_files_into; - gboolean selection_is_read_only; - gboolean selection_contains_recent; - gboolean is_read_only; - GtkAction *action; - - selection_is_read_only = selection_count == 1 && - (!nautilus_file_can_write (NAUTILUS_FILE (selection->data)) && - !nautilus_file_has_activation_uri (NAUTILUS_FILE (selection->data))); - - is_read_only = nautilus_view_is_read_only (view); - selection_contains_recent = showing_recent_directory (view); - - can_paste_files_into = (!selection_contains_recent && - selection_count == 1 && - can_paste_into_file (NAUTILUS_FILE (selection->data))); - - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_PASTE); - gtk_action_set_sensitive (action, !is_read_only); - gtk_action_set_visible (action, !selection_contains_recent); - - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_PASTE_FILES_INTO); - gtk_action_set_visible (action, can_paste_files_into); - gtk_action_set_sensitive (action, !selection_is_read_only); - - /* Ask the clipboard */ - g_object_ref (view); /* Need to keep the object alive until we get the reply */ - gtk_clipboard_request_targets (nautilus_clipboard_get (GTK_WIDGET (view)), - clipboard_targets_received, - view); -} - -static void -real_update_location_menu (NautilusView *view) -{ - GtkAction *action; - char *label; - - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_LOCATION_OPEN_ALTERNATE); - - label = _("Open in New _Window"); - g_object_set (action, - "label", label, - NULL); - - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_LOCATION_OPEN_IN_NEW_TAB); - - label = _("Open in New _Tab"); - g_object_set (action, - "label", label, - NULL); + return can_restore; } static void clipboard_changed_callback (NautilusClipboardMonitor *monitor, NautilusView *view) { - GList *selection; - gint selection_count; - - if (!view->details->active) { - return; - } - - selection = nautilus_view_get_selection (view); - selection_count = g_list_length (selection); - - real_update_paste_menu (view, selection, selection_count); - - nautilus_file_list_free (selection); - + /* Update paste menu item */ + nautilus_view_update_context_menus (view); } static gboolean @@ -7253,44 +5686,65 @@ can_trash_all (GList *files) return TRUE; } +GActionGroup * +nautilus_view_get_action_group (NautilusView *view) +{ + g_assert (NAUTILUS_IS_VIEW (view)); + + return view->details->view_action_group; +} + static void -real_update_menus (NautilusView *view) +real_update_actions_state (NautilusView *view) { GList *selection, *l; + NautilusFile *file; gint selection_count; - const char *tip, *label; - char *label_with_underscore; gboolean selection_contains_special_link; gboolean selection_contains_desktop_or_home_dir; gboolean selection_contains_recent; gboolean selection_contains_search; - gboolean selection_all_in_trash; + gboolean selection_is_read_only; gboolean can_create_files; gboolean can_delete_files; gboolean can_move_files; gboolean can_trash_files; gboolean can_copy_files; + gboolean can_paste_files_into; gboolean show_separate_delete_command; - gboolean show_open_alternate; - gboolean show_open_in_new_tab; - gboolean can_open; gboolean show_app, show_run; - GtkAction *action; + gboolean item_opens_in_view; + gboolean is_read_only; + GAction *action; GAppInfo *app; - GIcon *app_icon; - GtkWidget *menuitem; gboolean show_properties; + GActionGroup *view_action_group; + gboolean show_mount; + gboolean show_unmount; + gboolean show_eject; + gboolean show_start; + gboolean show_stop; + gboolean show_detect_media; + GDriveStartStopType start_stop_type; + NautilusFileUndoInfo *info; + NautilusFileUndoManagerState undo_state; + gboolean undo_active, redo_active; + gboolean is_undo; + + view_action_group = view->details->view_action_group; selection = nautilus_view_get_selection (view); selection_count = g_list_length (selection); - selection_contains_special_link = special_link_in_selection (selection); selection_contains_desktop_or_home_dir = desktop_or_home_dir_in_selection (selection); selection_contains_recent = showing_recent_directory (view); selection_contains_search = view->details->model && NAUTILUS_IS_SEARCH_DIRECTORY (view->details->model); - selection_all_in_trash = all_selected_items_in_trash (selection); + selection_is_read_only = selection_count == 1 && + (!nautilus_file_can_write (NAUTILUS_FILE (selection->data)) && + !nautilus_file_has_activation_uri (NAUTILUS_FILE (selection->data))); + is_read_only = nautilus_view_is_read_only (view); can_create_files = nautilus_view_supports_creating_files (view); can_delete_files = can_delete_all (selection) && @@ -7304,62 +5758,47 @@ real_update_menus (NautilusView *view) !selection_contains_desktop_or_home_dir; can_copy_files = selection_count != 0 && !selection_contains_special_link; - can_move_files = can_delete_files && !selection_contains_recent; - - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_RENAME); - /* rename sensitivity depending on selection */ + can_paste_files_into = (!selection_contains_recent && + selection_count == 1 && + can_paste_into_file (NAUTILUS_FILE (selection->data))); + show_properties = !showing_network_directory (view) && + (!NAUTILUS_IS_DESKTOP_CANVAS_VIEW (view) || selection_count > 0); + + /* Right click actions */ + /* Selection menu actions */ + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "new-folder-with-selection"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + can_create_files && can_delete_files && (selection_count > 1) && !selection_contains_recent); + + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "rename"); if (selection_count > 1) { - /* If multiple files are selected, sensitivity depends on whether a bulk renamer is registered. */ - gtk_action_set_sensitive (action, have_bulk_rename_tool ()); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + have_bulk_rename_tool ()); } else { - gtk_action_set_sensitive (action, - selection_count == 1 && - nautilus_view_can_rename_file (view, selection->data)); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + selection_count == 1 && + nautilus_view_can_rename_file (view, selection->data)); } - gtk_action_set_visible (action, !selection_contains_recent); - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_SET_AS_WALLPAPER); - /* rename sensitivity depending on selection */ - if (can_set_wallpaper (selection)) { - gtk_action_set_visible (action, TRUE); - } else { - gtk_action_set_visible (action, FALSE); - } + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "open-item-location"); - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_OPEN_ITEM_LOCATION); - if (selection_count == 1 && - (selection_contains_recent || selection_contains_search)) - { - gtk_action_set_visible (action, TRUE); - } else { - gtk_action_set_visible (action, FALSE); - } - - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_NEW_FOLDER); - gtk_action_set_sensitive (action, can_create_files); - gtk_action_set_visible (action, !selection_contains_recent); - - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_NEW_FOLDER_WITH_SELECTION); - gtk_action_set_sensitive (action, can_create_files && can_delete_files && (selection_count > 1)); - gtk_action_set_visible (action, !selection_contains_recent && (selection_count > 1)); - label_with_underscore = g_strdup_printf (ngettext("New Folder with Selection (%'d Item)", - "New Folder with Selection (%'d Items)", - selection_count), - selection_count); - g_object_set (action, "label", label_with_underscore, NULL); - g_free (label_with_underscore); - - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_OPEN); - gtk_action_set_sensitive (action, selection_count != 0); - - can_open = show_app = show_run = selection_count != 0; + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + selection_count == 1 && + (selection_contains_recent || selection_contains_search)); + + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "new-folder"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), can_create_files); + + + selection = nautilus_view_get_selection (view); + selection_count = g_list_length (selection); + + show_app = show_run = item_opens_in_view = selection_count != 0; for (l = selection; l != NULL; l = l->next) { NautilusFile *file; @@ -7374,236 +5813,515 @@ real_update_menus (NautilusView *view) show_run = FALSE; } - if (!show_app && !show_run) { - break; + if (!nautilus_mime_file_opens_in_view (file)) { + item_opens_in_view = FALSE; } - } - label_with_underscore = NULL; + if (!show_app && !show_run && !item_opens_in_view) { + break; + } + } + /* Open With <App> menu item */ app = NULL; - app_icon = NULL; - - if (can_open && show_app) { + if (show_app) { app = nautilus_mime_get_default_application_for_files (selection); } - if (app != NULL) { - char *escaped_app; - - escaped_app = eel_str_double_underscores (g_app_info_get_name (app)); - label_with_underscore = g_strdup_printf (_("_Open With %s"), - escaped_app); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "open-with-default-application"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), selection_count != 0); + + /* Allow to select a different application to open the item */ + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "open-with-other-application"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), app != NULL); + + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "open-item-new-tab"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), item_opens_in_view); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "open-item-new-window"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), item_opens_in_view); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "set-as-wallpaper"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), can_set_wallpaper (selection)); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "restore-from-trash"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), can_restore_from_trash (selection)); + + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "move-to-trash"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), can_trash_files); + + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "delete"); + /* Only show it in trash folder or if the setting to include a delete + * menu item is enabled */ + show_separate_delete_command = g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_ENABLE_DELETE); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + can_delete_files && + (!can_trash_files || show_separate_delete_command)); + + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "cut"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + can_move_files && !selection_contains_recent); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "copy"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + can_copy_files); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "copy-to"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + can_copy_files); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "move-to"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + can_move_files && !selection_contains_recent); + + /* Drive menu */ + show_mount = show_unmount = show_eject = show_start = show_stop = show_detect_media = FALSE; + for (l = selection; l != NULL && (show_mount || show_unmount + || show_eject + || show_start || show_stop + || show_detect_media); + l = l->next) { + gboolean show_mount_one; + gboolean show_unmount_one; + gboolean show_eject_one; + gboolean show_start_one; + gboolean show_stop_one; + gboolean show_detect_media_one; - app_icon = g_app_info_get_icon (app); - if (app_icon != NULL) { - g_object_ref (app_icon); - } + file = NAUTILUS_FILE (l->data); + file_should_show_foreach (file, + &show_mount_one, + &show_unmount_one, + &show_eject_one, + &show_start_one, + &show_stop_one, + &show_detect_media_one, + &start_stop_type); - g_free (escaped_app); - g_object_unref (app); - } else if (show_run) { - label_with_underscore = g_strdup (_("Run")); - } else { - label_with_underscore = g_strdup (_("_Open")); - } + show_mount &= show_mount_one; + show_unmount &= show_unmount_one; + show_eject &= show_eject_one; + show_start &= show_start_one; + show_stop &= show_stop_one; + show_detect_media &= show_detect_media_one; + } + + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "mount-volume"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + show_mount); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "unmount-volume"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + show_unmount); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "eject-volume"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + show_eject); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "start-volume"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + show_start); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "stop-volume"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + show_stop); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "detect-media"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + show_detect_media); + + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "scripts"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + view->details->scripts_present); + + /* Background menu actions */ + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "new-folder"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), can_create_files); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "paste"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + !is_read_only && !selection_contains_recent); + + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "paste-into"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + !selection_is_read_only && !selection_contains_recent && + can_paste_files_into); + + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "properties"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + show_properties); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "new-document"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + can_create_files && + !selection_contains_recent && + view->details->templates_present); - g_object_set (action, "label", label_with_underscore, NULL); - g_free (label_with_underscore); + /* Ask the clipboard */ + g_object_ref (view); /* Need to keep the object alive until we get the reply */ + gtk_clipboard_request_targets (nautilus_clipboard_get (GTK_WIDGET (view)), + clipboard_targets_received, + view); - menuitem = gtk_ui_manager_get_widget ( - nautilus_view_get_ui_manager (view), - NAUTILUS_VIEW_POPUP_PATH_OPEN); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "select-all"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + !nautilus_view_is_empty (view)); - /* Only force displaying the icon if it is an application icon */ - gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), app_icon != NULL); + /* Toolbar menu actions */ + /* Undo and Redo */ + info = nautilus_file_undo_manager_get_action (); + undo_state = nautilus_file_undo_manager_get_state (); + undo_active = redo_active = FALSE; + if (info != NULL && + (undo_state > NAUTILUS_FILE_UNDO_MANAGER_STATE_NONE)) { + is_undo = (undo_state == NAUTILUS_FILE_UNDO_MANAGER_STATE_UNDO); + undo_active = is_undo; + redo_active = !is_undo; + } + + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "undo"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), undo_active); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "redo"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), redo_active); + + g_action_group_change_action_state (view_action_group, + "show-hidden-files", + g_variant_new_boolean (view->details->show_hidden_files)); + + /* Zoom */ + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "zoom-in"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + nautilus_view_can_zoom_in (view)); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "zoom-out"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + nautilus_view_can_zoom_out (view)); + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "zoom-default"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + nautilus_view_supports_zooming (view)); +} + +/* Convenience function to be called when updating menus, + * so children can subclass it and it will be called when + * they chain up to the parent in update_context_menus + * or update_toolbar_menus + */ +void +nautilus_view_update_actions_state (NautilusView *view) +{ + g_assert(NAUTILUS_IS_VIEW (view)); - if (app_icon == NULL) { - app_icon = g_themed_icon_new ("gtk-open"); - } + NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->update_actions_state (view); +} - gtk_action_set_gicon (action, app_icon); - g_object_unref (app_icon); +static void +update_selection_menu (NautilusView *view) +{ + GList *selection, *l; + NautilusFile *file; + gint selection_count; + gboolean show_app, show_run; + gboolean item_opens_in_view; + gchar *item_label; + GAppInfo *app; + GIcon *app_icon; + GMenuItem *menu_item; + gboolean show_mount; + gboolean show_unmount; + gboolean show_eject; + gboolean show_start; + gboolean show_stop; + gboolean show_detect_media; + GDriveStartStopType start_stop_type; - gtk_action_set_visible (action, can_open); + selection = nautilus_view_get_selection (view); + selection_count = g_list_length (selection); - show_open_alternate = file_list_all_are_folders (selection) && - selection_count > 0 && - !NAUTILUS_IS_DESKTOP_CANVAS_VIEW (view); + show_mount = (selection != NULL); + show_unmount = (selection != NULL); + show_eject = (selection != NULL); + show_start = (selection != NULL && selection_count == 1); + show_stop = (selection != NULL && selection_count == 1); + show_detect_media = (selection != NULL && selection_count == 1); + + item_label = g_strdup_printf (_("New Folder with Selection (%'d Items)"), + selection_count); + menu_item = g_menu_item_new (item_label, "view.new-folder-with-selection"); + g_menu_item_set_attribute (menu_item, "hidden-when", "s", "action-disabled"); + nautilus_gmenu_add_item_in_submodel (view->details->selection_menu, + menu_item, + "new-folder-with-selection-section", + FALSE); + g_object_unref (menu_item); + g_free (item_label); + + /* Open With <App> menu item */ + show_app = show_run = item_opens_in_view = selection_count != 0; + for (l = selection; l != NULL; l = l->next) { + NautilusFile *file; - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_OPEN_ALTERNATE); + file = NAUTILUS_FILE (selection->data); - gtk_action_set_sensitive (action, selection_count != 0); - gtk_action_set_visible (action, show_open_alternate); + if (!nautilus_mime_file_opens_in_external_app (file)) { + show_app = FALSE; + } - if (selection_count == 0 || selection_count == 1) { - label_with_underscore = g_strdup (_("Open in New _Window")); - } else { - label_with_underscore = g_strdup_printf (ngettext("Open in %'d New _Window", - "Open in %'d New _Windows", - selection_count), - selection_count); - } + if (!nautilus_mime_file_launches (file)) { + show_run = FALSE; + } - g_object_set (action, "label", - label_with_underscore, - NULL); - g_free (label_with_underscore); + if (!nautilus_mime_file_opens_in_view (file)) { + item_opens_in_view = FALSE; + } - show_open_in_new_tab = show_open_alternate; - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_OPEN_IN_NEW_TAB); - gtk_action_set_sensitive (action, selection_count != 0); - gtk_action_set_visible (action, show_open_in_new_tab); + if (!show_app && !show_run && !item_opens_in_view) { + break; + } + } - if (selection_count == 0 || selection_count == 1) { - label_with_underscore = g_strdup (_("Open in New _Tab")); - } else { - label_with_underscore = g_strdup_printf (ngettext("Open in %'d New _Tab", - "Open in %'d New _Tabs", - selection_count), - selection_count); + item_label = NULL; + app = NULL; + app_icon = NULL; + if (show_app) { + app = nautilus_mime_get_default_application_for_files (selection); } - g_object_set (action, "label", - label_with_underscore, - NULL); - g_free (label_with_underscore); + char *escaped_app; - /* Broken into its own function just for convenience */ - reset_open_with_menu (view, selection); - reset_extension_actions_menu (view, selection); + if (app != NULL) { + escaped_app = eel_str_double_underscores (g_app_info_get_name (app)); + item_label = g_strdup_printf (_("Open With %s"), escaped_app); - if (selection_all_in_trash) { - label = _("_Delete Permanently"); - tip = _("Delete all selected items permanently"); - show_separate_delete_command = FALSE; - } else { - label = _("Mo_ve to Trash"); - tip = _("Move each selected item to the Trash"); - show_separate_delete_command = g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_ENABLE_DELETE); - } - - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_TRASH); - g_object_set (action, - "label", label, - "tooltip", tip, - "icon-name", selection_all_in_trash ? - NAUTILUS_ICON_DELETE : NAUTILUS_ICON_TRASH_FULL, - NULL); - /* if the backend supports delete but not trash then don't show trash */ - if (!can_trash_files && can_delete_files) { - gtk_action_set_visible (action, FALSE); + app_icon = g_app_info_get_icon (app); + if (app_icon != NULL) { + g_object_ref (app_icon); + } + g_free (escaped_app); + g_object_unref (app); + } else if (show_run) { + item_label = g_strdup (_("Run")); } else { - gtk_action_set_visible (action, TRUE); - gtk_action_set_sensitive (action, can_trash_files); + item_label = g_strdup (_("Open")); } - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_DELETE); - /* if the backend doesn't support trash but supports delete - show the delete option. or if the user set this pref */ - gtk_action_set_visible (action, (!can_trash_files && can_delete_files) || show_separate_delete_command); + menu_item = g_menu_item_new (item_label, "view.open-with-default-application"); + if (app_icon != NULL) + g_menu_item_set_icon (menu_item, app_icon); - if (selection_contains_recent) { - label = _("Remo_ve from Recent"); - tip = _("Remove each selected item from the recently used list"); - } else { - label = _("_Delete"); - tip = _("Delete each selected item, without moving to the Trash"); - } + nautilus_gmenu_add_item_in_submodel (view->details->selection_menu, + menu_item, + "open-with-default-application-section", + FALSE); - if ((!can_trash_files && can_delete_files) || show_separate_delete_command) { - g_object_set (action, - "label", label, - "tooltip", tip, - "icon-name", NAUTILUS_ICON_DELETE, - NULL); - } - gtk_action_set_sensitive (action, can_delete_files); + g_free (item_label); + g_object_unref (menu_item); + /* Drives */ + for (l = selection; l != NULL && (show_mount || show_unmount + || show_eject + || show_start || show_stop + || show_detect_media); + l = l->next) { + gboolean show_mount_one; + gboolean show_unmount_one; + gboolean show_eject_one; + gboolean show_start_one; + gboolean show_stop_one; + gboolean show_detect_media_one; - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_RESTORE_FROM_TRASH); - update_restore_from_trash_action (action, selection, FALSE); + file = NAUTILUS_FILE (l->data); + file_should_show_foreach (file, + &show_mount_one, + &show_unmount_one, + &show_eject_one, + &show_start_one, + &show_stop_one, + &show_detect_media_one, + &start_stop_type); - show_properties = !showing_network_directory (view) - && (!NAUTILUS_IS_DESKTOP_CANVAS_VIEW (view) || selection_count > 0); + show_mount &= show_mount_one; + show_unmount &= show_unmount_one; + show_eject &= show_eject_one; + show_start &= show_start_one; + show_stop &= show_stop_one; + show_detect_media &= show_detect_media_one; + } - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_PROPERTIES); + if (show_start) { + switch (start_stop_type) { + default: + case G_DRIVE_START_STOP_TYPE_UNKNOWN: + case G_DRIVE_START_STOP_TYPE_SHUTDOWN: + item_label = _("_Start"); + break; + case G_DRIVE_START_STOP_TYPE_NETWORK: + item_label = _("_Connect"); + break; + case G_DRIVE_START_STOP_TYPE_MULTIDISK: + item_label = _("_Start Multi-disk Drive"); + break; + case G_DRIVE_START_STOP_TYPE_PASSWORD: + item_label = _("U_nlock Drive"); + break; + } - gtk_action_set_sensitive (action, show_properties); - gtk_action_set_visible (action, show_properties); + menu_item = g_menu_item_new (item_label, "view.start-volume"); + nautilus_gmenu_add_item_in_submodel (view->details->selection_menu, + menu_item, + "drive-section", + FALSE); + g_object_unref (menu_item); + } - if (selection_count == 0) { - gtk_action_set_tooltip (action, _("View or modify the properties of the open folder")); - } else { - gtk_action_set_tooltip (action, _("View or modify the properties of each selected item")); + if (show_stop) { + switch (start_stop_type) { + default: + case G_DRIVE_START_STOP_TYPE_UNKNOWN: + item_label = _("Stop Drive"); + break; + case G_DRIVE_START_STOP_TYPE_SHUTDOWN: + item_label = _("_Safely Remove Drive"); + break; + case G_DRIVE_START_STOP_TYPE_NETWORK: + item_label = _("_Disconnect"); + break; + case G_DRIVE_START_STOP_TYPE_MULTIDISK: + item_label = _("_Stop Multi-disk Drive"); + break; + case G_DRIVE_START_STOP_TYPE_PASSWORD: + item_label = _("_Lock Drive"); + break; + } + + menu_item = g_menu_item_new (item_label, "view.stop-volume"); + nautilus_gmenu_add_item_in_submodel (view->details->selection_menu, + menu_item, + "drive-section", + FALSE); + g_object_unref (menu_item); } - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_PROPERTIES_ACCEL); + update_scripts_menu (view); +} - gtk_action_set_sensitive (action, show_properties); - gtk_action_set_visible (action, show_properties); +static void +update_background_menu (NautilusView *view) +{ - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_SELECT_ALL); - gtk_action_set_sensitive (action, !nautilus_view_is_empty (view)); + if (nautilus_view_supports_creating_files (view) && + !showing_recent_directory (view)) + update_templates_menu (view); +} - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_SELECT_PATTERN); - gtk_action_set_sensitive (action, !nautilus_view_is_empty (view)); +static void +real_update_context_menus (NautilusView *view) +{ + g_clear_object (&view->details->background_menu); + g_clear_object (&view->details->selection_menu); + g_clear_object (&view->details->pathbar_menu); - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_INVERT_SELECTION); - gtk_action_set_sensitive (action, !nautilus_view_is_empty (view)); + GtkBuilder *builder; + builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-view-context-menus.xml"); + view->details->background_menu = g_object_ref (G_MENU (gtk_builder_get_object (builder, "background-menu"))); + view->details->selection_menu = g_object_ref (G_MENU (gtk_builder_get_object (builder, "selection-menu"))); + view->details->pathbar_menu = g_object_ref (G_MENU (gtk_builder_get_object (builder, "pathbar-menu"))); + g_object_unref (builder); - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_CUT); - gtk_action_set_sensitive (action, can_move_files); - gtk_action_set_visible (action, !selection_contains_recent); + update_selection_menu (view); + update_background_menu (view); + nautilus_view_update_actions_state (view); +} - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_COPY); - gtk_action_set_sensitive (action, can_copy_files); +/* Convenience function to reset the context menus owned by the view and update + * them with the current state. + * Children can subclass it and add items on the menu after chaining up to the + * parent, so menus are already reseted. + * It will also update the actions state, which will also update children + * actions state if the children subclass nautilus_view_update_actions_state + */ +void +nautilus_view_update_context_menus (NautilusView *view) +{ + g_assert(NAUTILUS_IS_VIEW (view)); - real_update_paste_menu (view, selection, selection_count); + NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->update_context_menus (view); +} - real_update_menus_volumes (view, selection, selection_count); +static void +real_update_toolbar_menus (NautilusView *view) +{ + NautilusToolbar *toolbar; + NautilusWindow *window; + NautilusFileUndoInfo *info; + NautilusFileUndoManagerState undo_state; + gboolean undo_active, redo_active; + gchar *undo_label, *undo_description, *redo_label, *redo_description; + GMenuItem *undo_menu_item, *redo_menu_item; + gboolean is_undo; - update_undo_actions (view); + undo_label = undo_description = redo_label = redo_description = NULL; - nautilus_file_list_free (selection); + toolbar = NAUTILUS_TOOLBAR (nautilus_window_get_toolbar (nautilus_view_get_window (view))); + window = nautilus_view_get_window (view); + nautilus_toolbar_reset_menus (toolbar); + nautilus_window_reset_menus (window); - if (view->details->scripts_invalid) { - update_scripts_menu (view); + /* Undo and Redo */ + info = nautilus_file_undo_manager_get_action (); + undo_state = nautilus_file_undo_manager_get_state (); + undo_active = redo_active = FALSE; + if (info != NULL && + (undo_state > NAUTILUS_FILE_UNDO_MANAGER_STATE_NONE)) { + is_undo = (undo_state == NAUTILUS_FILE_UNDO_MANAGER_STATE_UNDO); + undo_active = is_undo; + redo_active = !is_undo; + nautilus_file_undo_info_get_strings (info, + &undo_label, &undo_description, + &redo_label, &redo_description); } - if (can_create_files - && !selection_contains_recent - && view->details->templates_invalid) { - update_templates_menu (view); - } - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_NEW_DOCUMENTS); - gtk_action_set_sensitive (action, can_create_files); - gtk_action_set_visible (action, !selection_contains_recent && view->details->templates_present); + undo_label = undo_active ? undo_label : _("Undo"); + redo_label = redo_active ? redo_label : _("Redo"); + undo_menu_item = g_menu_item_new (undo_label, "view.undo"); + redo_menu_item = g_menu_item_new (redo_label, "view.redo"); + nautilus_toolbar_action_menu_add_item (toolbar, undo_menu_item, "undo-redo-section"); + nautilus_toolbar_action_menu_add_item (toolbar, redo_menu_item, "undo-redo-section"); + + nautilus_view_update_actions_state (view); - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_COPY_TO); - gtk_action_set_sensitive (action, can_copy_files); + g_object_unref (undo_menu_item); + g_object_unref (redo_menu_item); +} - action = gtk_action_group_get_action (view->details->dir_action_group, - NAUTILUS_ACTION_MOVE_TO); - gtk_action_set_sensitive (action, can_move_files); - gtk_action_set_visible (action, !selection_contains_recent); +/* Convenience function to reset the menus owned by the but that are managed on + * the toolbar and update them with the current state. + * Children can subclass it and add items on the menu after chaining up to the + * parent, so menus are already reseted. + * It will also update the actions state, which will also update children + * actions state if the children subclass nautilus_view_update_actions_state + */ +void +nautilus_view_update_toolbar_menus (NautilusView *view) +{ + g_assert(NAUTILUS_IS_VIEW (view)); - action = gtk_action_group_get_action (view->details->dir_action_group, NAUTILUS_ACTION_SHOW_HIDDEN_FILES); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), view->details->show_hidden_files); + NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->update_toolbar_menus (view); } /** @@ -7623,13 +6341,11 @@ nautilus_view_pop_up_selection_context_menu (NautilusView *view, /* Make the context menu items not flash as they update to proper disabled, * etc. states by forcing menus to update now. */ - update_menus_if_pending (view); + update_context_menus_if_pending (view); update_context_menu_position_from_event (view, event); - eel_pop_up_context_menu (create_popup_menu - (view, NAUTILUS_VIEW_POPUP_PATH_SELECTION), - event); + nautilus_pop_up_context_menu (GTK_WIDGET (view), view->details->selection_menu, event); } /** @@ -7648,27 +6364,24 @@ nautilus_view_pop_up_background_context_menu (NautilusView *view, /* Make the context menu items not flash as they update to proper disabled, * etc. states by forcing menus to update now. */ - update_menus_if_pending (view); + update_context_menus_if_pending (view); update_context_menu_position_from_event (view, event); - - eel_pop_up_context_menu (create_popup_menu - (view, NAUTILUS_VIEW_POPUP_PATH_BACKGROUND), - event); + nautilus_pop_up_context_menu (GTK_WIDGET (view), view->details->background_menu, event); } static void real_pop_up_pathbar_context_menu (NautilusView *view) { - /* always update the menu before showing it. Shouldn't be too expensive. */ - real_update_location_menu (view); + /* Make the context menu items not flash as they update to proper disabled, + * etc. states by forcing menus to update now. + */ + update_context_menus_if_pending (view); update_context_menu_position_from_event (view, view->details->pathbar_popup_event); - eel_pop_up_context_menu (create_popup_menu - (view, NAUTILUS_VIEW_POPUP_PATH_LOCATION), - view->details->pathbar_popup_event); + nautilus_pop_up_context_menu (GTK_WIDGET (view), view->details->pathbar_menu, view->details->pathbar_popup_event); } static void @@ -7761,7 +6474,7 @@ nautilus_view_pop_up_pathbar_context_menu (NautilusView *view, } static void -schedule_update_menus (NautilusView *view) +schedule_update_context_menus (NautilusView *view) { g_assert (NAUTILUS_IS_VIEW (view)); @@ -7774,9 +6487,9 @@ schedule_update_menus (NautilusView *view) } /* Schedule a menu update with the current update interval */ - if (view->details->update_menus_timeout_id == 0) { - view->details->update_menus_timeout_id - = g_timeout_add (view->details->update_interval, update_menus_timeout_callback, view); + if (view->details->update_context_menus_timeout_id == 0) { + view->details->update_context_menus_timeout_id + = g_timeout_add (view->details->update_interval, update_context_menus_timeout_callback, view); } } @@ -7862,7 +6575,7 @@ nautilus_view_notify_selection_changed (NautilusView *view) */ /* Schedule an update of menu item states to match selection */ - schedule_update_menus (view); + schedule_update_context_menus (view); } } @@ -7873,7 +6586,7 @@ file_changed_callback (NautilusFile *file, gpointer callback_data) schedule_changes (view); - schedule_update_menus (view); + schedule_update_context_menus (view); schedule_update_status (view); } @@ -7908,7 +6621,7 @@ load_directory (NautilusView *view, * location, so they won't have any false lingering knowledge * of old selection. */ - schedule_update_menus (view); + schedule_update_context_menus (view); while (view->details->subdirectory_list != NULL) { nautilus_view_remove_subdirectory (view, @@ -8340,7 +7053,7 @@ nautilus_view_trash_state_changed_callback (NautilusTrashMonitor *trash_monitor, view = (NautilusView *) callback_data; g_assert (NAUTILUS_IS_VIEW (view)); - schedule_update_menus (view); + schedule_update_context_menus (view); } void @@ -8505,13 +7218,9 @@ nautilus_view_parent_set (GtkWidget *widget, if (view->details->slot == nautilus_window_get_active_slot (nautilus_view_get_window (view))) { view->details->active = TRUE; - - nautilus_view_merge_menus (view); - schedule_update_menus (view); } } else { - nautilus_view_unmerge_menus (view); - remove_update_menus_timeout_callback (view); + remove_update_context_menus_timeout_callback (view); } } @@ -8521,7 +7230,6 @@ nautilus_view_class_init (NautilusViewClass *klass) GObjectClass *oclass; GtkWidgetClass *widget_class; GtkScrolledWindowClass *scrolled_window_class; - GtkBindingSet *binding_set; widget_class = GTK_WIDGET_CLASS (klass); scrolled_window_class = GTK_SCROLLED_WINDOW_CLASS (klass); @@ -8605,13 +7313,6 @@ nautilus_view_class_init (NautilusViewClass *klass) NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, NAUTILUS_TYPE_FILE, NAUTILUS_TYPE_DIRECTORY); - signals[ZOOM_LEVEL_CHANGED] = - g_signal_new ("zoom-level-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); signals[SELECTION_CHANGED] = g_signal_new ("selection-changed", G_TYPE_FROM_CLASS (klass), @@ -8620,22 +7321,6 @@ nautilus_view_class_init (NautilusViewClass *klass) NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - signals[TRASH] = - g_signal_new ("trash", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (NautilusViewClass, trash), - g_signal_accumulator_true_handled, NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, 0); - signals[DELETE] = - g_signal_new ("delete", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (NautilusViewClass, delete), - g_signal_accumulator_true_handled, NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, 0); klass->get_selected_icon_locations = real_get_selected_icon_locations; klass->is_read_only = real_is_read_only; @@ -8643,11 +7328,12 @@ nautilus_view_class_init (NautilusViewClass *klass) klass->start_renaming_file = start_renaming_file; klass->get_backing_uri = real_get_backing_uri; klass->using_manual_layout = real_using_manual_layout; - klass->merge_menus = real_merge_menus; - klass->unmerge_menus = real_unmerge_menus; - klass->update_menus = real_update_menus; - klass->trash = real_trash; - klass->delete = real_delete; + klass->get_window = nautilus_view_get_window; + klass->get_action_group = nautilus_view_get_action_group; + klass->update_context_menus = real_update_context_menus; + klass->update_actions_state = real_update_actions_state; + klass->update_toolbar_menus = real_update_toolbar_menus; + klass->zoom_to_level = real_zoom_to_level; copied_files_atom = gdk_atom_intern ("x-special/gnome-copied-files", FALSE); @@ -8667,14 +7353,139 @@ nautilus_view_class_init (NautilusViewClass *klass) G_PARAM_STATIC_STRINGS); g_object_class_install_properties (oclass, NUM_PROPERTIES, properties); +} + +static void +nautilus_view_init (NautilusView *view) +{ + AtkObject *atk_object; + NautilusDirectory *scripts_directory; + NautilusDirectory *templates_directory; + gchar *templates_uri; + GApplication *app; + + nautilus_profile_start (NULL); + + view->details = G_TYPE_INSTANCE_GET_PRIVATE (view, NAUTILUS_TYPE_VIEW, + NautilusViewDetails); + + /* Default to true; desktop-icon-view sets to false */ + view->details->show_foreign_files = TRUE; + + view->details->non_ready_files = + g_hash_table_new_full (file_and_directory_hash, + file_and_directory_equal, + (GDestroyNotify)file_and_directory_free, + NULL); + + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (view), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (view), NULL); + gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (view), NULL); + + gtk_style_context_set_junction_sides (gtk_widget_get_style_context (GTK_WIDGET (view)), + GTK_JUNCTION_TOP | GTK_JUNCTION_LEFT); + + if (set_up_scripts_directory_global ()) { + scripts_directory = nautilus_directory_get_by_uri (scripts_directory_uri); + add_directory_to_scripts_directory_list (view, scripts_directory); + nautilus_directory_unref (scripts_directory); + } else { + g_warning ("Ignoring scripts directory, it may be a broken link\n"); + } + + if (nautilus_should_use_templates_directory ()) { + templates_uri = nautilus_get_templates_directory_uri (); + templates_directory = nautilus_directory_get_by_uri (templates_uri); + g_free (templates_uri); + add_directory_to_templates_directory_list (view, templates_directory); + nautilus_directory_unref (templates_directory); + } + update_templates_directory (view); + + view->details->sort_directories_first = + g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_SORT_DIRECTORIES_FIRST); + view->details->show_hidden_files = + g_settings_get_boolean (gtk_filechooser_preferences, NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES); + + g_signal_connect_object (nautilus_trash_monitor_get (), "trash-state-changed", + G_CALLBACK (nautilus_view_trash_state_changed_callback), view, 0); + + /* React to clipboard changes */ + g_signal_connect_object (nautilus_clipboard_monitor_get (), "clipboard-changed", + G_CALLBACK (clipboard_changed_callback), view, 0); + + /* Register to menu provider extension signal managing menu updates */ + g_signal_connect_object (nautilus_signaller_get_current (), "popup-menu-changed", + G_CALLBACK (schedule_update_context_menus), view, G_CONNECT_SWAPPED); + + gtk_widget_show (GTK_WIDGET (view)); - binding_set = gtk_binding_set_by_class (klass); - gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_CONTROL_MASK, - "trash", 0); - gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_CONTROL_MASK, - "trash", 0); - gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_SHIFT_MASK, - "delete", 0); + g_signal_connect_swapped (nautilus_preferences, + "changed::" NAUTILUS_PREFERENCES_ENABLE_DELETE, + G_CALLBACK (schedule_update_context_menus), view); + g_signal_connect_swapped (nautilus_preferences, + "changed::" NAUTILUS_PREFERENCES_CLICK_POLICY, + G_CALLBACK (click_policy_changed_callback), + view); + g_signal_connect_swapped (nautilus_preferences, + "changed::" NAUTILUS_PREFERENCES_SORT_DIRECTORIES_FIRST, + G_CALLBACK (sort_directories_first_changed_callback), view); + g_signal_connect_swapped (gtk_filechooser_preferences, + "changed::" NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES, + G_CALLBACK (show_hidden_files_changed_callback), view); + g_signal_connect_swapped (gnome_lockdown_preferences, + "changed::" NAUTILUS_PREFERENCES_LOCKDOWN_COMMAND_LINE, + G_CALLBACK (schedule_update_context_menus), view); + + g_signal_connect_object (nautilus_file_undo_manager_get (), "undo-changed", + G_CALLBACK (undo_manager_changed), view, 0); + + /* Accessibility */ + atk_object = gtk_widget_get_accessible (GTK_WIDGET (view)); + atk_object_set_name (atk_object, _("Content View")); + atk_object_set_description (atk_object, _("View of the current folder")); + + view->details->view_action_group = G_ACTION_GROUP (g_simple_action_group_new ()); + g_action_map_add_action_entries (G_ACTION_MAP (view->details->view_action_group), + view_entries, + G_N_ELEMENTS (view_entries), + view); + gtk_widget_insert_action_group (GTK_WIDGET (view), + "view", + G_ACTION_GROUP (view->details->view_action_group)); + + app = g_application_get_default (); + + /* Toolbar menu */ + nautilus_application_add_accelerator (app, "view.zoom-in", "<control>plus"); + nautilus_application_add_accelerator (app, "view.zoom-out", "<control>minus"); + nautilus_application_add_accelerator (app, "view.undo", "<control>z"); + nautilus_application_add_accelerator (app, "view.redo", "<shift><control>z"); + nautilus_application_add_accelerator (app, "view.show-hidden-files", "<control>h"); + /* Background menu */ + nautilus_application_add_accelerator (app, "view.select-all", "<control>a"); + nautilus_application_add_accelerator (app, "view.paste", "<control>v"); + /* Selection menu */ + nautilus_application_add_accelerator (app, "view.open-with-default-application", "<control>o"); + nautilus_application_add_accelerator (app, "view.open-item-new-tab", "<shift><control>t"); + nautilus_application_add_accelerator (app, "view.open-item-new-window", "<shift><control>w"); + nautilus_application_add_accelerator (app, "view.move-to-trash", "<control>Delete"); + nautilus_application_add_accelerator (app, "view.delete", "<shift>Delete"); + nautilus_application_add_accelerator (app, "view.properties", "<control>i"); + nautilus_application_add_accelerator (app, "view.open-item-location", "<control><alt>o"); + nautilus_application_add_accelerator (app, "view.rename", "F2"); + nautilus_application_add_accelerator (app, "view.cut", "<control>x"); + nautilus_application_add_accelerator (app, "view.copy", "<control>c"); + nautilus_application_add_accelerator (app, "view.delete", "<shift>Delete"); + /* Only accesible by shorcuts */ + nautilus_application_add_accelerator (app, "view.select-pattern", "<control>s"); + nautilus_application_add_accelerator (app, "view.zoom-default", "<control>0"); + nautilus_application_add_accelerator (app, "view.invert-selection", "<shift><control>i"); + nautilus_application_add_accelerator (app, "view.open-file-and-close-window", "<control><shift>Down"); + + nautilus_profile_end (NULL); } NautilusView * diff --git a/src/nautilus-view.h b/src/nautilus-view.h index 12fafc40d..9c0644fc2 100644 --- a/src/nautilus-view.h +++ b/src/nautilus-view.h @@ -219,7 +219,11 @@ struct NautilusViewClass { * It is called (at least) whenever the selection changes. If overridden, * subclasses must call parent class's function. */ - void (* update_menus) (NautilusView *view); + void (* update_context_menus) (NautilusView *view); + + void (* update_toolbar_menus) (NautilusView *view); + + void (* update_actions_state) (NautilusView *view); /* sort_files is a function pointer that subclasses can override * to provide a sorting order to determine which files should be @@ -284,9 +288,8 @@ struct NautilusViewClass { void (* scroll_to_file) (NautilusView *view, const char *uri); - /* Signals used only for keybindings */ - gboolean (* trash) (NautilusView *view); - gboolean (* delete) (NautilusView *view); + NautilusWindow * (*get_window) (NautilusView *view); + GActionGroup * (*get_action_group) (NautilusView *view); }; /* GObject support */ @@ -323,7 +326,6 @@ void nautilus_view_preview_files (NautilusView void nautilus_view_start_batching_selection_changes (NautilusView *view); void nautilus_view_stop_batching_selection_changes (NautilusView *view); void nautilus_view_notify_selection_changed (NautilusView *view); -GtkUIManager * nautilus_view_get_ui_manager (NautilusView *view); NautilusDirectory *nautilus_view_get_model (NautilusView *view); NautilusFile *nautilus_view_get_directory_as_file (NautilusView *view); void nautilus_view_pop_up_background_context_menu (NautilusView *view, @@ -350,6 +352,7 @@ void nautilus_view_remove_subdirectory (NautilusView NautilusDirectory*directory); gboolean nautilus_view_is_editable (NautilusView *view); +NautilusWindow * nautilus_view_get_window (NautilusView *view); /* NautilusView methods */ const char * nautilus_view_get_view_id (NautilusView *view); @@ -403,6 +406,14 @@ void nautilus_view_pop_up_pathbar_context_menu (NautilusView *vi void nautilus_view_grab_focus (NautilusView *view); void nautilus_view_update_menus (NautilusView *view); +void nautilus_view_update_context_menus (NautilusView *view); +void nautilus_view_update_toolbar_menus (NautilusView *view); +void nautilus_view_update_actions_state (NautilusView *view); + gboolean nautilus_view_get_show_hidden_files (NautilusView *view); +void nautilus_view_action_show_hidden_files (NautilusView *view, + gboolean show_hidden); + +GActionGroup * nautilus_view_get_action_group (NautilusView *view); #endif /* NAUTILUS_VIEW_H */ diff --git a/src/nautilus-window-private.h b/src/nautilus-window-private.h index 5531d8e71..0a4fab9da 100644 --- a/src/nautilus-window-private.h +++ b/src/nautilus-window-private.h @@ -36,13 +36,6 @@ /* FIXME bugzilla.gnome.org 42575: Migrate more fields into here. */ struct NautilusWindowDetails { - GtkUIManager *ui_manager; - GtkActionGroup *main_action_group; /* owned by ui_manager */ - - /* Menus. */ - guint extensions_menu_merge_id; - GtkActionGroup *extensions_menu_action_group; - GtkWidget *notebook; /* available slots, and active slot. @@ -103,13 +96,5 @@ void nautilus_window_sync_allow_stop (NautilusWindow *window, NautilusWindowSlot *slot); void nautilus_window_sync_title (NautilusWindow *window, NautilusWindowSlot *slot); -void nautilus_window_sync_zoom_widgets (NautilusWindow *window); -void nautilus_window_sync_up_button (NautilusWindow *window); - -/* window menus */ -void nautilus_window_initialize_actions (NautilusWindow *window); -void nautilus_window_initialize_menus (NautilusWindow *window); - -void nautilus_window_update_show_hide_menu_items (NautilusWindow *window); #endif /* NAUTILUS_WINDOW_PRIVATE_H */ diff --git a/src/nautilus-window-slot.c b/src/nautilus-window-slot.c index 875995dab..03183fe4d 100644 --- a/src/nautilus-window-slot.c +++ b/src/nautilus-window-slot.c @@ -24,7 +24,6 @@ #include "nautilus-window-slot.h" -#include "nautilus-actions.h" #include "nautilus-application.h" #include "nautilus-canvas-view.h" #include "nautilus-desktop-window.h" @@ -168,11 +167,10 @@ nautilus_window_slot_content_view_matches_iid (NautilusWindowSlot *slot, return g_strcmp0 (nautilus_view_get_view_id (slot->details->content_view), iid) == 0; } -static void -nautilus_window_slot_sync_view_as_menus (NautilusWindowSlot *slot) +void +nautilus_window_slot_sync_view_mode (NautilusWindowSlot *slot) { - GtkActionGroup *action_group; - GtkAction *action; + GAction *action; if (slot != nautilus_window_get_active_slot (slot->details->window)) { return; @@ -182,18 +180,14 @@ nautilus_window_slot_sync_view_as_menus (NautilusWindowSlot *slot) return; } - action_group = nautilus_window_get_main_action_group (slot->details->window); + action = g_action_map_lookup_action (G_ACTION_MAP (slot->details->window), "view-mode"); if (nautilus_window_slot_content_view_matches_iid (slot, NAUTILUS_LIST_VIEW_ID)) { - action = gtk_action_group_get_action (action_group, NAUTILUS_ACTION_VIEW_LIST); + g_action_change_state (action, g_variant_new_string ("list")); } else if (nautilus_window_slot_content_view_matches_iid (slot, NAUTILUS_CANVAS_VIEW_ID)) { - action = gtk_action_group_get_action (action_group, NAUTILUS_ACTION_VIEW_GRID); + g_action_change_state (action, g_variant_new_string ("grid")); } else { - action = NULL; - } - - if (action != NULL) { - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE); } } @@ -381,8 +375,7 @@ void nautilus_window_slot_set_search_visible (NautilusWindowSlot *slot, gboolean visible) { - GtkActionGroup *action_group; - GtkAction *action; + GAction *action; gboolean old_visible; GFile *return_location; gboolean active_slot; @@ -423,9 +416,8 @@ nautilus_window_slot_set_search_visible (NautilusWindowSlot *slot, } /* also synchronize the window action state */ - action_group = nautilus_window_get_main_action_group (slot->details->window); - action = gtk_action_group_get_action (action_group, NAUTILUS_ACTION_SEARCH); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible); + action = g_action_map_lookup_action (G_ACTION_MAP (slot->details->window), "toggle-search"); + g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_boolean (visible)); /* If search was active on this slot and became inactive, change * the slot location to the real directory. @@ -478,14 +470,9 @@ real_active (NautilusWindowSlot *slot) /* sync window to new slot */ nautilus_window_sync_allow_stop (window, slot); nautilus_window_sync_title (window, slot); - nautilus_window_sync_zoom_widgets (window); nautilus_window_sync_location_widgets (window); nautilus_window_slot_sync_search_widgets (slot); - - if (slot->details->viewed_file != NULL) { - nautilus_window_slot_sync_view_as_menus (slot); - nautilus_window_load_extension_menus (window); - } + nautilus_window_slot_sync_view_mode (slot); } static void @@ -1522,9 +1509,9 @@ end_location_change (NautilusWindowSlot *slot) nautilus_window_slot_set_allow_stop (slot, FALSE); - /* Now we can free details->pending_scroll_to, since the load_complete - * callback already has been emitted. - */ + /* Now we can free details->pending_scroll_to, since the load_complete + * callback already has been emitted. + */ g_free (slot->details->pending_scroll_to); slot->details->pending_scroll_to = NULL; @@ -1534,10 +1521,6 @@ end_location_change (NautilusWindowSlot *slot) static void free_location_change (NautilusWindowSlot *slot) { - NautilusWindow *window; - - window = nautilus_window_slot_get_window (slot); - g_clear_object (&slot->details->pending_location); g_list_free_full (slot->details->pending_selection, g_object_unref); slot->details->pending_selection = NULL; @@ -1563,7 +1546,6 @@ free_location_change (NautilusWindowSlot *slot) nautilus_view_stop_loading (slot->details->new_content_view); slot->details->temporarily_ignore_view_signals = FALSE; - nautilus_window_disconnect_content_view (window, slot->details->new_content_view); g_object_unref (slot->details->new_content_view); slot->details->new_content_view = NULL; } @@ -2148,15 +2130,8 @@ nautilus_window_slot_update_for_new_location (NautilusWindowSlot *slot) nautilus_window_slot_set_location (slot, new_location); if (slot == nautilus_window_get_active_slot (window)) { - /* Sync up and zoom action states */ - nautilus_window_sync_up_button (window); - nautilus_window_sync_zoom_widgets (window); - /* Sync the content view menu for this new location. */ - nautilus_window_slot_sync_view_as_menus (slot); - - /* Load menus from nautilus extensions for this location */ - nautilus_window_load_extension_menus (window); + nautilus_window_slot_sync_view_mode (slot); } if (slot == nautilus_window_get_active_slot (window) && @@ -2361,8 +2336,6 @@ nautilus_window_slot_switch_new_content_view (NautilusWindowSlot *slot) window = nautilus_window_slot_get_window (slot); if (slot->details->content_view != NULL) { - nautilus_window_disconnect_content_view (window, slot->details->content_view); - widget = GTK_WIDGET (slot->details->content_view); gtk_widget_destroy (widget); g_object_unref (slot->details->content_view); @@ -2377,9 +2350,6 @@ nautilus_window_slot_switch_new_content_view (NautilusWindowSlot *slot) gtk_container_add (GTK_CONTAINER (slot->details->view_overlay), widget); gtk_widget_show (widget); - /* connect new view */ - nautilus_window_connect_content_view (slot->details->window, slot->details->content_view); - if (!NAUTILUS_IS_SEARCH_DIRECTORY (nautilus_view_get_model (slot->details->content_view)) && slot == nautilus_window_get_active_slot (window)) { nautilus_view_grab_focus (slot->details->content_view); @@ -2446,9 +2416,6 @@ nautilus_window_slot_dispose (GObject *object) nautilus_window_slot_remove_extra_location_widgets (slot); if (slot->details->content_view) { - nautilus_window_disconnect_content_view (nautilus_window_slot_get_window (slot), - slot->details->content_view); - widget = GTK_WIDGET (slot->details->content_view); gtk_widget_destroy (widget); g_object_unref (slot->details->content_view); diff --git a/src/nautilus-window-slot.h b/src/nautilus-window-slot.h index aa9766d85..ed4c8737b 100644 --- a/src/nautilus-window-slot.h +++ b/src/nautilus-window-slot.h @@ -123,5 +123,6 @@ void nautilus_window_slot_go_up (NautilusWindowSlot * void nautilus_window_slot_set_status (NautilusWindowSlot *slot, const char *primary_status, const char *detail_status); +void nautilus_window_slot_sync_view_mode (NautilusWindowSlot *slot); #endif /* NAUTILUS_WINDOW_SLOT_H */ diff --git a/src/nautilus-window.c b/src/nautilus-window.c index 2faed7da9..b56ce6f93 100644 --- a/src/nautilus-window.c +++ b/src/nautilus-window.c @@ -30,7 +30,6 @@ #include "nautilus-window-private.h" -#include "nautilus-actions.h" #include "nautilus-application.h" #include "nautilus-bookmarks-window.h" #include "nautilus-desktop-window.h" @@ -42,7 +41,7 @@ #include "nautilus-toolbar.h" #include "nautilus-window-slot.h" #include "nautilus-list-view.h" -#include "nautilus-canvas-view.h" +#include "nautilus-view.h" #include <eel/eel-debug.h> #include <eel/eel-gtk-extensions.h> @@ -65,6 +64,7 @@ #include <libnautilus-private/nautilus-clipboard.h> #include <libnautilus-private/nautilus-signaller.h> #include <libnautilus-private/nautilus-trash-monitor.h> +#include <libnautilus-private/nautilus-ui-utilities.h> #define DEBUG_FLAG NAUTILUS_DEBUG_WINDOW #include <libnautilus-private/nautilus-debug.h> @@ -80,6 +80,7 @@ static int mouse_back_button = 8; static void mouse_back_button_changed (gpointer callback_data); static void mouse_forward_button_changed (gpointer callback_data); static void use_extra_mouse_buttons_changed (gpointer callback_data); +static void nautilus_window_initialize_actions (NautilusWindow *window); /* Sanity check: highest mouse button value I could find was 14. 5 is our * lower threshold (well-documented to be the one of the button events for the @@ -112,24 +113,358 @@ static const struct { const char *action; } extra_window_keybindings [] = { #ifdef HAVE_X11_XF86KEYSYM_H - { XF86XK_AddFavorite, NAUTILUS_ACTION_ADD_BOOKMARK }, - { XF86XK_Favorites, NAUTILUS_ACTION_EDIT_BOOKMARKS }, - { XF86XK_Go, NAUTILUS_ACTION_ENTER_LOCATION }, - { XF86XK_HomePage, NAUTILUS_ACTION_GO_HOME }, - { XF86XK_OpenURL, NAUTILUS_ACTION_ENTER_LOCATION }, - { XF86XK_Refresh, NAUTILUS_ACTION_RELOAD }, - { XF86XK_Reload, NAUTILUS_ACTION_RELOAD }, - { XF86XK_Search, NAUTILUS_ACTION_SEARCH }, - { XF86XK_Start, NAUTILUS_ACTION_GO_HOME }, - { XF86XK_Stop, NAUTILUS_ACTION_STOP }, - { XF86XK_ZoomIn, NAUTILUS_ACTION_ZOOM_IN }, - { XF86XK_ZoomOut, NAUTILUS_ACTION_ZOOM_OUT }, - { XF86XK_Back, NAUTILUS_ACTION_BACK }, - { XF86XK_Forward, NAUTILUS_ACTION_FORWARD } + /* Window actions */ + { XF86XK_AddFavorite, "bookmark-current-location" }, + { XF86XK_Favorites, "edit-bookmarks" }, + { XF86XK_Go, "enter-location" }, + { XF86XK_HomePage, "go-home" }, + { XF86XK_OpenURL, "enter-location" }, + { XF86XK_Refresh, "reload" }, + { XF86XK_Reload, "reload" }, + { XF86XK_Search, "search" }, + { XF86XK_Start, "go-home" }, + { XF86XK_Stop, "stop" }, + { XF86XK_Back, "back" }, + { XF86XK_Forward, "forward" }, + /* View actions */ + { XF86XK_ZoomIn, "zoom-in" }, + { XF86XK_ZoomOut, "zoom-out" }, #endif }; +static void +action_close_current_view (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusWindow *window; + NautilusWindowSlot *slot; + + window = NAUTILUS_WINDOW (user_data); + slot = nautilus_window_get_active_slot (window); + + nautilus_window_slot_close (window, slot); +} + +static void +action_go_home (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusWindow *window; + NautilusWindowSlot *slot; + + window = NAUTILUS_WINDOW (user_data); + slot = nautilus_window_get_active_slot (window); + + nautilus_window_slot_go_home (slot, + nautilus_event_get_window_open_flags ()); +} + +static void +action_reload (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusWindowSlot *slot; + + slot = nautilus_window_get_active_slot (NAUTILUS_WINDOW (user_data)); + nautilus_window_slot_queue_reload (slot); +} + +static void +action_stop (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusWindow *window; + NautilusWindowSlot *slot; + + window = NAUTILUS_WINDOW (user_data); + slot = nautilus_window_get_active_slot (window); + + nautilus_window_slot_stop_loading (slot); +} + +static void +action_up (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusWindowSlot *slot; + GFile *parent, *location; + + slot = nautilus_window_get_active_slot (NAUTILUS_WINDOW (user_data)); + location = nautilus_window_slot_get_location (slot); + + if (location != NULL) { + parent = g_file_get_parent (location); + if (parent != NULL) + nautilus_window_slot_go_up (slot, nautilus_event_get_window_open_flags ()); + + g_clear_object (&parent); + } +} + +static void +action_back (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + nautilus_window_back_or_forward (NAUTILUS_WINDOW (user_data), + TRUE, 0, nautilus_event_get_window_open_flags ()); +} + +static void +action_forward (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + nautilus_window_back_or_forward (NAUTILUS_WINDOW (user_data), + FALSE, 0, nautilus_event_get_window_open_flags ()); +} + +static void +action_bookmark_current_location (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusWindow *window = user_data; + NautilusApplication *app = NAUTILUS_APPLICATION (g_application_get_default ()); + NautilusWindowSlot *slot; + + slot = nautilus_window_get_active_slot (window); + nautilus_bookmark_list_append (nautilus_application_get_bookmarks (app), + nautilus_window_slot_get_bookmark (slot)); +} + +static void +action_new_tab (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + nautilus_window_new_tab (NAUTILUS_WINDOW (user_data)); +} + +static void +action_enter_location (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + g_action_group_activate_action (G_ACTION_GROUP (g_application_get_default ()), + "enter-location", NULL); +} + +static void +action_tab_previous (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusWindow *window = user_data; + + nautilus_notebook_prev_page (NAUTILUS_NOTEBOOK (window->details->notebook)); +} + +static void +action_tab_next (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusWindow *window = user_data; + + nautilus_notebook_next_page (NAUTILUS_NOTEBOOK (window->details->notebook)); +} + +static void +action_tab_move_left (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusWindow *window = user_data; + + nautilus_notebook_reorder_current_child_relative (NAUTILUS_NOTEBOOK (window->details->notebook), -1); +} + +static void +action_tab_move_right (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusWindow *window = user_data; + + nautilus_notebook_reorder_current_child_relative (NAUTILUS_NOTEBOOK (window->details->notebook), 1); +} + +static void +action_go_to_tab (GSimpleAction *action, + GVariant *value, + gpointer user_data) +{ + NautilusWindow *window = NAUTILUS_WINDOW (user_data); + GtkNotebook *notebook; + gint16 num; + + notebook = GTK_NOTEBOOK (window->details->notebook); + + num = g_variant_get_int32 (value); + if (num < gtk_notebook_get_n_pages (notebook)) { + gtk_notebook_set_current_page (notebook, num); + } +} + +static void +action_toggle_search (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusWindowSlot *slot; + + slot = nautilus_window_get_active_slot (NAUTILUS_WINDOW (user_data)); + nautilus_window_slot_set_search_visible (slot, g_variant_get_boolean (state)); + + g_simple_action_set_state (action, state); +} + +static void +action_prompt_for_location_root (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + GFile *location; + + location = g_file_new_for_path ("/"); + nautilus_window_prompt_for_location (NAUTILUS_WINDOW (user_data), location); + g_object_unref (location); +} + +static void +action_prompt_for_location_home (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + GtkWidget *entry; + + entry = nautilus_window_ensure_location_entry (NAUTILUS_WINDOW (user_data)); + nautilus_location_entry_set_special_text (NAUTILUS_LOCATION_ENTRY (entry), + "~"); + gtk_editable_set_position (GTK_EDITABLE (entry), -1); +} + +static void +action_toggle_state_action_button (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + GVariant *current_state; + + current_state = g_action_get_state (G_ACTION (action)); + g_action_change_state (G_ACTION (action), + g_variant_new_boolean (!g_variant_get_boolean (current_state))); + g_variant_unref (current_state); +} + +static void +action_view_mode (GSimpleAction *action, + GVariant *value, + gpointer user_data) +{ + const gchar *name; + NautilusWindowSlot *slot; + NautilusToolbar *toolbar; + + name = g_variant_get_string (value, NULL); + slot = nautilus_window_get_active_slot (NAUTILUS_WINDOW (user_data)); + toolbar = NAUTILUS_TOOLBAR (nautilus_window_get_toolbar (NAUTILUS_WINDOW (user_data))); + + if (g_strcmp0 (name, "list") == 0) { + nautilus_window_slot_set_content_view (slot, NAUTILUS_LIST_VIEW_ID); + } else if (g_strcmp0 (name, "grid") == 0) { + nautilus_window_slot_set_content_view (slot, NAUTILUS_CANVAS_VIEW_ID); + } else { + g_assert_not_reached (); + } + + nautilus_toolbar_update_view_mode (toolbar, name); + + g_simple_action_set_state (action, value); +} + +const GActionEntry win_entries[] = { + { "back", action_back }, + { "forward", action_forward }, + { "up", action_up }, + { "action-menu", action_toggle_state_action_button, NULL, "false", NULL }, + { "reload", action_reload }, + { "stop", action_stop }, + { "new-tab", action_new_tab }, + { "enter-location", action_enter_location }, + { "bookmark-current-location", action_bookmark_current_location }, + { "toggle-search", NULL, NULL, "false", action_toggle_search }, + { "view-mode", NULL, "s", "''", action_view_mode }, + /* Only accesible by shorcuts */ + { "close-current-view", action_close_current_view }, + { "go-home", action_go_home }, + { "tab-previous", action_tab_previous }, + { "tab-next", action_tab_next }, + { "tab-move-left", action_tab_move_left }, + { "tab-move-right", action_tab_move_right }, + { "prompt-root-location", action_prompt_for_location_root }, + { "prompt-home-location", action_prompt_for_location_home }, + { "go-to-tab", NULL, "i", "0", action_go_to_tab }, +}; + +static void +nautilus_window_initialize_actions (NautilusWindow *window) +{ + GApplication *app; + GAction *action; + GVariant *state; + gchar detailed_action[80]; + gchar accel[80]; + gint i; + + g_action_map_add_action_entries (G_ACTION_MAP (window), + win_entries, G_N_ELEMENTS (win_entries), + window); + + app = g_application_get_default (); + nautilus_application_add_accelerator (app, "win.back", "<alt>Left"); + nautilus_application_add_accelerator (app, "win.forward", "<alt>Right"); + nautilus_application_add_accelerator (app, "win.enter-location", "<control>l"); + nautilus_application_add_accelerator (app, "win.new-tab", "<control>t"); + nautilus_application_add_accelerator (app, "win.toggle-search", "<control>f"); + nautilus_application_add_accelerator (app, "win.view-mode('list')", "<control>1"); + nautilus_application_add_accelerator (app, "win.view-mode('grid')", "<control>2"); + nautilus_application_add_accelerator (app, "win.close-current-view", "<control>w"); + nautilus_application_add_accelerator (app, "win.reload", "<control>r"); + /* Only accesible by shorcuts */ + nautilus_application_add_accelerator (app, "win.bookmark-current-location", "<control>d"); + nautilus_application_add_accelerator (app, "win.up", "<alt>Up"); + nautilus_application_add_accelerator (app, "win.go-home", "<alt>Home"); + nautilus_application_add_accelerator (app, "win.tab-previous", "<control>Page_Up"); + nautilus_application_add_accelerator (app, "win.tab-next", "<control>Page_Down"); + nautilus_application_add_accelerator (app, "win.tab-move-left", "<shift><control>Page_Up"); + nautilus_application_add_accelerator (app, "win.tab-move-right", "<shift><control>Page_Down"); + nautilus_application_add_accelerator (app, "win.prompt-root-location", "slash"); + nautilus_application_add_accelerator (app, "win.prompt-home-location", "asciitilde"); + nautilus_application_add_accelerator (app, "win.action-menu", "F10"); + + /* Alt+N for the first 9 tabs */ + for (i = 0; i < 9; ++i) { + g_snprintf(detailed_action, sizeof (detailed_action), "win.go-to-tab(%i)", i); + g_snprintf(accel, sizeof (accel), "<alt>%i", i + 1); + nautilus_application_add_accelerator (app, detailed_action, accel); + } + + action = g_action_map_lookup_action (G_ACTION_MAP (app), "show-hide-sidebar"); + state = g_action_get_state (action); + if (g_variant_get_boolean (state)) + nautilus_window_show_sidebar (window); + + g_variant_unref (state); +} + void nautilus_window_go_to (NautilusWindow *window, GFile *location) { @@ -380,18 +715,24 @@ update_cursor (NautilusWindow *window) } void +nautilus_window_reset_menus (NautilusWindow *window) +{ + nautilus_window_sync_allow_stop (window, nautilus_window_get_active_slot (window)); +} + +void nautilus_window_sync_allow_stop (NautilusWindow *window, NautilusWindowSlot *slot) { - GtkAction *stop_action; - GtkAction *reload_action; + GAction *stop_action; + GAction *reload_action; gboolean allow_stop, slot_is_active, slot_allow_stop; - stop_action = gtk_action_group_get_action (nautilus_window_get_main_action_group (window), - NAUTILUS_ACTION_STOP); - reload_action = gtk_action_group_get_action (nautilus_window_get_main_action_group (window), - NAUTILUS_ACTION_RELOAD); - allow_stop = gtk_action_get_sensitive (stop_action); + stop_action = g_action_map_lookup_action (G_ACTION_MAP (window), + "stop"); + reload_action = g_action_map_lookup_action (G_ACTION_MAP (window), + "reload"); + allow_stop = g_action_get_enabled (stop_action); slot_allow_stop = nautilus_window_slot_get_allow_stop (slot); slot_is_active = (slot == nautilus_window_get_active_slot (window)); @@ -399,10 +740,16 @@ nautilus_window_sync_allow_stop (NautilusWindow *window, if (!slot_is_active || allow_stop != slot_allow_stop) { if (slot_is_active) { - gtk_action_set_visible (stop_action, slot_allow_stop); - gtk_action_set_visible (reload_action, !slot_allow_stop); + g_simple_action_set_enabled (G_SIMPLE_ACTION (stop_action), slot_allow_stop); + g_simple_action_set_enabled (G_SIMPLE_ACTION (reload_action), !slot_allow_stop); + if (slot_allow_stop) { + nautilus_toolbar_hide_reload (NAUTILUS_TOOLBAR (window->details->toolbar)); + nautilus_toolbar_show_stop (NAUTILUS_TOOLBAR (window->details->toolbar)); + } else { + nautilus_toolbar_hide_stop (NAUTILUS_TOOLBAR (window->details->toolbar)); + nautilus_toolbar_show_reload (NAUTILUS_TOOLBAR (window->details->toolbar)); + } } - if (gtk_widget_get_realized (GTK_WIDGET (window))) { update_cursor (window); } @@ -452,8 +799,6 @@ nautilus_window_set_initial_window_geometry (NautilusWindow *window) GdkScreen *screen; guint max_width_for_screen, max_height_for_screen; guint default_width, default_height; - gboolean show_sidebar; - GtkAction *action; screen = gtk_window_get_screen (GTK_WINDOW (window)); @@ -468,17 +813,6 @@ nautilus_window_set_initial_window_geometry (NautilusWindow *window) max_width_for_screen), MIN (default_height, max_height_for_screen)); - - show_sidebar = g_settings_get_boolean (nautilus_window_state, NAUTILUS_WINDOW_STATE_START_WITH_SIDEBAR); - action = gtk_action_group_get_action (window->details->main_action_group, - NAUTILUS_ACTION_SHOW_HIDE_SIDEBAR); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), show_sidebar); - - if (show_sidebar) { - nautilus_window_show_sidebar (window); - } else { - nautilus_window_hide_sidebar (window); - } } static gboolean @@ -992,7 +1326,7 @@ nautilus_window_sync_bookmarks (NautilusWindow *window) gboolean can_bookmark = FALSE; NautilusWindowSlot *slot; NautilusBookmarkList *bookmarks; - GtkAction *action; + GAction *action; GFile *location; slot = window->details->active_slot; @@ -1004,18 +1338,15 @@ nautilus_window_sync_bookmarks (NautilusWindow *window) can_bookmark = nautilus_bookmark_list_can_bookmark_location (bookmarks, location); } - action = gtk_action_group_get_action (nautilus_window_get_main_action_group (window), - NAUTILUS_ACTION_ADD_BOOKMARK); - gtk_action_set_sensitive (action, can_bookmark); + action = g_action_map_lookup_action (G_ACTION_MAP (window), "bookmark-current-location"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), can_bookmark); } void nautilus_window_sync_location_widgets (NautilusWindow *window) { - NautilusWindowSlot *slot, *active_slot; + NautilusWindowSlot *slot; GFile *location; - GtkActionGroup *action_group; - GtkAction *action; slot = window->details->active_slot; location = nautilus_window_slot_get_location (slot); @@ -1032,17 +1363,7 @@ nautilus_window_sync_location_widgets (NautilusWindow *window) nautilus_path_bar_set_path (NAUTILUS_PATH_BAR (path_bar), location); } - nautilus_window_sync_up_button (window); - - /* Check if the back and forward buttons need enabling or disabling. */ - active_slot = nautilus_window_get_active_slot (window); - action_group = nautilus_window_get_main_action_group (window); - - action = gtk_action_group_get_action (action_group, NAUTILUS_ACTION_BACK); - gtk_action_set_sensitive (action, nautilus_window_slot_get_back_history (active_slot) != NULL); - - action = gtk_action_group_get_action (action_group, NAUTILUS_ACTION_FORWARD); - gtk_action_set_sensitive (action, nautilus_window_slot_get_forward_history (active_slot) != NULL); + nautilus_toolbar_sync_navigation_buttons (NAUTILUS_TOOLBAR (window->details->toolbar)); nautilus_window_sync_bookmarks (window); } @@ -1269,6 +1590,12 @@ notebook_popup_menu_cb (GtkWidget *widget, return TRUE; } +GtkWidget * +nautilus_window_get_toolbar (NautilusWindow *window) +{ + return window->details->toolbar; +} + static GtkWidget * create_toolbar (NautilusWindow *window) { @@ -1294,10 +1621,6 @@ create_toolbar (NautilusWindow *window) /* connect to the location entry signals */ location_entry = nautilus_toolbar_get_location_entry (NAUTILUS_TOOLBAR (toolbar)); - nautilus_clipboard_set_up_editable (GTK_EDITABLE (location_entry), - nautilus_window_get_ui_manager (NAUTILUS_WINDOW (window)), - TRUE); - g_signal_connect_object (location_entry, "location-changed", G_CALLBACK (location_entry_location_changed_callback), window, 0); g_signal_connect_object (location_entry, "cancel", @@ -1457,13 +1780,6 @@ nautilus_window_constructed (GObject *self) gtk_widget_show (grid); gtk_container_add (GTK_CONTAINER (window), grid); - nautilus_window_initialize_menus (window); - nautilus_window_initialize_actions (window); - - /* Register to menu provider extension signal managing menu updates */ - g_signal_connect_object (nautilus_signaller_get_current (), "popup-menu-changed", - G_CALLBACK (nautilus_window_load_extension_menus), window, G_CONNECT_SWAPPED); - window->details->toolbar = create_toolbar (window); gtk_window_set_titlebar (GTK_WINDOW (window), window->details->toolbar); @@ -1482,6 +1798,10 @@ nautilus_window_constructed (GObject *self) window->details->notebook = create_notebook (window); nautilus_window_set_initial_window_geometry (window); + /* Is required that the UI is constructed before initializating the actions, since + * some actions trigger UI widgets to show/hide. */ + nautilus_window_initialize_actions (window); + slot = nautilus_window_open_slot (window, 0); nautilus_window_set_active_slot (window, slot); @@ -1602,8 +1922,6 @@ nautilus_window_finalize (GObject *object) window->details->sidebar_width_handler_id = 0; } - g_clear_object (&window->details->ui_manager); - /* nautilus_window_close() should have run */ g_assert (window->details->slots == NULL); @@ -1707,7 +2025,6 @@ void nautilus_window_set_active_slot (NautilusWindow *window, NautilusWindowSlot *new_slot) { NautilusWindowSlot *old_slot; - NautilusView *view; g_assert (NAUTILUS_IS_WINDOW (window)); @@ -1725,12 +2042,6 @@ nautilus_window_set_active_slot (NautilusWindow *window, NautilusWindowSlot *new /* make old slot inactive if it exists (may be NULL after init, for example) */ if (old_slot != NULL) { - view = nautilus_window_slot_get_view (old_slot); - if (view != NULL) { - /* inform window */ - nautilus_window_disconnect_content_view (window, view); - } - /* inform slot & view */ g_signal_emit_by_name (old_slot, "inactive"); } @@ -1739,12 +2050,6 @@ nautilus_window_set_active_slot (NautilusWindow *window, NautilusWindowSlot *new /* make new slot active, if it exists */ if (new_slot) { - view = nautilus_window_slot_get_view (new_slot); - if (view != NULL) { - /* inform window */ - nautilus_window_connect_content_view (window, view); - } - /* inform sidebar panels */ nautilus_window_report_location_change (window); @@ -1799,20 +2104,18 @@ nautilus_window_key_press_event (GtkWidget *widget, for (i = 0; i < G_N_ELEMENTS (extra_window_keybindings); i++) { if (extra_window_keybindings[i].keyval == event->keyval) { - const GList *action_groups; - GtkAction *action; - - action = NULL; + const GActionGroup *action_group; + GAction *action; - action_groups = gtk_ui_manager_get_action_groups (window->details->ui_manager); - while (action_groups != NULL && action == NULL) { - action = gtk_action_group_get_action (action_groups->data, extra_window_keybindings[i].action); - action_groups = action_groups->next; + action = g_action_map_lookup_action (G_ACTION_MAP (window), extra_window_keybindings[i].action); + if (action == NULL) { + action_group = nautilus_view_get_action_group (view); + action = g_action_map_lookup_action (G_ACTION_MAP (action_group), extra_window_keybindings[i].action); } g_assert (action != NULL); - if (gtk_action_is_sensitive (action)) { - gtk_action_activate (action); + if (g_action_get_enabled (action)) { + g_action_activate (action, NULL); return TRUE; } @@ -1832,33 +2135,6 @@ nautilus_window_key_press_event (GtkWidget *widget, } void -nautilus_window_sync_up_button (NautilusWindow *window) -{ - GtkAction *action; - GtkActionGroup *action_group; - NautilusWindowSlot *slot; - gboolean allowed; - GFile *parent, *location; - - slot = nautilus_window_get_active_slot (window); - location = nautilus_window_slot_get_location (slot); - - allowed = FALSE; - if (location != NULL) { - parent = g_file_get_parent (location); - allowed = parent != NULL; - - g_clear_object (&parent); - } - - action_group = nautilus_window_get_main_action_group (window); - - action = gtk_action_group_get_action (action_group, - NAUTILUS_ACTION_UP); - gtk_action_set_sensitive (action, allowed); -} - -void nautilus_window_sync_title (NautilusWindow *window, NautilusWindowSlot *slot) { @@ -1875,106 +2151,6 @@ nautilus_window_sync_title (NautilusWindow *window, nautilus_notebook_sync_tab_label (NAUTILUS_NOTEBOOK (window->details->notebook), slot); } -void -nautilus_window_sync_zoom_widgets (NautilusWindow *window) -{ - NautilusWindowSlot *slot; - NautilusView *view; - GtkActionGroup *action_group; - GtkAction *action; - gboolean supports_zooming; - gboolean can_zoom, can_zoom_in, can_zoom_out; - - slot = nautilus_window_get_active_slot (window); - view = nautilus_window_slot_get_view (slot); - - if (view != NULL) { - supports_zooming = nautilus_view_supports_zooming (view); - can_zoom_in = supports_zooming && nautilus_view_can_zoom_in (view); - can_zoom_out = supports_zooming && nautilus_view_can_zoom_out (view); - can_zoom = can_zoom_out || can_zoom_in; - } else { - supports_zooming = FALSE; - can_zoom = FALSE; - can_zoom_in = FALSE; - can_zoom_out = FALSE; - } - - action_group = nautilus_window_get_main_action_group (window); - - action = gtk_action_group_get_action (action_group, - NAUTILUS_ACTION_ZOOM_IN); - gtk_action_set_visible (action, supports_zooming); - gtk_action_set_sensitive (action, can_zoom_in); - - action = gtk_action_group_get_action (action_group, - NAUTILUS_ACTION_ZOOM_OUT); - gtk_action_set_visible (action, supports_zooming); - gtk_action_set_sensitive (action, can_zoom_out); - - action = gtk_action_group_get_action (action_group, - NAUTILUS_ACTION_ZOOM_NORMAL); - gtk_action_set_visible (action, supports_zooming); - gtk_action_set_sensitive (action, can_zoom); -} - -static void -zoom_level_changed_callback (NautilusView *view, - NautilusWindow *window) -{ - g_assert (NAUTILUS_IS_WINDOW (window)); - - /* This is called each time the component in - * the active slot successfully completed - * a zooming operation. - */ - nautilus_window_sync_zoom_widgets (window); -} - - -/* These are called - * A) when switching the view within the active slot - * B) when switching the active slot - * C) when closing the active slot (disconnect) -*/ -void -nautilus_window_connect_content_view (NautilusWindow *window, - NautilusView *view) -{ - NautilusWindowSlot *slot; - - g_assert (NAUTILUS_IS_WINDOW (window)); - g_assert (NAUTILUS_IS_VIEW (view)); - - slot = nautilus_view_get_nautilus_window_slot (view); - - if (slot != nautilus_window_get_active_slot (window)) { - return; - } - - g_signal_connect (view, "zoom-level-changed", - G_CALLBACK (zoom_level_changed_callback), - window); -} - -void -nautilus_window_disconnect_content_view (NautilusWindow *window, - NautilusView *view) -{ - NautilusWindowSlot *slot; - - g_assert (NAUTILUS_IS_WINDOW (window)); - g_assert (NAUTILUS_IS_VIEW (view)); - - slot = nautilus_view_get_nautilus_window_slot (view); - - if (slot != nautilus_window_get_active_slot (window)) { - return; - } - - g_signal_handlers_disconnect_by_func (view, G_CALLBACK (zoom_level_changed_callback), window); -} - /** * nautilus_window_show: * @widget: GtkWidget @@ -1984,30 +2160,8 @@ nautilus_window_disconnect_content_view (NautilusWindow *window, */ static void nautilus_window_show (GtkWidget *widget) -{ - NautilusWindow *window; - - window = NAUTILUS_WINDOW (widget); - - GTK_WIDGET_CLASS (nautilus_window_parent_class)->show (widget); - - gtk_ui_manager_ensure_update (window->details->ui_manager); -} - -GtkUIManager * -nautilus_window_get_ui_manager (NautilusWindow *window) -{ - g_return_val_if_fail (NAUTILUS_IS_WINDOW (window), NULL); - - return window->details->ui_manager; -} - -GtkActionGroup * -nautilus_window_get_main_action_group (NautilusWindow *window) { - g_return_val_if_fail (NAUTILUS_IS_WINDOW (window), NULL); - - return window->details->main_action_group; + GTK_WIDGET_CLASS (nautilus_window_parent_class)->show (widget); } NautilusWindowSlot * diff --git a/src/nautilus-window.h b/src/nautilus-window.h index f95eedee5..75c6fc89d 100644 --- a/src/nautilus-window.h +++ b/src/nautilus-window.h @@ -91,10 +91,6 @@ GType nautilus_window_get_type (void); NautilusWindow * nautilus_window_new (GdkScreen *screen); void nautilus_window_close (NautilusWindow *window); -void nautilus_window_connect_content_view (NautilusWindow *window, - NautilusView *view); -void nautilus_window_disconnect_content_view (NautilusWindow *window, - NautilusView *view); void nautilus_window_go_to (NautilusWindow *window, GFile *location); @@ -104,9 +100,6 @@ void nautilus_window_go_to_full (NautilusWindow *window gpointer user_data); void nautilus_window_new_tab (NautilusWindow *window); -GtkUIManager * nautilus_window_get_ui_manager (NautilusWindow *window); -GtkActionGroup * nautilus_window_get_main_action_group (NautilusWindow *window); - void nautilus_window_view_visible (NautilusWindow *window, NautilusView *view); NautilusWindowSlot * nautilus_window_get_active_slot (NautilusWindow *window); @@ -126,6 +119,7 @@ void nautilus_window_back_or_forward (NautilusWindow *window, gboolean back, guint distance, NautilusWindowOpenFlags flags); +void nautilus_window_reset_menus (NautilusWindow *window); gboolean nautilus_window_disable_chrome_mapping (GValue *value, @@ -135,4 +129,5 @@ gboolean nautilus_window_disable_chrome_mapping (GValue *value, NautilusWindowOpenFlags nautilus_event_get_window_open_flags (void); void nautilus_window_show_about_dialog (NautilusWindow *window); +GtkWidget *nautilus_window_get_toolbar (NautilusWindow *window); #endif diff --git a/src/nautilus.gresource.xml b/src/nautilus.gresource.xml index 37a5bbf7f..ff0a1cac4 100644 --- a/src/nautilus.gresource.xml +++ b/src/nautilus.gresource.xml @@ -3,12 +3,11 @@ <gresource prefix="/org/gnome/nautilus"> <file compressed="true">nautilus-bookmarks-window.ui</file> <file compressed="true">nautilus-file-management-properties.ui</file> - <file>nautilus-canvas-view-ui.xml</file> - <file>nautilus-desktop-canvas-view-ui.xml</file> - <file>nautilus-directory-view-ui.xml</file> - <file>nautilus-list-view-ui.xml</file> - <file>nautilus-shell-ui.xml</file> <file>nautilus-app-menu.ui</file> + <file>nautilus-toolbar-ui.xml</file> + <file>nautilus-toolbar-view-menu.xml</file> + <file>nautilus-toolbar-action-menu.xml</file> + <file>nautilus-view-context-menus.xml</file> <file alias="icons/thumbnail_frame.png">../icons/thumbnail_frame.png</file> <file alias="icons/filmholes.png">../icons/filmholes.png</file> <file alias="icons/knob.png">../icons/knob.png</file> |